从0到1:搭建你的第一个 MCP 服务器实战

基于 Python FastMCP SDK,零基础动手搭建一个完整可用的 MCP 服务器


一、MCP 是什么

MCP(Model Context Protocol)是连接 AI 助手与外部数据源和工具的通信协议,可以理解为 AI 的 "USB 接口"------AI 通过 MCP 连接外部的工具、数据和服务。

核心设计思想

复制代码
┌─────────────┐    MCP 协议     ┌─────────────┐
│   AI 客户端  │ ◄────────────► │  MCP 服务器  │
│  (Trae等)   │   JSON-RPC     │  (Python)   │
└─────────────┘                └─────────────┘
     │                               │
     │                               ├── Tools(工具)
   
   ### MCP 三大支柱
能力 比喻 作用
Tools AI的"手" 让 AI 能执行操作(计算、搜索等)
Resources AI的"眼" 让 AI 能读取数据(知识库、文件等)
Prompts AI的"嘴" 让 AI 能规范输出(代码审查、错误解释等)

二、项目结构

核心依赖

复制代码
mcp >= 1.0.0       # MCP Python SDK(FastMCP)
uvicorn >= 0.30.0  # ASGI 服务器(HTTP 模式用)
starlette >= 0.40.0 # Web 框架(HTTP 模式用)

server.py 五层架构

┌─────────────────────────────────────────────────────────────┐

│ 第 5 层:MCP 客户端 (Trae) │

│ ↕ 通过 mcp.json 配置连接 │

├─────────────────────────────────────────────────────────────┤

│ 第 4 层:MCP 协议传输层 │

│ stdio (进程管道) ←→ HTTP/SSE (网络) │

├─────────────────────────────────────────────────────────────┤

│ 第 3 层:FastMCP 调度器 │

│ 接收协议请求 → 路由到注册的函数 │

├─────────────────────────────────────────────────────────────┤

│ 第 2 层:装饰器注册层 │

│ @mcp.tool() / @mcp.resource() / @mcp.prompt() │

├─────────────────────────────────────────────────────────────┤

│ 第 1 层:业务函数 │

│ calculate() / get_time() / search_knowledge() ... │

└─────────────────────────────────────────────────────────────┘


三、核心概念:容器 + 装饰器 + docstring

3.1 快速理解

如果你学过 FastAPI,可以这样类比:

概念 FastAPI MCP 本质
容器 APIRouter FastMCP 一个注册表对象
装饰器 @router.get() @mcp.tool() 往容器里注册函数
注册内容 HTTP 路由 + 处理函数 Tool/Resource/Prompt 都是"能力声明"
启动方式 app.include_router() mcp.run() 激活容器,开始对外服务

3.2 什么是 docstring?

docstring 就是 Python 函数的第一个多行注释 ,用 """ 或 ''' 包裹。它不是普通的代码注释,而是 Python 语言规范的一部分,可以通过 __doc__ 属性访问。

普通注释 用 # 开头,给人看的:

复制代码
# 这是一个普通注释,Python 不会读取

docstring 用 """ 包裹,Python 会自动保存:

复制代码
def get_time() -> str:
    """获取当前时间"""  # 这就是 docstring,Python 会自动保存
    ...

你可以这样访问 docstring:

复制代码
print(get_time.__doc__)  # 输出: "获取当前时间"
### 3.3 docstring 对 MCP 的重要性

对 Python 来说 ,docstring 是可选的(没有也不会报错)。

对 MCP 来说 ,docstring 是极其重要的------AI 就是靠 docstring 来理解每个工具是干什么的。

看一下 server.py 中的例子:

示例:带 docstring 的工具(推荐写法)

