1. 为什么要在本地把 Ollama 接进 MCP如果你手上已经跑着 Ollama本地模型能聊天、能补全但一到让模型自己决定调用哪个工具这一步就卡住了——模型只会输出一段文字不会真的去执行函数。MCPModel Context Protocol解决的正是这件事它给大模型和外部工具之间定了一套标准协议模型按协议描述我想调用哪个工具、传什么参数客户端负责真正执行并把结果回传。把 Ollama 和 MCP 拼在一起你得到的是一个完全跑在本地、不依赖外部模型服务的工具调用链路。适合谁适合想在自己机器上做 Agent 原型、又不想把请求发到公网的开发者也适合已经在用 Ollama 做本地推理、想给它加上手脚的人。不过本地链路有个现实问题工具调用过程中往往还要访问外部模型做兜底、做结构化输出校验或者你同时想用云端更强的模型处理复杂推理。这时候如果每个服务都单独配一套 Key管理起来很乱。我的做法是用 TaoToken 做统一入口一个 Key 覆盖模型对话和 API 通道本地 Ollama 负责轻量推理重活走统一通道。下面从环境准备一路做到端到端自测。2. TaoToken 前置统一 Key 与通道准备TaoToken 在这里的角色是统一 Key API 通道。你不需要为每个模型、每个工具单独申请凭证注册后在控制台生成一个 API Key模型对话、编码计划、API 调用都走这一个入口。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。具体操作分三步。第一步进控制台创建 Key地址 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 生成后立刻复制保存页面刷新就不再完整显示。第二步如果你要验证模型连通性用模型对话页面 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 直接发一条消息确认 Key 有效。第三步长期做编码或 Agent 的去 Coding Plan 页面 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 看套餐比按量调用更划算。Key 的管理入口在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 接入细节看文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。把 Key 存到环境变量里别硬编码进代码export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api注意Key 只存在本地环境变量或密钥管理工具里不要提交到 Git 仓库。一旦泄露去控制台立即吊销重建。3. 可复制配置settings.json 与 config.toml 骨架MCP 客户端读取配置的方式因工具而异常见两种JSON 格式的settings.json和 TOML 格式的config.toml。下面两份骨架可以直接改路径用。先看settings.json这是给支持 JSON 配置的 MCP 客户端用的核心是mcpServers节点{ mcpServers: { ollama-bridge: { command: uv, args: [run, python, server.py], cwd: /Users/you/project/mcp-ollama, env: { OLLAMA_HOST: http://127.0.0.1:11434, TAOTOKEN_API_KEY: ${TAOTOKEN_API_KEY}, TAOTOKEN_BASE_URL: https://taotoken.net/api } } } }command和args决定怎么启动你的 MCP 服务端cwd是工作目录env把 Ollama 地址和 TaoToken 凭证注入进去。${TAOTOKEN_API_KEY}这种写法表示从系统环境变量读取避免明文。再看config.toml给偏好 TOML 的工具用[mcp.servers.ollama-bridge] command uv args [run, python, server.py] cwd /Users/you/project/mcp-ollama [mcp.servers.ollama-bridge.env] OLLAMA_HOST http://127.0.0.1:11434 TAOTOKEN_API_KEY ${TAOTOKEN_API_KEY} TAOTOKEN_BASE_URL https://taotoken.net/api两份配置结构一致只是语法不同。改的时候重点盯三个值cwd指向你放server.py的目录OLLAMA_HOST指向本地 Ollama 服务TAOTOKEN_BASE_URL保持 API 基址不变。4. 服务端与模型映射server.py 骨架配置写好后服务端本身要能暴露工具。用 FastMCP 建一个最小服务端暴露一个工具供模型调用# server.py from fastmcp import FastMCP mcp FastMCP(OllamaBridge) mcp.tool() def magicoutput(obj1: str, obj2: str) - str: 接收两个字符串返回拼接后的魔法输出 print(f收到参数obj1{obj1}, obj2{obj2}) return f输入obj1{obj1}, obj2{obj2}魔法输出Hello MCP if __name__ __main__: mcp.run()mcp.tool()装饰器把函数注册成 MCP 工具模型通过list_tools就能看到它的名字、描述和参数结构。启动前先装依赖uv add fastmcp ollama mcp pydanticOllama 模型映射这块关键是让模型按结构化格式输出。用 Pydantic 动态生成响应模型把工具参数映射进去再通过 Ollama 的format字段约束输出from ollama import Client client Client(hosthttp://127.0.0.1:11434) response client.chat( modelgemma3:latest, messagesconversation, formatformat_schema # 传入 Pydantic 生成的 JSON Schema )format_schema来自response_model.model_json_schema()它告诉 Ollama你必须按这个结构返回。模型返回的 JSON 里如果tool字段有值就说明它想调用工具客户端解析出函数名和参数后真正执行。5. 验证请求连通性自测命令配置和服务端都就位后先单独验证 Ollama 通不通curl http://127.0.0.1:11434/api/tags返回模型列表就说明 Ollama 正常。再验证 MCP 服务端能列出工具用 FastMCP 自带的调试器fastmcp dev server.py终端会输出类似MCP Inspector is up and running at http://127.0.0.1:6274浏览器打开这个地址进 Tools 标签页能看到magicoutput工具点进去填参数执行返回拼接字符串就说明服务端没问题。最后跑客户端脚本验证完整链路# client.py import asyncio from pathlib import Path from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): params StdioServerParameters( commanduv, args[run, python, server.py], cwdstr(Path.cwd()) ) async with stdio_client(params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools await session.list_tools() print(可用工具, [t.name for t in tools.tools]) result await session.call_tool( magicoutput, {obj1: Ollama, obj2: MCP} ) print(调用结果, result) asyncio.run(main())成功时你会看到工具列表里有magicoutput调用结果返回输入obj1Ollama, obj2MCP魔法输出Hello MCP。到这一步Ollama 通过 MCP 调用工具的链路就通了。6. 本篇常见错排查报错一Connection refused连不上 Ollama。检查OLLAMA_HOST是不是http://127.0.0.1:11434别写成localhost有时会解析到 IPv6。确认 Ollama 服务在跑ollama serve或看系统托盘图标。报错二ModuleNotFoundError: No module named fastmcp。依赖没装到当前环境。用uv add fastmcp ollama mcp pydantic重装或者确认uv run用的是项目虚拟环境而不是全局 Python。报错三MCP 客户端启动后工具列表为空。多半是cwd路径不对服务端没找到server.py。把cwd改成绝对路径或者确认args里的文件名和实际一致。报错四Ollama 返回的 JSON 解析失败。模型没按format_schema输出。换一个支持结构化输出的模型或者在系统提示里明确要求只返回 JSON不要额外文字。gemma3系列对结构化输出支持较好。报错五TaoToken 请求 401。Key 没读到或已失效。确认环境变量TAOTOKEN_API_KEY在当前 shell 里能echo出来去控制台 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 检查 Key 状态。7. 下一步把链路用起来链路通了之后你可以按用途分流。想验证不同模型在工具调用上的表现去模型对话页面 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 直接对比。要把这套 MCP 集成进日常编码流程、让 Agent 长期跑看 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入细节和参数说明在文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到协议层问题先翻这里。我踩过的一个坑一开始把cwd写成相对路径本地跑没问题换到别的工具里启动就找不到server.py。后来统一改成绝对路径再没出过这个问题。另外 Ollama 的模型名要写全gemma3和gemma3:latest在某些版本行为不一致建议显式带 tag。