feat: enable generated applications to support MCP tool invocation
English | 简体中文
PR Checklist
Please check if your PR fulfills the following requirements:
- [x] The commit message follows our Commit Message Guidelines
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
- [ ] Built its own designer, fully self-validated
PR Type
What kind of change does this PR introduce?
- [ ] Bugfix
- [x] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Documentation content changes
- [ ] Other... Please describe:
Background and solution
What is the current behavior?
Issue Number: N/A
What is the new behavior?
自定义 MCP 出码功能
一、出码流程概览
1.1 整体流程图
用户配置 MCP
↓
Schema 解析 (parseSchemaPlugin)
↓
插件系统初始化 (generateApp)
├─→ 加载 MCP 插件配置
└─→ 传递 context.pluginConfig.mcp
↓
MCP 插件执行 (genMcpPlugin)
├─→ 配置验证 (validateMcpConfig)
├─→ 生成基础配置文件 (base.ts)
│ └─→ 使用 mcpBaseTemplate
├─→ 生成 MCP 服务器管理器 (server.ts)
│ └─→ 使用 mcpServerTemplate(动态导入工具)
├─→ 配置驱动的工具生成
│ ├─→ 遍历 toolGenerators 注册表
│ ├─→ navigation: mcpNavigationToolsTemplate
│ ├─→ application: generateApplicationTools
│ └─→ 错误隔离(单个工具失败不影响其他)
├─→ 处理 tiny_mcp_config(递归转换)
│ └─→ transformTinyMcpConfig
└─→ 修改应用入口文件(使用模板片段)
├─→ App.vue: 5 个模板片段组合
│ ├─→ mcp-imports.ts
│ ├─→ mcp-setup.ts
│ ├─→ mcp-onMounted.ts
│ ├─→ mcp-template.ts
│ └─→ mcp-style.ts
└─→ main.ts: 添加样式导入
↓
页面/区块生成 (genPagePlugin/genBlockPlugin)
├─→ 接收 context.pluginConfig.mcp.enabled
├─→ 传递 mcpEnabled 到 SFC 生成器
└─→ 钩子链处理 tiny_mcp_config
└─→ handleTinyMcpConfigAttrHook
├─→ 格式转换(简单 → JSExpression)
├─→ 添加 usePageMcpServer 导入
└─→ 添加生命周期钩子(onMounted/onUnmounted)
↓
依赖管理 (genDependenciesPlugin)
├─→ 接收 context.pluginConfig.mcp
└─→ 条件性添加 MCP 依赖(仅当 enabled === true)
├─→ @opentiny/next-remoter: 0.0.2
├─→ @opentiny/next-sdk: ^0.1.0
├─→ @opentiny/tiny-robot: ^0.3.0-alpha.16
└─→ @opentiny/tiny-vue-mcp: ~0.0.3
↓
代码格式化 (formatCodePlugin)
↓
生成最终代码
1.2 生成的文件结构
生成的应用/
├── src/
│ ├── base.ts # MCP 基础配置(agentRoot, sessionId)
│ ├── mcp/
│ │ ├── server.ts # MCP 服务器管理器
│ │ └── tools/
│ │ ├── navigationTools.ts # 导航工具(页面跳转、前进后退)
│ │ └── applicationTools.ts # 应用工具(状态管理)
│ ├── App.vue # 修改后的应用入口(集成 MCP 客户端)
│ ├── main.ts # 修改后的主文件(引入 MCP 样式)
│ └── views/ # 页面文件(可能包含 tiny_mcp_config)
└── package.json # 添加 MCP 相关依赖
1.3 关键依赖包
{
"@opentiny/next-remoter": "0.0.2", // MCP UI 组件(聊天界面)
"@opentiny/next-sdk": "^0.1.0", // MCP SDK(客户端/服务器)
"@opentiny/tiny-robot": "^0.3.0-alpha.16", // AI 机器人组件
"@opentiny/tiny-vue-mcp": "~0.0.3", // TinyVue MCP 集成
"@opentiny/vue-common": "与 @opentiny/vue 版本一致" // Vue 通用工具
}
依赖添加逻辑(genDependenciesPlugin.js):
- 只有在
mcpConfig.enabled === true时才添加 MCP 相关依赖 - 通过 context 传递 MCP 配置到依赖插件
- 自动处理 TinyVue 相关依赖的版本一致性
二、出码流程解析
2.1 配置阶段
2.1.1 默认配置(genMcpPlugin.js)
const defaultOption = {
enabled: false, // 默认禁用,需显式启用
agentRoot: 'https://agent.opentiny.design/api/v1/webmcp-trial/',
sessionId: '78b66563-95c0-4839-8007-e8af634dd658',
capabilities: {
prompts: { listChanged: true },
resources: { subscribe: true, listChanged: true },
tools: { listChanged: true },
completions: {},
logging: {}
},
tools: {
navigation: true, // 导航工具
application: true // 应用工具
},
customTools: []
}
2.1.2 配置验证
插件会验证配置的有效性:
enabled必须是布尔值agentRoot必须是有效的 URLtools中的工具类型必须是已知类型customTools必须是数组且每个工具有 name 和 implementation
2.2 插件执行阶段
2.2.1 插件生命周期(generateApp.js)
// 三个阶段的钩子
const codeGenInstance = new CodeGenerator({
plugins: {
transformStart: [parseSchemaPlugin, ...], // 预处理
transform: [
genTemplatePlugin,
genMcpPlugin, // ⭐ MCP 插件
genPagePlugin,
genBlockPlugin,
genDataSourcePlugin,
genDependenciesPlugin,
genGlobalState,
genI18nPlugin,
genRouterPlugin,
genUtilsPlugin,
...
],
transformEnd: [formatCodePlugin, ...] // 后处理
},
context: {
pluginConfig: config?.pluginConfig || {} // 包含 mcp 配置
}
})
2.2.2 MCP 插件执行流程(采用模板驱动)
run(schema) {
// 1. 检查是否启用
if (!realOptions.enabled) return []
try {
const files = []
const { tools } = realOptions
// 2. 确定启用的工具类别
const enabledTools = Object.keys(tools).filter(tool => tools[tool])
// 3. 生成基础配置文件(使用模板)
files.push({
fileType: 'ts',
fileName: 'base.ts',
path: './src',
fileContent: mcpBaseTemplate(null, {
agentRoot: realOptions.agentRoot,
sessionId: realOptions.sessionId
})
})
// 4. 生成 MCP 服务器管理器(使用模板)
files.push({
fileType: 'ts',
fileName: 'server.ts',
path: './src/mcp',
fileContent: mcpServerTemplate(null, { enabledTools })
})
// 5. mcp 的工具生成
Object.entries(tools).forEach(([toolName, enabled]) => {
if (enabled && toolGenerators[toolName]) {
const generator = toolGenerators[toolName]
const toolFileName = `${toolName}Tools.ts`
files.push({
fileType: 'ts',
fileName: toolFileName,
path: './src/mcp/tools',
fileContent: generator(
toolName === 'navigation' ? schema.pageSchema || [] : schema
)
})
}
})
// 6. 处理 tiny_mcp_config(递归转换)
if (schema.pageSchema && Array.isArray(schema.pageSchema)) {
schema.pageSchema.forEach(page => {
if (pageHasTinyMcpConfig(page)) {
transformTinyMcpConfig(page)
}
})
}
// 7. 修改应用入口文件(使用模板片段)
const existingAppVue = this.getFile('./src', 'App.vue')
if (existingAppVue) {
const modifiedAppVue = modifyAppVue(existingAppVue.fileContent, realOptions)
this.replaceFile({
fileType: 'vue',
fileName: 'App.vue',
path: './src',
fileContent: modifiedAppVue
})
}
// 8. 修改 main.ts 添加样式导入
const existingMainTs = this.getFile('./src', 'main.ts') || this.getFile('./src', 'main.js')
if (existingMainTs && existingMainTs.fileName) {
const modifiedMainTs = modifyMainTs(existingMainTs.fileContent)
this.replaceFile({
fileType: existingMainTs.fileName.endsWith('.ts') ? 'ts' : 'js',
fileName: existingMainTs.fileName,
path: './src',
fileContent: modifiedMainTs
})
}
return files
} catch (error) {
console.error('MCP 插件生成失败:', error)
if (this.addLog) {
this.addLog({
type: 'error',
message: `MCP 插件生成失败: ${error.message}`,
plugin: 'genMcpPlugin',
stack: error.stack
})
}
return []
}
}
三、 默认出码流程 vs MCP 出码流程对比
3.1 架构对比
| 维度 | 默认出码流程 | MCP 出码流程 |
|---|---|---|
| 插件数量 | 11 个核心插件 | 12 个插件(新增 genMcpPlugin) |
| 生成文件数 | ~10-15 个 | ~15-20 个(新增 MCP 相关文件) |
| 依赖包数量 | 基础依赖 | 新增 4 个 MCP 相关包 |
| 应用入口修改 | 无 | 修改 App.vue 和 main.ts |
3.2 代码生成流程对比
默认流程
Schema 输入
↓
parseSchemaPlugin (解析)
↓
genTemplatePlugin (模板)
↓
genPagePlugin (页面)
↓
genBlockPlugin (区块)
↓
genRouterPlugin (路由)
↓
genDataSourcePlugin (数据源)
↓
genGlobalState (全局状态)
↓
genI18nPlugin (国际化)
↓
genUtilsPlugin (工具函数)
↓
genDependenciesPlugin (依赖)
↓
formatCodePlugin (格式化)
↓
输出代码
MCP 流程(新增部分)
Schema 输入
↓
parseSchemaPlugin (解析)
↓
genTemplatePlugin (模板)
↓
genMcpPlugin ⭐ (MCP 集成)
├─ 生成 base.ts
├─ 生成 server.ts
├─ 生成 navigationTools.ts
├─ 生成 applicationTools.ts
├─ 修改 App.vue
├─ 修改 main.ts
└─ 转换 tiny_mcp_config
↓
genPagePlugin (页面,传递 mcpEnabled)
└─ handleTinyMcpConfigAttrHook ⭐
↓
genBlockPlugin (区块,传递 mcpEnabled)
└─ handleTinyMcpConfigAttrHook ⭐
↓
... (其他插件)
↓
genDependenciesPlugin (依赖)
└─ 添加 MCP 依赖 ⭐
↓
formatCodePlugin (格式化)
↓
输出代码(包含 MCP 能力)
四、相关界面与过程截图
4.1 基本使用流程(以 tiny-grid 组件为例
目前仅适配
tiny-grid组件,后期会拓展更多组件...
-
给 tiny-grid 添加 mcp 相关配置
-
开启 mcp 出码相关配置、生成代码
-
运行出码应用、通过对话对 mcp 组件进行操作
自定义出码 MCP 工具
如何在 MCP 插件中添加新的工具生成器。通过配置驱动的方式,添加新工具只需两步:
- 编写工具生成函数
- 在
toolGenerators中注册
1. 编写工具生成函数
在 genMcpPlugin.js 中添加生成函数:
/**
* 生成通知工具代码
* @param {Object} schema 应用程序模式
* @returns {string} 工具代码
*/
function generateNotificationTools(schema) {
return `import { z } from "@opentiny/next-sdk"
import type { WebMcpServer } from "@opentiny/next-sdk"
export function registerNotificationTools(server: WebMcpServer) {
server.registerTool(
"send-notification",
{
title: "发送通知",
description: "向用户发送系统通知",
inputSchema: {
title: z.string().describe("通知标题"),
message: z.string().describe("通知内容"),
type: z.enum(['info', 'success', 'warning', 'error']).describe("通知类型")
}
},
async ({ title, message, type }) => {
try {
window.$notification[type]({ title, message })
return {
content: [{ type: "text", text: "通知已发送" }]
}
} catch (error) {
return {
content: [{ type: "text", text: \`发送失败:\${error}\` }]
}
}
}
)
}
`
}
2. 注册到工具生成器
在 toolGenerators 对象中添加:
const toolGenerators = {
navigation: generateNavigationTools,
application: generateApplicationTools,
notification: generateNotificationTools // 新增这一行
}
3. 配置启用工具
用户在配置中启用:
const mcpConfig = {
enabled: true,
tools: {
navigation: true,
application: true,
notification: true // 启用通知工具
}
}
Does this PR introduce a breaking change?
- [ ] Yes
- [x] No
Other information
Summary by CodeRabbit
-
New Features
- MCP toggle added to the code-generation UI with state sync and automatic re-generation.
- Table column configuration now exposes an MCP settings section.
- Generated projects gain optional MCP integration: runtime bootstrap, UI remoter, styles, navigation and application tools, and build-time wiring.
-
Chores
- Many component version references updated to 3.26.0.
Walkthrough
Adds MCP (Model Context Protocol) support across generator and UI: new genMcpPlugin, MCP templates and server tooling, generator plumbing to propagate pluginConfig.mcp, conditional dependency injection, UI toggle and caching for code generation, plus mock schema/version updates.
Changes
| Cohort / File(s) | Summary |
|---|---|
Mock Data designer-demo/public/mock/bundle.json, mockServer/src/mock/get/app-center/v1/apps/schema/1.json |
Add MCP configuration block to table column schema; bulk-update many component version fields to 3.26.0 (some entries remain at other versions). |
UI — File Selector packages/toolbars/generate-code/src/FileSelector.vue |
Add MCP toggle UI, enableMcp prop, update:enableMcp emit, local mcpEnabled state, watchers, openDialog sync, and styles. |
UI — Main Code Generator packages/toolbars/generate-code/src/Main.vue |
Add enableMcp and appSchemaCache state; wire FileSelector MCP prop/emit; implement handleMcpToggle(enabled) to (re)generate code using cached schema and include MCP config in generation; expose handler. |
Generator Core packages/vue-generator/src/generator/generateApp.js |
Import/include genMcpPlugin in default/custom plugins, merge mcp into plugins, and propagate pluginConfig (including mcp) into generation context/CodeGenerator. |
SFC Hook Integration packages/vue-generator/src/generator/vue/sfc/genSetupSFC.js |
Import and insert handleTinyMcpConfigAttrHook into defaultAttributeHook sequence. |
Plugin Index packages/vue-generator/src/plugins/index.js |
Re-export genMcpPlugin. |
Plugin Signatures & Context packages/vue-generator/src/plugins/genBlockPlugin.js, packages/vue-generator/src/plugins/genPagePlugin.js, packages/vue-generator/src/plugins/genDependenciesPlugin.js |
Update run() signatures to accept context; extract context?.pluginConfig?.mcp/mcpEnabled and propagate into SFC/dependency generation; parseSchema accepts MCP config; deps plugin conditionally injects MCP dependencies. |
MCP Plugin packages/vue-generator/src/plugins/genMcpPlugin.js |
New plugin providing defaults, validation, generation of MCP files (base, server, imports/onMounted/setup/style/template, tools), App/main modifications, handleTinyMcpConfigAttrHook, transform detection for tiny_mcp_config, and run(schema) behavior. |
Dependencies Plugin packages/vue-generator/src/plugins/genDependenciesPlugin.js |
Add conditional MCP-related dependencies (@opentiny/next-remoter, next-sdk, tiny-robot, tiny-vue-mcp) and adjust dependency composition when MCP enabled. |
Templates — MCP Files packages/vue-generator/src/templates/vue-template/templateFiles/src/mcp/* |
Add template generators and runtime code: App.vue.mcp-imports.ts, App.vue.mcp-onMounted.ts, App.vue.mcp-setup.ts, App.vue.mcp-style.ts, App.vue.mcp-template.ts, base.ts, server.ts (McpServerManager + composable), and tools/navigationTools.ts. |
Sequence Diagram(s)
sequenceDiagram
participant UI as FileSelector
participant Main as Main.vue
participant Gen as generateApp()
participant Plugins as Plugin Chain
participant MCP as genMcpPlugin
participant Templates as MCP Templates
participant Out as Generated Files
UI->>Main: emit update:enableMcp(enabled)
Main->>Main: handleMcpToggle(enabled) / use appSchemaCache
Main->>Gen: generateAppCode(schema, { pluginConfig: { mcp: { enabled } } })
Gen->>Plugins: run(schema, context)
Plugins->>Plugins: read context.pluginConfig.mcp -> mcpEnabled
Plugins->>Gen: pass mcpEnabled into SFC/deps generation
alt mcpEnabled == true
Gen->>MCP: genMcpPlugin.run(schema, context)
MCP->>Templates: generate MCP files (base, server, templates, tools)
MCP->>Out: emit MCP runtime files
else
Gen->>Out: skip MCP-specific files
end
Plugins->>Out: emit standard generated files
Main->>UI: update saveFilesInfo (file list)
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~60–75 minutes
Areas needing extra attention:
- packages/vue-generator/src/plugins/genMcpPlugin.js — template injection, App/main modifications, validation and schema transforms.
- packages/vue-generator/src/templates/.../server.ts — lifecycle, singleton/composable correctness.
- packages/vue-generator/src/plugins/genDependenciesPlugin.js — conditional dependency logic and version choices.
- Integration points: generateApp.js, genBlockPlugin.js, genPagePlugin.js, genSetupSFC.js for correct propagation of pluginConfig.mcp.
- UI: packages/toolbars/generate-code/src/Main.vue — caching, toggle wiring, and error handling.
Poem
🐰 I nibbled code by lantern's gleam,
A tiny switch began to dream,
Servers hummed and routes took wing,
Schemas whispered MCP's new spring,
Hopping bytes — a joyous thing! 🥕
Pre-merge checks and finishing touches
✅ Passed checks (3 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title Check | ✅ Passed | The title "feat: enable generated applications to support MCP tool invocation" directly and accurately describes the primary objective of this changeset. The PR introduces comprehensive MCP (Model Context Protocol) plugin support throughout the code generation pipeline, including a new genMcpPlugin, configuration validation, file generation, and integration with existing plugins and components. The title is concise, specific, and uses clear language that effectively communicates the feature being added without vague terms or unnecessary detail. |
| Docstring Coverage | ✅ Passed | Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%. |
✨ Finishing touches
- [ ] 📝 Generate docstrings
🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.