# mcp-gateway **Repository Path**: op-exa/mcp-gateway ## Basic Information - **Project Name**: mcp-gateway - **Description**: 统一 MCP 网关:把 wisedao 等业务能力以 MCP 工具暴露 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-22 - **Last Updated**: 2026-09-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # mcp-gateway 把平台后端能力以标准 MCP 工具的形式暴露给 AI 客户端(CodeBuddy 等),使团队成员可以直接用自然语言操作 wisedao 研发数据。 **一个 MCP 服务覆盖所有后端服务**:新增能力只需在这里注册工具,不必为每个后端服务各写一个 MCP server。 ## 架构 ``` IDE / CodeBuddy 技能 │ Streamable HTTP + 账号头(X-MCP-Username / X-MCP-Password / X-MCP-Tenant-Id) ▼ mcp-gateway :8300 │ ① 用账号换 IAM access_token(到期前自动续期) │ ② Authorization: Bearer + /api/wisedao/... ▼ api-gateway :8080 ← JWT 验签、注入 X-User-Id / X-Tenant-Id / X-Roles、限流 │ ▼ wisedao-service :8200 ← 既有 security.RequirePermission 照常判定,零改动 ``` ### 为什么必须经 api-gateway wisedao-service 的 `security.RequirePermission` 依赖网关注入的 `X-Roles`,服务自身不校验 JWT。直连并自行伪造身份头等于绕过平台权限体系(项目红线)。经 api-gateway 后,`wisedao:project:view`、`wisedao:dev:manage`、`wisedao:testcase:manage` 等判定全部照常生效。 ### 身份与令牌 - 使用者在自己的 MCP 配置里填写账号、密码与租户,**网关自动登录并续期**,无需手动更换令牌。 - IAM 的 `access_token` 有效期仅 1800 秒且**没有刷新接口**,因此网关采用「凭据换令牌 + 过期前重新登录」策略。 - 平台对连续密码错误会锁定账号,所以**登录失败绝不重试**,并做短暂负缓存(默认 30 秒),避免客户端高频重试把账号打锁。 - 每位使用者用自己的账号调用,创建人/开发人/测试人与权限判定都可追溯到本人。 ## 快速开始 ### 1. 启动服务 ```bash cd mcp-gateway go build -o bin/mcp-gateway . ./bin/mcp-gateway # 默认监听 :8300,需在仓库根目录下运行以便加载 manifest/config ``` 健康检查:`curl http://127.0.0.1:8300/health` ### 2. 配置 MCP 客户端 在 IDE 的 MCP 配置(`mcp.json`)中加入: ```json { "mcpServers": { "op-exa-wisedao": { "type": "streamable-http", "url": "http://:8300/mcp", "headers": { "X-MCP-Username": "你的平台账号", "X-MCP-Password": "你的密码", "X-MCP-Tenant-Id": "1" } } } } ``` > 各客户端对传输类型的字段名略有差异(`streamable-http` / `http`),以 IDE 的 MCP 面板生成的模板为准;`url` 与 `headers` 通用。`X-MCP-Tenant-Id` 可省略,省略时使用服务端 `mcp.default_tenant_id`。 ### 3. 安装技能(可选但推荐) 技能文件负责告诉模型「什么时候该调用哪个工具」: ```bash mkdir -p <你的项目>/.codebuddy/skills cp -r mcp-gateway/skill/wisedao <你的项目>/.codebuddy/skills/ ``` 技能内容见 `skill/wisedao/SKILL.md`,权限码清单与排障见 `skill/wisedao/references/permissions.md`。 ### 4. 验证 在 IDE 对话中试一句:`列一下我在 wisedao 里的项目`。 ## 工具清单 **只读(5 个)** | 工具 | 下游接口 | 权限码 | |---|---|---| | `wisedao_list_projects` | `GET /api/wisedao/projects` | `wisedao:project:view` | | `wisedao_list_tasks` | `GET /api/wisedao/projects/{id}/tasks` | `wisedao:dev:view` | | `wisedao_get_task` | `GET /api/wisedao/tasks/{id}` | `wisedao:dev:view` | | `wisedao_list_api_defs` | `GET /api/wisedao/projects/{id}/api-defs` | `wisedao:apidef:view` | | `wisedao_list_test_cases` | `GET /api/wisedao/projects/{id}/test-cases` | `wisedao:testcase:view` | **受控写(5 个)** | 工具 | 下游接口 | 权限码 | |---|---|---| | `wisedao_create_task` | `POST /api/wisedao/tasks` | `wisedao:dev:manage` | | `wisedao_update_task` | `PUT /api/wisedao/tasks/{id}` | `wisedao:dev:manage` | | `wisedao_transition_task` | `POST /api/wisedao/tasks/{id}/transition` | 按 action 判定(见下) | | `wisedao_create_test_case` | `POST /api/wisedao/projects/{id}/test-cases` | `wisedao:testcase:manage` | | `wisedao_update_test_case` | `PUT /api/wisedao/test-cases/{id}` | `wisedao:testcase:manage` | 状态流转的 action 与权限码:`start_dev` → `wisedao:dev:manage`;`reject_dev`、`submit_test` → `wisedao:dev:develop`;`reject_test`、`pass_test` → `wisedao:dev:test`。 **不开放**:所有删除类接口;接口定义的新建/编辑/删除与「运行接口」。 ## 配置项 `manifest/config/config.yaml`: | 配置项 | 默认值 | 说明 | |---|---|---| | `server.address` | `:8300` | 监听地址 | | `mcp.base_url` | `http://127.0.0.1:8080` | api-gateway 入口 | | `mcp.call_timeout_seconds` | `15` | 单次下游调用超时 | | `mcp.login_path` | `/api/iam/auth/login` | IAM 登录接口 | | `mcp.default_tenant_id` | `1` | 客户端未指定租户时的默认租户 | | `mcp.token_refresh_skew_seconds` | `120` | 令牌过期前提前续期的余量 | | `mcp.login_failure_backoff_seconds` | `30` | 登录失败负缓存时长(防账号锁定) | | `mcp.session_idle_timeout_minutes` | `30` | MCP 会话空闲回收时长 | | `redis.platform.*` | — | 服务注册发现(与仓库其它服务一致) | ## 详略控制 列表类接口的正文往往很长(项目 PRD、需求详情、接口报文、用例正文),默认全量返回会挤占模型上下文。列表工具因此支持 `detail_level`: - `brief`(默认):裁掉正文类长字段; - `full`:返回全部字段。 `wisedao_get_task` 默认就是 `full`(详情类接口本就为读正文而调)。 注意 `wisedao_update_test_case` 是**全量覆盖**语义,不传 `content` 会清空原正文,修改前应先用 `detail_level=full` 取回原文。 ## 安全与边界 - **明文凭据**:账号密码写在 MCP 客户端配置中,为明文,仅限团队内网使用;请勿把 `mcp.json` 提交到代码仓库或分享给外部人员。 - **日志不打敏感信息**:网关日志只记录用户名与会话建立事件,绝不打印密码与令牌。 - **不放行权限**:网关不硬编码角色、不绕过 `RequirePermission`,账号没有权限时返回明确原因(含权限码)。 - **不做删除**:工具集内不存在任何删除能力。 - **参数守卫**:所有 ID 必须为数字(防路径注入);必填校验由工具参数 schema 在前置完成。 使用前请确认账号已具备所需权限码,见 [skill/wisedao/references/permissions.md](skill/wisedao/references/permissions.md)。**当前环境中 `wisedao:apidef:view`、`wisedao:testcase:view/manage` 尚未授予任何角色**,需先补齐授权,接口定义与测试用例相关的 4 个工具才可用。 ## 开发与测试 ```bash go build ./... go vet ./... go test ./... # 覆盖工具注册、字段裁剪、权限错误映射、令牌缓存/续期/并发合并、失败不重试 ``` 手工联调(需要 api-gateway / iam-service / wisedao-service 与 Redis 已就绪): ```bash # 1) 初始化会话,拿到 Mcp-Session-Id curl -D - -X POST http://127.0.0.1:8300/mcp \ -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \ -H 'X-MCP-Username: <账号>' -H 'X-MCP-Password: <密码>' -H 'X-MCP-Tenant-Id: 1' \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2026-07-28","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}' # 2) 后续请求带上 Mcp-Session-Id 调用 tools/list 或 tools/call ``` ## 目录结构 ``` mcp-gateway/ ├── main.go 入口 ├── manifest/config/config.yaml 配置 ├── internal/ │ ├── cmd/ 启动、路由、配置读取 │ ├── mcpgw/ MCP server 装配、身份、工具注册、结果裁剪 │ ├── session/ 凭据换令牌与自动续期 │ └── upstream/ 经 api-gateway 的下游调用与错误映射 └── skill/wisedao/ 交付给团队成员的 AI 技能 ``` ## 扩展其他后端服务 1. 在 `api-gateway` 的 `config.yaml` 确认目标服务的 `prefix → upstream` 路由已存在; 2. 在 `internal/mcpgw/tools_read.go` 或 `tools_write.go` 中按同一模式注册新工具(建议用服务名前缀做命名空间); 3. 若新增返回长文本字段,在 `internal/mcpgw/render.go` 中登记裁剪字段; 4. 补充测试与权限码说明。