☰
手动写一个MCP server:用Python+uv从stdio到SSE的TaoToken配置骨架
2026/9/29 21:21:38 网站建设 项目流程

1. 为什么我要手写一个 MCP server

MCP server 说白了就是一段 Python 程序,它把「工具」「资源」「提示词」这三类能力暴露给大模型客户端,让模型能真正去调函数、读数据,而不是只会在对话框里编。你平时用的 Cherry Studio、Claude Desktop、Cline 这些客户端,背后连的就是一个个 MCP server。理解它最好的方式不是看文档,而是自己从零写一个,跑通 stdio 和 SSE 两种传输模式,再把它接到统一的 API 通道上。

这篇面向的是已经会一点 Python、想搞清楚 MCP 到底怎么跑起来的人。我会用 uv 管环境,用官方mcp[cli]SDK 写一个带加法工具、动态资源、提示词模板的最小 server,然后分别用 stdio 和 SSE 两种方式验证连通性。最后给出 TaoToken 的config.toml和settings.json骨架,让请求走统一 Key 通道转发。全程本地可复现,不需要你去折腾网络环境。

我试过把 stdio 和 SSE 混在一个文件里反复切,最容易踩的坑是端口没释放和客户端配置路径写错,后面排障章节会逐个说。

2. TaoToken 前置:统一 Key 与 API 通道准备

在写 server 之前,先把「请求往哪发」这件事定下来。TaoToken 提供统一的 API 通道,你只需要一个 Key,就能在模型对话、编码、Agent 这些场景里复用同一套接入参数,不用每个客户端单独配一遍。

你需要做两件事:拿到 Key,记住两个地址。

项目地址用途
官网https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=注册、看文档、进控制台
API Basehttps://taotoken.net/api所有请求的统一入口,不加 UTM

Key 在控制台的 API Keys 页面生成,格式一般是一串sk-开头的字符串。生成后先复制到本地一个安全的地方,后面config.toml和settings.json都要用。

注意:Key 只显示一次,页面刷新后就看不到了。建议生成后立刻写进本地配置文件,别只放在聊天窗口里。

如果你后面要长期跑编码类 Agent,可以顺带了解 Coding Plan,它把常用的编码模型额度打包,配合 MCP server 做工具调用会更顺。但这一篇的重点是骨架,先把最小链路跑通。

3. 用 uv 初始化工程并写最小 MCP server

3.1 安装 uv 与 Python 3.13

uv 是目前管 Python 环境最省心的工具,装完它连虚拟环境都不用你手动建。Windows 下用 PowerShell 一行搞定:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

装完确认一下版本和已有的 Python:

uv --version uv python list

然后装目标版本,我选 3.13:

uv python install 3.13

3.2 初始化项目并加依赖

新建文件夹并初始化,-p指定 Python 版本:

mkdir mcp_server cd mcp_server uv init . -p 3.13 uv add "mcp[cli]"

执行完你会看到.venv虚拟环境目录和pyproject.toml。pyproject.toml里记录了项目名、Python 版本和依赖,.venv是隔离环境,两者配合保证换台机器也能复现。

3.3 写 server 主体

把main.py改成下面这样。这段代码定义了一个加法工具、一个动态问候资源、一个提示词模板:

from mcp.server.fastmcp import FastMCP mcp = FastMCP("Demo") @mcp.tool() def add(a: int, b: int) -> int: """Add two numbers""" return a + b @mcp.resource("greeting://{name}") def get_greeting(name: str) -> str: """Get a personalized greeting""" return f"Hello, {name}!" @mcp.prompt() def greet_user(name: str, style: str = "friendly") -> str: """Generate a greeting prompt""" styles = { "friendly": "Please write a warm, friendly greeting", "formal": "Please write a formal, professional greeting", "casual": "Please write a casual, relaxed greeting", } return f"{styles.get(style, styles['friendly'])} for someone named {name}." if __name__ == "__main__": mcp.run(transport='stdio')

三个装饰器的语义要分清:@mcp.tool()相当于 HTTP 里的 POST,模型调它会触发副作用或计算;@mcp.resource()相当于 GET,只读数据,不该改状态;@mcp.prompt()是给模型用的提示词模板,客户端可以把它当快捷指令。理解这三者的区别,后面设计自己的 server 就不会乱。

4. 可复制配置:stdio 与 SSE 两种传输

4.1 stdio 模式配置

stdio 模式下,客户端把 server 当子进程拉起来,通过标准输入输出通信。Cherry Studio 这类客户端里配置 MCP 服务器时,命令和参数这样填:

