@leeoohoo/ui-apps-devkit 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +75 -60
  2. package/bin/chatos-uiapp.js +4 -4
  3. package/package.json +26 -20
  4. package/src/cli.js +53 -53
  5. package/src/commands/dev.js +14 -14
  6. package/src/commands/init.js +131 -129
  7. package/src/commands/install.js +47 -46
  8. package/src/commands/pack.js +72 -72
  9. package/src/commands/validate.js +138 -80
  10. package/src/lib/args.js +49 -49
  11. package/src/lib/config.js +29 -29
  12. package/src/lib/fs.js +78 -78
  13. package/src/lib/path-boundary.js +16 -16
  14. package/src/lib/plugin.js +45 -45
  15. package/src/lib/state-constants.js +2 -0
  16. package/src/lib/template.js +172 -168
  17. package/src/sandbox/server.js +1957 -692
  18. package/templates/basic/README.md +78 -54
  19. package/templates/basic/chatos.config.json +5 -5
  20. package/templates/basic/docs/CHATOS_UI_APPS_AI_CONTRIBUTIONS.md +214 -181
  21. package/templates/basic/docs/CHATOS_UI_APPS_BACKEND_PROTOCOL.md +75 -74
  22. package/templates/basic/docs/CHATOS_UI_APPS_HOST_API.md +136 -123
  23. package/templates/basic/docs/CHATOS_UI_APPS_OVERVIEW.md +112 -107
  24. package/templates/basic/docs/CHATOS_UI_APPS_PLUGIN_MANIFEST.md +242 -227
  25. package/templates/basic/docs/CHATOS_UI_APPS_STYLE_GUIDE.md +95 -0
  26. package/templates/basic/docs/CHATOS_UI_APPS_TROUBLESHOOTING.md +45 -0
  27. package/templates/basic/docs/CHATOS_UI_PROMPTS_PROTOCOL.md +392 -392
  28. package/templates/basic/plugin/apps/app/compact.mjs +41 -0
  29. package/templates/basic/plugin/apps/app/index.mjs +287 -263
  30. package/templates/basic/plugin/apps/app/mcp-prompt.en.md +7 -7
  31. package/templates/basic/plugin/apps/app/mcp-prompt.zh.md +7 -7
  32. package/templates/basic/plugin/apps/app/mcp-server.mjs +15 -15
  33. package/templates/basic/plugin/backend/index.mjs +37 -37
  34. package/templates/basic/template.json +7 -7
  35. package/templates/notepad/README.md +55 -24
  36. package/templates/notepad/chatos.config.json +4 -4
  37. package/templates/notepad/docs/CHATOS_UI_APPS_AI_CONTRIBUTIONS.md +214 -181
  38. package/templates/notepad/docs/CHATOS_UI_APPS_BACKEND_PROTOCOL.md +75 -74
  39. package/templates/notepad/docs/CHATOS_UI_APPS_HOST_API.md +136 -123
  40. package/templates/notepad/docs/CHATOS_UI_APPS_OVERVIEW.md +112 -107
  41. package/templates/notepad/docs/CHATOS_UI_APPS_PLUGIN_MANIFEST.md +242 -227
  42. package/templates/notepad/docs/CHATOS_UI_APPS_STYLE_GUIDE.md +95 -0
  43. package/templates/notepad/docs/CHATOS_UI_APPS_TROUBLESHOOTING.md +45 -0
  44. package/templates/notepad/docs/CHATOS_UI_PROMPTS_PROTOCOL.md +392 -392
  45. package/templates/notepad/plugin/apps/app/api.mjs +30 -30
  46. package/templates/notepad/plugin/apps/app/compact.mjs +41 -0
  47. package/templates/notepad/plugin/apps/app/dom.mjs +14 -14
  48. package/templates/notepad/plugin/apps/app/ds-tree.mjs +35 -35
  49. package/templates/notepad/plugin/apps/app/index.mjs +1056 -1056
  50. package/templates/notepad/plugin/apps/app/layers.mjs +338 -338
  51. package/templates/notepad/plugin/apps/app/markdown.mjs +120 -120
  52. package/templates/notepad/plugin/apps/app/mcp-prompt.en.md +22 -22
  53. package/templates/notepad/plugin/apps/app/mcp-prompt.zh.md +22 -22
  54. package/templates/notepad/plugin/apps/app/mcp-server.mjs +206 -199
  55. package/templates/notepad/plugin/apps/app/styles.mjs +355 -355
  56. package/templates/notepad/plugin/apps/app/tags.mjs +21 -21
  57. package/templates/notepad/plugin/apps/app/ui.mjs +280 -280
  58. package/templates/notepad/plugin/backend/index.mjs +99 -99
  59. package/templates/notepad/plugin/plugin.json +23 -23
  60. package/templates/notepad/plugin/shared/notepad-paths.mjs +59 -41
  61. package/templates/notepad/plugin/shared/notepad-store.mjs +765 -765
  62. package/templates/notepad/template.json +8 -8
