ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Llamaindex MCP 实战:把本地工具接入 Agent 工作流

Llamaindex MCP 实战:把本地工具接入 Agent 工作流 1. 本地工具接不进 Agent问题到底卡在哪如果你手上已经有一堆跑得好好的本地脚本——查数据库的、读文件的、调内部接口的——现在想让 Llamaindex 的 Agent 直接把它们当工具用大概率会卡在同一个地方每个工具都要单独写一遍 FunctionTool 包装参数 schema 手写返回值格式还得对齐工具一多维护成本直接爆炸。MCPModel Context Protocol解决的正是这件事。它把「工具怎么暴露、怎么描述、怎么调用」标准化成一套协议本地工具只要按 MCP 规范起一个 Server任何支持 MCP 的客户端都能直接发现并调用不用再为每个框架重复适配。Llamaindex 通过llama-index-tools-mcp这个包接入了 MCP 客户端能力你可以在 Agent 里把远端或本地的 MCP Server 当成普通工具列表来用。这篇面向的是已经有一两条本地工具链、想快速验证「Agent 能不能通过 MCP 调起来」的开发者。我会给出可复制的 MCP Server 注册配置、Llamaindex 侧的调用代码以及一次端到端验证动作确认整条链路真的通。适合谁写过 Python、用过 Llamaindex Agent、手里有现成脚本想复用的人。不适合谁完全没碰过 Agent 框架、想从零学 Llamaindex 的纯新手。先说清楚一个容易混的点。MCP Server 和 Llamaindex Agent 是两个进程前者负责「提供能力」后者负责「决定调哪个能力」。它们之间靠 SSE 或 stdio 通信。你本地工具跑在哪个进程里决定了你用哪种 transport。下面会分别覆盖。2. TaoToken 前置给 Agent 一个稳定的模型出口在接 MCP 之前Agent 本身得先能跑起来而 Agent 跑起来的前提是有一个能正常响应 function calling 的模型。Llamaindex 的FunctionAgent依赖模型返回结构化的工具调用请求如果模型侧不稳定或者不支持 function calling你会看到 Agent 压根不触发工具或者报解析错误。我这边习惯把模型出口统一走 TaoToken原因是它的 API 兼容 OpenAI 格式Llamaindex 的OpenAILike可以直接对接不用改代码结构。官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点是 https://taotoken.net/api 。你需要准备三样东西后面配置里会反复用到第一是 Base URL填https://taotoken.net/api注意不要带 UTM 参数那是给网页跳转用的API 请求带上反而可能出问题。第二是 API Key去控制台生成地址是 https://taotoken.net/console/api-keys 。生成后复制保存页面上只显示一次。第三是 Model ID这个取决于你想用哪个模型。Llamaindex 侧要显式声明is_function_calling_modelTrue否则 Agent 不会走工具调用路径。选模型的时候优先挑明确支持 function calling 的不然 MCP 工具挂上去也是摆设。如果你只是想先验证模型通不通可以打开模型对话页面 https://taotoken.net/models 手动发一条消息试试确认返回正常再往下走。这一步能省掉后面很多「到底是模型问题还是 MCP 问题」的排查时间。对于长期要跑编码类 Agent、或者工具调用频率比较高的场景可以考虑 Coding Plan地址是 https://taotoken.net/coding-plan 配额和稳定性会比按量更可控。不过这篇的重点是 MCP 链路模型出口你按自己习惯来就行只要保证支持 function calling。有一点要提醒不要把 TaoToken 理解成某种特殊通道它就是一个标准的 OpenAI 兼容 API 出口你填的 Base URL 和 Key 跟填官方地址在代码层面没区别。这样理解后面配置出问题时排查思路才清晰。3. 可复制配置MCP Server 注册 Llamaindex 调用这一节是核心我给两套配置一套是 MCP Server 的注册以 stdio 本地脚本为例一套是 Llamaindex 侧的调用代码。你按自己的工具形态选。先装依赖pip install llama-index-tools-mcp llama-index-core llama-index-llms-openai mcp如果你要用mcp dev调试 Server还需要mcp[cli]pip install mcp[cli]3.1 MCP Server 注册配置假设你有一个本地脚本my_tools_server.py里面用 FastMCP 暴露了两个工具。注册配置我习惯写成一个 JSON方便版本管理和复用{ mcpServers: { local-tools: { command: python, args: [/abs/path/to/my_tools_server.py], env: { PYTHONUNBUFFERED: 1 } }, remote-tools: { url: http://127.0.0.1:8000/sse, transport: sse } } }这里local-tools走 stdioremote-tools走 SSE。stdio 适合本地脚本进程由客户端拉起SSE 适合已经独立跑着的 Server。路径一定用绝对路径相对路径在不同工作目录下会找不到文件这是最常见的坑之一。如果你用的是 Cline 或者 Claude Code 这类工具它们的 MCP 配置格式基本一致把上面这段贴进对应的 settings 文件即可。三件套要写全Base URL、Key、Model ID缺一个都跑不起来。3.2 Llamaindex 侧调用代码Llamaindex 这边最省事的方式是用get_tools_from_mcp_url直接拿工具列表import asyncio from llama_index.tools.mcp import get_tools_from_mcp_url from llama_index.core.agent.workflow import FunctionAgent from llama_index.llms.openai_like import OpenAILike async def main(): tools await get_tools_from_mcp_url(http://127.0.0.1:8000/sse) print(f发现工具数量: {len(tools)}) for t in tools: print(-, t.metadata.name) llm OpenAILike( modelyour-model-id, api_basehttps://taotoken.net/api, api_keyyour-api-key, is_chat_modelTrue, is_function_calling_modelTrue, ) agent FunctionAgent( nameLocalToolAgent, description调用本地 MCP 工具的 Agent, llmllm, toolstools, system_prompt你可以调用工具来完成任务优先使用工具而不是猜测。, ) resp await agent.run(帮我调用工具查一下当前状态) print(resp) asyncio.run(main())如果你要更细粒度控制比如只暴露部分工具、或者要连 stdio 的 Server用BasicMCPClientMcpToolSpecfrom llama_index.tools.mcp import BasicMCPClient, McpToolSpec mcp_client BasicMCPClient(python, args[/abs/path/to/my_tools_server.py]) mcp_tool_spec McpToolSpec( clientmcp_client, allowed_tools[tool_a, tool_b], include_resourcesFalse, ) tools mcp_tool_spec.to_tool_list()allowed_tools这个过滤很实用。工具一多全塞给模型会稀释它的选择准确率只放当前任务相关的几个命中率明显更高。include_resources默认关除非你的 Server 暴露了资源读取能力且 Agent 真的需要否则开着只会增加上下文负担。3.3 把工作流反向暴露成 MCP还有一种反向场景你有一个 Llamaindex Workflow想让它被别的 MCP 客户端调用。用workflow_as_mcpfrom llama_index.core.workflow import Context, Workflow, Event, StartEvent, StopEvent, step from llama_index.tools.mcp import workflow_as_mcp class RunEvent(StartEvent): msg: str class LoudWorkflow(Workflow): step async def step_one(self, ctx: Context, ev: RunEvent) - StopEvent: return StopEvent(resultev.msg.upper() !) workflow LoudWorkflow() mcp workflow_as_mcp(workflow, start_event_modelRunEvent)然后mcp dev script.py就能把它当 MCP Server 跑起来。这个能力在「已有 Agent 想被别的 Agent 调用」的编排场景里很有用。4. 验证请求一次端到端跑通配置写完别急着上复杂任务先用一个最小验证确认链路通。分三步。第一步单独验证 MCP Server 活着。如果是 SSE 的直接 curlcurl -N http://127.0.0.1:8000/sse能看到事件流输出就说明 Server 在跑。如果是 stdio 的用mcp dev起一个调试界面手动点一下工具看返回。第二步验证 Llamaindex 能发现工具。跑这段import asyncio from llama_index.tools.mcp import BasicMCPClient async def check(): client BasicMCPClient(http://127.0.0.1:8000/sse) tools await client.list_tools() print(工具列表:, [t.name for t in tools]) result await client.call_tool(your_tool_name, {arg1: value1}) print(调用结果:, result) asyncio.run(check())这一步不经过模型纯粹验证 MCP 客户端和 Server 的通信。如果这里就报错问题在 MCP 层跟模型无关。第三步验证 Agent 真的会调工具。用第 3 节的完整 Agent 代码发一个明确需要工具才能回答的问题。观察日志里有没有 tool call 记录。成功的话你会看到类似这样的输出发现工具数量: 2 - get_status - query_data [Agent] 调用工具 get_status [Agent] 工具返回: {status: ok, count: 42} 最终回答: 当前状态正常数量为 42。关键看两点工具被发现的数量对不对以及 Agent 的回答里有没有用到工具返回的真实数据。如果 Agent 直接编了个答案没调工具八成是模型不支持 function calling或者is_function_calling_model没设成 True。实测下来这三步分开验证比一上来就跑完整 Agent 高效得多。哪一层出问题一目了然不用在混合日志里猜。5. 本篇常见错排查这一节列几个真实会撞上的报错对照着看。401 Unauthorized。模型侧报这个检查 API Key 有没有复制全、有没有多余空格。TaoToken 的 Key 在 https://taotoken.net/console/api-keys 生成如果确认 Key 没问题看 Base URL 是不是写成了带 UTM 的网页地址。API 请求必须用https://taotoken.net/api不能带查询参数。local proxy failed / connection refused。MCP 侧报这个通常是 Server 没起来或者端口不对。先确认curl能通再检查 Llamaindex 里填的 URL 和 Server 实际监听地址一致。stdio 模式下如果报找不到文件检查args里的路径是不是绝对路径。Error reading choices / 返回结构解析失败。这个多半是模型返回的不是标准 OpenAI 格式或者模型不支持 function calling 却被当成了支持。换一个明确支持 function calling 的 Model ID并确认is_function_calling_modelTrue。如果用的是OpenAILikeis_chat_model也要设 True。OAuth 相关报错。如果你连的是需要认证的 MCP ServerBasicMCPClient.with_oauth需要提供redirect_handler和callback_handler。生产环境别用内存存储 token实现一个FileTokenStorage落盘否则进程重启就要重新授权。回调里拿 authorization code 的那步确保用户能实际看到跳转 URL。工具被发现但 Agent 不调用。先看allowed_tools有没有把工具过滤掉。再看 system_prompt 有没有引导模型用工具。最后确认工具的描述description写得够清楚——模型是靠描述决定调不调的描述含糊它就不敢调。Codex auth.json 相关。如果你在用 Codex 类工具接 MCP认证信息写在auth.json里格式要对齐。Base URL、Key、Model ID 三件套缺一不可路径别写错。排查顺序建议固定先 curl 验 Server再list_tools验客户端最后跑 Agent 验模型。从下往上查别跳步。6. 把链路固定下来再谈扩展链路跑通之后我建议做一件事把 MCP Server 的启动和 Llamaindex 的调用封装成一个可重复执行的脚本而不是每次手动起进程。stdio 模式下尤其重要因为进程生命周期由客户端管理手动起容易和客户端拉起冲突。另一个实用技巧是给工具描述加「使用时机」。比如不要只写「查询状态」写成「当用户询问系统当前运行状态时调用返回 status 和 count 字段」。模型对时机的判断比对你参数 schema 的理解更依赖描述文本。这一条改完工具命中率通常会有肉眼可见的提升。工具数量控制在 5 到 8 个以内比较稳。超过这个量考虑按任务分组不同 Agent 挂不同子集。MCP 的好处就是工具发现是动态的你可以按需组合不用把所有能力塞进一个 Agent。最后验证脚本留着。每次改完 Server 或换模型先跑一遍第 4 节的三步验证比直接上业务任务省时间。这套流程固定下来之后再加新工具就是往 Server 里加一个函数、在配置里加一行的事扩展成本很低。
返回列表