MCP 快速入门:从 stdio 命令到 Agent 可调用工具
2026/9/23 23:54:06 网站建设 项目流程

简介:这是一份面向大模型应用开发者与Agent方向学习者的MCP入门实战资料,围绕Model Context Protocol这一由Anthropic提出的智能体工具调用协议展开,帮助读者跨越Function calling门槛过高、外部函数重复开发的痛点,从零搭建可运行的MCP客户端与服务器。内容覆盖MCP技术体系与Agent开发脉络回顾、uv依赖管理工具使用、极简客户端搭建、接入OpenAI与DeepSeek在线模型及本地ollama、vLLM模型,以及天气查询服务器的完整创建与Inspector调试,并延伸至客户端与服务器的进阶功能。资源为1个PDF文件,压缩包约47.66MB,适合按章节顺序阅读并同步动手实践。目前已有1124人学习下载,可作为理解MCP通讯机制、掌握客户端与服务器协作流程的参考材料。

1. MCP 快速入门:从一条 stdio 命令到能被 Agent 调用的工具

很多人第一次接触 MCP,是在某个 AI 编辑器里看到「添加 MCP Server」的按钮,点进去填了个命令,然后就没有然后了。真正卡住的地方从来不是概念,而是:我写的这个 Server,怎么让 Agent 稳定地发现、调用、拿到结构化结果?MCP(Model Context Protocol)解决的正是这件事——它把「模型能调用的能力」抽象成一套标准协议,Server 暴露 tools、resources、prompts,Client(也就是 Agent 宿主)负责握手、列能力、转发调用。你不需要改模型,只需要按协议把工具挂上去。

这篇面向想动手的人:会用 Python 写函数、装过 uv、知道 Agent 大概是什么。目标是从零跑通一个本地 stdio Server,再用一个最小 Client 调通它,最后讲清楚参数、传输方式和排错。全程不依赖任何云端账号,本地就能复现。

2. MCP 协议核心概念与 uv 环境准备

2.1 MCP 的三种原语:tool、resource、prompt 到底怎么选

MCP 把 Server 能提供的东西分成三类,选错了后面调用会很别扭。

  • tool:有副作用、需要参数、返回执行结果。比如查数据库、发请求、写文件。Agent 会把它当成「函数」来调。
  • resource:只读数据,用 URI 标识,比如file:///logs/app.log。适合把上下文喂给模型,而不是让模型去执行。
  • prompt:预置的提示模板,Server 提供、Client 选用,常用于把复杂任务固化成可复用入口。

判断标准很简单:要执行动作选 tool,要读数据选 resource,要复用一段提示词选 prompt。新手最容易把所有东西都塞成 tool,结果模型面对一堆「读文件」工具反复试错。

2.2 用 uv 装 Python 环境,避开依赖地狱

MCP 官方 Python SDK 迭代快,用 uv 管理最省心。uv 是 Rust 写的包与环境管理器,装依赖比 pip 快一个量级,还能直接锁定 Python 版本。

# 安装 uv(Linux/macOS) curl -LsSf https://astral.sh/uv/install.sh | sh # Ubuntu 上如果 curl 装完找不到命令,重开 shell 或 source 一下 source $HOME/.local/bin/env # 初始化项目,指定 Python 版本 uv init mcp-demo cd mcp-demo uv python pin 3.11 # 添加 MCP SDK uv add "mcp[cli]"

逻辑说明:uv init生成pyproject.tomluv python pin把解释器版本写进.python-version,避免团队里有人用 3.8 跑不起来。uv add "mcp[cli]"会同时装 SDK 和命令行工具mcp,后面调试要用。

参数说明:mcp[cli]里的方括号是 extras 语法,只装核心 SDK 不带 CLI 的话,mcp dev这类命令会缺失。国内网络慢可以设UV_INDEX_URL指向镜像,但别写死在项目文件里,用环境变量更干净。

提示:如果机器完全离线,先在能联网的机器上uv pip download或直接拷贝 uv 缓存目录,再在目标机uv sync --offline。别用系统 pip 混装,版本冲突排查成本很高。

2.3 传输方式选型:stdio 还是 HTTP

传输方式适用场景启动方式注意点
stdio本地工具、编辑器集成Client 拉起子进程日志绝不能写 stdout
Streamable HTTP远程共享、多 ClientServer 常驻监听需要处理会话与鉴权
SSE(旧)兼容老 ClientHTTP 长连接新项目不建议再用

本地开发一律先上 stdio,因为它最简单:Client 用命令启动 Server,两者通过标准输入输出交换 JSON-RPC 消息。代价是任何print()都会污染协议流,导致 Client 解析失败。调试信息一律走stderr或 logging。

3. 写一个最小 MCP Server 并本地跑通

3.1 用 FastMCP 定义第一个 tool

官方 SDK 提供FastMCP装饰器风格,几行就能起一个 Server。

# server.py from mcp.server.fastmcp import FastMCP mcp = FastMCP("demo-server") @mcp.tool() def add(a: int, b: int) -> int: """两数相加。a 和 b 必须是整数。""" return a + b @mcp.tool() def word_count(text: str) -> dict: """统计文本的字符数和词数。""" return {"chars": len(text), "words": len(text.split())} if __name__ == "__main__": mcp.run(transport="stdio")

逻辑说明:@mcp.tool()把普通函数注册成 MCP tool,函数签名和类型注解会被自动转成 JSON Schema,Agent 靠这个 Schema 决定怎么传参。docstring 不是装饰,它会作为工具描述发给模型——写清楚「参数是什么、返回什么」,模型调用准确率会明显提升。