@@ -1,58 +1,82 @@
1
- # __PLUGIN_NAME__
2
-
3
- 这是一个 **ChatOS UI Apps 插件工程**(UI Apps Plugins)。
4
-
5
- ## 你应该在哪写什么
6
-
7
- - `plugin/plugin.json`:插件清单(应用列表、入口、后端、AI 贡献)
8
- - `plugin/apps/__APP_ID__/index.mjs`:**module 入口**(导出 `mount({ container, host, slots })`)
9
- - `plugin/backend/index.mjs`:**插件后端**(导出 `createUiAppsBackend(ctx)`,通过 `host.backend.invoke()` 调用)
10
- - `plugin/apps/__APP_ID__/mcp-server.mjs`:应用自带 MCP Server(可选)
11
- - `plugin/apps/__APP_ID__/mcp-prompt.zh.md` / `.en.md`:MCP Prompt(可选)
12
-
13
- ## 开发与预览(本地沙箱)
14
-
15
- ```bash
16
- npm install
17
- npm run dev
18
- ```
19
-
20
- 沙箱会:
21
-
22
- - 用 HTTP 运行你的 `module` 入口(模拟 ChatOS 的 `mount()` 调用)
23
- - 提供 `host.*`mock(含 `host.backend.invoke()`、`host.uiPrompts.*`、`host.chat.*`)
24
-
25
- ## 复用 ChatOS 的 AI 调用(推荐)
26
-
27
- 本模板演示两种“复用宿主模型/密钥/工具链”的方式:
28
-
29
- 1) **前端直连 Chat 域**:用 `host.chat.*` 创建 agent/session、`host.chat.send()` 发送消息、`host.chat.events.subscribe()` 订阅流式事件。
30
- 2) **后端调用 LLM**:在 `plugin/backend/index.mjs` 里通过 `ctx.llm.complete()` 调用模型;前端用 `host.backend.invoke('llmComplete', { input })` 触发。
31
-
32
- 说明:本地沙箱只提供 mock(不会真实调用模型);要验证真实 AI 行为请安装到 ChatOS 后运行。
33
-
34
- ## 安装到本机 ChatOS
35
-
36
- ```bash
37
- npm run validate
38
- npm run install:chatos
39
- ```
40
-
41
- 或打包成 zip(用于 ChatOS UI:应用 导入应用包):
42
-
43
- ```bash
44
- npm run pack
45
- ```
46
-
47
- ## 协议文档
48
-
49
- `docs/` 目录包含当前版本的协议快照(建议团队内统一对齐)。
50
-
51
- ## 启用 MCP(可选)
52
-
1
+ # __PLUGIN_NAME__
2
+
3
+ 这是一个 **ChatOS UI Apps 插件工程**(UI Apps Plugins)。
4
+
5
+ ## 你应该在哪写什么
6
+
7
+ - `plugin/plugin.json`:插件清单(应用列表、入口、后端、AI 贡献)
8
+ - `plugin/apps/__APP_ID__/index.mjs`:**module 入口**(导出 `mount({ container, host, slots })`)
9
+ - `plugin/apps/__APP_ID__/compact.mjs`:**compact 入口**(可选;用于侧边抽屉/分栏场景)
10
+ - `plugin/backend/index.mjs`:**插件后端**(导出 `createUiAppsBackend(ctx)`,通过 `host.backend.invoke()` 调用)
11
+ - `plugin/apps/__APP_ID__/mcp-server.mjs`:应用自带 MCP Server(可选)
12
+ - `plugin/apps/__APP_ID__/mcp-prompt.zh.md` / `.en.md`:MCP Prompt(可选)
13
+
14
+ ## 开发与预览(本地沙箱)
15
+
16
+ ```bash
17
+ npm install
18
+ npm run dev
19
+ ```
20
+
21
+ 沙箱会:
22
+
23
+ - HTTP 运行你的 `module` 入口(模拟 ChatOS 的 `mount()` 调用)
24
+ - 提供 `host.*` 的 mock(含 `host.backend.invoke()`、`host.uiPrompts.*`、`host.chat.*`)
25
+
26
+ ## 主题与样式(重要)
27
+
28
+ - 宿主通过 `document.documentElement.dataset.theme` 下发 `light` / `dark`,用 `host.theme.get()` / `host.theme.onChange()` 读取与监听。
29
+ - 推荐使用 CSS Tokens(`--ds-*`)做主题适配,避免硬编码颜色。
30
+ - 本地沙箱右上角提供 Theme 切换(light/dark/system)用于测试样式响应。
31
+ - 本地沙箱 Inspect 面板可查看 `host.context` 与 `--ds-*` tokens。
32
+
33
+ ## 开发清单(建议)
34
+
35
+ - `plugin/plugin.json`:`apps[i].entry.type` 必须是 `module`,且 `path` 在插件目录内。
36
+ - `plugin/plugin.json`:可选 `apps[i].entry.compact.path`,用于 compact UI。
37
+ - 安全:插件目录内尽量避免 symlink(`npm run validate` 会提示),以免路径边界与打包行为不一致。
38
+ - `mount()`:返回卸载函数并清理事件/订阅;滚动放在应用内部,固定内容用 `slots.header`。
39
+ - 主题:用 `host.theme.*` 与 `--ds-*` tokens;避免硬编码颜色。
40
+ - 宿主能力:先判断 `host.bridge.enabled`,非宿主环境要可降级运行。
41
+ - Node 能力:前端不直接用 Node API,需要时走 `host.backend.invoke()`。
42
+ - 打包:依赖需 bundle 成单文件;ChatOS 导入会排除 `node_modules`,MCP server 不能直接 import 第三方依赖。
43
+ - 提交前:`npm run validate`,必要时再 `pack/install`。
44
+
45
+ ## 复用 ChatOS 的 AI 调用(推荐)
46
+
47
+ 本模板演示两种“复用宿主模型/密钥/工具链”的方式:
48
+
49
+ 1) **前端直连 Chat 域**:用 `host.chat.*` 创建 agent/session、`host.chat.send()` 发送消息、`host.chat.events.subscribe()` 订阅流式事件。
50
+ 2) **后端调用 LLM**:在 `plugin/backend/index.mjs` 里通过 `ctx.llm.complete()` 调用模型;前端用 `host.backend.invoke('llmComplete', { input })` 触发。
51
+
52
+ 说明:本地沙箱默认是 mock;可通过右上角 `AI Config` 配置 `API Key / Base URL / Model ID` 后启用真实模型调用,并用于测试应用 MCP(需配置 `ai.mcp`)。
53
+ 补充:沙箱默认把 `_meta.workdir` 设为 `dataDir`;如需模拟其它工作目录,可在 `AI Config` 里设置 `Workdir` 覆盖(支持 `$dataDir/$pluginDir/$projectRoot`)。
54
+
55
+ ## 安装到本机 ChatOS
56
+
57
+ ```bash
58
+ npm run validate
59
+ npm run install:chatos
60
+ ```
61
+
62
+ 或打包成 zip(用于 ChatOS UI:应用 → 导入应用包):
63
+
64
+ ```bash
65
+ npm run pack
66
+ ```
67
+
68
+ ## 协议文档
69
+
70
+ `docs/` 目录包含当前版本的协议快照(建议团队内统一对齐),并包含主题样式指南与排错清单。
71
+
72
+ ## 启用 MCP(可选)
73
+
53
74
  本模板默认只启用 `ai.mcpPrompt`(不启用 `ai.mcp`),避免第三方插件在未打包依赖时运行失败。