复制代码
@mcp.tool()
def calculate(expression: str) -> str:
    """
    计算数学表达式              ← 工具的功能描述(AI 看这个)
    
    Args:
        expression: 数学表达式,如 "2 + 3 * 4"  ← 参数说明(AI 看这个)
    Returns:
        计算结果                ← 返回值说明(AI 看这个)
    """
    try:
        result = eval(expression)
        return f"结果: {result}"
         except Exception as e:
        return f"计算错误: {str(e)}"

这个 docstring 不是给人看的,是给 AI 看的!当 MCP 启动后,会把 docstring 转换成 JSON Schema 返回给 AI:

复制代码
// AI 收到的工具列表(自动从 docstring 生成)
{
  "name": "calculate",
  "description": "计算数学表达式\n\nArgs:\n    expression: 数学表达式,如 \"2 + 3 * 4\"\nReturns:\n    计算结果",
  "inputSchema": {
    "type": "object",
    "properties": {
      "expression": {
        "type": "string",
     "description": "数学表达式,如 \"2 + 3 * 4\""
      }
    },
    "required": ["expression"]
  }
}

3.4 注册流程

当 Python 导入 server.py 时,代码从上到下逐行执行:

第1步:创建空的"注册表"

复制代码
mcp = FastMCP("HelloMCP")
# 内部有3个空字典: _tools={}, _resources={}, _prompts={}

# 第2步:装饰器逐个注册(自动提取 docstring 信息)
@mcp.tool()
def calculate(expression: str) -> str:
    """计算数学表达式"""  # ← 这个 docstring 会被提取
    ...
# 等价于: mcp._tools["calculate"] = {
#     "description": "计算数学表达式",
#     "inputSchema": {...},
#     "function": calculate
# }
装饰器做了三件事:
  1. 把函数存入注册表
  2. 解析函数签名(参数名、类型 → 生成 JSON Schema)
  3. 提取 docstring(描述、参数说明 → 告诉 AI 这个工具是干什么的)

3.5 对比:有 docstring vs 没有 docstring

写法一:有清晰的 docstring(推荐)

复制代码
@mcp.tool()
def get_time() -> str:
    """获取当前时间
    
    Returns:
        当前日期和时间
    """
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# → AI 清楚知道这个工具是"获取时间",会精准调用

# 写法二:没有 docstring(不推荐)
@mcp.tool()
def get_time() -> str:
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# → AI 只看到名字 get_time,可能不知道它的用途
## 四、完整核心代码:server.py

以下是 server.py 的完整代码,按模块分块展示。

4.1 导入与初始化

复制代码
"""
MCP Server 示例 - 学习 MCP 协议
这个服务器演示了 MCP 的核心概念:工具(Tools)、资源(Resources)、提示(Prompts)
支持 HTTP/SSE 传输,外部系统可通过 HTTP 调用
"""

from mcp.server.fastmcp import FastMCP
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
import socket
import uvicorn
# 自定义中间件:修复 Host header 验证问题
class HostFixMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        # 修复 Host header 问题,确保通过验证
        request.scope['server'] = ('127.0.0.1', 8080)
        response = await call_next(request)
        return response

# 创建 MCP 服务器实例
mcp = FastMCP("HelloMCP")

4.2 示例工具(Tools)

复制代码
# ============================================
# 示例工具 (Tools) - AI 可以调用的函数

============================================

复制代码
@mcp.tool()
def calculate(expression: str) -> str:
    """
    计算数学表达式
    
    Args:
        expression: 数学表达式,如 "2 + 3 * 4"
    Returns:
        计算结果
    """
    try:
        result = eval(expression)
        return f"结果: {result}"
    except Exception as e:
        return f"计算错误: {str(e)}"
         @mcp.tool()
def get_time() -> str:
    """
    获取当前时间
    
    Returns:
        当前日期和时间
    """
    from datetime import datetime
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")


@mcp.tool()
def reverse_text(text: str) -> str:
    """
    反转文本
    
    Args:
        text: 要反转的文本
    Returns:
        反转后的文本
    """
    return text[::-1]

4.3 示例资源(Resources)

============================================

