尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

用 Python + FastMCP 搭建私有 MCP 服务器,让 ChatGPT 安全接入你的 API 与数据

用 Python + FastMCP 搭建私有 MCP 服务器,让 ChatGPT 安全接入你的 API 与数据 1. 为什么我要把私有 API 塞进 MCP 服务器MCPModel Context Protocol说白了就是给大模型装了一根“数据吸管”模型本身不知道你公司内部的订单表、知识库、监控指标长什么样但通过 MCP 协议它可以按你定义好的工具去调用、去检索再把结果拼进上下文里回答。ChatGPT 桌面端和网页端的 Connector 功能已经支持挂载远程 MCP 服务器这意味着你不需要把数据上传到任何第三方向量库只要服务在你自己的机器或内网跑着模型就能“够得着”。这套方案适合谁三类人最合适一是手里有私有 API比如内部 CRM、工单系统想接进对话的开发者二是本地有一堆 PDF、Markdown 文档想做语义检索的团队三是想给 ChatGPT 加“记忆”和“动作能力”的个人玩家。我这次用 Python FastMCP 从零搭一个工具定义、资源暴露、鉴权通道一次讲清最后用 TaoToken 统一 Key 通道完成端到端验证。FastMCP 是 MCP 官方 Python SDK 之上的一层封装把mcp.tool()装饰器、SSE/stdio 传输、参数校验都简化了。你写一个普通 async 函数加个装饰器它就能被 ChatGPT 识别成可调用工具。下面从环境准备开始每一步都能直接复制。2. TaoToken 前置统一 Key 与 API 通道在写代码之前先把“模型侧”的通道理清楚。ChatGPT 要调用你的 MCP 服务器中间涉及两类请求一类是 ChatGPT 平台去连你的 MCP 地址走 SSE/HTTP另一类是你的 MCP 服务器内部去调模型或向量检索 API。后者如果每个工具都硬编码不同厂商的 Key维护起来很痛苦。我的做法是MCP 服务器内部所有对外 API 调用统一走 TaoToken 的 API 通道Key 只存一份环境变量。TaoToken 提供兼容 OpenAI 风格的接口base_url 填https://taotoken.net/api模型名按需选。这样你的search、fetch工具内部调 embedding 或对话补全时不用改代码就能换模型。先去控制台拿 Keyhttps://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。创建后复制 sk- 开头的字符串后面写进.env。如果你还没决定用哪个模型可以先去模型对话页试一下https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 确认模型可用再写进配置。注意Key 只放服务端环境变量绝对不要写进前端代码或提交到 Git。MCP 服务器如果暴露在公网必须加鉴权头否则任何人拿到地址就能调你的工具。3. 可复制配置FastMCP 服务端骨架 config.toml3.1 环境与依赖Python 3.10 以上建议用虚拟环境。依赖只有两个核心包python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install fastmcp openai python-dotenvfastmcp负责协议层openai用来调 TaoToken 的兼容接口python-dotenv读环境变量。3.2 项目结构mcp-server/ ├── server.py ├── config.toml ├── .env └── data/ └── docs.jsondata/docs.json放你的本地数据格式随意下面示例用列表套字典。3.3 config.toml 配置示例[server] name private-mcp host 0.0.0.0 port 8000 transport sse [taotoken] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY default_model gpt-4o-mini [auth] # 简单 Bearer 鉴权ChatGPT 连接时带上 enabled true token_env MCP_AUTH_TOKEN [data] docs_path data/docs.json3.4 server.py 核心代码import os import json import tomllib from typing import Any from dotenv import load_dotenv from fastmcp import FastMCP from openai import OpenAI load_dotenv() with open(config.toml, rb) as f: cfg tomllib.load(f) client OpenAI( api_keyos.environ[cfg[taotoken][api_key_env]], base_urlcfg[taotoken][base_url], ) with open(cfg[data][docs_path], r, encodingutf-8) as f: DOCS json.load(f) mcp FastMCP( namecfg[server][name], instructions提供本地文档检索与全文获取能力支持关键词搜索和按 ID 取全文。, ) mcp.tool() async def search(query: str, top_k: int 3) - dict[str, Any]: 根据关键词在本地文档中检索返回摘要片段列表。 if not query.strip(): return {results: []} scored [] for doc in DOCS: text doc.get(text, ) score text.lower().count(query.lower()) if score 0: scored.append((score, doc)) scored.sort(keylambda x: x[0], reverseTrue) results [] for _, doc in scored[:top_k]: results.append({ id: doc[id], title: doc.get(title, doc[id]), snippet: doc[text][:200] ..., }) return {results: results} mcp.tool() async def fetch(id: str) - dict[str, Any]: 根据文档 ID 返回完整内容。 for doc in DOCS: if doc[id] id: return { id: id, title: doc.get(title, id), text: doc[text], metadata: doc.get(metadata, {}), } return {error: fdocument {id} not found} mcp.resource(docs://list) def list_docs() - str: 列出所有可用文档的 ID 与标题。 return json.dumps( [{id: d[id], title: d.get(title, d[id])} for d in DOCS], ensure_asciiFalse, ) if __name__ __main__: mcp.run( transportcfg[server][transport], hostcfg[server][host], portcfg[server][port], )这段代码里search和fetch是两个工具docs://list是一个资源。ChatGPT 连接后会自动读取工具描述决定什么时候调哪个。top_k参数带默认值模型可以自己决定返回几条。3.5 .env 文件TAOTOKEN_API_KEYsk-你的key MCP_AUTH_TOKEN一个随机长字符串MCP_AUTH_TOKEN用openssl rand -hex 32生成后面 ChatGPT 连接时作为 Bearer Token 带上。4. 验证请求从本地 curl 到 ChatGPT 连通4.1 启动服务python server.py看到Uvicorn running on http://0.0.0.0:8000就说明 SSE 传输起来了。MCP 的 SSE 端点在/sse/消息回传在/messages/。4.2 本地 curl 验证工具列表先用 curl 确认服务活着再谈 ChatGPT 接入curl -N http://localhost:8000/sse/ \ -H Authorization: Bearer 你的MCP_AUTH_TOKEN正常会返回一串event: endpoint和data: /messages/?session_id...。这说明 SSE 通道建立成功。如果返回 401检查MCP_AUTH_TOKEN是否一致如果连接被拒检查端口和防火墙。4.3 用 MCP Inspector 做一次工具调用FastMCP 自带调试入口开发阶段强烈建议先用它验证工具逻辑再挂到 ChatGPTfastmcp dev server.py浏览器打开提示的地址在 Tools 面板里选search输入query订单点 Run。右侧会返回 JSON 结果。这一步能跑通说明工具定义和参数校验都没问题。4.4 ChatGPT 侧接入ChatGPT 桌面端或网页端进入设置找到 Connectors添加自定义 MCP 服务器地址填你的公网地址加/sse/例如https://your-domain.com/sse/鉴权方式选 Bearer填入MCP_AUTH_TOKEN。保存后 ChatGPT 会拉取工具列表你应该能看到search和fetch。然后开一个新对话问一句“帮我搜一下订单相关的文档”观察 ChatGPT 是否触发search工具。成功的话回答里会引用你本地docs.json里的内容。这一步就是端到端连通性验证的终点。提示本地开发时公网地址可以用内网穿透工具临时映射但生产环境请用正规 HTTPS 域名并开启 OAuth 或至少 Bearer 鉴权。5. 本篇常见错排查报错一ModuleNotFoundError: No module named fastmcp虚拟环境没激活或者 pip 装到了全局。确认which python指向 venv 目录再重装一次。报错二SSE 连接后 ChatGPT 提示no tools found多半是工具函数没有正确加mcp.tool()装饰器或者函数签名里有不支持的类型。FastMCP 要求参数和返回值都是 JSON 可序列化的基础类型别返回自定义对象。报错三401 Unauthorized但 Token 明明是对的检查 ChatGPT 连接配置里 Bearer 后面有没有多余空格以及服务端读取的环境变量名是否和 config.toml 里token_env一致。我踩过的坑是.env里写了引号导致 Token 带上了引号字符。报错四工具调用超时search里如果做了同步阻塞的 IO比如读大文件、调慢 API会卡住整个事件循环。所有工具函数都用async def内部阻塞操作丢到run_in_executor或换成异步客户端。报错五TaoToken 返回model not found模型名写错了。去模型对话页确认可用模型名再填进 config.toml 的default_model。base_url 必须是https://taotoken.net/api不要多加/v1后缀OpenAI SDK 会自己拼。报错六本地 curl 通ChatGPT 连不上九成是公网地址问题。ChatGPT 的服务器在境外你的地址必须能被公网访问且证书有效。自签名证书会被拒。另外确认/sse/末尾的斜杠不能省。6. 把 Key 管好把工具做小跑通之后下一步不是加更多工具而是把鉴权和日志补上。MCP 服务器一旦暴露工具就是模型的“手”fetch能读什么、search能搜什么边界要卡死。我的习惯是每个工具内部再做一次权限判断比如根据请求头里的用户标识过滤文档范围而不是把所有数据一股脑返回。Key 管理上TaoToken 的 API Key 和 MCP 的鉴权 Token 分开存前者管模型调用后者管接入认证。需要长期跑编码类 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 API Key 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。Claude Code 相关接入参考 https://taotoken.net/claude-code?utm_sourcetaotoken_aicg_blog_endutm_contentclaude-codeutm_campaignrewrite 。最后留一个实用技巧在search工具里加一行logger.info记录 query 和命中数跑一周你就能看出模型最爱问什么反过来优化你的文档结构。这比盲目堆工具有用得多。
返回列表