Skip to content

第 8 章 · 连接 MCP 工具生态

本章目标:理解 MCP 协议在 Agent 架构中的位置,掌握 useMcpConnection() 的连接、认证与工具筛选,学会安全地接入第三方服务。

8.1 为什么需要 MCP

第 6 章的工具要你自己写:接 Linear 要写一个工具、接 Notion 再写一个、GitHub 又一个……每个服务都是一套 API 封装。

MCP(Model Context Protocol) 把这件事标准化:服务方自己实现一个 MCP server 暴露工具,任何支持协议的 agent 直接连上去就能用。一次对接,处处可用:

text
你的 Agent ──┬── 自有工具(defineTool)      → 业务逻辑
             ├── 沙箱内置工具                → 文件与 shell
             └── MCP 工具(useMcpConnection)→ Linear/Notion/GitHub…生态

8.2 连接一个 MCP Server

在 agent 函数体内调用 useMcpConnection() 即可:

typescript
// 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 支持两种形态:

typescript
'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 白名单只挂需要的:

typescript
'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 状态。';
}
typescript
// 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 安全须知

typescript
// ⚠️ 不可信的第三方 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 白名单?

🛠️ 动手实践

  1. 接入任一公开 MCP server(如 GitHub 官方),列出它发现的全部工具名并测试其中两个。
  2. tools 白名单把工具面砍到 3 个以内,对比模型选择工具的准确率变化。
  3. 实现"用户输入 API Key 后才连接"的条件式 MCP 挂载流程。

单体 Agent 已经很强。下一章让它学会委派:Subagents 专家团队