复制代码
# 示例资源 (Resources) - 可读取的数据
# ============================================

@mcp.resource("greeting://hello")
def get_greeting() -> str:
    """返回一个问候语资源"""
    return "Hello! Welcome to MCP Server!"


@mcp.resource("info://server")
def get_server_info() -> str:
    """返回服务器信息"""
    import platform
    return f"""
Server Info:
- Python Version: {platform.python_version()}
- Platform: {platform.platform()}
- MCP SDK Version: 1.0.0
"""

4.4 知识库资源与工具

============================================

复制代码
# 知识库资源 (Knowledge Resources) - RAG 应用
# ============================================

import os
from pathlib import Path

# 知识库目录
KNOWLEDGE_DIR = Path(__file__).parent / "knowledge"


@mcp.resource("knowledge://products")
def get_product_knowledge() -> str:
    """产品知识库"""
   file_path = KNOWLEDGE_DIR / "products.md"
    if file_path.exists():
        return file_path.read_text(encoding="utf-8")
    return "产品知识库暂无内容"


@mcp.resource("knowledge://policies")
def get_policy_knowledge() -> str:
    """政策文档知识库"""
    file_path = KNOWLEDGE_DIR / "policies.md"
    if file_path.exists():
        return file_path.read_text(encoding="utf-8")
    return "政策文档暂无内容"
    @mcp.resource("knowledge://faq")
def get_faq_knowledge() -> str:
    """常见问题知识库"""
    file_path = KNOWLEDGE_DIR / "faq.md"
    if file_path.exists():
        return file_path.read_text(encoding="utf-8")
    return "FAQ 暂无内容"


# ============================================
# 知识库工具 (Knowledge Tools) - 检索
# ============================================

@mcp.tool()
def search_knowledge(keyword: str) -> str:
    """
    在知识库中搜索关键词

    Args:
        keyword: 搜索关键词
    Returns:
        匹配的知识点
    """
    if not KNOWLEDGE_DIR.exists():
        return "知识库目录不存在"

    results = []
    for file_path in KNOWLEDGE_DIR.glob("*.md"):
        content = file_path.read_text(encoding="utf-8")
        if keyword.lower() in content.lower():
            lines = content.split("\n")
            matching_lines = [line for line in lines if keyword.lower() in line.lower()]
            results.append(f"【{file_path.stem}】匹配到 {len(matching_lines)} 处:\n" + "\n".join(matching_lines[:10]))

    if results:
    return f"找到 {len(results)} 个相关知识:\n\n" + "\n\n---\n\n".join(results)
    return f"未找到与 '{keyword}' 相关的知识"

4.5 文件搜索与目录树工具

============================================

复制代码
# 实用工具 (Tools) - 文件搜索
# ============================================

@mcp.tool()
def search_files(directory: str, pattern: str) -> str:
    """
    搜索目录下包含特定模式的文件
    
    Args:
        directory: 要搜索的目录路径
        pattern: 文件名匹配模式(如 ".py", "test", "config")
    Returns:
        匹配的文件列表
    """
    try:
     matches = []
        path = Path(directory)
        if not path.exists():
            return f"目录不存在: {directory}"
        
        for f in path.rglob(f"*{pattern}*"):
            if f.is_file():
                matches.append(str(f.relative_to(path)))
        
        if matches:
            return f"找到 {len(matches)} 个匹配的文件:\n" + "\n".join(f"  - {m}" for m in matches[:20])
        else:
            return f"在 {directory} 中没有找到包含 '{pattern}' 的文件"
    except Exception as e:
        return f"搜索出错: {str(e)}"


# ============================================
# 实用工具 (Tools) - 目录树
# ============================================

