内容
# blueos-mcp-server
本地 STDIO MCP 服务,用于识别、创建、修改和检查 vivo BlueOS 工程。当前版本只操作工程文件,不控制 BlueOS Studio GUI,也不执行签名、打包、上传或删除。
## 能力
- 识别普通应用和表盘工程
- 读取、深度合并更新并校验 `src/manifest.json`
- 创建普通页面并注册 `router.pages`
- 创建基础表盘并注册 `router.watchfaces`
- 添加应用或表盘 feature 声明(幂等)
- 校验 UX 三段结构、单根节点、标签闭合、资源路径和常见 API feature
- 安全复制图片、字体、音频资源
- 生成完整 Markdown 工程报告
- 所有工程写路径都限制在 `projectRoot` 内;manifest 修改前必定备份
## 环境与安装
要求 Node.js 20 或更高版本。
```powershell
cd F:\watch\blueos-mcp-server
npm install
npm run build
npm test
npm run test:mcp
```
开发模式:
```powershell
npm run dev
```
生产启动:
```powershell
npm start
```
STDIO 是协议通道,服务正常启动后不会向 stdout 打印普通日志。
## Codex 配置
在用户级 `~/.codex/config.toml` 或受信任项目的 `.codex/config.toml` 中加入:
```toml
[mcp_servers.blueos]
command = "node"
args = ["F:/watch/blueos-mcp-server/dist/index.js"]
startup_timeout_sec = 20
tool_timeout_sec = 60
enabled = true
```
开发阶段也可直接运行 TypeScript:
```toml
[mcp_servers.blueos]
command = "npx"
args = ["tsx", "F:/watch/blueos-mcp-server/src/index.ts"]
startup_timeout_sec = 20
tool_timeout_sec = 60
enabled = true
```
修改配置后重新启动 Codex 会话,再检查 MCP 工具列表。也可以用 Codex CLI 添加本地服务:
```powershell
codex mcp add blueos -- node F:/watch/blueos-mcp-server/dist/index.js
```
## 工具
### `blueos.inspect_project`
输入:
```json
{ "projectRoot": "D:/Projects/MyBlueOSApp" }
```
输出示例:
```json
{
"isBlueOSProject": true,
"projectRoot": "D:/Projects/MyBlueOSApp",
"hasPackageJson": true,
"hasManifest": true,
"hasAppUx": true,
"hasPagesDir": true,
"projectType": "app",
"pages": ["Demo"],
"watchfaces": [],
"warnings": []
}
```
### `blueos.read_manifest`
输入:
```json
{ "projectRoot": "D:/Projects/MyBlueOSApp" }
```
输出为解析后的完整 manifest JSON 对象。
### `blueos.validate_manifest`
输入:
```json
{ "projectRoot": "D:/Projects/MyBlueOSApp" }
```
输出示例:
```json
{
"valid": false,
"errors": [
{ "code": "ROUTER_PAGE_FILE_MISSING", "message": "router.pages 中声明了 Detail,但对应 .ux 文件不存在" }
],
"warnings": []
}
```
检查必填字段、`versionCode`、`config.designWidth`、`features`、普通应用/表盘路由、重复 path、icon、页面组件和表盘预览图。
### `blueos.create_page`
输入:
```json
{
"projectRoot": "D:/Projects/MyBlueOSApp",
"pageName": "StressPage",
"routePath": "/stress",
"title": "压力监测",
"setAsEntry": false
}
```
创建 `src/pages/StressPage/index.ux`,并兼容更新已有的对象式或数组式 `router.pages`。对象式新路由形状为:
```json
{
"StressPage": { "path": "/stress", "component": "pages/StressPage" }
}
```
### `blueos.update_manifest`
输入:
```json
{
"projectRoot": "D:/Projects/MyBlueOSApp",
"patch": {
"versionName": "1.1.0",
"versionCode": 2,
"config": { "designWidth": 466 }
}
}
```
对象字段深度合并,数组和标量整体替换。写入后自动运行 manifest 校验;`success: false` 表示修改已落盘但校验未通过,详情在 `validation` 中。
### `blueos.add_feature`
普通应用:
```json
{
"projectRoot": "D:/Projects/MyBlueOSApp",
"featureName": "blueos.communication.network.fetch",
"target": "app"
}
```
表盘:
```json
{
"projectRoot": "D:/Projects/MyBlueOSWatchface",
"featureName": "blueos.app.router",
"target": "watchface",
"watchPath": "watch3000"
}
```
feature 已存在时不写文件、不产生无意义备份,并返回修改前后数组。
### `blueos.create_watchface`
输入:
```json
{
"projectRoot": "D:/Projects/MyBlueOSWatchface",
"watchId": 3000,
"watchName": "压力动态表盘",
"packageName": "com.example.watch.stress",
"previewImage": "assets/preview.png",
"editable": true,
"designWidth": 466
}
```
创建 `src/watch3000/index.ux`,可选创建 `edit.ux`,并写入 `router.watchfaces.watch3000`。若工程为空,还会创建最小 `package.json`、`src/app.ux` 和 manifest。工具不会伪造预览图;预览图缺失会返回 `WATCHFACE_PREVIEW_MISSING` 警告而不是令创建失败。
### `blueos.validate_ux_file`
输入:
```json
{
"filePath": "D:/Projects/MyBlueOSApp/src/pages/Demo/index.ux",
"projectRoot": "D:/Projects/MyBlueOSApp"
}
```
`projectRoot` 可选;提供时额外检查资源路径和 manifest feature。输出:
```json
{
"valid": true,
"errors": [],
"warnings": [
{ "code": "STYLE_EMPTY", "message": "style 标签为空,页面可能没有样式" }
]
}
```
feature 检查是静态启发式规则,当前覆盖网络 fetch 和路由 API;它不能替代 BlueOS 编译器。
### `blueos.add_asset`
输入:
```json
{
"projectRoot": "D:/Projects/MyBlueOSApp",
"sourceFile": "C:/Users/User/Desktop/bg.png",
"targetDir": "src/assets/images",
"renameTo": "stress-bg.png",
"conflictStrategy": "autoRename"
}
```
`conflictStrategy` 可为 `autoRename`(默认)、`overwrite` 或 `error`。允许常见图片、字体和音频扩展名。输出包含目标绝对路径和 BlueOS 引用路径:
```json
{
"success": true,
"targetFile": "D:/Projects/MyBlueOSApp/src/assets/images/stress-bg.png",
"blueosPath": "/assets/images/stress-bg.png"
}
```
### `blueos.generate_report`
输入:
```json
{ "projectRoot": "D:/Projects/MyBlueOSApp" }
```
输出 Markdown 报告,包括工程状态、严重错误、警告、未注册页面和建议修复。
## 写操作返回约定
`create_page`、`update_manifest`、`add_feature`、`create_watchface`、`add_asset` 都返回:
```json
{
"success": true,
"changedFiles": ["src/manifest.json"],
"createdFiles": [],
"backupFiles": [".backups/manifest-20260702-153000.json"],
"summary": "具体变更摘要"
}
```
manifest 备份保存在项目根目录 `.backups/`。同一秒内多次修改会选择后续未占用的秒级文件名,避免覆盖历史备份。所有 JSON 以两空格缩进和末尾换行写回。
失败返回具体错误码:
```json
{
"success": false,
"errorCode": "MANIFEST_NOT_FOUND",
"message": "未找到 src/manifest.json,请确认 projectRoot 是否为 BlueOS 工程根目录"
}
```
## 安全边界
- 所有目标写路径会在规范化后验证属于 `projectRoot`。
- 已存在目录还会解析真实路径,阻止借助符号链接写出工程。
- `update_manifest` 拒绝 `__proto__`、`prototype`、`constructor` 等原型污染字段。
- 不提供删除工具,不调用 GUI,不假设存在官方构建 CLI。
- `add_asset` 允许读取工程外的用户指定源文件,但目标始终必须在工程内。
## 测试样例
夹具:
```text
tests/fixtures/sample-blueos-app/
tests/fixtures/sample-blueos-watchface/
```
自动测试覆盖:正常识别、缺 manifest、缺 app.ux、缺路由页面、未注册页面、缺表盘预览图、feature 幂等、创建页面、创建表盘、跨目录写入拒绝和 UX 单根节点。
```powershell
npm test
npm run test:mcp
```
`test:mcp` 会先构建,再用官方 MCP TypeScript SDK 的 STDIO client 启动服务,确认恰好注册 10 个工具,并实际调用 `blueos.inspect_project`。
## 已知边界
- BlueOS 不同版本可能存在额外 manifest 字段;本服务保留未知字段,不把未知字段视为错误。
- UX 静态检查不是完整语法编译器,复杂模板表达式仍应在 BlueOS Studio 中最终编译验证。
- 第一版不做构建、签名、模拟器、应用商店上传或 GUI 自动点击。