54
75
 
76
+ ⚠️ ChatOS 导入插件时会排除 `node_modules/`。因此 MCP server 只要用了第三方依赖(如 `@modelcontextprotocol/sdk`、`zod`),就必须先 bundle 成单文件,或把依赖源码放进插件目录。
77
+ 若看到 `Cannot find package '@modelcontextprotocol/sdk'`,说明依赖未被 bundle。
78
+
55
79
  如果你要启用 MCP:
56
80
 
57
- 1) 实现并打包 `plugin/apps/__APP_ID__/mcp-server.mjs`(建议 bundle 成单文件)
58
- 2) 在 `plugin/plugin.json` 的 `apps[i].ai.mcp` 写入 `entry/command/args/...`
81
+ 1) 实现并打包 `plugin/apps/__APP_ID__/mcp-server.mjs`(必须 bundle 成单文件,除非完全不依赖第三方)
82
+ 2) 在 `plugin/plugin.json` 的 `apps[i].ai.mcp` 写入 `entry/command/args/...` 并指向 bundle 产物
@@ -1,5 +1,5 @@
1
- {
2
- "pluginDir": "plugin",
3
- "appId": "__APP_ID__"
4
- }
5
-
1
+ {
2
+ "pluginDir": "plugin",
3
+ "appId": "__APP_ID__"
4
+ }
5
+
@@ -1,181 +1,214 @@
1
- # ChatOS UI Apps:AI 暴露(MCP / Prompts)协议
2
-
3
- 本文件描述应用如何对 ChatOS 的 Chat Agent 暴露能力,包括:
4
-
5
- - 声明一个专属 MCP Server(让工具随应用交付、随插件安装)
6
- - 声明应用的默认 MCP Prompt(告诉模型如何使用这些工具/这个应用)
7
- - 聚合暴露“已有的”全局 MCP Servers / Prompts(面板型应用常用)
8
- - 内置应用的“开关 + 精细清单”两层机制(清单在 `aide` 维护)
9
-
10
- 实现对照(以代码为准):
11
-
12
- - schema:`deepseek_cli/electron/ui-apps/schemas.js`
13
- - 扫描与贡献解析:`deepseek_cli/electron/ui-apps/index.js`(`#resolveAi` / `getAiContribution()`;可选 `#syncAiContributes` 持久化到 Admin DB)
14
- - 内置默认清单:`aide/shared/defaults/ui-apps-expose/`
15
-
16
- ## 1. 两种暴露方式(应用侧选择其一或组合)
17
-
18
- ### 方式 A:应用自带 MCP Server + MCP Prompt
19
-
20
- 用于:应用包含专属 tools(数据库查询、系统诊断、内部系统调用等)。
21
-
22
- 在 `apps[i].ai` 里声明:
23
-
24
- - `ai.mcp`:宿主会创建/更新一个 MCP server(`serverName` 固定为 `${pluginId}.${appId}`)
25
- - `ai.mcpPrompt`:宿主会创建/更新对应 system prompt(prompt 名称固定派生)
26
-
27
- 示例(节选):
28
-
29
- ```json
30
- {
31
- "id": "db-client",
32
- "name": "数据库客户端",
33
- "entry": { "type": "module", "path": "db-client/index.mjs" },
34
- "ai": {
35
- "mcp": { "entry": "db-client/mcp-server.mjs", "command": "node", "allowMain": true, "allowSub": true },
36
- "mcpPrompt": { "zh": "db-client/mcp-prompt.zh.md", "en": "db-client/mcp-prompt.en.md" }
37
- }
38
- }
39
- ```
40
-
41
- ### 方式 B:聚合暴露“已有的” MCP servers / Prompts(面板型应用常用)
42
-
43
- 用于:应用以“工作台/面板”形态聚合展示能力,不提供新的 MCP server,但需要按应用维度暴露已有 MCP servers / Prompts。
44
-
45
- 在 `apps[i].ai` 里声明:
46
-
47
- - `ai.mcpServers: true | false | string[]`
48
- - `ai.prompts: true | false | string[]`
49
-
50
- 注意:这是“可见/可选范围”的声明;最终是否启用、启用哪些,仍由 Agent 编辑页对该应用的多选结果决定。
51
-
52
- ## 2. 命名规则(宿主自动派生)
53
-
54
- 对每个 app:
55
-
56
- - MCP `serverName`:`${pluginId}.${appId}`
57
- - Prompt name:
58
- - 中文:`mcp_<normalize(serverName)>`
59
- - 英文:`mcp_<normalize(serverName)>__en`
60
-
61
- `normalize()`:
62
-
63
- - 转小写
64
- - 把非 `[a-z0-9_-]` 的字符替换为 `_`
65
- - 去掉首尾 `_`
66
-
67
- ## 3. `ai.mcp` 的 url 生成规则(entry → cmd://)
68
-
69
- 当 `ai.mcp.entry` 存在时,宿主会把它转换为:
70
-
71
- - `cmd://<command> <absEntryOrRelEntry> <args...>`
72
- - `command` 默认为 `node`
73
-
74
- 当 `ai.mcp.url` 存在时,直接使用该 url(远程/HTTP/WS 等)。
75
-
76
- ## 4. Agent UI 如何消费应用暴露(你需要知道的运行机制)
77
-
78
- ### 4.1 体现在哪里(持久化 vs 运行时注入)
79
-
80
- 当你把插件放进插件目录并在 UI「应用」页点击“刷新”后:
81
-
82
- 1) 宿主扫描插件并解析 `plugin.json`
83
- 2) 若发现 `apps[i].ai`:
84
- - 宿主会在 UI Apps 注册表中暴露该应用的 `ai` 声明;
85
- - **无论是否写入 Admin DB**,Chat Agent 运行时都可通过 `uiApps.getAiContribution()` 读取 `mcp.url` 与 `mcpPrompt` 文本,并按需“临时注入”到本次运行(见第 4.3 节)。
86
- - (可选)若宿主启用 `syncAiContributes`,则会把 `ai.mcp` / `ai.mcpPrompt` **持久化同步**到 Admin DB(出现在 `MCP Servers` / `Prompts` 列表中,便于管理与复用)。
87
- 3) 在 `Chat → Agents` 创建/编辑 agent 时:
88
- - 先选择应用(按应用维度)
89
- - 再为每个应用分别勾选 MCP/Prompt,并在多选框中选择要挂载的 servers/prompts
90
-
91
- ### 4.2 保存结构(简化)
92
-
93
- ```json
94
- {
95
- "uiApps": [
96
- {
97
- "pluginId": "com.example.tools",
98
- "appId": "db-client",
99
- "mcp": true,
100
- "prompt": true,
101
- "mcpServerIds": ["<admin.mcpServers.id>", "..."],
102
- "promptIds": ["<admin.prompts.id>", "..."]
103
- }
104
- ]
105
- }
106
- ```
107
-
108
- ### 4.3 运行时关键规则
109
-
110
- - 主流程(MAIN)默认只启用 `allowMain=true` 的 MCP server(安全/权限控制)
111
- - 如果希望 prompt 生效,请确保在应用下勾选 Prompt 并选择需要的 prompts(或提供 app 自己的 `ai.mcpPrompt`)
112
-
113
- ## 5. 内置应用的“开关 + 精细清单”机制
114
-
115
- 内置应用采用两层设计:
116
-
117
- 1) 宿主侧(`deepseek_cli` `plugin.json`)只保留粗粒度开关:
118
-
119
- ```json
120
- { "ai": { "mcpServers": true, "prompts": true } }
121
- ```
122
-
123
- 2) 精细清单由应用团队在 `aide` 侧维护:
124
-
125
- - 路径:`aide/shared/defaults/ui-apps-expose/<pluginId>__<appId>.yaml`(也支持 `.yml/.json`)
126
-
127
- 示例:
128
-
129
- ```yaml
130
- mcpServers:
131
- - project_files
132
- - task_manager
133
-
134
- prompts:
135
- - default
136
- - internal_main
137
- - mcp_project_files
138
- - mcp_task_manager
139
- ```
140
-
141
- 文件名规范:
142
-
143
- - `<pluginId>__<appId>.yaml`(全部小写;不合法字符替换为 `_`)
144
-
145
- 重要:如果 `plugin.json` 未显式写 `ai.mcpServers/prompts`(或写成 `false`),宿主不会自动启用默认清单,避免“意外暴露”。
146
-
147
- ## 6. 暴露范围的合并优先级(精确规则)
148
-
149
- 对 `mcpServers` / `prompts` 分别适用相同规则(从高到低):
150
-
151
- 1) `plugin.json` inline 的 `ai.mcpServers/ai.prompts`
152
- 2) `ai.config` 文件(插件目录内)的 `mcpServers/prompts`
153
- 3) 内置默认清单(`aide/shared/defaults/ui-apps-expose`)
154
-
155
- 规则要点:
156
-
157
- - inline 为 `false`:强制关闭(无视文件与默认清单)
158
- - inline 为 `string[]`:强制使用该列表
159
- - inline 为 `true`:优先用 `ai.config` 的值;若没有,再用默认清单;若仍没有,表示“全部”
160
- - inline 未设置:只允许 `ai.config` 生效(不会自动启用默认清单)
161
-
162
- ## 7. MCP Server 最小骨架(Node.js / stdio)
163
-
164
- MCP server 进程通过 stdio 与宿主通信(不要输出到 stdout,日志写 stderr):
165
-
166
- ```js
167
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
168
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
169
-
170
- const server = new McpServer({ name: 'my_server', version: '0.1.0' });
171
-
172
- // server.tool('tool_name', schema, handler) ...
173
-
174
- const transport = new StdioServerTransport();
175
- await server.connect(transport);
176
- ```
177
-
178
- 提示:
179
-
180
- - tools 最终名字通常会变成 `mcp_<serverName>_<toolName>`(由宿主注册/派生)
181
- - `serverName` 为 MCP server 的 `name`(应用方式 A 下由宿主固定派生为 `${pluginId}.${appId}`)
1
+ # ChatOS UI Apps:AI 暴露(MCP / Prompts)协议
2
+
3
+ 本文件描述应用如何对 ChatOS 的 Chat Agent 暴露能力,包括:
4
+
5
+ - 声明一个专属 MCP Server(让工具随应用交付、随插件安装)
6
+ - 声明应用的默认 MCP Prompt(告诉模型如何使用这些工具/这个应用)
7
+ - 聚合暴露“已有的”全局 MCP Servers / Prompts(面板型应用常用)
8
+ - 内置应用的“开关 + 精细清单”两层机制(清单在 `aide` 维护)
9
+
10
+ 实现对照(以代码为准):
11
+
12
+ - schema:`chatos/electron/ui-apps/schemas.js`
13
+ - 扫描与贡献解析:`chatos/electron/ui-apps/index.js`(`#resolveAi` / `getAiContribution()`;可选 `#syncAiContributes` 持久化到 Admin DB)
14
+ - 内置默认清单:`aide/shared/defaults/ui-apps-expose/`
15
+
16
+ ## 1. 两种暴露方式(应用侧选择其一或组合)
17
+
18
+ ### 方式 A:应用自带 MCP Server + MCP Prompt
19
+
20
+ 用于:应用包含专属 tools(数据库查询、系统诊断、内部系统调用等)。
21
+
22
+ 在 `apps[i].ai` 里声明:
23
+
24
+ - `ai.mcp`:宿主会创建/更新一个 MCP server(`serverName` 固定为 `${pluginId}.${appId}`)
25
+ - `ai.mcpPrompt`:宿主会创建/更新对应 system prompt(prompt 名称固定派生)
26
+
27
+ 示例(节选):
28
+
29
+ ```json
30
+ {
31
+ "id": "db-client",
32
+ "name": "数据库客户端",
33
+ "entry": { "type": "module", "path": "db-client/index.mjs" },
34
+ "ai": {
35
+ "mcp": { "entry": "db-client/mcp-server.mjs", "command": "node", "allowMain": true, "allowSub": true },
36
+ "mcpPrompt": { "zh": "db-client/mcp-prompt.zh.md", "en": "db-client/mcp-prompt.en.md" }
37
+ }
38
+ }
39
+ ```
40
+
41
+ ### 方式 B:聚合暴露“已有的” MCP servers / Prompts(面板型应用常用)
42
+
43
+ 用于:应用以“工作台/面板”形态聚合展示能力,不提供新的 MCP server,但需要按应用维度暴露已有 MCP servers / Prompts。
44
+
45
+ 在 `apps[i].ai` 里声明:
46
+
47
+ - `ai.mcpServers: true | false | string[]`
48
+ - `ai.prompts: true | false | string[]`
49
+
50
+ 注意:这是“可见/可选范围”的声明;最终是否启用、启用哪些,仍由 Agent 编辑页对该应用的多选结果决定。
51
+
52
+ ## 2. 命名规则(宿主自动派生)
53
+
54
+ 对每个 app:
55
+
56
+ - MCP `serverName`:`${pluginId}.${appId}`
57
+ - Prompt name:
58
+ - 中文:`mcp_<normalize(serverName)>`
59
+ - 英文:`mcp_<normalize(serverName)>__en`
60
+
61
+ `normalize()`:
62
+
63
+ - 转小写
64
+ - 把非 `[a-z0-9_-]` 的字符替换为 `_`
65
+ - 去掉首尾 `_`
66
+
67
+ ## 3. `ai.mcp` 的 url 生成规则(entry → cmd://)
68
+
69
+ 当 `ai.mcp.entry` 存在时,宿主会把它转换为:
70
+
71
+ - `cmd://<command> <absEntryOrRelEntry> <args...>`
72
+ - `command` 默认为 `node`
73
+
74
+ 当 `ai.mcp.url` 存在时,直接使用该 url(远程/HTTP/WS 等)。
75
+
76
+ ### 3.1 `ai.mcp.callMeta`(调用方上下文 / 非工具参数)
77
+
78
+ ChatOS 调用 MCP tools 时,会把 `ai.mcp.callMeta` 注入到 `tools/call` 的 `_meta` 中(不属于工具参数,因此不会暴露给 AI)。
79
+
80
+ 同时,宿主默认注入 `_meta.chatos.uiApp`,包含:
81
+
82
+ - `pluginId` / `appId`
83
+ - `pluginDir` / `dataDir`
84
+ - `stateDir` / `sessionRoot` / `projectRoot`
85
+
86
+ 同时,宿主默认注入 `_meta.workdir`(默认等于 `dataDir`;如需指定其它目录,可在 `ai.mcp.callMeta.workdir` 覆盖)。
87
+
88
+ > DevKit sandbox:右上角 `AI Config` 支持设置 `Workdir` 覆盖;留空即使用 `dataDir`(也支持 `$dataDir/$pluginDir/$projectRoot`)。
89
+
90
+ 示例(`plugin.json`):
91
+
92
+ ```json
93
+ {
94
+ "ai": {
95
+ "mcp": {
96
+ "entry": "my-app/mcp-server.mjs",
97
+ "callMeta": { "workdir": "$dataDir" }
98
+ }
99
+ }
100
+ }
101
+ ```
102
+
103
+ 在 MCP server 中读取(SDK handler 的 `extra._meta`):
104
+
105
+ ```js
106
+ const workdir = extra?._meta?.workdir || extra?._meta?.chatos?.uiApp?.dataDir;
107
+ ```
108
+
109
+ ## 4. Agent UI 如何消费应用暴露(你需要知道的运行机制)
110
+
111
+ ### 4.1 体现在哪里(持久化 vs 运行时注入)
112
+
113
+ 当你把插件放进插件目录并在 UI「应用」页点击“刷新”后:
114
+
115
+ 1) 宿主扫描插件并解析 `plugin.json`
116
+ 2) 若发现 `apps[i].ai`:
117
+ - 宿主会在 UI Apps 注册表中暴露该应用的 `ai` 声明;
118
+ - **无论是否写入 Admin DB**,Chat Agent 运行时都可通过 `uiApps.getAiContribution()` 读取 `mcp.url` 与 `mcpPrompt` 文本,并按需“临时注入”到本次运行(见第 4.3 节)。
119
+ - (可选)若宿主启用 `syncAiContributes`,则会把 `ai.mcp` / `ai.mcpPrompt` **持久化同步**到 Admin DB(出现在 `MCP Servers` / `Prompts` 列表中,便于管理与复用)。
120
+ 3) `Chat Agents` 创建/编辑 agent 时:
121
+ - 先选择应用(按应用维度)
122
+ - 再为每个应用分别勾选 MCP/Prompt,并在多选框中选择要挂载的 servers/prompts
123
+
124
+ ### 4.2 保存结构(简化)
125
+
126
+ ```json
127
+ {
128
+ "uiApps": [
129
+ {
130
+ "pluginId": "com.example.tools",
131
+ "appId": "db-client",
132
+ "mcp": true,
133
+ "prompt": true,
134
+ "mcpServerIds": ["<admin.mcpServers.id>", "..."],
135
+ "promptIds": ["<admin.prompts.id>", "..."]
136
+ }
137
+ ]
138
+ }
139
+ ```
140
+
141
+ ### 4.3 运行时关键规则
142
+
143
+ - 主流程(MAIN)默认只启用 `allowMain=true` 的 MCP server(安全/权限控制)
144
+ - 如果希望 prompt 生效,请确保在应用下勾选 Prompt 并选择需要的 prompts(或提供 app 自己的 `ai.mcpPrompt`)
145
+
146
+ ## 5. 内置应用的“开关 + 精细清单”机制
147
+
148
+ 内置应用采用两层设计:
149
+
150
+ 1) 宿主侧(`chatos` 的 `plugin.json`)只保留粗粒度开关:
151
+
152
+ ```json
153
+ { "ai": { "mcpServers": true, "prompts": true } }
154
+ ```
155
+
156
+ 2) 精细清单由应用团队在 `aide` 侧维护:
157
+
158
+ - 路径:`aide/shared/defaults/ui-apps-expose/<pluginId>__<appId>.yaml`(也支持 `.yml/.json`)
159
+
160
+ 示例:
161
+
162
+ ```yaml
163
+ mcpServers:
164
+ - project_files
165
+ - task_manager
166
+
167
+ prompts:
168
+ - default
169
+ - internal_main
170
+ - mcp_project_files
171
+ - mcp_task_manager
172
+ ```
173
+
174
+ 文件名规范:
175
+
176
+ - `<pluginId>__<appId>.yaml`(全部小写;不合法字符替换为 `_`)
177
+
178
+ 重要:如果 `plugin.json` 未显式写 `ai.mcpServers/prompts`(或写成 `false`),宿主不会自动启用默认清单,避免“意外暴露”。
179
+
180
+ ## 6. 暴露范围的合并优先级(精确规则)
181
+
182
+ 对 `mcpServers` / `prompts` 分别适用相同规则(从高到低):
183
+
184
+ 1) `plugin.json` inline 的 `ai.mcpServers/ai.prompts`
185
+ 2) `ai.config` 文件(插件目录内)的 `mcpServers/prompts`
186
+ 3) 内置默认清单(`aide/shared/defaults/ui-apps-expose`)
187
+
188
+ 规则要点:
189
+
190
+ - inline 为 `false`:强制关闭(无视文件与默认清单)
191
+ - inline 为 `string[]`:强制使用该列表
192
+ - inline 为 `true`:优先用 `ai.config` 的值;若没有,再用默认清单;若仍没有,表示“全部”
193
+ - inline 未设置:只允许 `ai.config` 生效(不会自动启用默认清单)
194
+
195
+ ## 7. MCP Server 最小骨架(Node.js / stdio)
196
+
197
+ MCP server 进程通过 stdio 与宿主通信(不要输出到 stdout,日志写 stderr):
198
+
199
+ ```js
200
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
201
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
202
+
203
+ const server = new McpServer({ name: 'my_server', version: '0.1.0' });
204
+
205
+ // server.tool('tool_name', schema, handler) ...
206
+
207
+ const transport = new StdioServerTransport();
208
+ await server.connect(transport);
209
+ ```
210
+
211
+ 提示:
212
+
213
+ - tools 最终名字通常会变成 `mcp_<serverName>_<toolName>`(由宿主注册/派生)
214
+ - `serverName` 为 MCP server 的 `name`(应用方式 A 下由宿主固定派生为 `${pluginId}.${appId}`)