{ "mcpServers": { "demo-stdio": { "command": "uv", "args": [ "--directory", "D:\\userApplication\\mcp_server", "run", "mcp", "run", "main.py" ] } } }

--directory指向你的工程目录,uv run mcp run main.py是启动命令。客户端会自己拉起这个进程,你不需要手动开终端。

4.2 SSE 模式配置

SSE 模式要把 server 单独跑起来,客户端通过 URL 远程调用。先把main.py最后一行改掉:

mcp.run(transport='sse')

然后手动启动:

uv run mcp run main.py

默认监听http://127.0.0.1:8000,SSE 端点是/sse。客户端里配置成 URL 形式:

{ "mcpServers": { "demo-sse": { "url": "http://127.0.0.1:8000/sse" } } }

4.3 TaoToken 统一通道骨架

如果你希望 server 内部调用模型时走 TaoToken 的统一通道,用config.toml存接入参数:

[taotoken] api_base = "https://taotoken.net/api" api_key = "sk-你的Key" default_model = "你的模型名" [mcp] transport = "stdio"

对应的settings.json给客户端用:

{ "taotoken": { "apiBase": "https://taotoken.net/api", "apiKey": "sk-你的Key" }, "mcp": { "transport": "stdio", "sseUrl": "http://127.0.0.1:8000/sse" } }

提示:api_base不要带 UTM 参数,保持https://taotoken.net/api干净,避免某些客户端拼接路径时出错。

5. 验证请求:stdio 与 SSE 连通性实测

5.1 stdio 验证

在 Cherry Studio 里添加 MCP 服务器,按 4.1 的 JSON 填好命令和参数,保存后客户端会尝试启动进程。启动成功的话,工具列表里会出现add,资源里会出现greeting://{name}。

调用add,传a=3, b=5,返回8就说明 stdio 链路通了。这一步的本质是客户端把 JSON-RPC 请求写进子进程的 stdin,server 处理后把结果写回 stdout。

5.2 SSE 验证

先确认 server 在跑:

uv run mcp run main.py

终端会打印监听地址。然后在客户端里添加 URL 类型的 MCP 服务器,填http://127.0.0.1:8000/sse。添加后同样调add,返回8即成功。

你也可以用 curl 直接探一下 SSE 端点是否活着:

curl -N http://127.0.0.1:8000/sse

-N关闭缓冲,能看到服务端持续推送的事件流就说明 SSE 通道正常。

5.3 两种模式的区别

维度stdioSSE
部署位置客户端本机可单独部署
通信方式标准输入输出HTTP 长连接
距离近,进程级远,网络级
适用场景本地工具、单机远程服务、多客户端共享

stdio 适合本地一次性工具,SSE 适合把 server 放到一台机器上给多个客户端用。选哪个取决于你的 server 要不要被共享。

6. 本篇常见错排查

端口被占用:SSE 模式启动报Address already in use,说明 8000 端口有别的进程。换端口可以在FastMCP初始化时传port参数,或者先netstat -ano | findstr 8000找到进程结束掉。

客户端拉不起 stdio 进程:多半是--directory路径写错,或者uv不在系统 PATH 里。把路径换成绝对路径,并确认终端里uv --version能正常输出。

SSE 连不上:检查 server 是否真的在跑,以及 URL 是不是/sse结尾。有些客户端要求填完整端点,只填http://127.0.0.1:8000会失败。

Key 无效或 401:确认api_key复制完整,没有多余空格。如果走 TaoToken 通道报错,去控制台 API Keys 页面核对 Key 状态,必要时重新生成。

改了 transport 没生效:mcp.run(transport=...)是启动时读的,改完必须重启 server,客户端也要重新连接。

排障时优先看 server 端终端的输出,大部分错误信息会直接打在那里,比客户端日志清楚。

7. 下一步:把骨架接到真实场景

骨架跑通后,你可以按同样的结构加自己的工具。比如加一个读本地文件的工具,或者加一个查数据库的只读资源。工具用@mcp.tool(),只读数据用@mcp.resource(),提示词模板用@mcp.prompt(),三者别混用。

接入参数统一走 TaoToken 的 API 通道,Key 和 Base 只维护一份,换客户端时改settings.json就行。需要生成新 Key 或查看额度,进控制台 API Keys 页面;接入细节看接入文档;想先验证模型对话是否正常,用模型对话页面发一条测试消息;长期跑编码 Agent 的话,Coding Plan 能把额度管得更省心。

把add换成你真正需要的函数,这个 server 就从 demo 变成你自己的工具了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询