你已经用 Go 写好了 MCP Server,工具也注册好了——但大模型还“看不见”它。
问题出在哪?光有服务端不够,Agent 还需要一个“眼睛和手”:MCP Client
本文将聚焦 如何在主流 LLM Agent 框架(以 LlamaIndex 为例)中集成 MCP Client,实现从“能提供工具”到“能被调用工具”的关键一步。我们将深入 Agent 执行引擎、设计高性能 Client、实现动态工具发现,并提供实用的调试技巧。无论你是 Agent 开发者还是工具提供方,这篇指南都将帮你打通最后一公里。


一、Agent 执行引擎如何调用外部工具?

在 LlamaIndex 等现代 Agent 框架中,工具调用并非由 LLM 直接发起,而是通过一个执行引擎(Execution Engine) 协调完成。其核心流程如下:

  1. LLM 生成工具调用意图:例如输出 JSON:{"tool_name": "query_db", "arguments": {"table": "orders"}}
  2. Agent 解析该意图:判断是否为合法工具调用;
  3. 执行引擎调用对应工具:通过 Client 向 MCP Server 发起请求;
  4. 将结果回填给 LLM:作为下一步推理的上下文。

关键点:Agent 本身不关心工具怎么实现,只关心“工具是否存在”和“如何调用”。而 MCP Client 的职责,就是将 Agent 的抽象工具调用,翻译成符合 MCP 协议的网络请求


二、MCP Client 的核心设计

一个生产级 MCP Client 需解决三大问题:连接管理、请求构造、容错控制

1. 连接管理

  • 使用 HTTP 客户端连接池(如 http.Client with Transport),避免每次请求新建 TCP 连接;
  • 支持配置 Base URL、超时、重试策略
  • 若使用 gRPC,则维护长连接和流控。

2. 请求序列化

Client 需将 Agent 的工具调用参数,严格按 MCP 规范封装为 JSON

{
  "type": "tool_request",
  "tool_name": "...",
  "arguments": { ... },
  "request_id": "uuid",
  "context_id": "session-xxx"
}
  • request_id 用于追踪;
  • context_id 由 Agent 会话管理器统一生成。

3. 超时与重试

  • 整体调用超时(如 10 秒)防止 Agent 卡死;
  • 可配置重试次数(如 2 次),配合指数退避;
  • 区分可重试错误(如网络超时)与不可重试错误(如参数校验失败)。

三、将自研 MCP Server 接入 LlamaIndex

LlamaIndex 从 v0.10 开始原生支持 MCP。接入步骤如下:

1. 安装依赖

pip install llama-index

2. 实现 MCP 工具包装器

from llama_index.core.tools import FunctionTool
from llama_index.mcp import MCPServerClient

# 创建 MCP Client
client = MCPServerClient(
    endpoint="http://localhost:8080/mcp",
    auth_token="your-secret-token"
)

# 获取工具列表(见下文“动态发现”)
tools = client.get_tools()

# 将每个 MCP 工具转为 LlamaIndex Tool
llama_tools = []
for tool_meta in tools:
    def make_tool_func(tool_name):
        def _func(**kwargs):
            return client.call_tool(tool_name, kwargs)
        return _func
    
    llama_tool = FunctionTool.from_defaults(
        fn=make_tool_func(tool_meta["name"]),
        name=tool_meta["name"],
        description=tool_meta["description"]
    )
    llama_tools.append(llama_tool)

3. 注入 Agent

from llama_index.core.agent import ReActAgent

agent = ReActAgent.from_tools(llama_tools, verbose=True)
response = agent.chat("查询用户 U123 的余额")
print(response)

至此,你的 Go 写的 MCP Server 已被 LlamaIndex Agent 完全集成


四、动态工具发现:Agent 如何知道有哪些工具?

硬编码工具列表不可维护。MCP 支持 动态发现机制
MCP Server 提供 /tools 接口,返回所有已注册工具的 Manifest。

# MCP Client 实现 get_tools()
def get_tools(self):
    resp = self.session.get(f"{self.endpoint}/tools")
    resp.raise_for_status()
    return resp.json()  # 返回 [{name, description, parameters}, ...]

Agent 启动时调用此接口,自动构建工具列表。当 Server 新增工具后,Agent 可通过热更新或重启获取最新能力。


五、性能优化:让 Agent 调用又快又稳

高并发场景下,MCP Client 必须考虑性能:

1. 连接复用

  • 使用 requests.Session(Python)或 http.Client(Go)保持连接;
  • 配置合理的 max_idle_connskeepalive

2. 异步执行

LlamaIndex 支持异步 Agent,Client 也应提供 async_call_tool

async def async_call_tool(self, tool_name, args):
    async with self.async_session.post(...) as resp:
        return await resp.json()

3. 批量请求(未来扩展)

虽然当前 MCP 以单请求为主,但可设计 批处理代理层,将多个独立工具调用合并为一次 HTTP 请求(需 Server 支持)。


六、调试技巧:快速定位“为什么没调用?”

MCP 调试常见痛点:Agent 没调工具?调了但失败?结果不对?以下是实用技巧:

1. 日志埋点

  • 在 Client 发送请求前,记录完整请求体(脱敏后);
  • 在 Agent 层开启 verbose=True,查看 LLM 是否生成了工具调用。

2. 请求录制与回放

  • 使用 mitmproxyCharles 抓包,确认请求是否发出;
  • 将请求保存为 JSON 文件,用 curl 回放:
curl -X POST http://localhost:8080/mcp -H "Authorization: Bearer xxx" -d @request.json

3. 协议合规性检查

  • 验证请求是否包含 type: "tool_request"
  • 检查 arguments 是否符合工具注册时的 JSON Schema。

七、MCP Client 与 Agent 协作流程图

下图展示了从用户提问到工具结果返回的完整链路:

该流程清晰分离了 智能决策(Agent)能力执行(MCP),是可扩展架构的关键。


结语:你不仅是工具提供者,更是 AI 能力生态的共建者

通过集成 MCP Client,你让 LlamaIndex Agent 能够安全、可靠、动态地调用你用 Go 构建的任意服务
这不仅是一次技术集成,更是将你的后端能力注入 AI 智能体的血液中
未来,随着 MCP 标准化推进,你的工具将无需修改,即可被 LangChain、AutoGen、甚至未来的新框架调用。
现在,你写的每一个工具,都是 AI 世界的一块积木

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