用途:在 Phoenix 1.7+(推荐 1.8)项目中加入生产可用的 Streamable HTTP MCP 端点,依赖 {:ex_mcp, "~> 1.1.1"},对每个受保护方法使用 Bearer 鉴权,采用 Phoenix/Bandit 适配器。要求项目已有 API key 机制(Accounts.verify_api_token/1 或 authenticate_api_key/1,密钥带 scopes 或 :public/:private),数据库为 PostgreSQL,Bandit 为默认服务器。
主要能力:按固定架构分层生成文件,包括 MCPServer(编译期 DSL 工具,不放入 supervisor)、MCP.Transport、AuthPlug、VaryOrigin、Bandit 安全的 SSE/SSEConn、JSON 错误模块与 CacheBody(拼接 {:more, chunk} 完整原始体)。请求流为:主机允许列表 403 → AuthPlug(GET/POST/DELETE 要求 Bearer,OPTIONS 免凭证)→ VaryOrigin → ExMCP.HttpPlug → GET SSE 在请求进程上 chunk → MCPServer.init/1 的临时 GenServer 状态。身份通过 handler_opts 传入 init/1 状态,工具读取 state.api_key。使用 principal_id/tenant_id 回调绑定会话。新增工具只需在 MCPServer 中写 tool 宏并给出 input_schema 与 run 函数,无需其他注册。
使用方式:先做 Phase 0 发现(读取 mix.exs、检查现有 MCP、确认鉴权函数与 scopes、endpoint 解析器选项),再按阶段执行:加依赖并 mix deps.get;配置 CacheBody、Transport 与 :mcp / :mcp_allowed_hosts;编写 MCPServer 与 HTTP 层;路由中让 /mcp 的 GET/POST/DELETE/OPTIONS 走 AuthPlug 且位于 dev_routes 与 :api 之外;最后写 MCPCase/ConnTest(initialize、notify 202、tools/list、ping、缺 Bearer 401)并用 Claude CLI 或 Inspector 验证。
限制:不使用 Anubis、不使用 use ExMCP.Server / deftool,不生成薄 Handler、RequestHandler、RequestContext、AuthSessions、SSEHub 或拦截通知的 CorsPlug;不在 supervisor 启动 MCPServer,不调用 HttpPlug.start_link/1。仅 HTTPS;mcp_allowed_hosts 只列公网主机;认证 MCP 上禁止 Access-Control-Allow-Origin: *。ExMCP 会话与 SSE 流为节点本地,需单实例提供 MCP,水平扩展需后续亲和或分布式存储设计;protocol_mode 保持 :legacy_only 直到客户端握手验证。OAuth 2.1 + PKCE 场景另用 /bootstrap-mcp-oauth。