参数说明:FastMCP("demo-server")里的名字是 Server 标识,Client 侧会看到。mcp.run(transport="stdio")指定传输方式,本地调试就用它。返回类型建议用dict或基础类型,别返回自定义对象,序列化会出问题。

3.2 用 mcp dev 做交互式调试

写完别急着接 Agent,先用官方调试器验证工具本身没问题。

# 启动调试界面 uv run mcp dev server.py

它会起一个本地 Inspector,你能看到 Server 暴露了哪些 tool、每个 tool 的 Schema、手动填参数调用看返回。这一步能挡掉 80% 的低级错误:类型写错、docstring 缺失、返回值不可序列化。

注意:如果 Inspector 里工具列表是空的,先检查函数有没有被@mcp.tool()装饰,再看有没有在if __name__ == "__main__"之前定义。装饰器必须在模块加载时就执行到。

3.3 常见启动报错与定位方法

现象大概率原因处理
Client 连不上,无输出Server 往 stdout 打了日志改用 stderr / logging
工具列表为空装饰器没生效或导入失败单独uv run python server.py看报错
调用返回 schema 错误类型注解缺失或用了复杂类型补注解,返回基础类型
进程秒退依赖没装进当前环境uv sync后重试

定位核心思路:把 Server 当普通进程先跑起来uv run python server.py能正常阻塞等待输入,说明进程没问题,问题在协议层;如果直接报错,就是代码或依赖问题。

4. 用 Client 调通 Server:从握手到工具调用

4.1 最小 Client 的完整调用链

Client 的职责是:启动 Server 子进程 → 初始化握手 → 列出工具 → 调用工具。下面是一个能直接跑的版本。

# client.py import asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client async def main(): params = StdioServerParameters( command="uv", args=["run", "python", "server.py"], ) async with stdio_client(params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() # 握手 tools = await session.list_tools() # 列能力 print("tools:", [t.name for t in tools.tools]) result = await session.call_tool( "add", {"a": 3, "b": 5} ) print("result:", result.content) asyncio.run(main())

逻辑说明:StdioServerParameters描述怎么拉起 Server,stdio_client建立管道,ClientSession封装 JSON-RPC 会话。initialize()是必须的握手步骤,跳过它后续调用会失败。list_tools()返回工具元数据,call_tool()按名字和参数字典调用。

参数说明:commandargs要能被系统直接执行,uv run python server.py是最稳的写法,因为它会自动用项目环境。call_tool的第二个参数是 dict,键必须和 Schema 里的参数名一致,类型也要对,传字符串给 int 参数会被拒。

4.2 把 Server 接进 Agent 宿主的配置写法

大多数支持 MCP 的编辑器或 Agent 框架,配置本质就是上面那段StdioServerParameters的 JSON 化。

{ "mcpServers": { "demo": { "command": "uv", "args": ["--directory", "/abs/path/to/mcp-demo", "run", "python", "server.py"] } } }

逻辑说明:--directory让 uv 切到项目目录再执行,避免相对路径找不到pyproject.toml。路径一定用绝对路径,Agent 宿主的工作目录和你终端不一样。

参数说明:不同宿主字段名可能叫mcpServersservers,但command/args结构一致。如果宿主支持环境变量,把密钥类配置放env字段,别硬编码进 args。

4.3 调用失败时的排查顺序

遇到「工具调用了但没结果」或「Agent 说找不到工具」,按这个顺序查:

  1. 单独跑 Client 脚本,确认list_tools()有输出。没有就是 Server 侧问题。
  2. 有工具但调用报错,看call_tool返回的isError字段和错误文本。
  3. 参数校验失败,对照 Inspector 里的 Schema 逐个核对类型。
  4. 宿主里不生效,检查配置路径是否为绝对路径、命令是否在宿主 PATH 里。

提示:Agent 宿主通常有日志目录,MCP 握手和调用记录会写进去。比起猜,直接翻日志里 Server 的 stderr 输出最快。

5. MCP 进阶:让工具被 Agent 稳定选中

5.1 工具描述与参数设计的三条经验

工具能不能被正确调用,一半取决于描述质量。三条实操经验:

  • 名字用动词开头search_docsdocs好,模型对动作语义更敏感。
  • docstring 写清边界:说明参数取值范围、返回结构、什么情况下不该用。比如「仅支持 UTF-8 文本,超过 10MB 请改用分片接口」。
  • 参数扁平化:能用strintbool就别嵌套对象,嵌套会让模型传参出错率上升。

5.2 用 resource 暴露只读上下文

当你要给模型喂日志、配置、文档时,用 resource 比 tool 更合适。

@mcp.resource("config://app") def get_config() -> str: """返回应用当前配置。""" return open("config.yaml", encoding="utf-8").read()

逻辑说明:URI 是 resource 的标识,Client 可以按 URI 读取。只读、无副作用,模型不会「误执行」。参数说明:URI scheme 自定义即可,但要保证唯一性和可读性,方便在 Client 侧做权限控制。

5.3 验证工具是否真的被调用

最后一步是确认 Agent 确实走了 MCP,而不是自己编了答案。最直接的办法是在 tool 里加一行 stderr 日志:

import sys @mcp.tool() def add(a: int, b: int) -> int: print(f"[call] add a={a} b={b}", file=sys.stderr) return a + b

跑一次 Agent 任务,看宿主日志里有没有这行输出。有,说明调用链通了;没有,说明模型选择了别的路径或工具没被注册。这个技巧在排查「Agent 答对了但不确定是不是调了工具」时特别有用,也是把 MCP 从 demo 推向可用工具的关键一步。

本文还有配套的精品资源,点击获取

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

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

立即咨询