ARTICLE DETAIL

资讯详情

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

本地手写MCP服务教程:用Python虚拟环境配TaoToken打通Claude与Postman

本地手写MCP服务教程:用Python虚拟环境配TaoToken打通Claude与Postman 1. 从零手写 MCP 服务为什么值得折腾一次MCP 全称 Model Context Protocol模型上下文协议你可以把它理解成 AI 世界的 USB-C 接口。以前你问大模型「帮我查一下北京天气」它只能回你一段操作步骤让你自己去浏览器里敲。有了 MCPAI 就能真正调用外部工具把结果直接拿回来。这个协议最早由 Anthropic 开源现在 Claude、各类支持 MCP 的客户端都能对接。但很多人卡在第一步想自己写一个本地 MCP 服务结果环境一团乱。系统里装着 Python 3.8MCP 又要求 3.9 以上改环境变量怕影响别的项目装依赖时 pip 报包不存在写好的服务 Claude 找不到Postman 又调不通。这篇就聚焦一件事用 Python 虚拟环境隔离依赖从零手写一个本地 MCP 服务再通过 TaoToken 统一 Key 和 API 通道把 Claude 和 Postman 两条联调链路都跑通。适合谁看会一点 Python、想搞懂 MCP 服务端到底怎么跑起来的人手里有 Claude 命令行客户端、想接自己写的工具的人以及习惯用 Postman 做接口验证的后端同学。全程可复制命令和代码都给全踩过的坑我也会标出来。2. TaoToken 前置统一 Key 与 API 通道写 MCP 服务绕不开一件事你的工具函数里总得调外部 API。天气、搜索、模型对话每个服务一套 Key、一套地址管理起来很烦。TaoToken 在这里的作用就是做统一入口一个 Key 打通模型对话和各类 API 调用MCP 服务里只认一个 base_url 和一个 Key换服务不用改一堆配置。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 注意 API 地址不带 UTM 参数配置里直接写这个就行。你需要先拿到一个 Key。进控制台创建https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 然后在 API Keys 页面生成https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。生成的 Key 形如sk-xxxx复制下来后面写进环境变量别硬编码在代码里。如果你后面要长期跑编码类 Agent可以了解下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。想先在网页里验证模型通不通用模型对话页https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。接入细节看文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。注意Key 只放环境变量不要提交到 Git。MCP 服务读os.environ拿 Key这样 Claude 和 Postman 两条链路共用同一份配置。3. 可复制配置虚拟环境 MCP 服务骨架3.1 用指定 Python 版本创建虚拟环境系统里 Python 版本不对是第一个坑。假设你本地有 3.10但环境变量指向 3.8不用改环境变量直接指定解释器建虚拟环境。cd ~ mkdir MyMcp cd MyMcp # 先确认 3.10 的路径 which python3.10 # 输出示例/Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 # 用指定版本创建虚拟环境 python3 -m venv -p /Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 venv # 激活 source venv/bin/activate # 激活后命令行前面会出现 (venv)激活成功后which python应该指向MyMcp/venv/bin/python。这一步很关键后面 Claude 配置里填的就是这个虚拟环境里的解释器路径。3.2 安装依赖并锁定版本pip install --upgrade pip pip install mcp aiohttp anyio fastmcp pip list实测下来mcp 1.26.0、fastmcp 3.0.2、aiohttp 3.13.3、anyio 4.12.1这套组合能正常跑。如果你遇到「包不存在」的报错八成是 pip 本身有问题用虚拟环境里的 python 升级 pip/Users/xxx/MyMcp/venv/bin/python -m pip install --upgrade pip3.3 写 MCP 服务骨架stdio HTTP 双模式新建server.py下面这份代码同时支持 stdio给 Claude 用和 streamable-http给 Postman 用Key 从环境变量读base_url 指向 TaoToken。import os import asyncio import contextlib import aiohttp from mcp.server.fastmcp import FastMCP from starlette.applications import Starlette from starlette.routing import Mount from starlette.middleware.cors import CORSMiddleware # 服务名自定义 mcp FastMCP(taotoken-mcp-server, stateless_httpTrue, json_responseTrue) # 从环境变量读取避免硬编码 TAOTOKEN_KEY os.environ.get(TAOTOKEN_API_KEY, ) TAOTOKEN_BASE https://taotoken.net/api mcp.tool() async def ask_model(prompt: str) - str: 把问题转发给 TaoToken 统一通道返回模型回答。 Args: prompt: 用户输入的问题文本 url f{TAOTOKEN_BASE}/v1/chat/completions headers { Authorization: fBearer {TAOTOKEN_KEY}, Content-Type: application/json, } payload { model: claude-3-5-sonnet, messages: [{role: user, content: prompt}], } timeout aiohttp.ClientTimeout(total30) try: async with aiohttp.ClientSession(timeouttimeout) as session: async with session.post(url, headersheaders, jsonpayload) as resp: resp.raise_for_status() data await resp.json() return data[choices][0][message][content] except asyncio.TimeoutError: return 请求超时请稍后重试 except aiohttp.ClientResponseError as e: return fHTTP 错误: {e.status} except Exception as e: return f调用失败: {str(e)} contextlib.asynccontextmanager async def lifespan(app: Starlette): async with contextlib.AsyncExitStack() as stack: await stack.enter_async_context(mcp.session_manager.run()) yield starlette_app Starlette( routes[Mount(/, mcp.streamable_http_app())], lifespanlifespan, ) starlette_app CORSMiddleware( starlette_app, allow_origins[*], allow_methods[GET, POST, DELETE], expose_headers[Mcp-Session-Id], ) if __name__ __main__: # 默认 stdio改成 transportstreamable-http 走 HTTP mcp.run(transportstreamable-http)mcp.tool()装饰器把函数注册成 MCP 工具函数签名和 docstring 会自动变成工具 SchemaAI 靠它判断怎么调。mcp.run()不带参数是 stdio 模式Claude 会自动拉起进程带transportstreamable-http就是 HTTP 模式Postman 能直接打。3.4 配置 Claude 客户端找到~/.claude.json在全局mcpServers下加配置。注意别写到projects里否则只在那个目录生效。{ mcpServers: { taotoken-mcp-server: { command: /Users/xxx/MyMcp/venv/bin/python, args: [/Users/xxx/MyMcp/server.py], env: { TAOTOKEN_API_KEY: sk-你的Key } } } }command填虚拟环境里的 python 路径用which python在激活状态下查。env里把 Key 传进去服务启动时就能读到。4. 验证请求Claude 与 Postman 双链路4.1 Claude 侧验证stdio 模式下不用手动启动服务Claude 会自己拉起。启动 Claude 后如果右下角没提示1 mcp failed基本就成了。输入/mcp能看到刚配的服务名。然后直接问「用 ask_model 工具帮我解释一下 MCP 是什么」。Claude 会自动推断调用工具返回模型回答。如果它没调明确说「使用 taotoken-mcp-server 的 ask_model 工具」。4.2 Postman 侧验证HTTP 模式要手动启动服务export TAOTOKEN_API_KEYsk-你的Key python server.py控制台会输出监听地址默认http://127.0.0.1:8000/mcp。Postman 里新建 POST 请求填这个地址。请求头加Accept: application/json和Content-Type: application/json。Body 选 raw JSON{ jsonrpc: 2.0, id: 2, method: tools/call, params: { name: ask_model, arguments: { prompt: 用一句话说明 MCP 的作用 } } }发送后正常会返回result.content里带模型回答。如果返回Mcp-Session-Id相关错误检查请求头有没有带Accept以及服务是不是 streamable-http 模式启动的。链路启动方式关键配置验证动作Claude自动拉起.claude.json全局 mcpServers/mcp查看 提问Postman手动python server.py请求头 Accept JSON-RPC bodytools/call 返回结果5. 本篇常见错排查报错一ModuleNotFoundError: No module named mcp虚拟环境没激活或者 Claude 配置里的 python 路径指向了系统 python。用which python确认路径填进.claude.json。报错二Claude 启动提示1 mcp failed先看.claude.json是不是写在了projects下。全局配置才在任何目录生效。再看command路径和args脚本路径有没有写错路径里别用~写绝对路径。报错三pip 装包报「找不到包」pip 本身坏了。用虚拟环境里的 python 升级/Users/xxx/MyMcp/venv/bin/python -m pip install --upgrade pip再重装依赖。报错四Postman 返回 406 或 session 错误请求头缺Accept: application/json。streamable-http 模式对 Accept 有要求补上再试。另外确认服务是用transportstreamable-http启动的stdio 模式 Postman 连不上。报错五调用模型返回 401Key 没读到。检查export TAOTOKEN_API_KEY...有没有执行或者 Claude 配置的env里 Key 拼写对不对。Key 去 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 重新生成一个。报错六端口 8000 被占用改 FastMCP 初始化时的端口参数或者先lsof -i:8000找到占用进程处理掉。6. 继续往下走服务跑通之后你可以把ask_model换成任意工具查数据库、读本地文件、调内部接口只要在函数上挂mcp.tool()就行。Key 和通道统一走 TaoTokenMCP 服务里只维护一份 base_url换模型或换服务不用动业务代码。如果你要长期跑编码类 Agent建议看下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入过程中遇到配置问题对照接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。想先在网页里验证模型响应用模型对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。Key 管理在 API Keys 页https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。最后提醒一句虚拟环境别提交进 Git.claude.json里的 Key 也别截图发出去。本地跑通只是第一步把工具函数写扎实MCP 才真正帮你干活。
返回列表