@mcp.tool()
def get_directory_tree() -> str:
"""返回当前目录的树状结构"""
    def build_tree(path: Path, prefix: str = "", max_depth: int = 2, current_depth: int = 0) -> str:
        if current_depth >= max_depth:
            return ""
        result = []
        try:
            items = sorted(path.iterdir(), key=lambda x: (not x.is_dir(), x.name))
            for i, item in enumerate(items[:10]):
                is_last = i == len(items[:10]) - 1
                connector = "└── " if is_last else "├── "
                result.append(f"{prefix}{connector}{item.name}")
                if item.is_dir():
                    extension = "    " if is_last else "│   "
                    result.append(build_tree(item, prefix + extension, max_depth, current_depth + 1))
        except PermissionError:
            pass
        return "\n".join(result)
        return f"当前目录结构:\n{build_tree(Path.cwd())}"

4.6 提示模板(Prompts)

⚠️ 以下代码中的 ``````````` 是 Python f-string 中的字符串内容,用于生成提示词模板,不是 Markdown 代码块。实际代码中用三反引号替换 <CODEBLOCK> 和 </CODEBLOCK>。

复制代码
# ============================================
# 提示模板 (Prompts) - 代码解释
# ============================================

@mcp.prompt()
def explain_code_prompt(code: str, language: str = "python") -> str:
    """生成代码解释的提示模板"""
    return f"""请解释以下 {language} 代码:
    1. 这段代码的主要功能是什么?
2. 关键逻辑和执行流程
3. 可能的用途和应用场景

<CODEBLOCK>{language}
{code}
</CODEBLOCK>"""


@mcp.prompt()
def code_review_prompt(code: str) -> str:
    """代码审查提示模板"""
    return f"""请审查以下代码并提供建议:

<CODEBLOCK>{code}
</CODEBLOCK>"""
 @mcp.prompt()
def generate_tests_prompt(code: str, language: str = "python") -> str:
    """生成单元测试提示模板"""
    return f"""你是一个测试工程师,负责为代码生成单元测试。

请为以下 {language} 代码生成全面的单元测试:

要求:
1. 使用 pytest 测试框架
2. 覆盖正常用例和边界用例
3. 测试函数命名清晰,表达测试意图
4. 包含必要的 setup/teardown(如需要)
<CODEBLOCK>{language}
{code}
</CODEBLOCK>

请生成完整的测试代码:"""


@mcp.prompt()
def explain_error_prompt(error_message: str, code: str = "") -> str:
    """代码错误解释提示模板"""
    context = f"\n相关代码:\n<CODEBLOCK>{code}\n</CODEBLOCK>" if code else ""
    return f"""你是一个耐心的编程导师,帮助解释代码错误。

错误信息:
{error_message}
{context}
 请按以下格式解释:
1. 错误原因:简单清晰地解释为什么会出错
2. 解决方法:提供修复建议或正确做法
3. 预防建议:如何避免类似错误"""


@mcp.prompt()
def optimize_code_prompt(code: str, language: str = "python") -> str:
    """代码优化提示模板"""
    return f"""你是一个性能优化专家,负责优化代码性能和可读性。

请优化以下 {language} 代码:
<CODEBLOCK>{language}
{code}
</CODEBLOCK>

分析维度:
1. 性能优化(时间/空间复杂度)
2. 代码可读性
3. 最佳实践
4. 潜在问题

请给出优化后的代码和优化说明:"""

4.7 启动服务器

java 复制代码
mcp.run()

代码结构说明

部分 说明
HostFixMiddleware 自定义中间件,修复 HTTP 模式下的 Host header 验证问题
mcp = FastMCP("HelloMCP") 创建 MCP 服务器容器实例
@mcp.tool() 注册的函数 AI 可调用的工具函数
@mcp.resource() 注册的函数 AI 可读取的资源数据
@mcp.prompt() 注册的函数 AI 可获取的提示词模板
if __name__ == "__main__": 启动入口,支持 stdio 和 HTTP 两种模式

启动mcp,mcp作为容器,其里面的tool、resource、prompt就可以用了,类似于fastApi的router变量和router变量对应的接口函数

五、客户端配置:mcp.json 详解

5.1 mcp.json 是什么

mcp.json 是客户端(如 Trae)的 MCP 配置文件,告诉客户端:

  • 去哪里找 MCP 服务器
  • 用什么方式连接
  • 服务器叫什么名字

5.2 完整配置文件

复制代码
{
  "mcpServers": {
    "helloMCP": {
      "command": "python",
      "args": ["C:\\path\\to\\server.py"],
      "env": {},
      "description": "MCP 学习示例服务器"
    }
  }
}

5.3 每个字段的含义

字段 含义 说明
mcpServers MCP 服务器列表 可以配置多个 MCP 服务器
helloMCP 服务器名称 自定义名字,方便识别
command 启动命令 stdio 模式下用什么命令启动
args 启动参数 传递给启动命令的参数(如 server.py 路径)
env 环境变量 启动时的环境变量(可留空)
description 描述信息 对这个 MCP 的简单说明

5.4 两种配置方式

方式一:stdio 模式(推荐,本地开发用)

复制代码
{
  "mcpServers": {
    "helloMCP": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}
  • command: 用什么命令启动服务器(如 python)
  • args: 启动参数,指向 server.py 文件
  • 客户端自动管理:按需启动、用完关闭,不需要手动启动

方式二:HTTP 模式(远程服务用)

复制代码
{
  "mcpServers": {
    "helloMCP-remote": {
      "url": "http://example.com:9088/mcp"
    }
  }
}
  • url: 远程 MCP 服务的 HTTP 地址
  • 需要服务器提前启动 :python server.py -t http -p 9088
  • 客户端通过 HTTP/SSE 连接

5.5 路径问题

复制代码
// 相对路径(项目级专用,不推荐)
"args": ["${workspaceFolder}/mcpProject/server.py"]
// → 切换项目后 workspaceFolder 变了 → 路径失效

// 绝对路径(推荐,跨项目可用)
"args": ["C:\\absolute\\path\\to\\server.py"]
// → 任何项目都能使用

5.6 两种配置层级

┌─────────────────────────────────────────────────┐

│ 项目级(项目根目录 .trae/mcp.json) │

│ - 只在当前项目生效 │

│ - 用 ${workspaceFolder} 或绝对路径 │

│ - 适合项目专属的 MCP │

├─────────────────────────────────────────────────┤

│ 全局级(用户设置) │

│ - 所有项目都生效 │

│ - 用绝对路径 │

│ - 适合通用的 MCP │

└─────────────────────────────────────────────────┘

5.7 配置后发生了什么?

复制代码
1. 客户端读取 mcp.json
2. 发现有一个名为 "helloMCP" 的 MCP 服务器
3. 配置为 stdio 模式,command=python,args=[server.py 路径]
4. 当你第一次使用 MCP 时,客户端自动 fork 子进程
5. 通过 stdin/stdout 与 server.py 进行 JSON-RPC 通信
6. 服务器启动后,自动执行:
   - tools/list → 返回所有工具
   - resources/list → 返回所有资源
   - prompts/list → 返回所有模板
7. 客户端拿到这些信息,AI 就知道有哪些能力可以用了

六、三大能力详解

6.1 Tools:让 AI 会做事

Tool 是 AI 可调用的函数 ,通过 @mcp.tool() 装饰器注册。

已实现的工具:

工具名 功能 参数
calculate 计算数学表达式 expression: str
get_time 获取当前时间 无
reverse_text 文本反转 text: str
search_knowledge 知识库关键词搜索 keyword: str
search_files 文件名模式搜索 directory, pattern
get_directory_tree 目录树结构 无

工作流程:

复制代码
用户: "现在几点了?"
         ↓
    AI 思考: 需要获取时间
         ↓
    AI 读取工具列表:
    ┌──────────────────────────────────────┐
    │ calculate    → "计算数学表达式"     │  ❌
    │ get_time     → "获取当前时间"       │  ✅ 完美匹配
    │ reverse_text → "反转文本"           │  ❌
    └──────────────────────────────────────┘
     ↓
    AI 发送: tools/call → get_time
         ↓
    MCP 执行 get_time() → "2026-10-30 16:02:23"
         ↓
    AI 组织成自然语言回复用户

测试方法: 在对话框输入以下内容即可测试:

现在几点了?

(15 + 5) * 3 / 2

帮我搜一下 knowledge 目录下有哪些 .md 文件

注意事项: calculate 工具使用了 eval() 函数,存在安全隐患。生产环境应使用 ast.literal_eval() 或 simpleeval 库。

6.2 Resources:让 AI 能读数据

Resource 是 AI 可读取的数据源 ,通过 @mcp.resource(uri) 装饰器注册,AI 通过 URI(统一资源标识符)来读取内容。

已实现的资源:

URI 功能 关联文件
greeting://hello 问候语 无
info://server 服务器信息 无
knowledge://products 产品知识库 knowledge/products.md
knowledge://policies 政策文档 knowledge/policies.md
knowledge://faq 常见问题 knowledge/faq.md
URI 的含义:
复制代码
knowledge://products
   ↑          ↑
  方案        资源标识符
(scheme)   (identifier)

URI 是 MCP 协议中的资源标识符,与物理文件路径无关 ,只是 AI 和 MCP 协议之间的"资源门牌号"。

两个路径的区别:

复制代码
KNOWLEDGE_DIR = Path(__file__).parent / "knowledge"  # ① 物理路径(代码读文件用)

@mcp.resource("knowledge://products")                  # ② MCP URI(AI 识别用)
def get_product_knowledge() -> str:
    file_path = KNOWLEDGE_DIR / "products.md"          # ③ 物理路径(读文件用)

触发注意事项: Resources 是被动的数据源,AI 不一定会主动触发:

  • ✅ 明确提示:"从产品知识库中介绍一下"
  • ⚠️ 模糊提示:"介绍一下产品"(AI 可能用默认知识回答)
  • ❌ 不提知识库:大概率不触发

最佳实践: 如果需要可靠的知识库检索,建议用 Tool 实现 (如 search_knowledge)

测试方法:

复制代码
从产品知识库中介绍一下你们的产品
退款政策是什么?
知识库中关于 MCP 是什么的说明?

6.3 Prompts:让 AI 说好话

Prompt 是预定义的提示词模板 ,通过 @mcp.prompt() 装饰器注册,AI 可以获取模板来规范自己的输出格式。

已实现的模板:

模板名 用途 触发词示例
explain_code 代码解释 "解释这段代码"
code_review 代码审查 "审查代码"
generate_tests 生成单元测试 "写单元测试"
explain_error 错误解释 "这个报错是什么意思"
optimize_code 代码优化 "优化代码"
translate_code 代码转换 "转成 Java"
write_docs 生成文档 "写文档"
quick_refactor 快速重构 "重构代码"
security_review 安全审查 "检查安全"

Prompt 的本质: 一个返回字符串的模板函数:

复制代码
@mcp.prompt()
def explain_code_prompt(code: str, language: str = "python") -> str:
    """生成代码解释的提示模板"""
    return f"""请解释以下 {language} 代码:
1. 主要功能是什么?
2. 关键逻辑和执行流程
3. 可能的用途和应用场景
<CODEBLOCK>{language}
{code}
</CODEBLOCK>"""
# 返回一段格式化的提示词文本,告诉 AI 应该怎么回答

三种能力的区别:

Tool: 输入 → 执行操作 → 返回结果

calculate("2+3") → "5"

复制代码
Resource: URI → 读取数据 → 返回内容
          knowledge://products → "产品介绍..."

Prompt:   输入参数 → 返回提示词文本
          explain_code(code) → "请解释这段代码:..."
          ↑
          返回的不是答案,而是告诉 AI "应该怎么回答"

触发注意事项: Prompt 触发概率较低,需要明确指定:

  • ❌ "检查代码" → AI 不会主动找 Prompt
  • ❌ "解释一下" → AI 可能直接回答
  • ✅ "用 MCP 的 explain_code 模板解释" → 明确触发

测试方法:

用 MCP 的 explain_code 模板解释:

def fibonacci(n):

if n <= 1: return n

return fibonacci(n-1) + fibonacci(n-2)

复制代码
调用 MCP 的 code_review 模板审查:
def calc(a, b): return a / b

七、传输层:stdio vs HTTP

7.1 两种模式对比

本地 stdio 模式 远程 HTTP 模式
配置方式 command + args url
谁启动 MCP 客户端自动启动 远程服务器提前启动
通信方式 进程管道(不走网络) HTTP/SSE(走网络)
稳定性 ✅ 稳定(不受网络影响) ❌ 可能断(受网络/服务器影响)
适用场景 本地开发、单机使用 远程服务、多客户端共享

7.2 stdio 模式(默认,推荐)

复制代码
{
  "mcpServers": {
    "helloMCP": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}

客户端 ──fork子进程──→ python server.py
  ↕ stdin/stdout(进程管道通信)
  ↕ JSON-RPC 协议
  **核心优势**:本地不需要手动启动,客户端自动管理生命周期。

7.3 HTTP 模式

复制代码
{
  "mcpServers": {
    "helloMCP-remote": {
      "url": "http://example.com:9088/mcp"
    }
  }
}

远程服务器(提前启动好):
$ python server.py -t http -p 9088
客户端 ──HTTP/SSE──→ http://example.com:9088/mcp

核心注意:远程 MCP 必须提前启动,服务器停了就连不上。

7.4 为什么不需要手动启动?

stdio 模式下,客户端配置 mcp.json 后会自动管理 MCP 进程:

  • ❌ 不需要手动启动 python server.py
  • ✅ 客户端按需自动 fork 子进程
  • ✅ 客户端通过 stdin/stdout 双向通信
  • ✅ 客户端不需要时自动终止进程

八、常见问题与解答

Q1: 手动关闭了 python server.py,客户端还会启动吗?

会!它们是两个独立进程:

  • 你手动启动的进程:闲置在那里(没人给它发消息)
  • 客户端启动的进程:真正在工作

手动启动那个可以关掉,不影响正常使用。

Q2: 换了项目路径,MCP 就失效了?

取决于配置方式:

  • ${workspaceFolder}/... → 会失效(绑定当前项目)
  • 绝对路径 → 不会失效(跨项目可用)

建议将 MCP 配置为全局配置,使用绝对路径。

Q3: 为什么 Resources 和 Prompts 没有自动触发?

AI 客户端的设计策略:

  • ✅ 自动获取 tools/list → 主动使用 Tools
  • ❌ 不主动获取 resources/list → Resources 需明确提示
  • ❌ 不主动获取 prompts/list → Prompts 需明确指定

这是正常现象,不是代码问题。

Q4: 远程 MCP 为什么偶尔会断?

远程 HTTP 模式的不稳定因素:

  1. 网络问题(VPN/防火墙/超时)
  2. 服务器状态(重启/崩溃/连接数超限)
  3. SSE 长连接超时(中间层 Nginx 设置)
  4. 认证 Token 过期

本地 stdio 模式不会有这个问题,因为一切在进程内部通信。

Q5: eval() 安全吗?

不安全!eval() 可以执行任意 Python 代码:

复制代码
eval("__import__('os').system('calc.exe')")  # 会打开计算器!

生产环境应使用 ast.literal_eval() 或 simpleeval 库。

Q6: docstring 是必须的吗?

docstring对应的是工具的注释

对 Python 不是必须的,但对 MCP 极其重要:

  • 有 docstring → AI 精准选择工具
  • 没有 docstring → AI 只能靠函数名猜测

Q7: MCP 和 FastAPI 的关系?

两者的装饰器注册模式完全一致:

复制代码
FastAPI: APIRouter + @router.get()/@router.post()
MCP:     FastMCP + @mcp.tool()/@mcp.resource()/@mcp.prompt()

FastAPI 是"HTTP 能力容器",MCP 是"AI 能力容器"。

九、核心知识点总结

9.1 一句话概括

MCP = FastMCP 容器 + 三大能力(Tools/Resources/Prompts)+ 传输层(stdio/HTTP)

9.2 核心公式

复制代码
MCP 服务器 = 装饰器注册 + JSON-RPC 协议 + 传输层

1. 装饰器注册:@mcp.tool() / @mcp.resource() / @mcp.prompt()
2. JSON-RPC 协议:tools/list, tools/call, resources/read, prompts/get
3. 传输层:stdio(本地)/ HTTP(远程)
### 9.3 关键实践经验
经验 说明
docstring 必写 AI 靠它选择工具,写得越清晰越好
stdio 不需要手动启动 客户端自动管理进程生命周期
用绝对路径配置 跨项目可用,不受 workspaceFolder 限制
知识库检索用 Tool search_knowledge 比 Resource 更可靠
Prompts 需明确触发 "用 MCP 的 xxx 模板" 比 "帮我审查" 更有效

9.4 三种能力的定位

复制代码
┌──────────────────────────────────────────────────────┐
│  Tool:     AI 的"手"(执行操作)                    │
│            → 触发难度低,AI 自动发现               │
├──────────────────────────────────────────────────────┤
│  Resource: AI 的"眼"(读取数据)                    │
│            → 触发难度中,需明确提示                │
├──────────────────────────────────────────────────────┤
│  Prompt:   AI 的"嘴"(规范输出)                    │
│            → 触发难度高,需明确指定                │
└──────────────────────────────────────────────────────┘

9.5 学习路径建议

复制代码
入门阶段(已完成)
      ↓
    掌握 @mcp.tool() 的用法和 docstring 编写
      ↓
    进阶阶段
      ↓
    学习 HTTP 模式部署、多客户端共享
      ↓
    深入阶段
      ↓
    研究 FastMCP 源码、JSON-RPC 协议细节
      ↓
    实战阶段
      ↓
    开发实用 MCP(数据库操作、API 集成、企业知识库等)
    ```
