尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

从零构建一个 MCP Server:让 Claude 和 ChatGPT 接入你自己的工具(TaoToken 统一 Key 配置版)

发布时间:2026/9/29 2:42:21

资讯中心
01
ARTICLE

从零构建一个 MCP Server:让 Claude 和 ChatGPT 接入你自己的工具(TaoToken 统一 Key 配置版)

从零构建一个 MCP Server:让 Claude 和 ChatGPT 接入你自己的工具(TaoToken 统一 Key 配置版)
1. 为什么我要自己写一个 MCP ServerMCP Server 说白了就是给 AI 装的一双手模型本身只会聊天但通过 MCP 协议它能调用你写的工具去查数据库、读文件、发请求。Claude Desktop、Cursor、Continue 这些客户端都支持 MCP你写一次工具换个客户端照样能用。适合谁适合手里有一堆内部 API、脚本、数据源想让 AI 直接操作它们又不想每个平台单独写一遍 function calling 适配层的人。我之前的做法是给 OpenAI 写一套 tools 定义再给 Anthropic 写一套 tool use参数格式还不一样改一个字段要动两处。MCP 把这件事统一了Server 端只描述一次工具Host 端负责协议转换。本文聚焦 stdio 传输方式因为本地工具用它最省事——不用起端口、不用配证书进程之间通过标准输入输出通信客户端拉起 Server 进程就能用。整篇会交付三样东西一个能跑起来的 Python MCP Server 骨架、Claude Desktop 和 ChatGPT 侧的配置片段、以及本地 stdio 联调验证的完整步骤。同时说明在 TaoToken 统一 Key 的通道下怎么把请求入口和密钥管理收敛到一处避免每个客户端各配一份。2. TaoToken 前置统一 Key 与请求入口自己写 MCP Server 只是第一步真正跑起来还要解决模型侧的调用问题。Claude Desktop 走的是 Anthropic 官方通道ChatGPT 走 OpenAI 通道两边 Key 分开管理额度、账单、限流各看各的工具一多就容易乱。我的做法是把模型请求统一走 TaoToken 的 API 入口一个 Key 覆盖多个模型Server 里需要调用模型做二次处理时也不用再维护多套凭证。具体操作先到官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册账号进控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 创建 API Key。Key 只在创建时完整显示一次复制后存到环境变量里别硬编码进 server.py。export TAOTOKEN_API_KEYsk-你的key请求入口统一用 https://taotoken.net/api这个地址不加任何查询参数直接作为 base_url 使用。模型对话可以在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 页面先试跑确认模型名和返回格式没问题再写进代码。如果你打算长期跑编码类 AgentCoding Plan 页面 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 有对应的套餐说明按用量选就行。注意API Key 属于敏感凭证不要提交到 Git 仓库也不要在 MCP Server 的日志里打印完整 Key。建议用 .env 文件加 python-dotenv 加载。3. 可复制配置Python SDK 搭建 stdio Server3.1 环境准备与依赖安装Python 版本建议 3.10 以上MCP SDK 用官方包。虚拟环境里装避免污染系统 Python。python -m venv mcp-env source mcp-env/bin/activate # Windows 用 mcp-env\Scripts\activate pip install mcp httpx python-dotenvmcp是协议 SDKhttpx用来在工具里发 HTTP 请求python-dotenv读环境变量。装完可以用pip show mcp确认版本SDK 迭代较快遇到 API 变动先看官方仓库的 release note。3.2 Server 骨架工具注册与调用分发下面这个骨架包含两个工具一个查本地文件信息一个调用 TaoToken 的模型接口做文本摘要。工具描述写得具体模型才知道什么时候该调。# server.py import asyncio import os from pathlib import Path import httpx from dotenv import load_dotenv from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent load_dotenv() API_BASE https://taotoken.net/api API_KEY os.environ.get(TAOTOKEN_API_KEY, ) server Server(taotoken-tools) server.list_tools() async def list_tools() - list[Tool]: return [ Tool( namefile_info, description查看本地文件的基本信息包括大小、修改时间和行数。输入必须是绝对路径。, inputSchema{ type: object, properties: { file_path: { type: string, description: 文件的绝对路径例如 /home/user/data.txt, } }, required: [file_path], }, ), Tool( namesummarize_text, description调用模型对一段文本做摘要。适合处理较长的日志、文档片段。, inputSchema{ type: object, properties: { text: {type: string, description: 需要摘要的原始文本}, max_words: { type: integer, description: 摘要的目标字数默认 100, }, }, required: [text], }, ), ] server.call_tool() async def call_tool(name: str, arguments: dict) - list[TextContent]: if name file_info: return await handle_file_info(arguments) if name summarize_text: return await handle_summarize(arguments) raise ValueError(f未知工具: {name}) async def handle_file_info(arguments: dict) - list[TextContent]: path Path(arguments.get(file_path, )) if not path.exists(): return [TextContent(typetext, textf文件不存在: {path})] if not path.is_file(): return [TextContent(typetext, textf路径不是文件: {path})] stat path.stat() try: line_count sum(1 for _ in path.open(r, encodingutf-8, errorsignore)) except Exception: line_count -1 text ( f路径: {path}\n f大小: {stat.st_size} 字节\n f修改时间: {stat.st_mtime}\n f行数: {line_count} ) return [TextContent(typetext, texttext)] async def handle_summarize(arguments: dict) - list[TextContent]: text arguments.get(text, ) max_words arguments.get(max_words, 100) if not API_KEY: return [TextContent(typetext, text错误: 未配置 TAOTOKEN_API_KEY)] if len(text) 8000: text text[:8000] payload { model: claude-3-5-sonnet, messages: [ { role: user, content: f请用不超过 {max_words} 字摘要以下内容:\n\n{text}, } ], } headers { Authorization: fBearer {API_KEY}, Content-Type: application/json, } async with httpx.AsyncClient(timeout30) as client: resp await client.post( f{API_BASE}/v1/messages, jsonpayload, headersheaders ) if resp.status_code ! 200: return [TextContent(typetext, textf模型调用失败: {resp.status_code} {resp.text[:200]})] data resp.json() content data.get(content, []) summary content[0].get(text, ) if content else return [TextContent(typetext, textsummary or 模型返回为空)] async def main(): async with stdio_server() as (read_stream, write_stream): await server.run( read_stream, write_stream, server.create_initialization_options() ) if __name__ __main__: asyncio.run(main())几个关键点list_tools返回的工具描述会被模型逐字读取file_path的 description 里写了绝对路径和示例模型填参数时就不容易给相对路径。call_tool里对未知工具抛异常对业务错误返回 TextContent这样模型能根据错误信息调整而不是整个会话崩掉。3.3 Claude Desktop 配置片段Claude Desktop 的配置文件在 macOS 上是~/Library/Application Support/Claude/claude_desktop_config.jsonWindows 在%APPDATA%\Claude\claude_desktop_config.json。写入以下内容{ mcpServers: { taotoken-tools: { command: /path/to/mcp-env/bin/python, args: [/path/to/server.py], env: { TAOTOKEN_API_KEY: sk-你的key } } } }command要指向虚拟环境里的 python不要用系统 python否则找不到 mcp 包。env里传 KeyServer 进程启动时就能读到。改完配置重启 Claude Desktop在工具列表里应该能看到file_info和summarize_text。3.4 ChatGPT 侧接入说明ChatGPT 桌面端目前对 MCP 的原生支持还在演进稳妥的做法是通过支持 MCP 的客户端如 Cursor、Continue或自建 Host 来连接同一个 Server。如果你用的是支持自定义 MCP 的客户端配置格式和上面类似把 command 和 args 指向同一个 server.py 即可。模型请求侧统一走 TaoToken 的 API 入口Key 用同一个不用为不同客户端分别申请。4. 验证请求与成功结果4.1 本地 stdio 联调不依赖任何客户端先用官方提供的调试工具验证 Server 能正常响应。MCP SDK 自带一个 inspector或者用简单的 stdio 测试脚本npx modelcontextprotocol/inspector python /path/to/server.py启动后浏览器会打开一个调试界面左侧能看到 Server 暴露的工具列表点击file_info填入一个真实文件路径右侧会返回文件信息。这一步能过说明 stdio 通信和工具注册都没问题。4.2 在 Claude Desktop 里实测重启 Claude Desktop 后新建对话输入用 file_info 工具看一下 /etc/hosts 的信息正常情况下 Claude 会请求调用工具返回文件大小、修改时间和行数。再试摘要工具用 summarize_text 把下面这段日志摘要成 50 字粘贴一段日志如果模型返回了摘要内容说明 Server 内部调用 TaoToken API 的链路也通了。实测下来stdio 方式的响应延迟基本在百毫秒级比走 HTTP 的 MCP Server 快不少。4.3 验证模型对话入口在正式写进 Server 之前建议先在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 页面手动发一条请求确认模型名、返回结构和你在代码里解析的字段一致。不同模型的返回格式可能有差异比如 content 数组的结构提前对齐能省掉不少调试时间。5. 本篇常见错排查报错ModuleNotFoundError: No module named mcp原因Claude Desktop 用的 python 不是你装包的那个。检查 config 里的 command 是否指向虚拟环境的 python用绝对路径。工具列表为空Claude 看不到工具原因Server 启动就崩了但客户端没显示错误。手动在终端跑python server.py如果没有任何输出且不退出说明在等 stdio 消息这是正常的如果直接报错按报错修。另外确认 config JSON 格式合法多余逗号会导致整个配置被忽略。模型调用返回 401原因API Key 没传进去或传错。检查 env 里的 Key 是否完整有没有多余空格。Key 只在创建时显示一次如果丢了就重新创建一个。summarize_text返回模型调用失败: 400原因请求体字段和模型不匹配。Anthropic 风格接口用messages加contentOpenAI 风格用messages加content字符串两者结构不同。先确认你调用的模型走哪种格式再调整 payload。文件读取返回乱码或解码错误原因文件不是 UTF-8 编码。代码里用了errorsignore跳过无法解码的字节如果内容重要改成先检测编码再读。stdio 通信卡死原因Server 里用了print()输出调试信息。stdio 传输下标准输出是协议通道任何非协议内容都会污染消息流。调试信息一律写sys.stderr。提示排障时优先看客户端的日志。Claude Desktop 的日志在~/Library/Logs/Claude/下里面有 Server 进程的 stderr 输出比猜快得多。6. 把 Key 和入口收敛到一处Server 写完之后真正影响长期维护成本的是凭证和入口的管理。我的做法是所有需要调用模型的地方base_url 统一写 https://taotoken.net/apiKey 从环境变量读不在代码里出现第二份。这样换模型、调额度、看用量都只在一个控制台里操作不用翻好几个平台的账单页。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 有完整的接口说明和示例遇到字段不确定的时候直接对照。API Key 管理页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 可以创建和吊销 Key建议给不同用途的 Server 分配不同的 Key方便出问题时快速定位和回收。如果你用的是 Claude Code 这类编码 AgentAnthropic 兼容通道的配置在 https://taotoken.net/claudecode-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentClaudeCodeAnthropicutm_campaignrewrite 有说明和本文的 MCP Server 配合使用工具调用和模型请求走同一条通道排查问题时链路更清晰。最后留一个我踩过的坑Server 里的工具描述不要写得太泛比如处理文件这种模型根本判断不出什么时候该调。描述里写清楚输入格式、适用场景、返回什么调用准确率会明显不一样。工具数量也别一次堆太多先跑通两三个确认链路稳定再往上加。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。