Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
作者提供的说明(英文原文)
Generate runnable Vue 3 / Vue 2 CRUD pages from one JSON config or a natural-language request.
这三项永远不会合并成一个分数:意见、测量和人气是不同的东西。
我们还没有为它写通俗的介绍。下面是我们从注册中心读取到的事实。
选择你使用的 AI 应用,然后复制设置。
ESPLUS_MCP_PROFILE你需要
你用的是哪个应用?
在上方选择你的应用。我们会记住它,下次按钮会显示“安装到 …”。
打开 Claude Desktop → Settings → Developer → Edit Config,把下面的内容粘贴到 claude_desktop_config.json
{
"mcpServers": {
"es-plus": {
"command": "npx",
"args": [
"-y",
"@es-plus/mcp-server"
],
"env": {
"ESPLUS_MCP_PROFILE": "your-value"
}
}
}
}在终端中运行这条命令
claude mcp add es-plus --env ESPLUS_MCP_PROFILE=your-value -- npx -y @es-plus/mcp-server运行前请先填写空着的值。
粘贴到项目中的 .cursor/mcp.json,或 ~/.cursor/mcp.json
{
"mcpServers": {
"es-plus": {
"command": "npx",
"args": [
"-y",
"@es-plus/mcp-server"
],
"env": {
"ESPLUS_MCP_PROFILE": "your-value"
}
}
}
}浏览器会先询问是否打开应用,然后应用会显示设置并请你确认。密钥的值会留空,由你自己填写。
粘贴到项目中的 .vscode/mcp.json
{
"servers": {
"es-plus": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@es-plus/mcp-server"
],
"env": {
"ESPLUS_MCP_PROFILE": "your-value"
}
}
}
}浏览器会先询问是否打开应用,然后应用会显示设置并请你确认。密钥的值会留空,由你自己填写。
这个服务器在你的电脑上运行,而 ChatGPT 只能连接互联网上的服务器。请选择其他应用。
你的选择通过 Cookie 保存在这台设备上,无需账户。
ESPLUS_MCP_PROFILE env这些设置是根据作者在注册中心的条目生成的。如果 README 的写法不同,请以 README 为准。
它在你的电脑上运行;安装后,工具列表会显示在你的 AI 应用中。
我们检查的是任何人都能看到的信息;我们没有阅读代码。不适用的检查项不计入总数。 · 检查于 2026年11月7日
注册名称已通过 GitHub 账户 liujiaao 验证,该账户拥有此仓库
我们还没有从 GitHub 读取这个仓库
我们还没有从 GitHub 读取这个仓库
它在你的电脑上运行,没有互联网端点
在你的电脑上运行,改用本地设置
它在你的电脑上运行;我们只能读取互联网端点的工具列表
与注册中心里这个分类中所有活跃的服务器比较。只有当发布者拥有该仓库时,星标数才计入。
它在 1 项适用的基础检查中通过了 1 项。我们没有阅读代码。在添加密钥或令牌之前,请先看看这个服务器要求哪些权限,并使用只具备所需权限的密钥。
注册中心没有列出必需的密钥,不过有些服务器会在首次使用时要求你登录。
它在你的电脑上运行。你的 AI 应用会在需要时启动它,数据不会经过作者的服务器(除非它自己调用在线服务)。
GitHub 仓库最后更新于–,最新版本(1.5.0)于昨天进入注册中心。
支持 MCP 的应用,例如 Claude Desktop、Claude Code、Cursor 和 VS Code。你的电脑上还需要有 Node.js。
同一分类中有:Spec Driven Development, Remote Desktop Commander, OpenTakeoff
同一分类中其他作者的服务器,按星标数排序。
如何看卡片:★ GitHub 星标i三大支柱:评价 · 检查 · 使用情况i更新 = 最新版本发布到注册中心的时间i
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Construction takeoff for AI agents: load plans, set scale, measure, count, export with provenance.
按原文从作者的仓库复制。PopNx MCP 没有审查或背书其内容。HTML、图片和脚本已被移除。链接会离开本站。
让 AI 生成的 CRUD 页面可以直接合进代码库:LLM 只写一份 JSON 配置,ES-Plus 负责 Schema 校验 + 确定性编译,一次产出 Vue 3 + Element Plus / Vue 2 + Element UI / Vue 3 + Ant Design Vue 三套可运行代码 —— 同一份配置、三端一致、可复现。
中文 | English
两个徽章都来自夜间 Layer-2 评估对 golden 语料留出集(few-shot 未见域、已排除近变体)的实测,不是营销数字。徽章 label 里标着测量所用的模型:读数随模型变化,不同模型之间不可横向比较,也不与历史读数拼成一条曲线。
第一个是门禁口径:in-schema intent 命中率 = 「零编辑 ∨ 3 轮内收敛」—— 模型首轮就给出可零改合并的配置,或在至多 3 轮自然语言修正内收敛到同一份配置,都算命中(定义)。
第二个是其中更严的一半:只算首轮零编辑,不给收敛机会,用来分辨「一次就对」和「改几轮才对」。
语料目前 216 例(留出 194 例),是回归哨兵而非统计显著的 benchmark,提升靠补语料而非调口径;门禁目标 ≥95%,当前实测以上方徽章为准(由夜间 eval 从 __tests__/golden/last-accuracy.json 生成)。
[在线文档](https://main.esplus-ai.com/) · [Playground](https://main.esplus-ai.com/#/playground) · [AI CRUD 生成器](https://main.esplus-ai.com/#/ai-crud) · [更新日志](https://github.com/liujiaao/es-plus/releases) · [v1.4 迁移指南](./docs/migrate-v1.4.md)
同一份配置的三个渲染端,各自一个线上站:Vue 3 + Element Plus · Vue 3 + Ant Design Vue · Vue 2 + Element UI —— 三个站都跑在线上,示例由各自站点的构建与守卫覆盖。
v1.4.0 起重命名:
es-plus-ui已重命名为@es-plus/vue3,同时新增 Vue 2 渲染器@es-plus/vue2与框架无关的@es-plus/core。原es-plus-ui包继续作为 stub 包工作,详见 迁移指南。
2026 年用 AI 生成前端早不稀奇,稀奇的是敢不敢把生成结果直接合并。多数 AI codegen 是「凭感觉」:每次输出都不一样、对不上你的设计系统、没人替它校验 —— 于是你还得逐行 review、改、再 review。
ES-Plus 把这件事反过来做:让 LLM 只做它擅长的语义推理(需求 → 一份配置),把「生成正确代码」这件必须确定的事交给编译器。
而且它首先是个好用的 CRUD 库:中后台系统 80% 的页面是 CRUD —— 表单查询 → 表格展示 → 弹窗编辑。用原生 Element Plus 每个页面需要 200+ 行模板代码,用 ES-Plus 只需 30 行配置。
| 传统写法 | ES-Plus |
|---|---|
每个字段 5-8 行 + | 一行配置 { prop, label, formtype } |
手动 v-model 绑定每个字段 | 自动绑定到 model |
手动 @click 查询 + resetFields() 重置 | triggerEvent: true 全自动 |
模板声明 | 函数调用 dialog({ title, render }) |
| 手动编写分页事件处理 | 分页切换自动触发请求 |
同一页面、同一功能范围:模板与事件胶水代码减少 76.5%(115 → 27 行),整页非空行减少 40.4%(136 → 81 行);查询 / 重置 / 翻页 / 取数零事件代码。
数字由
npm run one-config:gen从docs/brand/one-config/{native,esplus}.vue实测得出,
由
npm run check:site-claims守住院线。口径:模板区行数 +handle*/fetch*事件与取数函数行数。
useDialog() 命令式调用,JSX 渲染,表单验证集成cachePageSelection 分页切换保留勾选configTableOut 配置化映射 API 响应字段permissionValue 声明式按钮权限,无需 v-iflabelKey + 自定义翻译函数,兼容任意 i18n 方案check:readme 校验)npm create es-plus@latest
交互式选渲染器(Vue 3 + Element Plus / Vue 2 + Element UI / Vue 3 + Ant Design Vue),可选一键写入 MCP(AI 生成)配置,产出一个装上就能跑的 CRUD 示例项目(查询表单 + 表格,零后端)。CI 用脚手架 smoke 守着三端 scaffold → install → build 全绿。详见 create-es-plus。
想手动集成到已有项目,继续往下看。
npm install @es-plus/vue3 element-plus @element-plus/icons-vue
import { createApp } from 'vue'
import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import ESPlus from '@es-plus/vue3' import '@es-plus/vue3/dist/style.css' import App from './App.vue'
const app = createApp(App) app.use(ElementPlus) app.use(ESPlus) app.mount('#app')
npm install @es-plus/vue2 element-ui
参见 @es-plus/vue2 README,配置 API 与 Vue 3 版本完全一致。
npm install @es-plus/adapter-antdv ant-design-vue @ant-design/icons-vue dayjs
import { createApp } from 'vue'
import Antd from 'ant-design-vue' import 'ant-design-vue/dist/reset.css' import ESPlus from '@es-plus/adapter-antdv' import '@es-plus/adapter-antdv/dist/style.css'
const app = createApp(App) app.use(Antd) app.use(ESPlus) app.mount('#app')
@es-plus/adapter-antdv 是 Ant Design Vue 4.x 渲染适配器,与 `@es-plus/vue3` 共享同一份 JSON 配置 Schema,配置 API 完全一致,仅底层 UI 组件不同。详见 adapter-antdv 文档。
<template>
EsForm 嵌套在 EsTable 中,查询/重置/分页全自动联动,零事件处理代码。
┌───────────────────────────────────────────────┐
│ EsTable(通过 provide/inject 提供表格实例) │ │ ┌─────────────────────────────────────────┐ │ │ │ EsForm(自动发现父级 EsTable) │ │ │ │ [查询] → 自动调用 table.httpRequest() │ │ │ │ [重置] → 重置表单 + 重新查询 │ │ │ └─────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────┐ │ │ │ 表格数据(自动分页) │ │ │ └─────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────┐ │ │ │ 分页器(翻页自动触发 httpRequest) │ │ │ └─────────────────────────────────────────┘ │ └───────────────────────────────────────────────┘
EsForm 放在 EsTable 的默认插槽中,通过 Vue 的 provide/inject 自动发现父级表格。按钮配置 triggerEvent: true 后,自动调用表格的数据请求方法,无需手动连接。
| 组件 | 说明 | 典型场景 |
|---|---|---|
| EsForm | 配置化表单 | 查询表单、弹窗编辑表单、筛选条件 |
| EsTable | 配置化表格 | 数据列表、跨页多选、多级表头 |
| useDialog | 编程式弹窗 | 新增/编辑弹窗、详情查看、嵌套弹窗 |
| EsDialog | 增强弹窗组件 | 拖拽、全屏切换、自定义头部/底部 |
| EsCrudPage | CRUD 页面组件 | 传入 Schema 一键生成完整 CRUD 页面 |
| SvgIcon | SVG 图标 | 图标展示 |
const formItems = [
// 文本输入 { prop: 'name', label: '姓名', formtype: 'Input', span: 6 }, // 下拉选择(静态选项) { prop: 'status', label: '状态', formtype: 'Select', span: 6, dataOptions: [{ label: '启用', value: 1 }, { label: '禁用', value: 0 }] }, // 日期范围 { prop: 'date', label: '日期', formtype: 'datePicker', span: 8, attrs: { type: 'daterange', valueFormat: 'YYYY-MM-DD' } }, // 远程数据加载 { prop: 'category', label: '分类', formtype: 'Select', span: 6, apiParams: { url: '/api/categories' }, callOptionListFormat: (data) => data.map(i => ({ label: i.name, value: i.id })) }, // 条件显隐 { prop: 'remark', label: '备注', formtype: 'Input', span: 12, attrs: { type: 'textarea' }, isHidden: (model) => model.status !== 1 } ]
| 字段 | 类型 | 说明 |
|---|---|---|
prop | string | 字段名(必填) |
label | string | 标签(必填) |
formtype | string | 控件类型(14 种) |
span | number | 栅格列宽(1-24) |
attrs | object | 透传到 Element Plus 组件 |
dataOptions | array | Select/Radio/Checkbox 选项 |
isHidden | (model) => boolean | 条件显隐 |
render | (h, model) => VNode | 自定义渲染 |
apiParams | object | 远程加载选项数据 |
labelKey | string | i18n 翻译键 |
const columns = [
{ prop: 'name', label: '姓名' }, { prop: 'amount', label: '金额', formatter: (row) => ¥${row.amount.toFixed(2)} }, // 自定义渲染 { prop: 'status', label: '状态', render: (_, { row }) => h(ElTag, { type: row.status === 1 ? 'success' : 'danger' }, () => row.status === 1 ? '启用' : '禁用') }, // 操作按钮(prop 必须为 'operate') { prop: 'operate', label: '操作', btns: [ { name: '编辑', type: 'primary', clickEvent: (row) => openForm('编辑', row) }, { name: '删除', type: 'danger', clickEvent: (row) => handleDelete(row) } ] } ]
const options = { border: true, stripe: true, highlightCurrentRow: true, httpRequest: fetchList, configTableOut: { total: 'total', tableData: 'records', pageSize: 'size', current: 'page' }, rowkey: 'id', cachePageSelection: true }
后端返回 { result: { items: [...], count: 50 } }?只需配置:
configTableOut: { total: 'count', tableData: 'items', pageSize: 'pageSize', current: 'pageIndex' }
组件会递归查找响应中的字段,适配任意嵌套结构。
options: {
listenToCallBack: { brcb: (params) => ({ ...params, token: getToken() }), // 请求前拦截 qrcb: (response) => transformResponse(response) // 响应后转换 } }
import { useDialog } from '@es-plus/vue3'
const dialog = useDialog()
function openEditForm(row) { const formData = reactive({ ...row }) dialog({ title: '编辑用户', width: '500px', render: (h, { registerRef }) => ( el && registerRef('form', el)} model={formData} formItemList={[ { prop: 'name', label: '姓名', formtype: 'Input', span: 24 }, { prop: 'email', label: '邮箱', formtype: 'Input', span: 24 } ]}
只显示了开头部分;其余内容请在仓库中阅读