相关推荐
jerrywus1 小时前
Skill、MCP、Workflow、Rules、Memory 有什么区别?拿几次真实开发任务讲清楚
前端·agent·claude
七夜zippoe2 小时前
第一季收官:Agent 架构设计模式语言与选型决策框架
ai·agent·架构设计·模式语言·选择决策
yunzerui2 小时前
模型不是选错,是干脆不调用:一次 function-calling 失败的真实归因
agent
小易老师2 小时前
用中间件把任务规划嵌入 Agent 循环:告别把计划写死在 Prompt 里
人工智能·agent
weixin_449229382 小时前
Skill应用11:详细设计自动生成|强制“文字先行”,杜绝AI只堆代码不讲设计
人工智能·agent·架构设计·详细设计·trae·skill应用
終不似少年遊*3 小时前
【Skill】为中型研发团队制作的敏捷迭代AI副驾Skill
人工智能·python·华为云·agent·ai编程·skill
lee_curry4 小时前
第十周完整学习笔记:继续升级为“检索更准、权限安全、索引可维护、失败可恢复、长期可运行”的企业级 RAG 系统
python·ai·langchain·agent·langgraph
sg_knight4 小时前
Bug 定位实战:把报错丢给 Codex,它是怎么修的
chatgpt·llm·bug·openai·agent·ai编程·codex
情 九5 小时前
MCP 工具开发实战:参数校验、结构化输出与错误处理
mcp