节点在线、应用在线、配置在线使用令牌查询
|
# MCP(Model Context Protocol)HTTP æœåŠ¡ Spec
> âš ï¸ **废弃说明(2026-08-03)**:本文åŠåŒç›®å½•æ–‡æ¡£ä¸æåˆ°çš„ `McpController`(HTTP 端点 Controller)**å·²åºŸå¼ƒå¹¶åˆ é™¤**,改为 `McpMiddleware`(ASP.NET ä¸é—´ä»¶ï¼‰æ‰¿è½½ `/mcp` 端点。
> **缘由**:`McpMiddleware` åœ¨ç®¡çº¿ä¸æ³¨å†ŒäºŽ `UseCube` 之å‰ï¼Œå¯¹ `/mcp` çŸè·¯å¤„ç†ï¼Œå¯é¿å… Cube çš„ device-id Cookie è§£æžï¼ˆ`Convert.FromBase64String`)在畸形 Cookie 时抛 `FormatException` 返回错误页,导致 MCP 客户端收到 HTML è€Œéž JSON-RPC。而 `McpController` ç» MVC 路由ä½äºŽ `UseCube` 之åŽï¼Œåœ¨çŽ°æœ‰ç®¡çº¿ä¸å§‹ç»ˆä¸å¯è¾¾ï¼ˆæ»ä»£ç ï¼‰ï¼Œæ•…åˆ é™¤ã€‚è¯¦è§ `Doc/MCP-3-客户端接入.md`。
## Why
Stardust 已具备完整的"èŠ‚ç‚¹ç®¡ç† + åº”ç”¨ç®¡ç† + é…ç½®ä¸å¿ƒ + 注册ä¸å¿ƒ + 监控ä¸å¿ƒ + 远程å‘布 + 网关管ç†"能力(M1–M12 å…± 117 个功能),但所有能力**åªèƒ½é€šè¿‡ Web æŽ§åˆ¶å°æˆ–ç§æœ‰ RPC åè®®**调用,**æ— æ³•è¢« LLM/智能体直接消费**:
- 用户想问"现在哪些节点离线?" 必须自己打开æµè§ˆå™¨æŸ¥ Web
- 用户想问"把 XXX 应用部署到 YYY 节点" å¿…é¡»æ‰‹åŠ¨ç‚¹å‡»æµæ°´çº¿
- 用户想问"AAA æœåŠ¡çš„å½“å‰é…置是什么" 必须进入é…ç½®ä¸å¿ƒé¡µé¢
缺少一个**é¢å‘ LLM çš„æ ‡å‡†å议入å£**,让 AI 助手能直接查询系统状æ€ã€æ‰§è¡Œè¿ç»´æ“作。MCP(Model Context Protocol)是 Anthropic ä¸»å¯¼çš„äº‹å®žæ ‡å‡†ï¼Œå·²è¢«ä¸»æµ IDE/Agent(Traeã€Claude Desktopã€Cursor)原生支æŒã€‚通过在 Stardust æœåŠ¡ç«¯å®žçŽ° MCP HTTP 端点,å¯è®©ä»»æ„ MCP 客户端把 Stardust 当作一个工具æœåŠ¡å™¨è°ƒç”¨ï¼Œ**æ— éœ€ä¸ºæ¯ä¸ª Agent 釿–°å¼€å‘适é…层**。
现有用户 token 体系走 Cube 框架 Cookie/Session(外部库,æºç ä¸åœ¨ä»“库),Server è¿›ç¨‹æ— æ³•ç›´æŽ¥è§£ç ;且该 token ä»…æ ¡éªŒ"是å¦ç™»å½•的用户",未与项目/节点/应用资æºåšå¼ºåˆ¶æŽˆæƒç»‘å®šã€‚å› æ¤ MCP 需è¦ä¸€å¥—**ç‹¬ç«‹çš„èµ„æºæŽˆæƒ Token 体系**:æ¯ä¸ª Token 显å¼ç»‘定å¯è®¿é—®çš„项目ã€èŠ‚ç‚¹ã€åº”用集åˆï¼Œç¦ç”¨ Token å³ç«‹å³å¤±åŽ»å¯¹ç›¸åº”èµ„æºçš„访问能力。
## Clarifications
### Session 2026-07-16
- Q: 四个 MCP 工具的具体结构? → A: 4 工具:`list_authorized_resources` + `get_resource` + `list_actions` + `invoke_action`
- Q: 资æºä¸ŽåŠ¨ä½œçš„æ‰©å±•æœºåˆ¶ï¼Ÿ → A: 纯代ç 驱动(实现接å£è‡ªåŠ¨æ³¨å†Œï¼Œæ— DB é…置表)
- Q: `get_resource` 的资æºç±»åž‹èŒƒå›´ï¼Ÿ → A: 6 ç±»æ ¸å¿ƒï¼šproject / node / app / deploy / pipeline / service
- Q: `invoke_action` çš„æŽˆæƒæ¨¡åž‹ï¼Ÿ → A: ä»…æ¡†æž¶å±‚ç»Ÿä¸€æ ¡éªŒï¼ˆaction 声明资æºä¾èµ–,框架æå–èµ„æº ID æ ¡éªŒï¼Œaction 内ä¸å†æ ¡éªŒï¼‰
- Q: 首批 Action 清å•边界? → A: 精简到 ~20 个高频 action + 补充 search_resources å’Œ list_deploy_nodes
### Session 2026-07-16(补充审视)
- Q: æ˜¯å¦æœ‰ action é€‚åˆæŠ½æˆ MCP 工具? → A: `search_resources` æå‡ä¸ºç¬¬ 5 个 MCP 工具(与 `get_resource` å½¢æˆ"æœç´¢â†’获å–"查询原è¯å¯¹ï¼‰
- Q: 是å¦è¡¥å……审计查询 action? → A: 补充 `get_audit_log`(LLM 自çœç”¨ï¼ŒæŸ¥å½“å‰ Token 最近的调用记录)
- Q: 是å¦è¡¥å……è¿ç»´ action? → A: 补充 5 个:`app_restart` / `app_stop` / `app_start`(应用生命周期)+ `deploy_compile`(仅编译ä¸éƒ¨ç½²ï¼‰+ `pipeline_cancel`ï¼ˆå–æ¶ˆæµæ°´çº¿ï¼‰
- 最终工具数:5 个 MCP 工具;最终 action 数:27 个(原 22 - search_resources æå‡ + 6 新增)
## What Changes
在 Stardust.Server 䏿–°å¢ž MCP HTTP æœåŠ¡ç«¯ï¼Œå¯¹å¤–æš´éœ² **5 个 MCP 工具**(`list_authorized_resources` / `search_resources` / `get_resource` / `list_actions` / `invoke_action`),通过这 5 个工具组åˆè®¿é—® Stardust å…¨éƒ¨èƒ½åŠ›ï¼›å¹¶è®¾è®¡ç‹¬ç«‹çš„èµ„æºæŽˆæƒ Token 体系。
**æ ¸å¿ƒè®¾è®¡ç†å¿µ**:é¿å…暴露过多细粒度工具导致 LLM 选择困难和å议臃肿。MCP 工具èšç„¦"å议级查询原è¯"(授æƒå‘现/æœç´¢/获å–/动作å‘现/动作调用),业务æ“作统一走 `invoke_action`。LLM 典型工作æµï¼š`list_authorized_resources` → `search_resources(keyword)` → `get_resource(type, id)` → `list_actions` → `invoke_action(action, params)`。å•个动作按 snake_case 命å(如 `node_send_command`ã€`app_restart`),åå—+å°‘é‡å‚æ•°å³å¯è¡¨æ„。
- 新增 `McpToken` 表:Token å‡è¯ï¼ˆåç§°ã€Token å—符串ã€Enableã€è¿‡æœŸæ—¶é—´ã€æœ€åŽè°ƒç”¨ä¿¡æ¯ï¼‰
- 新增 `McpTokenResource` 表:Token 与资æºçš„æŽˆæƒå…³ç³»ï¼ˆTokenId + ResourceType[Project/Node/App] + ResourceId),支æŒ"全部资æº"æŽˆæƒæ ‡è®°
- 新增 `McpAction` 抽象(`IMcpAction` æŽ¥å£ + `McpActionBase` 基类):代ç 驱动自动注册,æ¯ä¸ª action 自æè¿° name/description/inputSchema/requiredResource
- 新增 5 个 MCP 工具实现:`list_authorized_resources` / `search_resources` / `get_resource` / `list_actions` / `invoke_action`
- 新增 ~27 个首批 action 实现(按 7 模å—组织)
- 新增 MCP é…置项:`StarServerSetting.EnableMcp`(默认 `false`)ã€`StarServerSetting.McpActionSet`(动作集开关,默认全开)
- 新增 `McpController`:实现 MCP åè®®ä¸‰ä¸ªæ ¸å¿ƒæ–¹æ³•ï¼ˆ`initialize` / `tools.list` / `tools.call`),基于 JSON-RPC 2.0 over HTTP
- 新增 `McpService`:Token æ ¡éªŒã€èµ„æºæŽˆæƒæ£€æŸ¥ï¼ˆæ¡†æž¶å±‚统一)ã€åŠ¨ä½œæ³¨å†Œä¸Žè·¯ç”±ã€å®¡è®¡æ—¥å¿—
- 新增审计表 `McpAudit`ï¼šè®°å½•æ¯æ¬¡å·¥å…·è°ƒç”¨ï¼ˆå·¥å…·å/调用方 IP/入傿‘˜è¦/TokenId/返回状æ€/耗时)
- å¤ç”¨çŽ°æœ‰èƒ½åŠ›ï¼š`AppController.SearchService`ã€`NodeOnlineService`ã€`ConfigService.GetAll`ã€`DeployService`ã€`PipelineService`ã€`GatewayService.GetConfig` ç‰
- **䏿”¹åЍ** 任何已有 Controllerã€Serviceã€å®žä½“表的对外行为
- **ä¸ç ´å** 现有 `[ApiFilter]` / JWT / `BaseController` 鉴æƒé“¾è·¯
- MCP 端点独立鉴æƒï¼š`Authorization: Bearer {McpToken}`,**ä¸å¤ç”¨** 设备 token 体系,**ä¸å¤ç”¨** Web 用户登录æ€
## Impact
- Affected specs:
- 节点管ç†ï¼ˆM5ï¼Œæ— å˜åŠ¨ï¼Œä»…ä½œä¸ºèµ„æº + åŠ¨ä½œæ•°æ®æºï¼‰
- 应用管ç†ï¼ˆM4ï¼Œæ— å˜åŠ¨ï¼Œä»…ä½œä¸ºèµ„æº + åŠ¨ä½œæ•°æ®æºï¼‰
- é…ç½®ä¸å¿ƒï¼ˆM6ï¼Œæ— å˜åŠ¨ï¼Œä»…ä½œä¸ºåŠ¨ä½œæ•°æ®æºï¼‰
- 远程å‘布(M10ï¼Œæ— å˜åŠ¨ï¼Œä»…ä½œä¸ºèµ„æº + åŠ¨ä½œæ•°æ®æºï¼‰
- 网关管ç†ï¼ˆM11ï¼Œæ— å˜åŠ¨ï¼Œä»…ä½œä¸ºåŠ¨ä½œæ•°æ®æºï¼‰
- 监控ä¸å¿ƒï¼ˆM8ï¼Œæ— å˜åŠ¨ï¼Œä»…ä½œä¸ºåŠ¨ä½œæ•°æ®æºï¼‰
- å¹³å°ç®¡ç†ï¼ˆM3ï¼Œæ— å˜åŠ¨ï¼Œä»…ä½œä¸ºèµ„æºæŽˆæƒå¯¹è±¡ï¼‰
- **新增** MCP 工具æœåŠ¡èƒ½åŠ› + MCP Token èµ„æºæŽˆæƒä½“ç³»
- Affected code:
- `Stardust.Server/Setting.cs` — 新增 `EnableMcp` / `McpActionSet` å—æ®µ
- `Stardust.Server/Controllers/McpController.cs` — 新增(MCP HTTP 端点)
- `Stardust.Server/Services/McpService.cs` — 新增(Token æ ¡éªŒã€èµ„æºæŽˆæƒã€åŠ¨ä½œè·¯ç”±ã€å®¡è®¡ï¼‰
- `Stardust.Server/Mcp/IMcpAction.cs` — 新增(动作接å£ä¸ŽåŸºç±»ï¼‰
- `Stardust.Server/Mcp/IMcpTool.cs` — 新增(4 个工具接å£ä¸ŽåŸºç±»ï¼‰
- `Stardust.Server/Mcp/Actions/*.cs` — æ–°å¢žï¼ˆå…·ä½“åŠ¨ä½œå®žçŽ°ï¼ŒæŒ‰æ¨¡å—æ‹†åˆ†ï¼‰
- `Stardust.Data/Platform/Model.xml` — 新增 `McpToken`ã€`McpTokenResource`ã€`McpAudit` ä¸‰å¼ è¡¨
- `Stardust.Server/Startup.cs` — 注册 `McpService` 与 MCP 路由
- `Stardust.Web/Areas/Platform/Controllers/McpTokenController.cs` — 新增(Token 管ç†ï¼šåˆ—表/新建/编辑/é‡ç½®/ç¦ç”¨ï¼‰
- `Stardust.Web/Areas/Platform/Controllers/McpTokenResourceController.cs` — 新增(Token èµ„æºæŽˆæƒç®¡ç†ï¼‰
- `Stardust.Web/Areas/Platform/Controllers/McpAuditController.cs` — 新增(审计日志查看)
- `Stardust.Web/Areas/Platform/Views/McpToken/_Form_Body.cshtml` — 新增(Token 表å•,å«èµ„æºå‹¾é€‰ï¼‰
## æ ¸å¿ƒè®¾è®¡
### 1. MCP å议端点
MCP 端点路径:`POST /mcp`(å•一端点,JSON-RPC 2.0)
支æŒçš„æ–¹æ³•:
| JSON-RPC method | 说明 |
|---|---|
| `initialize` | åè®®æ¡æ‰‹ï¼Œè¿”回 `serverInfo`(name=`Stardust`ã€version)和 `capabilities` |
| `tools.list` | 返回 4 个固定工具的清å•(`list_authorized_resources` / `get_resource` / `list_actions` / `invoke_action`) |
| `tools.call` | è°ƒç”¨æŒ‡å®šå·¥å…·ï¼Œä¼ å…¥ `name` å’Œ `arguments`,返回 `content` 数组 |
> ä¼ è¾“æ–¹å¼ï¼šçº¯ HTTP(å•请求å•å“应),暂ä¸å®žçް SSE 长连接。
### 2. 五个 MCP 工具
MCP å议层é¢åªæš´éœ² 5 个工具,é¿å…工具列表臃肿。MCP 工具èšç„¦"å议级查询原è¯"(授æƒå‘现/æœç´¢/获å–/动作å‘现/动作调用),业务æ“作统一走 `invoke_action`。LLM 通过这 5 个工具的组åˆå®Œæˆæ‰€æœ‰æ“作。
#### 2.1 `list_authorized_resources`
**æè¿°**ï¼šæŸ¥è¯¢å½“å‰ Token 授æƒäº†å“ªäº›èµ„æºï¼ˆé¡¹ç›®/节点/åº”ç”¨ï¼‰ï¼Œè¿”å›žèµ„æºæ ‡è¯†ç¬¦å’Œè¯´æ˜Žã€‚LLM 首次接入时调用æ¤å·¥å…·å»ºç«‹ä¸Šä¸‹æ–‡ã€‚
**å…¥å‚**:
- `resource_type?`(String):å¯é€‰è¿‡æ»¤ï¼Œå€¼ä¸º `project` / `node` / `app`ï¼›ä¸ä¼ 则返回全部三类
**返回**:按类型分组的资æºåˆ—表,æ¯é¡¹å« `id` / `name` / `type` / `description`
**资æºå£°æ˜Ž**ï¼šæ— ï¼ˆæŸ¥è¯¢è‡ªèº«æŽˆæƒï¼Œæ— éœ€èµ„æºæ ¡éªŒï¼‰
#### 2.2 `search_resources`
**æè¿°**:按关键å—跨类型æœç´¢èµ„æºï¼Œè¿”回匹é…çš„èµ„æºæ ‡è¯†ç¬¦å’Œè¯´æ˜Žã€‚与 `get_resource` å½¢æˆ"æœç´¢â†’获å–"的查询原è¯å¯¹â€”—LLM ä¸çŸ¥é“èµ„æº ID 时第一æ¥ç”¨ `search_resources` 查找,拿到 ID åŽç”¨ `get_resource` 获å–详情。
**å…¥å‚**:
- `keyword`(String,必填):æœç´¢å…³é”®å—(匹é…资æºåç§°/ç¼–ç /IP ç‰ï¼‰
- `resource_type?`(String):å¯é€‰è¿‡æ»¤ï¼Œå€¼ä¸º `project` / `node` / `app` / `deploy` / `pipeline` / `service`ï¼›ä¸ä¼ 则全æœ
**返回**:按类型分组的匹é…资æºåˆ—表,æ¯é¡¹å« `id` / `name` / `type` / `description`
**资æºå£°æ˜Ž**ï¼šæ— ï¼ˆæœç´¢ç»“果按 Token 授æƒèŒƒå›´è¿‡æ»¤è¿”回,ä¸è¿”回未授æƒèµ„æºï¼‰
#### 2.3 `get_resource`
**æè¿°**:按资æºç±»åž‹ + ID 获å–å•个资æºè¯¦æƒ…ã€‚é€‚åˆ LLM æ‹¿åˆ°èµ„æº ID åŽæŸ¥è¯¢å®Œæ•´ä¿¡æ¯ï¼ˆå¦‚ `get_resource(project, 100)`)。与 `search_resources` é…对使用。
**å…¥å‚**:
- `resource_type`(String,必填):`project` / `node` / `app` / `deploy` / `pipeline` / `service`
- `resource_id`(Int32ï¼Œå¿…å¡«ï¼‰ï¼šèµ„æº ID
**返回**:资æºè¯¦æƒ… JSON(å«å…³é”®å—段和关è”ä¿¡æ¯ï¼‰
**资æºå£°æ˜Ž**ï¼šæ ¹æ® `resource_type` 动æ€å†³å®š
- `project` / `node` / `app`ï¼šæ ¡éªŒå¯¹åº”ç±»åž‹çš„ Token 授æƒ
- `deploy` / `pipeline`:按其 `ProjectId` æ ¡éªŒé¡¹ç›®æŽˆæƒ
- `service`:按其 `AppId` æ ¡éªŒåº”ç”¨æŽˆæƒ
#### 2.4 `list_actions`
**æè¿°**:返回当å‰å¯è°ƒç”¨çš„动作清å•ï¼ˆå« name/description/inputSchema/requiredResource)。LLM 在执行æ“作å‰è°ƒç”¨æ¤å·¥å…·å‘现"能åšä»€ä¹ˆã€éœ€è¦ä»€ä¹ˆå‚æ•°"。
**å…¥å‚**:
- `module?`(String):å¯é€‰è¿‡æ»¤ï¼Œå€¼ä¸º `node` / `app` / `config` / `deploy` / `gateway` / `monitor` / `system`ï¼›ä¸ä¼ 则返回全部
**返回**ï¼šåŠ¨ä½œå…ƒä¿¡æ¯æ•°ç»„,æ¯é¡¹å«ï¼š
- `name`(如 `node_send_command`)
- `description`(é¢å‘ LLM 的功能说明)
- `module`(所属模å—)
- `input_schema`(JSON Schema 傿•°å®šä¹‰ï¼‰
- `required_resource`(资æºä¾èµ–声明,如 `{"type":"node","field":"node_id"}`)
**资æºå£°æ˜Ž**ï¼šæ— ï¼ˆæŸ¥è¯¢åŠ¨ä½œæ¸…å•ï¼Œæ— éœ€èµ„æºæ ¡éªŒï¼‰
#### 2.5 `invoke_action`
**æè¿°**:调用指定动作。这是 LLM 执行æ“作的唯一入å£ï¼Œé€šè¿‡ `action_name` + `params` 路由到具体实现。
**å…¥å‚**:
- `action_name`(String,必填):动作å(snake_case,如 `node_send_command`)
- `params`(Objectï¼Œå¿…å¡«ï¼‰ï¼šåŠ¨ä½œå‚æ•°ï¼Œç»“构由对应 action çš„ `input_schema` 定义
**返回**:动作执行结果(JSON 内容å—)
**资æºå£°æ˜Ž**:由被调 action çš„ `required_resource` å£°æ˜Žå†³å®šï¼Œæ¡†æž¶å±‚ç»Ÿä¸€æ ¡éªŒ
### 3. 鉴æƒï¼ˆèµ„æºæŽˆæƒ Token 体系)
#### 3.1 Token 实体(`McpToken` 表)
| å—æ®µ | 类型 | 说明 |
|---|---|---|
| Id | Int32 | 主键 |
| Name | String(50) | Token å称(如"è¿ç»´åŠ©æ‰‹-å°æ˜Ž"),便于管ç†å‘˜è¯†åˆ« |
| Token | String(64) | Token å—符串,64 ä½éšæœºå—符(主索引,唯一) |
| Enable | Boolean | 是å¦å¯ç”¨ã€‚ç¦ç”¨åŽè¯¥ Token 所有调用立å³è¿”回 `-32001` |
| ExpireTime | DateTime | 过期时间。null 表示永ä¸è¿‡æœŸ |
| LastTime | DateTime | 最åŽè°ƒç”¨æ—¶é—´ |
| LastIP | String(50) | 最åŽè°ƒç”¨æ–¹ IP |
| CallCount | Int32 | 累计调用次数 |
| Remark | String(200) | 备注 |
| CreateUserId/Time/IPã€UpdateUserId/Time/IP | — | æ ‡å‡†å®¡è®¡å—æ®µ |
Token å—符串在创建时自动生æˆï¼Œ**创建åŽä¸å¯ä¿®æ”¹**(如需更æ¢è¯·ç”¨"é‡ç½®"åŠŸèƒ½ï¼Œä¼šç”Ÿæˆæ–° Token å¹¶ä¿ç•™æ—§ Token çš„èµ„æºæŽˆæƒå…³ç³»è®°å½•到审计)。
#### 3.2 èµ„æºæŽˆæƒï¼ˆ`McpTokenResource` 表)
| å—æ®µ | 类型 | 说明 |
|---|---|---|
| Id | Int32 | 主键 |
| TokenId | Int32 | å…³è” `McpToken.Id`(索引) |
| ResourceType | String(20) | 资æºç±»åž‹ï¼š`Project` / `Node` / `App` |
| ResourceId | Int32 | èµ„æº ID(对应 `GalaxyProject.Id` / `Node.ID` / `App.Id`) |
| IsAll | Boolean | æ˜¯å¦æŽˆæƒè¯¥ç±»åž‹çš„"全部资æº"。true 时忽略 ResourceId |
| Enable | Boolean | 是å¦å¯ç”¨ï¼ˆæ”¯æŒä¸´æ—¶ç¦ç”¨æŸä¸ªèµ„æºæŽˆæƒè€Œä¸åˆ 除) |
| CreateTime | DateTime | æŽˆæƒæ—¶é—´ |
唯一索引 `IU_McpTokenResource_TokenId_ResourceType_ResourceId`,普通索引 `IX_McpTokenResource_TokenId`。
#### 3.3 授æƒè¯ä¹‰
- **项目(Project)授æƒ**:Token å¯è®¿é—®è¯¥é¡¹ç›®ä¸‹çš„æ‰€æœ‰èŠ‚ç‚¹ã€åº”用ã€éƒ¨ç½²é›†ã€æµæ°´çº¿ã€é…ç½®ç‰ï¼ˆé€šè¿‡ `Node.ProjectId`/`App.ProjectId` ç‰å¤–键关è”过滤)
- **节点(Node)授æƒ**:Token å¯å¯¹è¯¥èŠ‚ç‚¹æ‰§è¡ŒæŸ¥è¯¢ã€ä¸‹å‘命令ã€å‡çº§ç‰æ“作(独立于项目授æƒï¼Œå…许跨项目授æƒå•个节点)
- **应用(App)授æƒ**:Token å¯å¯¹è¯¥åº”用执行查询ã€ä¸‹å‘å‘½ä»¤ã€æŸ¥é…ç½®ç‰æ“作(独立于项目授æƒï¼Œå…许跨项目授æƒå•个应用)
- **`IsAll=true` 授æƒ**:该类型下的所有资æºï¼ˆå«æœªæ¥æ–°å¢žçš„)å‡å…许访问,适åˆç®¡ç†å‘˜ Token
- **ä¸‰ç±»èµ„æºæŽˆæƒæ˜¯ OR 关系**:如 Token 授æƒäº†"项目 A"且授æƒäº†"节点 X(属于项目 B)",则 Token 既能访问项目 A 的所有资æºï¼Œä¹Ÿèƒ½è®¿é—®èŠ‚ç‚¹ X
- **未授æƒçš„资æº**:`invoke_action` å’Œ `get_resource` å…¥å‚ä¸å¼•ç”¨çš„èµ„æº ID 必须在 Token 的授æƒèŒƒå›´å†…,å¦åˆ™è¿”回 JSON-RPC `-32003`ï¼ˆæ— æƒé™ï¼‰
#### 3.4 调用æµç¨‹
```
MCP 客户端
│ POST /mcp Authorization: Bearer {token}
â–¼
McpController
│ 1. 从 Header å– Token
│ 2. 查 McpToken 表:Token 是å¦å˜åœ¨ã€Enable=trueã€æœªè¿‡æœŸ
│ ↓ 失败 → 返回 -32001
│ 3. 更新 McpToken.LastTime/LastIP/CallCount
│ 4. è§£æž JSON-RPC method
│ ├─ initialize → 返回 serverInfo
│ ├─ tools.list → 返回 5 个固定工具
│ └─ tools.call {name, arguments}
│ ├─ list_authorized_resources → 直接返回 Token 授æƒèµ„æº
│ ├─ search_resources {keyword, resource_type?} → 按 Token 授æƒèŒƒå›´è¿‡æ»¤è¿”回æœç´¢ç»“æžœ
│ ├─ list_actions → 返回 McpActionSet 过滤åŽçš„动作清å•
│ ├─ get_resource {resource_type, resource_id}
│ │ │ 5. æ¡†æž¶å±‚èµ„æºæŽˆæƒæ ¡éªŒ
│ │ │ 6. è·¯ç”±åˆ°å¯¹åº”èµ„æº provider 返回详情
│ │ └─ 返回 content
│ └─ invoke_action {action_name, params}
│ │ 7. 查找 action,未找到 → -32601
│ │ 8. æ ¡éªŒå…¥å‚ input_schema,失败 → -32602
│ │ 9. **æ¡†æž¶å±‚èµ„æºæŽˆæƒæ ¡éªŒ**(仅æ¤å¤„,action 内ä¸å†æ ¡éªŒï¼‰ï¼š
│ │ - æ ¹æ® action çš„ required_resource 声明
│ │ - 从 params æå–èµ„æº ID
│ │ - 查 McpTokenResource åˆ¤æ–æ˜¯å¦åœ¨æŽˆæƒèŒƒå›´
│ │ - æœªæŽˆæƒ â†’ -32003
│ │ 10. 调用 action 的 InvokeAsync
│ │ 11. 写 McpAudit 审计日志
│ └─ 返回 content
â–¼
MCP 客户端
```
### 4. 开关é…ç½®
在 `StarServerSetting` 䏿–°å¢žï¼š
| å—æ®µ | 类型 | 默认 | 说明 |
|---|---|---|---|
| `EnableMcp` | Boolean | `false` | MCP æœåŠ¡æ€»å¼€å…³ã€‚å…³é—æ—¶ `/mcp` 返回 404 |
| `McpActionSet` | String | `*` | å¯ç”¨çš„动作集,逗å·åˆ†éš”ï¼›`*` 表示全部å¯ç”¨ï¼›å¦‚ `node,app,config` 表示åªå¯ç”¨è¿™ä¸‰ç±»æ¨¡å—的动作 |
> Token 本身有 `Enable` å—æ®µå¯å•独ç¦ç”¨ï¼›`EnableMcp` 是全局开关,关é—åŽæ‰€æœ‰ Token éƒ½æ— æ³•è°ƒç”¨ã€‚
### 5. 动作接å£è®¾è®¡ï¼ˆä»£ç 驱动自动注册)
```csharp
public interface IMcpAction
{
String Name { get; } // 动作å(snake_case,如 node_send_command)
String Description { get; } // 动作æè¿°ï¼ˆé¢å‘ LLM)
String Module { get; } // 所属模å—(node/app/config/deploy/gateway/monitor/system)
Object InputSchema { get; } // JSON Schema 傿•°å®šä¹‰
ResourceRequirement RequiredResource { get; } // 资æºä¾èµ–声明(null è¡¨ç¤ºæ— èµ„æºä¾èµ–)
Task<Object> InvokeAsync(JsonElement params, CancellationToken ct);
}
public abstract class McpActionBase : IMcpAction { /* 公共实现 */ }
public sealed class ResourceRequirement
{
public String ResourceType { get; init; } // project / node / app
public String IdField { get; init; } // params ä¸èµ„æº ID çš„å—æ®µå(如 "node_id")
public Boolean Indirect { get; init; } // true=èµ„æº ID 需通过ä¸é—´å®žä½“查 ProjectId/AppId(如 deploy_id → AppDeploy.ProjectId)
public String IndirectEntity { get; init; } // 间接查找的实体(如 "AppDeploy")
}
```
**注册机制**:`McpService` å¯åŠ¨æ—¶é€šè¿‡åå°„æ‰«ææ‰€æœ‰å®žçް `IMcpAction` 的类,自动注册到内å˜åŠ¨ä½œè¡¨ã€‚æ–°å¢žåŠŸèƒ½æ—¶åªéœ€æ·»åŠ ä¸€ä¸ªå®žçŽ°ç±»å³å¯æš´éœ²ä¸ºæ–°åŠ¨ä½œï¼Œæ— éœ€ä¿®æ”¹ `McpService` 或任何é…置文件。
`McpService` 在调用 action 剿 ¹æ® `RequiredResource` å£°æ˜Žåšæ¡†æž¶å±‚ç»Ÿä¸€èµ„æºæŽˆæƒæ ¡éªŒï¼Œaction 实现内**ä¸å†é‡å¤æ ¡éªŒ**授æƒï¼ˆä»…åšä¸šåŠ¡åˆæ³•æ€§æ ¡éªŒå¦‚"deploy 是å¦å˜åœ¨")。
### 6. 首批动作清å•(~27 个)
按模å—组织,动作å采用 `{module}_{action}` 蛇形命å。LLM 通过 `list_actions` 自å‘现,通过 `invoke_action` 调用。
#### 6.1 节点管ç†ï¼ˆnode)— 4 个
| 动作å | æè¿° | 傿•° | 资æºä¾èµ– |
|---|---|---|---|
| `node_list_online` | 列出在线节点 | `project_id?`ã€`keyword?`ã€`page?`ã€`page_size?` | æ— ï¼ˆæŒ‰ Token 授æƒé¡¹ç›®è¿‡æ»¤è¿”回) |
| `node_send_command` | å‘节点下å‘命令 | `node_id`ã€`command`ã€`args?`ã€`expire?` | node / `node_id` |
| `node_upgrade` | 触å‘节点å‡çº§æ£€æŸ¥ | `node_id`ã€`channel?` | node / `node_id` |
| `node_search` | 按åç§°/IP/ç¼–ç æœç´¢èŠ‚ç‚¹ | `keyword`ã€`project_id?` | æ— ï¼ˆæŒ‰ Token 授æƒé¡¹ç›®è¿‡æ»¤è¿”回) |
> 节点详情通过 `get_resource(node, id)` 获å–ï¼Œæ— éœ€é‡å¤ action。通用跨类型æœç´¢é€šè¿‡ `search_resources` 工具完æˆï¼Œ`node_search` ä¿ç•™ç”¨äºŽèŠ‚ç‚¹ä¸“å±žæœç´¢ï¼ˆæ”¯æŒ IP/ç¼–ç ç‰èŠ‚ç‚¹ç‰¹æœ‰å—æ®µï¼‰ã€‚
#### 6.2 应用管ç†ï¼ˆapp)— 7 个
| 动作å | æè¿° | 傿•° | 资æºä¾èµ– |
|---|---|---|---|
| `app_list_online` | 列出在线应用 | `project_id?`ã€`keyword?`ã€`page?`ã€`page_size?` | æ— ï¼ˆæŒ‰ Token 授æƒé¡¹ç›®è¿‡æ»¤è¿”回) |
| `app_send_command` | å‘应用下å‘命令 | `app_id`ã€`command`ã€`args?` | app / `app_id` |
| `app_resolve_service` | è§£æžæœåŠ¡åœ°å€ | `service_name`ã€`key?` | æ— ï¼ˆå…¬å¼€æœåŠ¡å‘现) |
| `app_search_service` | æœç´¢å·²æ³¨å†ŒæœåŠ¡ | `service_name?`ã€`key?` | æ— ï¼ˆå…¬å¼€æœåŠ¡å‘现) |
| `app_restart` | é‡å¯åº”用 | `app_id` | app / `app_id` |
| `app_stop` | åœæ¢åº”用 | `app_id` | app / `app_id` |
| `app_start` | å¯åŠ¨åº”ç”¨ | `app_id` | app / `app_id` |
> 应用详情通过 `get_resource(app, id)` 获å–。`app_restart`/`app_stop`/`app_start` 通过 `app_send_command` ä¸‹å‘ `restart`/`stop`/`start` 命令实现,但作为独立 action 暴露便于 LLM 直接调用且è¯ä¹‰æ¸…晰。
#### 6.3 é…ç½®ä¸å¿ƒï¼ˆconfig)— 2 个
| 动作å | æè¿° | 傿•° | 资æºä¾èµ– |
|---|---|---|---|
| `config_get` | 获å–应用é…ç½® | `app_id`ã€`scope?` | app / `app_id` |
| `config_set` | 设置应用é…置项 | `app_id`ã€`key`ã€`value`ã€`scope?` | app / `app_id` |
#### 6.4 远程å‘布(deploy)— 9 个
| 动作å | æè¿° | 傿•° | 资æºä¾èµ– |
|---|---|---|---|
| `deploy_list` | 列出应用部署集 | `project_id?`ã€`keyword?`ã€`page?`ã€`page_size?` | æ— ï¼ˆæŒ‰ Token 授æƒé¡¹ç›®è¿‡æ»¤è¿”回) |
| `deploy_compile` | 触å‘编译(ä¸éƒ¨ç½²ï¼‰ | `deploy_id`ã€`node_id?`(编译节点) | project(间接:deploy_id → AppDeploy.ProjectId)+ node / `node_id`ï¼ˆè‹¥ä¼ ï¼‰ |
| `deploy_list_versions` | 列出部署版本 | `deploy_id`ã€`page?`ã€`page_size?` | project(间接:deploy_id → AppDeploy.ProjectId) |
| `deploy_list_history` | åˆ—å‡ºéƒ¨ç½²åŽ†å² | `deploy_id`ã€`page?`ã€`page_size?` | project(间接:deploy_id → AppDeploy.ProjectId) |
| `deploy_list_nodes` | åˆ—å‡ºéƒ¨ç½²ç›®æ ‡èŠ‚ç‚¹ | `deploy_id` | project(间接:deploy_id → AppDeploy.ProjectId) |
| `deploy_install` | 触å‘部署到指定节点 | `deploy_id`ã€`node_id` | project(间接:deploy_id → AppDeploy.ProjectId)+ node / `node_id` |
| `pipeline_trigger` | æ‰‹åŠ¨è§¦å‘æµæ°´çº¿ | `pipeline_id`ã€`branch?` | project(间接:pipeline_id → AppPipeline.ProjectId) |
| `pipeline_get_run` | æŸ¥è¯¢æµæ°´çº¿è¿è¡ŒçŠ¶æ€ | `run_id` | project(间接:run_id → AppPipelineRun.ProjectId) |
| `pipeline_cancel` | å–æ¶ˆæ£åœ¨è¿è¡Œçš„æµæ°´çº¿ | `run_id` | project(间接:run_id → AppPipelineRun.ProjectId) |
> 部署集详情通过 `get_resource(deploy, id)` 获å–ï¼›æµæ°´çº¿è¯¦æƒ…通过 `get_resource(pipeline, id)` 获å–。`deploy_compile` 对应 `DeployService.Compile`ï¼Œä»…ç¼–è¯‘äº§ç‰©ä¸æ‰§è¡Œ install。
#### 6.5 网关管ç†ï¼ˆgateway)— 2 个
| 动作å | æè¿° | 傿•° | 资æºä¾èµ– |
|---|---|---|---|
| `gateway_list_routes` | 列出网关路由 | `keyword?`ã€`page?`ã€`page_size?` | æ— |
| `gateway_list_clusters` | 列出网关集群 | æ— | æ— |
> 网关全局é…置为åªè¯»ï¼Œé€šè¿‡ `get_resource` æš‚ä¸æš´éœ²ï¼ˆæ— 强授æƒéœ€æ±‚),如需å¯åŽç»æ‰©å±• `gateway_get_config` action。
#### 6.6 监控ä¸å¿ƒï¼ˆmonitor)— 2 个
| 动作å | æè¿° | 傿•° | 资æºä¾èµ– |
|---|---|---|---|
| `monitor_trace_search` | æœç´¢è°ƒç”¨é“¾ | `app_id?`ã€`keyword?`ã€`page?`ã€`page_size?` | app / `app_id`ï¼ˆè‹¥ä¼ app_id) |
| `monitor_alarm_list` | 列出告è¦è®°å½• | `app_id?`ã€`page?`ã€`page_size?` | app / `app_id`ï¼ˆè‹¥ä¼ app_id) |
> åº”ç”¨æ¯æ—¥ç»Ÿè®¡é€šè¿‡ `get_resource` æš‚ä¸æš´éœ²ï¼ˆå¯åŽç»æ‰©å±• `monitor_app_stat` action)。
#### 6.7 系统(system)— 1 个
| 动作å | æè¿° | 傿•° | 资æºä¾èµ– |
|---|---|---|---|
| `get_audit_log` | æŸ¥è¯¢å½“å‰ Token 最近的调用记录(用于 LLM 自çœå’Œå¤šè½®å¯¹è¯å›žé¡¾ä¸Šä¸‹æ–‡ï¼‰ | `page?`ã€`page_size?`ã€`success?`(过滤æˆåŠŸ/失败) | æ— ï¼ˆä»…è¿”å›žå½“å‰ Token 的审计记录) |
> 原 `system_info` / `system_list_apis` / `system_list_redis_nodes` / `system_list_mysql_nodes` ç‰æžšä¸¾ç±»å·¥å…·åŽ»æŽ‰ï¼Œä¿¡æ¯å¯ç”± `list_actions` 或 `search_resources` 间接获得。`search_resources` å·²æå‡ä¸º MCP 工具,ä¸å†ä½œä¸º action。
**总计 27 个 action**(4+7+2+9+2+2+1ï¼‰ï¼ŒåŠ ä¸Š 5 个 MCP 工具,LLM å¯å®ŒæˆèŠ‚ç‚¹/应用/é…ç½®/部署/网关/监控的全部è¿ç»´æ“作。
### 7. 扩展机制(代ç 驱动)
新增功能时暴露为 MCP 动作的æ¥éª¤ï¼š
1. 在 `Stardust.Server/Mcp/Actions/` 下新建类,实现 `IMcpAction`(或继承 `McpActionBase`)
2. 填写 `Name` / `Description` / `Module` / `InputSchema` / `RequiredResource`
3. 实现 `InvokeAsync` æ–¹æ³•ï¼ˆä»…ä¸šåŠ¡é€»è¾‘ï¼Œæ— éœ€æŽˆæƒæ ¡éªŒï¼‰
4. é‡å¯ Stardust.Server,`McpService` 自动å射注册,`list_actions` å³å¯è§
**æ— éœ€**:修改 `McpController`ã€ä¿®æ”¹ `McpService` 注册代ç ã€ä¿®æ”¹æ•°æ®åº“é…ç½®ã€ä¿®æ”¹å‰ç«¯ä»£ç 。
### 8. 审计日志
新增 `McpAudit` 表:
| å—æ®µ | 类型 | 说明 |
|---|---|---|
| Id | Int64 | 主键 |
| TokenId | Int32 | å…³è” `McpToken.Id`(索引) |
| TokenName | String(50) | Token å称快照(便于 Token åˆ é™¤åŽå®¡è®¡ï¼‰ |
| ToolName | String(50) | 工具å(`list_authorized_resources` / `get_resource` / `list_actions` / `invoke_action`) |
| ActionName | String(50) | 动作å(仅 `invoke_action` 时填写,如 `node_send_command`) |
| CallerIp | String(50) | 调用方 IP |
| CallerUserAgent | String(200) | 客户端 UA |
| Arguments | String(2000) | å…¥å‚ JSONï¼ˆæˆªæ– 2000 å—ç¬¦ï¼Œæ•æ„Ÿå—段脱æ•) |
| Success | Boolean | æ˜¯å¦æˆåŠŸ |
| ErrorMessage | String(500) | å¤±è´¥åŽŸå› |
| Duration | Int32 | 耗时(ms) |
| CreateTime | DateTime | 调用时间 |
## User Scenarios & Testing
### 场景 1:LLM 首次接入建立上下文
**å‰ç½®**:管ç†å‘˜åˆ›å»ºäº† Token "è¿ç»´åŠ©æ‰‹-å°æ˜Ž",勾选授æƒ"项目 A"å’Œ"项目 B"
1. LLM 调用 `initialize`,æœåŠ¡ç«¯è¿”å›ž `serverInfo`
2. LLM 调用 `list_authorized_resources`,返回项目 Aã€B çš„æ ‡è¯†ç¬¦å’Œè¯´æ˜Ž
3. LLM 调用 `list_actions`,返回 27 个å¯ç”¨åŠ¨ä½œåŠå‚æ•° schema
4. LLM 建立完整上下文:知é“能访问什么资æºã€èƒ½åšä»€ä¹ˆæ“作
**验è¯**:
- `list_authorized_resources` ä¸è¿”回项目 C(å³ä½¿æ•°æ®åº“䏿œ‰ï¼‰
- `list_actions` 返回所有 27 个动作的完整元信æ¯
### 场景 2:LLM 查询并æ“作节点
1. LLM 调用 `invoke_action(node_list_online, {})`ï¼Œæ¡†æž¶å±‚æ— èµ„æºä¾èµ–,action 内按 Token 授æƒé¡¹ç›®è¿‡æ»¤è¿”回节点列表
2. LLM 拿到节点 ID åŽè°ƒç”¨ `get_resource(node, 100)`ï¼Œæ¡†æž¶å±‚æ ¡éªŒ node 100 在授æƒèŒƒå›´ï¼Œè¿”回节点详情
3. LLM 调用 `invoke_action(node_send_command, {node_id:100, command:"restart"})`
4. æ¡†æž¶å±‚æ ¡éªŒ node_id=100 在 Token 授æƒèŒƒå›´ ✓,调用 action 执行
**验è¯**:
- 节点列表åªè¿”回项目 Aã€B 下的节点
- 未授æƒèŠ‚ç‚¹ `get_resource` 返回 `-32003`
- 未授æƒèŠ‚ç‚¹ `invoke_action(node_send_command)` 返回 `-32003`
### 场景 3:LLM 触å‘部署(写æ“ä½œï¼Œé—´æŽ¥èµ„æºæ ¡éªŒï¼‰
**å‰ç½®**:Token 授æƒäº†"项目 A"å’Œ"节点 X"(节点 X 属于项目 B)
1. LLM 调用 `invoke_action(deploy_install, {deploy_id:100, node_id:X})`
2. æ¡†æž¶å±‚æ ¡éªŒï¼š
- `deploy_id=100` → 查 `AppDeploy.ProjectId=A` → 在授æƒèŒƒå›´ ✓
- `node_id=X` → 在授æƒèŒƒå›´ ✓
3. 调用 `StarFactory.SendNodeCommand(install)`
**验è¯**:
- è‹¥ `deploy_id` 属于未授æƒé¡¹ç›® C → 返回 `-32003`
- è‹¥ `node_id` æœªæŽˆæƒ â†’ 返回 `-32003`
- å®¡è®¡æ—¥å¿—è®°å½•å…¥å‚æ‘˜è¦å’Œç»“æžœ
### 场景 4:LLM 跨类型æœç´¢èµ„æº
1. LLM 调用 `search_resources({keyword:"订å•"})` 工具
2. 工具跨 project/node/app/deploy/pipeline/service å…ç±»èµ„æºæœç´¢
3. 按 Token 授æƒèŒƒå›´è¿‡æ»¤è¿”回匹é…结果
**验è¯**:
- 返回结果åªåŒ…å« Token 授æƒèŒƒå›´å†…的资æº
- 未授æƒèµ„æºä¸å‡ºçŽ°åœ¨ç»“æžœä¸
### 场景 5:管ç†å‘˜åˆ›å»º Token 并勾选资æº
1. 管ç†å‘˜åœ¨ Web `/Platform/McpToken` 页é¢ç‚¹"新建"
2. 填写åç§°"è¿ç»´åŠ©æ‰‹-测试",勾选资æºï¼š
- 项目:勾选"项目 A"ã€"项目 B"
- 节点:勾选"节点 X"(属于项目 C)
- 应用:勾选"全部应用"(IsAll=true)
3. ä¿å˜åŽç³»ç»Ÿç”Ÿæˆ 64 ä½ Token å—符串并显示一次
4. 管ç†å‘˜å¤åˆ¶ Token é…置给 LLM 客户端
**验è¯**:
- Token å—符串创建åŽä¸å¯ä¿®æ”¹
- èµ„æºæŽˆæƒå…³ç³»å†™å…¥ `McpTokenResource` 表
- `McpTokenResource` ä¸åº”ç”¨ç±»åž‹æœ‰ä¸€æ¡ `IsAll=true` 记录
### 场景 6:管ç†å‘˜ç¦ç”¨ Token
1. 管ç†å‘˜åœ¨ Web å°† Token "è¿ç»´åŠ©æ‰‹-测试" çš„ `Enable` 改为 `false`
2. LLM 客户端使用该 Token 调用 `/mcp`
3. æœåŠ¡ç«¯è¿”å›ž `-32001`(未授æƒï¼‰
**验è¯**:
- ç¦ç”¨ç«‹å³ç”Ÿæ•ˆï¼Œæ— 需é‡å¯
- 审计日志记录ç¦ç”¨åŽçš„失败调用
### 场景 7:管ç†å‘˜ç¦ç”¨æŸç±»åŠ¨ä½œ
1. 管ç†å‘˜åœ¨ Web 设置页将 `McpActionSet` 改为 `node,app,config`
2. ä¿å˜åŽï¼Œ`list_actions` åªè¿”回这三类模å—的动作
3. `deploy_*` / `gateway_*` ç‰åŠ¨ä½œä¸å¯è§ä¸”ä¸å¯è°ƒç”¨
**验è¯**:
- `list_actions` 结果按é…置过滤
- 被ç¦ç”¨çš„动作调用返回 `-32601`(method not found)
### 场景 8:Token 过期
1. 管ç†å‘˜åˆ›å»º Token 时设置 `ExpireTime=2026-12-31`
2. 2027-01-01 时 LLM 调用 `/mcp`
3. æœåŠ¡ç«¯è¿”å›ž `-32001`(Token 已过期)
**验è¯**:
- 过期检查精确到秒
- 审计日志记录"Token 已过期"
### 场景 9:扩展新动作
1. å¼€å‘者在 `Stardust.Server/Mcp/Actions/` 新建 `RedisClearAction.cs`,实现 `IMcpAction`
2. é‡å¯ Stardust.Server
3. LLM 调用 `list_actions`,返回结果ä¸åŒ…嫿–°åŠ¨ä½œ `redis_clear`
4. LLM 调用 `invoke_action(redis_clear, {...})` 执行
**验è¯**:
- æ–°åŠ¨ä½œè‡ªåŠ¨æ³¨å†Œï¼Œæ— éœ€ä¿®æ”¹ `McpService`
- `list_actions` å‡†ç¡®åæ˜ 新动作
- æ¡†æž¶å±‚èµ„æºæŽˆæƒæ ¡éªŒå¯¹æ–°åŠ¨ä½œç”Ÿæ•ˆ
## 功能需求
### FR1:MCP å议端点
- FR1.1:Stardust.Server æä¾› `POST /mcp` ç«¯ç‚¹ï¼ŒæŽ¥å— JSON-RPC 2.0 请求
- FR1.2:实现 `initialize` 方法,返回 `serverInfo`(name=`Stardust`)和 `capabilities`
- FR1.3:实现 `tools.list` 方法,返回 5 个固定工具(`list_authorized_resources` / `search_resources` / `get_resource` / `list_actions` / `invoke_action`)
- FR1.4:实现 `tools.call` æ–¹æ³•ï¼Œæ ¹æ® `name` 路由到对应工具并返回结果
- FR1.5:未识别的 method 返回 JSON-RPC `-32601`
- FR1.6:JSON è§£æžå¤±è´¥è¿”回 JSON-RPC `-32700`
### FR2:Token å‡è¯ç®¡ç†
- FR2.1:新增 `McpToken` è¡¨ï¼Œå—æ®µè§"æ ¸å¿ƒè®¾è®¡ 3.1"
- FR2.2:Web 端æä¾› Token 列表/新建/编辑/åˆ é™¤/é‡ç½®é¡µé¢ï¼ˆ`/Platform/McpToken`)
- FR2.3:Token å—ç¬¦ä¸²åœ¨åˆ›å»ºæ—¶è‡ªåŠ¨ç”Ÿæˆ 64 ä½éšæœºå—符,创建åŽä¸å¯ä¿®æ”¹
- FR2.4:Token æ”¯æŒ `Enable` 开关,ç¦ç”¨åŽæ‰€æœ‰è°ƒç”¨ç«‹å³è¿”回 `-32001`
- FR2.5:Token æ”¯æŒ `ExpireTime`ï¼Œè¿‡æœŸåŽæ‰€æœ‰è°ƒç”¨è¿”回 `-32001`
- FR2.6:Token 支æŒ"é‡ç½®"æ“ä½œï¼šç”Ÿæˆæ–° Token å—符串,旧 Token ç«‹å³å¤±æ•ˆ
- FR2.7:Token åˆ é™¤æ—¶çº§è”åˆ é™¤ `McpTokenResource` å…³è”记录(`McpAudit` ä¿ç•™ï¼‰
### FR3ï¼šèµ„æºæŽˆæƒç®¡ç†
- FR3.1:新增 `McpTokenResource` è¡¨ï¼Œå—æ®µè§"æ ¸å¿ƒè®¾è®¡ 3.2"
- FR3.2:Web 端 Token è¡¨å•æ”¯æŒå‹¾é€‰æŽˆæƒèµ„æºï¼Œåˆ†ä¸‰ç±»ï¼šé¡¹ç›®ã€èŠ‚ç‚¹ã€åº”用
- FR3.3:æ¯ç±»èµ„æºæ”¯æŒ"全部资æº"勾选(`IsAll=true`),勾选åŽè¯¥ç±»åž‹æ‰€æœ‰èµ„æºå‡æŽˆæƒï¼ˆå«æœªæ¥æ–°å¢žï¼‰
- FR3.4ï¼šèµ„æºæŽˆæƒæ”¯æŒ `Enable` 开关,å¯ä¸´æ—¶ç¦ç”¨æŸæ¡æŽˆæƒè€Œä¸åˆ 除
- FR3.5:项目授æƒè¯ä¹‰ï¼šæŽˆæƒé¡¹ç›® → 该项目下所有节点/应用/部署集/æµæ°´çº¿/é…ç½®å‡å¯è®¿é—®
- FR3.6:节点授æƒè¯ä¹‰ï¼šæŽˆæƒèŠ‚ç‚¹ → 该节点å¯å•独æ“作(独立于项目授æƒï¼‰
- FR3.7:应用授æƒè¯ä¹‰ï¼šæŽˆæƒåº”用 → 该应用å¯å•独æ“作(独立于项目授æƒï¼‰
### FR4:鉴æƒä¸ŽæŽˆæƒæ ¡éªŒï¼ˆæ¡†æž¶å±‚统一)
- FR4.1:所有 `/mcp` 请求必须æºå¸¦ `Authorization: Bearer {token}` Header
- FR4.2:Token ä¸å˜åœ¨ / `Enable=false` / 已过期 → 返回 JSON-RPC `-32001`
- FR4.3:`get_resource` æ—¶æ¡†æž¶å±‚æ ¹æ® `resource_type` æ ¡éªŒèµ„æº ID 是å¦åœ¨ Token 授æƒèŒƒå›´
- FR4.4:`invoke_action` æ—¶æ¡†æž¶å±‚æ ¹æ® action çš„ `RequiredResource` 声明,从 params æå–èµ„æº ID æ ¡éªŒ
- FR4.5ï¼šèµ„æº ID ä¸åœ¨ Token 授æƒèŒƒå›´ → 返回 JSON-RPC `-32003`ï¼ˆæ— æƒé™ï¼‰
- FR4.6ï¼šé—´æŽ¥èµ„æºæ ¡éªŒï¼šå¦‚ `deploy_id` 需通过 `AppDeploy.ProjectId` åæŸ¥é¡¹ç›®æŽˆæƒ
- FR4.7:列表类 action(如 `node_list_online`)按 Token 授æƒèŒƒå›´è¿‡æ»¤è¿”回数æ®ï¼Œä¸è¿”回未授æƒèµ„æº
- FR4.8:`deploy_install` åŒæ—¶æ ¡éªŒ project(间接)+ node 两类资æºï¼Œä»»ä¸€æœªæŽˆæƒå³è¿”回 `-32003`
- FR4.9:action 实现内部**ä¸å†é‡å¤**èµ„æºæŽˆæƒæ ¡éªŒï¼Œä»…åšä¸šåŠ¡åˆæ³•æ€§æ ¡éªŒ
### FR5:开关é…ç½®
- FR5.1:`StarServerSetting.EnableMcp` 默认 `false`ï¼Œå…³é—æ—¶ `/mcp` 返回 404
- FR5.2:`StarServerSetting.McpActionSet` 默认 `*`(全部å¯ç”¨ï¼‰ï¼Œæ”¯æŒé€—å·åˆ†éš”的模å—å
- FR5.3:é…ç½®å˜æ›´ç«‹å³ç”Ÿæ•ˆï¼ˆæ— 需é‡å¯ï¼‰
### FR6:MCP 工具实现(5 个)
- FR6.1:实现 `list_authorized_resources` 工具,按 `resource_type?` 过滤返回 Token 授æƒèµ„æº
- FR6.2:实现 `search_resources` 工具,按 `keyword` + `resource_type?` 跨类型æœç´¢ï¼Œç»“果按 Token 授æƒèŒƒå›´è¿‡æ»¤
- FR6.3:实现 `get_resource` å·¥å…·ï¼Œæ”¯æŒ 6 类资æºï¼ˆproject/node/app/deploy/pipeline/service)
- FR6.4:实现 `list_actions` 工具,按 `module?` 过滤返回动作清å•ï¼ˆå« input_schema å’Œ required_resource)
- FR6.5:实现 `invoke_action` å·¥å…·ï¼Œæ ¹æ® `action_name` 路由到 `IMcpAction` 实现
### FR7:动作接å£ä¸Žæ³¨å†Œï¼ˆä»£ç 驱动)
- FR7.1:定义 `IMcpAction` 接å£ï¼Œå« Name/Description/Module/InputSchema/RequiredResource/InvokeAsync
- FR7.2:`McpService` å¯åŠ¨æ—¶é€šè¿‡åå°„æ‰«ææ‰€æœ‰ `IMcpAction` 实现类,自动注册到内å˜åŠ¨ä½œè¡¨
- FR7.3:`list_actions` åªè¿”回 `McpActionSet` å…许的动作
- FR7.4:被ç¦ç”¨çš„动作调用返回 `-32601`
- FR7.5ï¼šåŠ¨ä½œå…¥å‚æŒ‰ `InputSchema` æ ¡éªŒï¼Œæ ¡éªŒå¤±è´¥è¿”å›ž `-32602`(invalid params)
- FR7.6:新增动作åªéœ€æ·»åŠ å®žçŽ°ç±»ï¼Œæ— éœ€ä¿®æ”¹ `McpService` 或任何é…置文件
### FR8:动作实现(首批 27 个)
- FR8.1:实现节点管ç†ç±»åŠ¨ä½œ 4 个(`node_list_online` / `node_send_command` / `node_upgrade` / `node_search`)
- FR8.2:实现应用管ç†ç±»åŠ¨ä½œ 7 个(`app_list_online` / `app_send_command` / `app_resolve_service` / `app_search_service` / `app_restart` / `app_stop` / `app_start`)
- FR8.3:实现é…ç½®ä¸å¿ƒç±»åŠ¨ä½œ 2 个(`config_get` / `config_set`)
- FR8.4:实现远程å‘布类动作 9 个(`deploy_list` / `deploy_compile` / `deploy_list_versions` / `deploy_list_history` / `deploy_list_nodes` / `deploy_install` / `pipeline_trigger` / `pipeline_get_run` / `pipeline_cancel`)
- FR8.5:实现网关管ç†ç±»åŠ¨ä½œ 2 个(`gateway_list_routes` / `gateway_list_clusters`)
- FR8.6:实现监控ä¸å¿ƒç±»åŠ¨ä½œ 2 个(`monitor_trace_search` / `monitor_alarm_list`)
- FR8.7:实现系统类动作 1 个(`get_audit_log`)
- FR8.8:列表类动作必须按 Token 授æƒèŒƒå›´è¿‡æ»¤è¿”回数æ®ï¼Œä¸è¿”回未授æƒèµ„æº
- FR8.9:`app_restart`/`app_stop`/`app_start` 通过 `app_send_command` 下å‘对应命令实现,资æºä¾èµ–为 app / `app_id`
### FR9:审计日志
- FR9.1:新增 `McpAudit` è¡¨ï¼Œå—æ®µè§"æ ¸å¿ƒè®¾è®¡ 8"
- FR9.2ï¼šæ¯æ¬¡ `tools.call` 在 `McpAudit` 记录一æ¡ï¼ˆå« TokenId/TokenName/ToolName/ActionName/CallerIp/Arguments/Success/ErrorMessage/Duration)
- FR9.3:`Arguments` æˆªæ– 2000 å—ç¬¦ï¼Œæ•æ„Ÿå—段(`password`/`secret`/`token`)脱æ•
- FR9.4:Web 端æä¾› `McpAudit` 列表页é¢ï¼ˆ`/Platform/McpAudit`ï¼‰ï¼Œæ”¯æŒæŒ‰ TokenId/工具å/动作å/æ—¶é—´/æˆåŠŸä¸Žå¦ç›é€‰
- FR9.5:审计日志记录失败时ä¸å½±å“主调用返回
### FR10:错误处ç†
- FR10.1:所有动作异常被 `McpService` æ•获,转æ¢ä¸º JSON-RPC `-32000`(server error)+ 错误信æ¯
- FR10.2:超时(默认 30 秒)返回 `-32002`
- FR10.3ï¼šå‚æ•°ç¼ºå¤±è¿”回 `-32602`
- FR10.4ï¼šèµ„æºæœªæŽˆæƒè¿”回 `-32003`
- FR10.5:动作未找到返回 `-32601`
## éžåŠŸèƒ½éœ€æ±‚
- æ€§èƒ½ï¼šå•æ¬¡å·¥å…·è°ƒç”¨ P95 < 500ms(ä¸å«ä¸‹æ¸¸ RPC ç‰å¾…)
- å¹¶å‘ï¼šæ”¯æŒ 50 å¹¶å‘ MCP 调用
- 安全:Token å—符串ä¸åœ¨æ—¥å¿—䏿˜Žæ–‡æ‰“å°ï¼›å®¡è®¡æ—¥å¿—å…¥å‚脱æ•ï¼›Token æ ¡éªŒä½¿ç”¨æ’å®šæ—¶é—´æ¯”è¾ƒé˜²æ—¶åºæ”»å‡»
- 兼容:MCP å议版本 `2024-11-05`,兼容主æµå®¢æˆ·ç«¯ï¼ˆClaude Desktop / Trae / Cursor)
- æ‰©å±•æ€§ï¼šæ–°å¢žåŠ¨ä½œä»…éœ€æ·»åŠ ä¸€ä¸ª `IMcpAction` 实现类,零é…置零侵入
## Success Criteria
1. **å¯è°ƒç”¨**:LLM 客户端通过 5 个 MCP 工具 + 27 个 action å¯å®ŒæˆèŠ‚ç‚¹/应用/é…ç½®/部署/网关/监控的全部è¿ç»´æ“作
2. **坿²»ç†**:管ç†å‘˜å¯åœ¨ Web 设置页 1 æ¥å…³é— MCP æœåŠ¡ï¼ˆ`EnableMcp=false`),关é—åŽæ‰€æœ‰ `/mcp` 请求返回 404
3. **å¯ç®¡æŽ§**:管ç†å‘˜å¯æŒ‰æ¨¡å—å¯ç”¨/ç¦ç”¨åŠ¨ä½œå集(如åªå¼€ `node,app` 类),`list_actions` å‡†ç¡®åæ˜ é…ç½®
4. **å¯æŽˆæƒ**:管ç†å‘˜åˆ›å»º Token æ—¶å¯å‹¾é€‰æŽˆæƒçš„项目/节点/应用,未授æƒèµ„æº 100% ä¸å¯è®¿é—®ï¼ˆæŸ¥è¯¢ä¸è¿”å›žã€æ“作被拒ç»ï¼‰
5. **å¯ç¦ç”¨**:Token ç¦ç”¨åŽç«‹å³å¤±æ•ˆï¼Œæ‰€æœ‰è°ƒç”¨è¿”回 `-32001`ï¼›Token 过期åŽåŒæ ·ç«‹å³å¤±æ•ˆ
6. **å¯è¿½æº¯**ï¼šæ¯æ¬¡å·¥å…·è°ƒç”¨åœ¨ `McpAudit` è¡¨æœ‰å®Œæ•´è®°å½•ï¼ˆå« TokenId/ActionName),å¯é€šè¿‡ Web 页é¢ç›é€‰æŸ¥çœ‹
7. **安全**ï¼šæ— Token / Token 错误 / Token ç¦ç”¨ / Token 过期 / èµ„æºæœªæŽˆæƒçš„调用 100% 被拒ç»
8. **坿‰©å±•**ï¼šæ–°å¢žåŠ¨ä½œä»…éœ€æ·»åŠ ä¸€ä¸ª `IMcpAction` 实现类并é‡å¯ï¼Œæ— éœ€ä¿®æ”¹æ¡†æž¶ä»£ç æˆ–é…置文件
9. **零回归**:现有 6600 端å£çš„ RPC 接å£ã€Web 控制å°ã€è®¾å¤‡ç™»å½•/å¿ƒè·³é“¾è·¯æ— ä»»ä½•è¡Œä¸ºå˜åŒ–
## Key Entities
- **McpToken**(新增):MCP 调用å‡è¯ï¼Œå« Enable / ExpireTime / 调用统计
- **McpTokenResource**(新增):Token 与资æºï¼ˆé¡¹ç›®/节点/应用)的授æƒå…³ç³»
- **McpAudit**(新增):MCP å·¥å…·è°ƒç”¨å®¡è®¡æ—¥å¿—ï¼ˆå« ActionName å—æ®µï¼‰
- **StarServerSetting**(扩展):新增 `EnableMcp`(默认 `false`)/ `McpActionSet` é…ç½®å—æ®µ
- **IMcpAction**(新增):MCP 动作抽象接å£ï¼ˆä»£ç 驱动自动注册)
- **ResourceRequirement**(新增):动作的资æºä¾èµ–声明
- **McpService**(新增):MCP 工具路由ã€Token æ ¡éªŒã€æ¡†æž¶å±‚èµ„æºæŽˆæƒã€åŠ¨ä½œå射注册
## Assumptions
- å‡è®¾ MCP å®¢æˆ·ç«¯å‡æ”¯æŒ JSON-RPC 2.0 over HTTP çš„åŸºç¡€ä¼ è¾“æ¨¡å¼
- å‡è®¾ 4 个 MCP 工具 + 22 个 action 已能覆盖 80% çš„ LLM è¿ç»´åœºæ™¯ï¼ŒåŽç»æŒ‰éœ€ä»£ç 扩展
- å‡è®¾ Stardust æœåŠ¡ç«¯ä¸Ž LLM 客户端在åŒä¸€å¯ä¿¡ç½‘络或通过 HTTPS åå‘代ç†å¯¹å¤–,Token 通过 HTTPS Header ä¼ è¾“ä¿è¯æœºå¯†æ€§
- å‡è®¾ `McpAudit` 表数æ®é‡å¯æŽ§ï¼ˆæ—¥å‡ < 10 万æ¡ï¼‰ï¼Œæ— 需å•独分表
- å‡è®¾çŽ°æœ‰ `[ApiFilter]` 鉴æƒé“¾è·¯ä¸è¢« MCP 端点å¤ç”¨ï¼ŒMCP ç«¯ç‚¹ä½¿ç”¨ç‹¬ç«‹çš„èµ„æºæŽˆæƒ Token 体系
- å‡è®¾èµ„æºæŽˆæƒæ ¡éªŒåœ¨ `McpService` 框架层统一完æˆï¼Œaction 实现内仅åšä¸šåŠ¡åˆæ³•æ€§æ ¡éªŒï¼ˆå¦‚"实体是å¦å˜åœ¨"),ä¸å†é‡å¤èµ„æºæŽˆæƒæ ¡éªŒ
- å‡è®¾ `McpToken` 与 `McpTokenResource` 与现有 `GalaxyProject`/`Node`/`App` 实体通过 `ResourceId` 弱关è”(ä¸å»ºæ•°æ®åº“外键)
- å‡è®¾é—´æŽ¥èµ„æºæ ¡éªŒï¼ˆå¦‚ deploy_id → AppDeploy.ProjectId)通过框架层查询实体表实现,action æ— éœ€æ„ŸçŸ¥
- å‡è®¾åŠ¨ä½œæ³¨å†Œé‡‡ç”¨å射扫æç¨‹åºé›†æ–¹å¼ï¼Œå¯åŠ¨æ—¶ä¸€æ¬¡æ€§åŠ è½½ï¼ˆä¸åšåЍæ€çƒåŠ è½½ï¼Œé¿å…夿‚度)
## Out of Scope
- SSE 长连接与æµå¼å“应(`notifications/progress`):åŽç»æŒ‰éœ€æ‰©å±•
- MCP `resources` / `prompts` å议方法:本期åªå®žçް `tools`
- MCP 客户端 SDK:本期åªå®žçްæœåŠ¡ç«¯
- 工具调用的速率é™åˆ¶ï¼šæœ¬æœŸä¸å®žçް
- 现有接å£çš„é‰´æƒæ”¹é€ (如给 `NodeController.SendCommand` 补鉴æƒï¼‰ï¼šä¸åœ¨æœ¬æœŸèŒƒå›´
- å¤ç”¨ Web 用户登录æ€ï¼ˆCube Cookie/Session):ä¸å¤ç”¨ï¼ŒMCP Token 是独立体系
- Token 调用方 IP 白åå•:本期ä¸å®žçް
- 动æ€çƒåŠ è½½åŠ¨ä½œï¼šæœ¬æœŸä»…æ”¯æŒé‡å¯åŽç”Ÿæ•ˆ
- 动作的细粒度 RBAC(基于调用方身份é™åˆ¶å¯è°ƒåŠ¨ä½œï¼‰ï¼šæœ¬æœŸé€šè¿‡ `McpActionSet` 全局é…ç½® + èµ„æºæŽˆæƒæŽ§åˆ¶
|