ARTICLE DETAIL

资讯详情

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

Python 实现一个本地 MCP 工具服务器:把 endpoint 改到 TaoToken 的完整配置

Python 实现一个本地 MCP 工具服务器:把 endpoint 改到 TaoToken 的完整配置 1. 为什么本地 MCP 工具服务器总卡在鉴权这一步很多人第一次写 MCP Server代码跑起来挺顺npx modelcontextprotocol/inspector里五个工具都能点但一旦把 Server 接到真实客户端、或者让 Server 内部再去调用大模型做二次处理问题就来了Key 到底放哪、每个工具是不是都要单独配一遍、换一个客户端是不是又得重来。我试过最原始的做法把 Key 硬编码在mcp_local_toolbox.py顶部结果就是每加一个工具函数就要复制一遍os.getenv(OPENAI_API_KEY)之类的读取逻辑换到另一个项目又得把整段配置搬过去。更麻烦的是当你的 MCP Server 需要同时对接多个模型通道时endpoint、Key、Model ID 三件套散落在不同文件里改一个地方要全局搜索。MCP 本身解决的是「工具怎么被 AI 客户端发现和调用」它并不管你 Server 内部用什么模型通道。所以真正落地时你会遇到一个很具体的工程问题本地 MCP 工具服务器内部的模型请求endpoint 应该统一指向哪里。如果每个工具各自维护一套鉴权代码会迅速变成一坨。这篇要做的就是用 Python 从零搭一个本地 MCP 工具服务器然后把服务端所有模型请求的 endpoint 统一改到 TaoToken 的 API 通道用一套 Base URL Key Model ID 覆盖全部工具调用。适合正在做本地开发、自动化脚本、或者想把 MCP Server 接进自己工作流的同学。读完你能拿到一份可复制的 server 配置片段、环境变量写法以及一次完整的连通性验证动作。核心检索词先摆出来Python 实现本地 MCP 工具服务器、endpoint 统一配置、TaoToken API 通道、多工具 Key 分散问题。这几个词会贯穿全文你按这个思路往下看就行。2. TaoToken 前置准备把 endpoint 和 Key 收拢到一处在动手改代码之前先把「通道」这件事想清楚。MCP Server 内部如果要调用模型本质上就是发一个 HTTP 请求到某个 endpoint。传统写法是每个工具函数里写死https://api.xxx.com/v1/chat/completionsKey 从环境变量读。问题在于工具一多endpoint 就散开了。TaoToken 在这里扮演的角色是统一的 API 通道。你不需要在每个工具里判断「这个工具用哪个 Key」而是把所有模型请求都指向同一个 Base URLKey 也只维护一份。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 注意 API 地址不带 UTM 参数配置时直接用这个。具体要准备三样东西我把它叫「三件套」配置项作用示例值Base URL所有模型请求的统一入口https://taotoken.net/apiAPI Key鉴权凭证只维护一份在控制台生成Model ID指定调用的模型按需选择这三件套的获取路径先到官网注册然后进控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 创建 API KeyKey 的生成入口在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。如果你对模型能力还不确定可以先去模型对话 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 里试一下确认通道通了再写进代码。这里有个关键认知MCP Server 的 endpoint 统一指的是 Server 内部发起模型请求时用的地址统一而不是 MCP 协议本身的通信地址。MCP 协议走的是 stdio 或 SSE那是客户端和 Server 之间的事Server 内部再去调模型走的是 HTTP那才是我们要改到 TaoToken 的部分。很多人把这两个概念混在一起配置就乱了。环境变量建议这样组织放在项目根目录的.env里或者直接在启动脚本里 export# .env 示例不要提交到 git TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_API_KEYsk-你的key TAOTOKEN_MODEL_ID你的模型ID MCP_WORKSPACE/Users/you/projects/mcp_local_toolbox为什么用环境变量而不是写死在代码里因为 MCP Server 可能被不同客户端以不同工作目录启动环境变量是最容易在客户端配置里覆盖的一层。你在客户端 JSON 里写envServer 启动时就能读到不用改一行代码。如果你打算长期跑编码类任务或者 Agent 工作流可以考虑 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 它更适合高频调用的场景。但本文的重点是本地 MCP Server 的 endpoint 统一先把基础通道跑通。3. 可复制配置把 endpoint 写进 MCP Server 的 settings这一节是全文最核心的部分直接给可复制的配置片段。我按「Python 代码里的读取逻辑」和「客户端启动配置」两层来写你照着改就行。先看 Python 侧。在mcp_local_toolbox.py顶部加一段统一的配置读取所有工具函数都从这里拿 endpoint 和 Keyimport os from pathlib import Path # 统一通道配置所有模型请求都走这里 TAOTOKEN_BASE_URL os.getenv(TAOTOKEN_BASE_URL, https://taotoken.net/api) TAOTOKEN_API_KEY os.getenv(TAOTOKEN_API_KEY, ) TAOTOKEN_MODEL_ID os.getenv(TAOTOKEN_MODEL_ID, ) # 工作区边界 BASE_DIR Path(os.getenv(MCP_WORKSPACE, Path.cwd())).resolve() def build_model_headers() - dict: 所有工具共用一套鉴权头避免 Key 分散。 if not TAOTOKEN_API_KEY: raise RuntimeError(TAOTOKEN_API_KEY 未设置请检查环境变量) return { Authorization: fBearer {TAOTOKEN_API_KEY}, Content-Type: application/json, } def build_chat_payload(messages: list, **kwargs) - dict: 统一构造请求体endpoint 和 model 都从这里出。 payload { model: TAOTOKEN_MODEL_ID, messages: messages, } payload.update(kwargs) return payload这段代码的价值在于endpoint 只出现一次Key 只读一次Model ID 只配一次。后面无论你加多少个工具都调build_model_headers()和build_chat_payload()不会出现「这个工具用 A Key、那个工具用 B Key」的情况。接下来是客户端侧的启动配置。不同 MCP 客户端格式略有差异但核心字段一致。以常见的mcpServers结构为例把环境变量塞进env{ mcpServers: { local-toolbox: { command: python, args: [ /Users/you/projects/mcp_local_toolbox/mcp_local_toolbox.py ], env: { MCP_WORKSPACE: /Users/you/projects/mcp_local_toolbox, TAOTOKEN_BASE_URL: https://taotoken.net/api, TAOTOKEN_API_KEY: sk-你的key, TAOTOKEN_MODEL_ID: 你的模型ID } } } }如果你用的是 Claude Code 这类工具配置会落在settings.json或对应的 MCP 配置段里字段名可能是mcpServers或servers但command、args、env这三个是通用的。Claude Code 的接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有更细的字段说明。如果你用的是 Codex 系工具配置可能落在auth.json或类似的凭证文件里这时候三件套要写全Base URL 填https://taotoken.net/apiKey 填你的 API KeyModel ID 填你要用的模型。缺任何一个都会在请求时报错。再补一个 TOML 版本的配置方便用pyproject.toml管理项目的同学# pyproject.toml 片段 [tool.mcp.local-toolbox] command python args [mcp_local_toolbox.py] [tool.mcp.local-toolbox.env] MCP_WORKSPACE /Users/you/projects/mcp_local_toolbox TAOTOKEN_BASE_URL https://taotoken.net/api TAOTOKEN_API_KEY sk-你的key TAOTOKEN_MODEL_ID 你的模型ID配置写完后有一个容易踩的坑路径分隔符。Windows 下 JSON 里要用正斜杠/或者双反斜杠\\单反斜杠会被转义。我见过有人写C:\Users\...导致 JSON 解析失败排查半天。还有一点MCP_WORKSPACE和TAOTOKEN_BASE_URL是两个独立的东西前者限定工具能读哪些文件后者决定模型请求发到哪。不要因为都叫「配置」就混在一起。4. 验证请求一次完整的连通性检查配置写完不能直接信得验证。验证分两步先确认 MCP Server 本身能启动、工具能列出再确认 Server 内部的模型请求能打到 TaoToken 通道。第一步启动 Server 并用 Inspector 看工具列表cd /Users/you/projects/mcp_local_toolbox python mcp_local_toolbox.pystdio 模式下没有输出是正常的它在等客户端。换 Inspectornpx modelcontextprotocol/inspector python mcp_local_toolbox.py打开页面后在 Tools 里应该能看到你注册的工具比如workspace_info、list_files、search_text、csv_profile、csv_group_sum。点workspace_info传空对象{}预期返回类似{ workspace: /Users/you/projects/mcp_local_toolbox, file_count: 12, ignored_dirs: [.git, .venv, __pycache__, node_modules] }这一步证明 MCP 协议层通了。第二步验证模型通道。写一个最小的验证脚本verify_channel.py直接调 TaoToken 的 API确认三件套有效import os import json import urllib.request BASE_URL os.getenv(TAOTOKEN_BASE_URL, https://taotoken.net/api) API_KEY os.getenv(TAOTOKEN_API_KEY, ) MODEL_ID os.getenv(TAOTOKEN_MODEL_ID, ) def verify(): url f{BASE_URL}/v1/chat/completions payload { model: MODEL_ID, messages: [ {role: user, content: 只回复两个字通了} ], } req urllib.request.Request( url, datajson.dumps(payload).encode(utf-8), headers{ Authorization: fBearer {API_KEY}, Content-Type: application/json, }, methodPOST, ) with urllib.request.urlopen(req, timeout30) as resp: body json.loads(resp.read().decode(utf-8)) print(status:, resp.status) print(content:, body[choices][0][message][content]) if __name__ __main__: verify()运行export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_MODEL_ID你的模型ID python verify_channel.py预期输出status: 200 content: 通了看到status: 200和模型返回内容说明 endpoint、Key、Model ID 三件套都对。这时候你再回到 MCP Server把工具函数里需要调模型的地方接上build_model_headers()和build_chat_payload()整条链路就通了。如果你想更直观地确认模型能力可以到模型对话 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 里手动发一条消息对比一下返回是否一致。这一步不是必须的但对排查「是通道问题还是代码问题」很有帮助。验证通过后建议把verify_channel.py留在项目里每次改配置后跑一遍比直接上客户端调试快得多。5. 本篇常见错排查401、local proxy failed、reading choices配置和验证过程中报错基本集中在几个固定位置。我把真实遇到过的错误和对应处理列出来你对照着看。错误一401 Unauthorized{error: {message: Invalid API key, type: invalid_request_error}}原因通常是 Key 没读到、Key 写错、或者Authorization头格式不对。检查顺序先确认环境变量真的注入了在 Python 里print(os.getenv(TAOTOKEN_API_KEY))看是不是空再确认头是Bearer sk-xxx中间有一个空格最后确认 Key 没有多余换行。如果你是在客户端 JSON 里配的注意 JSON 字符串里不能有真实换行。错误二local proxy failed / connection refusedError: local proxy failed to connect这个报错通常出现在客户端启动 MCP Server 时command或args路径不对导致进程根本没起来。检查args里的 Python 脚本路径是不是绝对路径、文件是否存在。Windows 下路径用正斜杠。还有一种情况是虚拟环境没激活python指向了系统 Python缺依赖。建议command直接写虚拟环境里的 python 绝对路径比如/Users/you/projects/mcp_local_toolbox/.venv/bin/python。错误三reading choices of undefinedTypeError: Cannot read properties of undefined (reading choices)这个报错说明请求发出去了但返回体结构不对代码里取body[choices]时body是 undefined 或者没有choices字段。常见原因endpoint 拼错了比如多加了/v1或少加了/v1或者返回的是错误对象而不是正常响应。处理办法是在取choices之前先打印完整返回体print(json.dumps(body, ensure_asciiFalse, indent2))看清楚返回的到底是什么再决定改 endpoint 还是改解析逻辑。TaoToken 的 API 入口是https://taotoken.net/apichat completions 路径是/v1/chat/completions拼的时候注意。错误四OAuth 相关报错OAuth error: invalid_client如果你用的是 Claude Code 或类似工具配置里可能混了 OAuth 流程和 API Key 流程。用 API Key 接入时不需要走 OAuth把auth.json或settings.json里的 OAuth 字段清掉只保留 Base URL、Key、Model ID 三件套。Claude Code 的接入方式在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里有说明按文档走 API Key 模式即可。错误五MCP Server 启动后客户端看不到工具不是报错但很常见。原因通常是 Server 启动失败但被客户端静默吞掉了。解决办法是先在终端手动跑一遍python mcp_local_toolbox.py看有没有异常。另外确认mcp.tool()装饰器下的函数签名和 docstring 完整FastMCP 靠类型注解生成 schema注解缺失会导致工具注册失败。排查的核心思路就一条先分层再定位。MCP 协议层的问题工具看不到、进程起不来和模型通道层的问题401、choices 报错是两回事分开验证不要混在一起猜。6. 把 endpoint 统一之后本地 MCP 还能怎么扩展走到这里你已经有了一个能跑通的本地 MCP 工具服务器endpoint 统一指向 TaoToken 的 API 通道Key 只维护一份。接下来可以按自己的场景往下加。一个自然的扩展是给工具加「模型二次处理」能力。比如search_text搜到一堆命中行之后让模型帮你总结这些命中说明了什么或者csv_profile分析完字段后让模型给一段数据质量评价。这些都不需要新的 Key直接复用build_model_headers()和build_chat_payload()就行。这就是 endpoint 统一带来的好处加功能不用加配置。另一个方向是把本地工具服务器接到更长的编码工作流里。如果你经常让 AI 帮你读项目、搜代码、分析数据可以考虑 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 它更适合这种持续调用的场景。但无论用哪种方式三件套的配置逻辑是一样的。安全边界这块再强调一次。本文的 Server 只提供读取和分析工具没有删除、写入、执行命令的能力。你扩展的时候也建议保持这个原则先只读再考虑写入先限定目录再扩展范围。MCP_WORKSPACE不要设成整个磁盘根目录resolve_safe_path里的路径校验不要删。最后留一个实用技巧把verify_channel.py和 MCP Server 的启动脚本写进一个Makefile或者 shell 脚本每次改完配置先跑验证再启动 Server。这样能省掉大量「改了配置不知道哪层出问题」的时间。#!/bin/bash # check.sh set -e export $(grep -v ^# .env | xargs) python verify_channel.py npx modelcontextprotocol/inspector python mcp_local_toolbox.py配置这件事统一比聪明重要。endpoint 收拢到一处Key 只留一份后面加多少工具都不会乱。
返回列表