从零构建一个 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 里的工具描述不要写得太泛比如处理文件这种模型根本判断不出什么时候该调。描述里写清楚输入格式、适用场景、返回什么调用准确率会明显不一样。工具数量也别一次堆太多先跑通两三个确认链路稳定再往上加。

相关新闻

MCP化实践:从特征提炼到封装,用TaoToken统一Key打通JSON-RPC与stdio

MCP化实践:从特征提炼到封装,用TaoToken统一Key打通JSON-RPC与stdio

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/29 2:42:25 阅读更多 →
OpenClaw部署与飞书对接:从Docker启动到会话锁报错排查

OpenClaw部署与飞书对接:从Docker启动到会话锁报错排查

1. OpenClaw 能做什么:部署前先搞清楚它的定位先讲一个这周刚发生的场景。朋友公司想给内部团队配一个能拉进飞书群、随手一下就能查资料、记待办、做简单问答的 AI 助理,结果他搜了一晚上教程,看到的要么是讲半天的概念文,要么是…

2026/9/29 2:42:25 阅读更多 →
TypeScript 3.8 新特性全解析:类型导入、私有字段、顶层 await 与增量检查

TypeScript 3.8 新特性全解析:类型导入、私有字段、顶层 await 与增量检查

文档教程 【免费下载链接】TypeScript TypeScript 使用手册(中文版)翻译。http://www.typescriptlang.org 项目地址: https://gitcode.com/gh_mirrors/typ/TypeScript 点击查看 免费下载 导读 本文基于 TypeScript 使用手册(中文…

2026/9/29 2:41:24 阅读更多 →

最新新闻

MAS 激活:一条命令三分钟免费激活 Windows 和 Office

MAS 激活:一条命令三分钟免费激活 Windows 和 Office

MAS 激活:一条命令三分钟免费激活 Windows 和 Office 【免费下载链接】Microsoft-Activation-Scripts Open-source Windows and Office activator featuring HWID, Ohook, TSforge, and Online KMS activation methods, along with advanced troubleshooting. 项目…

2026/9/30 6:54:06 阅读更多 →
用 jobindex-cli 在丹麦 Jobindex.dk 上检索职位:一条命令完成搜索、详情抓取与 JSON 结构化输出

用 jobindex-cli 在丹麦 Jobindex.dk 上检索职位:一条命令完成搜索、详情抓取与 JSON 结构化输出

AI 应用AI 技能 【免费下载链接】ai-job-search The job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it. 项目地址: https://…

2026/9/30 6:54:06 阅读更多 →
ai-job-search 岗位评估框架实战指南:五维评分、硬性门槛与公司研究缓存机制

ai-job-search 岗位评估框架实战指南:五维评分、硬性门槛与公司研究缓存机制

AI 应用AI 技能 【免费下载链接】ai-job-search The job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it. 项目地址: https://…

2026/9/30 6:54:06 阅读更多 →
java-design-patterns 中的 Fluent Interface(流式接口)模式:用方法链构建可读、可维护的 Java API

java-design-patterns 中的 Fluent Interface(流式接口)模式:用方法链构建可读、可维护的 Java API

示例工程教程 【免费下载链接】java-design-patterns Design patterns implemented in Java 项目地址: https://gitcode.com/GitHub_Trending/ja/java-design-patterns 点击查看 免费下载 导读 本文以 java-design-patterns 仓库中的 fluent-interface 模块为依托…

2026/9/30 6:54:06 阅读更多 →
PhotoPrism 仓库提交规范实战指南:Commit 消息、GitHub Issue 与文档风格全解析

PhotoPrism 仓库提交规范实战指南:Commit 消息、GitHub Issue 与文档风格全解析

后端前端图像处理人工智能AI 应用 【免费下载链接】photoprism AI-Powered Photos App 🌈💎✨ 项目地址: https://gitcode.com/gh_mirrors/ph/photoprism 点击查看 免费下载 导读 本文以 PhotoPrism 仓库的 .claude/rules/commit-and-docs-…

2026/9/30 6:54:06 阅读更多 →
AI Agent 面试题 203:如何设计Agent的LLM调用链路追踪?

AI Agent 面试题 203:如何设计Agent的LLM调用链路追踪?

🔥 AI Agent 面试题 203:如何设计Agent的LLM调用链路追踪?摘要:本文深入解析了「如何设计Agent的LLM调用链路追踪?」这一 AI Agent 领域的核心面试题。文章从 多模型协同 的基本概念出发,系统性地剖析了 链…

2026/9/30 6:53:05 阅读更多 →

日新闻

Base64 图片头部特征识别:从文件头到格式判断的完整指南

Base64 图片头部特征识别:从文件头到格式判断的完整指南

1. 项目概述:为什么说看懂 base64 图片头部是基本功这几年跟 base64 打交道的机会越来越多,后端接口返回图片、前端渲染验证码、小程序里存小图、还有一些老系统导出报表,动不动就给你一段长到怀疑人生的 base64 字符串。很多人拿到字符串就直…

2026/9/30 0:00:35 阅读更多 →
Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

简介:本资源是一份面向Java初学者与课程设计学生的公交站牌广告灯箱管理系统毕业设计文档,聚焦城市公共广告资源信息化管理痛点,提供从需求分析到技术实现的完整方案。文档采用标准学术论文结构,含摘要、英文摘要、目录及五章正文…

2026/9/30 0:00:35 阅读更多 →
用 Redis Lua 构建大模型 API 多租户原子配额治理体系

用 Redis Lua 构建大模型 API 多租户原子配额治理体系

我去年年底接了一个内部 AI 平台的治理需求,背景很直接:公司把 DeepSeek、MiniMax 这类大模型 API 统一封装成内部网关,开放给几个业务团队用。结果第一个月账单出来,额度直接超了 4 倍。仔细查日志,发现原因并不复杂—…

2026/9/30 0:00:35 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/29 8:16:59 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/29 16:41:41 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/29 8:24:48 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/29 19:29:29 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/29 5:58:00 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/29 3:55:56 阅读更多 →