第 8 章 · 连接 MCP 工具生态
本章目标:理解 MCP 协议在 Agent 架构中的位置,掌握
useMcpConnection()的连接、认证与工具筛选,学会安全地接入第三方服务。
8.1 为什么需要 MCP
第 6 章的工具要你自己写:接 Linear 要写一个工具、接 Notion 再写一个、GitHub 又一个……每个服务都是一套 API 封装。
MCP(Model Context Protocol) 把这件事标准化:服务方自己实现一个 MCP server 暴露工具,任何支持协议的 agent 直接连上去就能用。一次对接,处处可用:
你的 Agent ──┬── 自有工具(defineTool) → 业务逻辑
├── 沙箱内置工具 → 文件与 shell
└── MCP 工具(useMcpConnection)→ Linear/Notion/GitHub…生态8.2 连接一个 MCP Server
在 agent 函数体内调用 useMcpConnection() 即可:
// src/agents/project-assistant.ts
'use agent';
import { useMcpConnection, useModel } from '@flue/runtime';
export function ProjectAssistant() {
useModel('anthropic/claude-sonnet-4-6');
// 连接 Linear 的官方 MCP server
useMcpConnection({
name: 'linear', // 连接名,用于生成工具前缀
url: 'https://mcp.linear.app/mcp', // server 地址
auth: process.env.LINEAR_API_KEY, // Bearer token 认证
});
return '为团队管理 Linear 上的 issue 与项目。';
}运行时行为:agent 开始处理消息时建立连接、自动发现 server 的全部工具并加入工具集;连接在实例存活期间复用——你不需要手动开关连接。MCP 工具以 mcp__<server>__<tool> 命名(如 mcp__linear__create_issue),避免与你自己的工具冲突。
8.3 认证:静态 Token 与动态函数
许多托管 MCP server 遵循 MCP 授权模型(OAuth 2.1),期望 Bearer token。auth 支持两种形态:
'use agent';
import { useMcpConnection, useInitialData } from '@flue/runtime';
export function MultiTenantAssistant() {
const { userId } = useInitialData<{ userId: string }>();
useMcpConnection({
name: 'linear',
url: 'https://mcp.linear.app/mcp',
// 动态认证:函数在每个请求前解析,天然支持轮换与吊销
auth: () => tokenStore.get(userId, 'linear'),
});
return '帮助用户管理其 Linear 任务。';
}两条安全边界:
- Flue 不存储也不管理你的 token——OAuth 流程、令牌存储、刷新逻辑全部由你的应用负责;
- 需要用户中途授权时,把连接声明成条件式:OAuth 完成后翻转持久标志,下一条消息起 agent 就拥有该 server 的工具。
8.4 工具筛选与连接复用
Server 动辄暴露几十个工具,每个都占模型上下文。用 tools 白名单只挂需要的:
'use agent';
import { useModel, useMcpConnection } from '@flue/runtime';
import { linear } from '../connections/linear.ts'; // defineMcpConnection 定义
export function IssueReader() {
useModel('anthropic/claude-haiku-4-5');
// 复用共享定义,但按需收窄工具面
useMcpConnection({ ...linear, tools: ['search_issues', 'get_issue'] });
return '查询并汇报项目 issue 状态。';
}// src/connections/linear.ts —— defineMcpConnection:定义一次,处处复用
import { defineMcpConnection } from '@flue/runtime';
export const linear = defineMcpConnection({
name: 'linear',
url: 'https://mcp.linear.app/mcp',
auth: process.env.LINEAR_API_KEY,
});注意:白名单里写了 server 不存在的工具会导致连接失败报错;optional: true 可让 server 不可达时降级运行(模型会被告知该组工具暂不可用)。
8.5 安全须知
// ⚠️ 不可信的第三方 MCP server 等于第三方依赖:
// 它的 tool descriptions 会进入你的 prompt,
// 它的返回结果会进入对话。
//
// 防护清单:
// 1. 用 tools 白名单限制暴露面
useMcpConnection({ ...untrusted, tools: ['read_only_search'] });
// 2. 优先使用官方/可信来源的 server
// 3. 对高权限操作保留自有 defineTool 实现(可加审批流)
// 4. 生产环境监控 MCP 工具调用日志(见 Observability 一章)进阶玩法:createMcpConnection(definition) 是更低层的接口——直接连上 server、发现工具并返回 ToolDefinition[],让受信任的应用代码先行过滤再挂载。
本章小结
- MCP 把"每个服务手写一套工具"变成"连上就用"的标准协议;
useMcpConnection()自动发现工具,命名mcp__<server>__<tool>;auth收静态字符串或动态函数(每请求解析);token 管理是你的责任;tools白名单控制上下文占用与暴露面;optional: true允许降级;- 第三方 server 视同第三方依赖,谨慎评估、白名单兜底。
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. 通过 useMcpConnection 连接后,server 的工具以什么命名规则进入工具集?
2. auth 传函数而非字符串的意义是?
3. 关于 Flue 对 MCP token 的处理,正确的是?
4. 为什么要对第三方 MCP server 使用 tools 白名单?
🛠️ 动手实践
- 接入任一公开 MCP server(如 GitHub 官方),列出它发现的全部工具名并测试其中两个。
- 用
tools白名单把工具面砍到 3 个以内,对比模型选择工具的准确率变化。 - 实现"用户输入 API Key 后才连接"的条件式 MCP 挂载流程。
单体 Agent 已经很强。下一章让它学会委派:Subagents 专家团队。