首页 › tutorials › MCP服务器Python开发:FastMCP全实战

概述

本教程面向希望用 Python 构建自定义 MCP 服务器的开发者,从零完成一个生产级 MCP 服务器项目。你将掌握 FastMCP 框架的核心 API、Tools/Resources/Prompts 三大原语的设计模式、Claude Code 集成配置、调试部署全链路。适合有 Python 基础、了解 Claude Code 基本用法的开发者。

学习目标:完成一个「代码审查助手」MCP 服务器,具备文件分析、规范检查、审查报告生成三大能力,可直接接入 Claude Code 使用。


一、前置条件

项目 要求
Python 3.10+
Claude Code 最新版(claude --version 确认)
包管理 uv 或 pip
操作系统 macOS / Linux / Windows(WSL)

安装核心依赖:

# 推荐 uv(更快)
uv pip install fastmcp

# 或传统 pip
pip install fastmcp

验证安装:

python -c "import fastmcp; print(fastmcp.__version__)"

预期输出类似 3.2.4(以实际版本为准)。


二、MCP 架构速览:从协议到实践

2.1 MCP 核心架构

MCP(Model Context Protocol)采用 Client-Server 架构, Claude Code 内置 MCP Client,你开发的是 MCP Server。

┌─────────────────┐    stdio/HTTP     ┌─────────────────┐
│   Claude Code    │◄───────────────►│   MCP Server     │
│  (MCP Client)   │   JSON-RPC 2.0   │  (你的 Python)   │
└─────────────────┘                   └────────┬────────┘
                                               │
                                    ┌──────────┼──────────┐
                                    │          │          │
                               ┌────▼───┐ ┌───▼────┐ ┌───▼────┐
                               │ Tools  │ │Resources│ │Prompts │
                               └────────┘ └────────┘ └────────┘

2.2 三大原语对比

graph TB
    subgraph "MCP Server 三大原语"
        T["🔧 Tools<br/>可执行函数<br/>模型主动调用"]
        R["📄 Resources<br/>只读数据源<br/>按 URI 访问"]
        P["💬 Prompts<br/>提示模板<br/>用户触发"]
    end

    T -->|副作用| E1["执行操作、修改状态"]
    R -->|无副作用| E2["获取上下文数据"]
    P -->|参数化| E3["生成结构化提示"]
原语 类比 何时使用 示例
Tool API 端点 需要执行操作、有副作用 代码分析、文件写入
Resource GET 请求 提供只读上下文数据 配置文件、数据库记录
Prompt 模板函数 参数化提示生成 审查模板、报告格式

2.3 两种传输方式

graph LR
    subgraph "本地开发"
        A["Claude Code"] -->|stdio| B["MCP Server<br/>子进程"]
    end

    subgraph "远程部署"
        C["Claude Code"] -->|Streamable HTTP| D["MCP Server<br/>HTTP 服务"]
    end

本教程使用 stdio 模式(最常用的 Claude Code 集成方式),最后介绍 HTTP 模式。


三、第一个 MCP 服务器:5 分钟 Hello World

3.1 创建项目结构

mkdir code-review-mcp && cd code-review-mcp
uv init

编辑 pyproject.toml:

[project]
name = "code-review-mcp"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = [
    "fastmcp>=3.0.0",
]

3.2 最小服务器代码

创建 server.py:

from fastmcp import FastMCP

mcp = FastMCP("code-review")

@mcp.tool()
def hello(name: str) -> str:
    """向用户打招呼"""
    return f"Hello, {name}! 代码审查助手已就绪。"

if __name__ == "__main__":
    mcp.run()

3.3 本地测试

# 安装依赖
uv sync

# 启动服务器(stdio 模式)
uv run python server.py

此时服务器等待 stdin 输入。按 Ctrl+C 退出,这是正常的——stdio 模式下由 Claude Code 作为客户端驱动。

3.4 接入 Claude Code

# 添加 MCP 服务器到 Claude Code
claude mcp add code-review -- uv run --directory /完整路径/code-review-mcp python server.py

验证:

claude mcp list

预期输出:

code-review: uv run --directory /.../code-review-mcp python server.py

在 Claude Code 会话中测试:

> 使用 hello 工具向 Alice 打招呼

Claude Code 会自动调用你的 hello Tool,返回 Hello, Alice! 代码审查助手已就绪。

常见问题:

问题 原因 解决方案
Server not found 路径不正确 使用绝对路径
Connection refused 依赖未安装 先执行 uv sync
Module not found Python 版本过低 确认 3.10+

四、深入三大原语:代码审查助手实现

4.1 整体架构

graph TB
    subgraph "code-review MCP Server"
        M["FastMCP 实例"]

        subgraph "Tools"
            T1["analyze_code<br/>代码复杂度分析"]
            T2["check_style<br/>编码规范检查"]
            T3["generate_report<br/>生成审查报告"]
        end

        subgraph "Resources"
            R1["config://rules<br/>审查规则配置"]
            R2["config://templates<br/>报告模板"]
        end

        subgraph "Prompts"
            P1["review_template<br/>审查提示模板"]
        end
    end

    CC["Claude Code"] -->|JSON-RPC| M
    M --> T1 & T2 & T3
    M --> R1 & R2
    M --> P1

4.2 Tool:代码复杂度分析

Tool 是 MCP 最核心的原语。FastMCP 使用 @mcp.tool() 装饰器,参数通过类型注解自动推断 JSON Schema。

import ast
from typing import Annotated
from pydantic import Field

@mcp.tool()
def analyze_code(
    source_code: Annotated[str, Field(description="要分析的 Python 源代码")],
    threshold: Annotated[int, Field(description="圈复杂度阈值,默认 10")] = 10,
) -> dict:
    """
    分析 Python 代码的圈复杂度和函数统计。
    返回每个函数的复杂度评分、行数、参数数量。
    """
    try:
        tree = ast.parse(source_code)
    except SyntaxError as e:
        return {"error": f"语法错误: {e}"}

    results = []
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
            complexity = _calculate_complexity(node)
            results.append({
                "function": node.name,
                "line": node.lineno,
                "complexity": complexity,
                "params": len(node.args.args),
                "lines_of_code": node.end_lineno - node.lineno + 1,
                "exceeds_threshold": complexity > threshold,
            })

    return {
        "total_functions": len(results),
        "exceeding_threshold": sum(1 for r in results if r["exceeds_threshold"]),
        "functions": results,
    }


def _calculate_complexity(node: ast.AST) -> int:
    """计算圈复杂度(简化版 McCabe)"""
    complexity = 1
    for child in ast.walk(node):
        if isinstance(child, (ast.If, ast.While, ast.For, ast.ExceptHandler)):
            complexity += 1
        elif isinstance(child, ast.BoolOp):
            complexity += len(child.values) - 1
    return complexity

关键设计要点:

  1. Annotated + Field:提供参数描述,Claude Code 据此决定何时调用
  2. 返回 dict:FastMCP 自动序列化为 JSON,Claude 直接理解
  3. docstring 是灵魂:Claude Code 通过 docstring 判断 Tool 的用途和适用场景
  4. 防御性解析:处理语法错误,避免服务器崩溃

4.3 Tool:编码规范检查

import re

STYLE_RULES = {
    "line_too_long": {"pattern": r".{121,}", "message": "行长度超过 120 字符"},
    "trailing_whitespace": {"pattern": r"[ \t]+$", "message": "行尾有多余空白"},
    "missing_type_hint": {
        "pattern": r"def\s+\w+\([^)]+\)(?!\s*->)",
        "message": "函数缺少返回类型注解",
    },
    "todo_without_ticket": {
        "pattern": r"#\s*TODO(?!\s*\(\#?\d+\))",
        "message": "TODO 未关联 ticket 编号",
    },
    "bare_except": {"pattern": r"except\s*:", "message": "使用裸 except,应指定异常类型"},
}

@mcp.tool()
def check_style(
    source_code: Annotated[str, Field(description="要检查的源代码")],
    rules: Annotated[list[str] | None, Field(
        description="要应用的规则名称列表,为空则应用全部规则"
    )] = None,
) -> dict:
    """
    检查代码是否符合编码规范。
    支持的规则:line_too_long, trailing_whitespace, missing_type_hint,
    todo_without_ticket, bare_except。
    """
    active_rules = rules if rules else list(STYLE_RULES.keys())
    violations = []
    lines = source_code.splitlines()

    for rule_name in active_rules:
        rule = STYLE_RULES.get(rule_name)
        if not rule:
            continue
        for i, line in enumerate(lines, 1):
            if re.search(rule["pattern"], line):
                violations.append({
                    "rule": rule_name,
                    "line": i,
                    "message": rule["message"],
                    "content": line.strip()[:80],
                })

    return {
        "total_violations": len(violations),
        "by_rule": {r: sum(1 for v in violations if v["rule"] == r)
                    for r in active_rules},
        "violations": violations,
    }

4.4 Tool:生成审查报告

@mcp.tool()
def generate_report(
    analysis: Annotated[dict, Field(description="analyze_code 的返回结果")],
    style_issues: Annotated[dict, Field(description="check_style 的返回结果")],
    project_name: Annotated[str, Field(description="项目名称")] = "未命名项目",
) -> str:
    """
    综合代码分析和规范检查结果,生成 Markdown 格式的审查报告。
    """
    lines = [
        f"# 代码审查报告:{project_name}",
        "",
        "## 概要",
        "",
        f"- 分析函数数量:{analysis.get('total_functions', 0)}",
        f"- 复杂度超标函数:{analysis.get('exceeding_threshold', 0)}",
        f"- 规范违规数量:{style_issues.get('total_violations', 0)}",
        "",
    ]

    # 复杂度警告
    high_complexity = [
        f for f in analysis.get("functions", [])
        if f.get("exceeds_threshold")
    ]
    if high_complexity:
        lines.append("## ⚠️ 复杂度警告")
        lines.append("")
        for func in high_complexity:
            lines.append(
                f"- `{func['function']}` (L{func['line']}): "
                f"复杂度 {func['complexity']}, {func['lines_of_code']} 行"
            )
        lines.append("")

    # 规范问题
    by_rule = style_issues.get("by_rule", {})
    if any(by_rule.values()):
        lines.append("## 📋 规范问题分布")
        lines.append("")
        for rule, count in by_rule.items():
            if count > 0:
                lines.append(f"- **{rule}**: {count} 处")
        lines.append("")

    # 详细违规
    violations = style_issues.get("violations", [])
    if violations:
        lines.append("## 详情")
        lines.append("")
        for v in violations[:20]:  # 限制前 20 条
            lines.append(f"- L{v['line']} [{v['rule']}]: {v['message']}")
        if len(violations) > 20:
            lines.append(f"- ... 还有 {len(violations) - 20} 条")
        lines.append("")

    lines.append("---")
    lines.append(f"*由 code-review MCP 自动生成*")

    return "\n".join(lines)

4.5 Resource:提供配置数据

Resource 是只读数据源,Claude Code 通过 URI 访问。适合提供上下文信息。

import json

REVIEW_RULES = {
    "complexity_threshold": 10,
    "max_line_length": 120,
    "required_type_hints": True,
    "severity_levels": {
        "critical": ["bare_except", "complexity > 20"],
        "warning": ["missing_type_hint", "complexity > 10"],
        "info": ["trailing_whitespace", "line_too_long"],
    },
}

REPORT_TEMPLATES = {
    "standard": "## {project} 审查报告\n\n{content}",
    "detailed": "# {project} 深度审查\n\n{content}\n\n## 附录\n{appendix}",
}

@mcp.resource("config://rules")
def get_review_rules() -> str:
    """获取代码审查规则配置"""
    return json.dumps(REVIEW_RULES, indent=2, ensure_ascii=False)

@mcp.resource("config://templates")
def get_report_templates() -> str:
    """获取报告模板列表"""
    return json.dumps(REPORT_TEMPLATES, indent=2, ensure_ascii=False)

Resource vs Tool 的选择原则:

graph TD
    A["需要暴露数据?"] -->|是| B{"有副作用?"}
    A -->|否| Z["不需要 MCP 原语"]
    B -->|是| C["用 Tool"]
    B -->|否| D{"数据量大?<br/>需要按需加载?"}
    D -->|是| E["用 Resource<br/>支持 URI 模板分页"]
    D -->|否| F{"需要参数化?"}
    F -->|是| G["用 Tool<br/>返回纯数据"]
    F -->|否| H["用 Resource"]

4.6 Prompt:参数化审查模板

Prompt 让用户可以通过 Claude Code 触发预定义的交互流程。

@mcp.prompt()
def review_template(
    file_path: str,
    focus: str = "all",
) -> str:
    """
    生成代码审查的提示模板。
    focus 参数控制审查重点:all / complexity / style / security
    """
    focus_instructions = {
        "all": "全面审查代码质量、复杂度、编码规范",
        "complexity": "重点审查函数复杂度和可维护性",
        "style": "重点审查编码规范和格式问题",
        "security": "重点审查安全漏洞和敏感信息泄露",
    }

    instruction = focus_instructions.get(focus, focus_instructions["all"])

    return f"""请对以下文件进行代码审查。

文件路径:{file_path}
审查重点:{instruction}

请按以下步骤执行:
1. 读取文件 {file_path} 的内容
2. 调用 analyze_code 工具分析代码复杂度
3. 调用 check_style 工具检查编码规范
4. 调用 generate_report 工具生成审查报告
5. 根据报告给出改进建议

先读取 config://rules 获取审查规则配置。"""

4.7 完整服务器代码

将以上所有部分合并为完整的 server.py:

#!/usr/bin/env python3
"""代码审查 MCP 服务器 - 基于 FastMCP"""

import ast
import json
import re
from typing import Annotated

from fastmcp import FastMCP
from pydantic import Field

mcp = FastMCP("code-review")

# ── 配置数据 ──────────────────────────────────────────

STYLE_RULES = { ... }  # 如上定义
REVIEW_RULES = { ... }
REPORT_TEMPLATES = { ... }

# ── 辅助函数 ──────────────────────────────────────────

def _calculate_complexity(node: ast.AST) -> int: ...  # 如上定义

# ── Tools ─────────────────────────────────────────────

@mcp.tool()
def analyze_code(...) -> dict: ...  # 如上定义

@mcp.tool()
def check_style(...) -> dict: ...  # 如上定义

@mcp.tool()
def generate_report(...) -> str: ...  # 如上定义

# ── Resources ─────────────────────────────────────────

@mcp.resource("config://rules")
def get_review_rules() -> str: ...

@mcp.resource("config://templates")
def get_report_templates() -> str: ...

# ── Prompts ───────────────────────────────────────────

@mcp.prompt()
def review_template(...) -> str: ...

# ── 启动入口 ──────────────────────────────────────────

if __name__ == "__main__":
    mcp.run()

五、Claude Code 集成配置

5.1 三种配置范围

graph TD
    subgraph "配置范围层级"
        L["Local Scope<br/>.claude/settings.local.json<br/>仅当前项目,个人使用"]
        P["Project Scope<br/>.mcp.json<br/>项目级,可提交 Git"]
        U["User Scope<br/>~/.claude.json<br/>全局,所有项目"]
    end

    L -->|"优先级最高"| P
    P -->|"次之"| U

推荐方案:团队共享用 .mcp.json(Project Scope),个人调试用 Local Scope。

5.2 使用 claude mcp add(推荐)

# User scope(全局可用)
claude mcp add code-review \
  --scope user \
  -- uv run --directory /home/user/code-review-mcp python server.py

# Project scope(提交到 Git,团队共享)
claude mcp add code-review \
  --scope project \
  -- uv run --directory ./tools/code-review-mcp python server.py

# Local scope(个人调试)
claude mcp add code-review \
  --scope local \
  -- uv run python server.py

5.3 手动配置 .mcp.json

在项目根目录创建 .mcp.json(推荐纳入版本控制):

{
  "mcpServers": {
    "code-review": {
      "command": "uv",
      "args": ["run", "--directory", "./tools/code-review-mcp", "python", "server.py"],
      "env": {}
    }
  }
}

带环境变量的配置:

{
  "mcpServers": {
    "code-review": {
      "command": "uv",
      "args": ["run", "python", "server.py"],
      "env": {
        "REVIEW_STRICTNESS": "high",
        "MAX_COMPLEXITY": "8"
      }
    }
  }
}

5.4 管理命令速查

# 列出已配置的服务器
claude mcp list

# 查看服务器详情
claude mcp get code-review

# 删除服务器
claude mcp remove code-review

# 重置所有 MCP 服务器配置
claude mcp reset

六、调试与测试

6.1 MCP Inspector:可视化调试利器

MCP Inspector 是官方调试工具,提供浏览器界面来测试服务器。

# 安装并启动 Inspector
npx @modelcontextprotocol/inspector uv run python server.py

浏览器打开 http://localhost:6274,你可以:

  1. Tools 标签页:选择 Tool → 填写参数 → 执行 → 查看返回值
  2. Resources 标签页:浏览可用 Resource,点击 URI 获取内容
  3. Prompts 标签页:列出 Prompt 模板,填参数预览结果
  4. Messages 标签页:查看底层 JSON-RPC 消息日志

6.2 编写单元测试

# test_server.py
import pytest
from server import analyze_code, check_style, generate_report

def test_analyze_code_simple():
    code = """
def add(a, b):
    return a + b
"""
    result = analyze_code(code)
    assert result["total_functions"] == 1
    assert result["functions"][0]["function"] == "add"
    assert result["functions"][0]["complexity"] == 1

def test_analyze_code_complex():
    code = """
def process(data):
    if data:
        for item in data:
            if item.active:
                try:
                    item.save()
                except ValueError:
                    pass
                except TypeError:
                    pass
"""
    result = analyze_code(code, threshold=5)
    assert result["total_functions"] == 1
    assert result["exceeding_threshold"] == 1

def test_check_style_bare_except():
    code = """try:
    x = 1
except:
    pass
"""
    result = check_style(code, rules=["bare_except"])
    assert result["total_violations"] == 1

def test_check_style_clean():
    code = "x = 1\n"
    result = check_style(code)
    assert result["total_violations"] == 0

def test_analyze_invalid_syntax():
    result = analyze_code("def (broken syntax")
    assert "error" in result

def test_generate_report():
    analysis = {
        "total_functions": 2,
        "exceeding_threshold": 1,
        "functions": [
            {"function": "ok_func", "line": 1, "complexity": 2,
             "lines_of_code": 3, "exceeds_threshold": False},
            {"function": "bad_func", "line": 5, "complexity": 15,
             "lines_of_code": 40, "exceeds_threshold": True},
        ],
    }
    style = {
        "total_violations": 3,
        "by_rule": {"bare_except": 1, "line_too_long": 2},
        "violations": [
            {"rule": "bare_except", "line": 10, "message": "裸 except"},
        ],
    }
    report = generate_report(analysis, style, "test-project")
    assert "# 代码审查报告:test-project" in report
    assert "bad_func" in report

运行测试:

uv add --dev pytest
uv run pytest test_server.py -v

6.3 直接调用调试

无需 Claude Code,直接在 Python 中测试:

# debug.py
from server import mcp

# 查看注册的所有原语
print("Tools:", [t.name for t in mcp._tool_manager.tools.values()])
print("Resources:", [r.name for r in mcp._resource_manager.resources.values()])
print("Prompts:", [p.name for p in mcp._prompt_manager.prompts.values()])

# 直接调用 Tool
result = mcp._tool_manager.call_tool("analyze_code", {
    "source_code": "def hello(): pass"
})
print("Result:", result)

6.4 常见调试排查

graph TD
    A["MCP 服务器异常"] --> B{"Claude Code<br/>能看到工具?"}
    B -->|"看不到"| C["检查 claude mcp list"]
    C --> C1["路径是否绝对?"]
    C --> C2["uv sync 是否执行?"]
    C --> C3["Python 版本 3.10+?"]

    B -->|"看到但调用失败"| D["查看 Claude Code 日志"]
    D --> D1["参数类型不匹配?"]
    D --> D2["返回值序列化失败?"]
    D --> D3["异常被吞掉了?"]

    D1 --> E["添加类型注解"]
    D2 --> F["确保返回 dict/str"]
    D3 --> G["添加 try/except 日志"]

七、进阶:Streamable HTTP 模式

当你需要远程部署或多客户端共享时,使用 Streamable HTTP 传输。

7.1 修改启动方式

# server.py 末尾修改
if __name__ == "__main__":
    mcp.run(transport="streamable-http", host="0.0.0.0", port=8080)

启动:

uv run python server.py
# 服务器监听 http://0.0.0.0:8080/mcp

7.2 Claude Code 配置远程服务器

{
  "mcpServers": {
    "code-review-remote": {
      "url": "http://your-server:8080/mcp"
    }
  }
}

7.3 Docker 部署

# Dockerfile
FROM python:3.12-slim

WORKDIR /app
COPY pyproject.toml .
RUN pip install uv && uv sync --no-dev
COPY server.py .

EXPOSE 8080
CMD ["uv", "run", "python", "server.py"]
# docker-compose.yml
services:
  code-review-mcp:
    build: .
    ports:
      - "8080:8080"
    environment:
      - REVIEW_STRICTNESS=high
    restart: unless-stopped
docker compose up -d

八、实战案例:完整的代码审查工作流

8.1 端到端工作流

sequenceDiagram
    participant User as 开发者
    participant CC as Claude Code
    participant MCP as code-review MCP
    participant FS as 文件系统

    User->>CC: /review src/auth/login.py
    CC->>MCP: 调用 review_template Prompt
    MCP-->>CC: 返回审查流程提示

    CC->>MCP: 读取 config://rules
    MCP-->>CC: 返回审查规则配置

    CC->>FS: 读取 src/auth/login.py
    FS-->>CC: 返回源代码内容

    CC->>MCP: 调用 analyze_code(source_code)
    MCP-->>CC: 返回复杂度分析结果

    CC->>MCP: 调用 check_style(source_code)
    MCP-->>CC: 返回规范检查结果

    CC->>MCP: 调用 generate_report(analysis, style)
    MCP-->>CC: 返回 Markdown 报告

    CC->>User: 展示审查报告 + 改进建议

8.2 增强版:支持多语言

扩展 Tool 支持不同语言的复杂度分析:

LANGUAGE_ANALYZERS = {
    "python": _analyze_python,
    "javascript": _analyze_javascript,
    "go": _analyze_go,
}

@mcp.tool()
def analyze_code_multilang(
    source_code: Annotated[str, Field(description="源代码")],
    language: Annotated[str, Field(description="语言: python/javascript/go")],
    threshold: Annotated[int, Field(description="复杂度阈值")] = 10,
) -> dict:
    """分析多种编程语言的代码复杂度"""
    analyzer = LANGUAGE_ANALYZERS.get(language)
    if not analyzer:
        return {"error": f"不支持的语言: {language},支持: {list(LANGUAGE_ANALYZERS.keys())}"}
    return analyzer(source_code, threshold)

8.3 增强版:进度反馈

对于长时间操作,使用 Progress 通知:

@mcp.tool()
async def analyze_large_project(
    directory: Annotated[str, Field(description="项目目录路径")],
    ctx: Annotated[Context, Field(description="MCP 上下文")] = None,
) -> dict:
    """分析整个项目的代码质量(带进度通知)"""
    import os

    py_files = []
    for root, _, files in os.walk(directory):
        py_files.extend(
            os.path.join(root, f) for f in files if f.endswith(".py")
        )

    all_results = []
    total = len(py_files)

    for i, filepath in enumerate(py_files):
        # 发送进度通知
        if ctx:
            await ctx.report_progress(i + 1, total)

        with open(filepath) as f:
            result = analyze_code(f.read())
            result["file"] = filepath
            all_results.append(result)

    return {
        "files_analyzed": total,
        "results": all_results,
    }

8.4 使用 Context 访问日志

from fastmcp import Context

@mcp.tool()
async def smart_review(
    source_code: str,
    ctx: Context,
) -> str:
    """带日志的智能审查"""
    # 记录日志(Claude Code 可见)
    await ctx.info(f"开始审查 {len(source_code)} 字符的代码")

    analysis = analyze_code(source_code)
    style = check_style(source_code)

    await ctx.info(f"发现 {analysis['exceeding_threshold']} 个高复杂度函数")
    await ctx.info(f"发现 {style['total_violations']} 处规范问题")

    report = generate_report(analysis, style)
    return report

九、生产级最佳实践

9.1 错误处理策略

from fastmcp import FastMCP

mcp = FastMCP("code-review", 
    # 错误不暴露内部堆栈
    mask_error_details=True
)

@mcp.tool()
def safe_analyze(code: str) -> dict:
    """安全的代码分析,错误友好返回"""
    try:
        result = analyze_code(code)
    except MemoryError:
        return {"error": "代码过大,请分段分析"}
    except RecursionError:
        return {"error": "代码嵌套层级过深"}
    except Exception as e:
        return {"error": f"分析失败: {type(e).__name__}"}
    return result

9.2 性能优化

import functools

# 缓存 Resource 数据(规则配置不常变)
@mcp.resource("config://rules")
@functools.lru_cache(maxsize=1)
def get_review_rules() -> str:
    """获取审查规则(缓存)"""
    return json.dumps(REVIEW_RULES, indent=2, ensure_ascii=False)

# 大文件分块处理
@mcp.tool()
def analyze_code_chunked(
    source_code: str,
    chunk_size: Annotated[int, Field(description="每块行数")] = 200,
) -> dict:
    """分块分析大文件"""
    lines = source_code.splitlines()
    chunks = [lines[i:i+chunk_size] for i in range(0, len(lines), chunk_size)]

    results = []
    for i, chunk in enumerate(chunks):
        chunk_code = "\n".join(chunk)
        result = analyze_code(chunk_code)
        result["chunk"] = i + 1
        results.append(result)

    return {
        "total_chunks": len(chunks),
        "chunk_results": results,
    }

9.3 安全考量

import os

@mcp.tool()
def analyze_file(
    file_path: Annotated[str, Field(description="文件路径")],
) -> dict:
    """安全地分析指定文件"""
    # 防止路径穿越
    base_dir = os.getenv("ALLOWED_DIR", ".")
    abs_path = os.path.abspath(os.path.join(base_dir, file_path))

    if not abs_path.startswith(os.path.abspath(base_dir)):
        return {"error": "路径越界,拒绝访问"}

    if not os.path.exists(abs_path):
        return {"error": f"文件不存在: {file_path}"}

    # 限制文件大小
    if os.path.getsize(abs_path) > 1_000_000:  # 1MB
        return {"error": "文件过大(>1MB),请分段处理"}

    with open(abs_path) as f:
        return analyze_code(f.read())

十、开发效率提升:完整项目结构

code-review-mcp/
├── pyproject.toml          # 项目配置
├── server.py               # MCP 服务器主入口
├── analyzers/              # 分析器模块
│   ├── __init__.py
│   ├── complexity.py       # 复杂度分析
│   ├── style.py            # 规范检查
│   └── security.py         # 安全检查
├── config/                 # 配置文件
│   ├── rules.json          # 审查规则
│   └── templates.json      # 报告模板
├── tests/                  # 测试
│   ├── test_complexity.py
│   ├── test_style.py
│   └── test_server.py
├── Dockerfile              # Docker 部署
├── docker-compose.yml      # 编排配置
└── .mcp.json               # Claude Code 项目级配置

十步交付清单

graph LR
    A["1. uv init"] --> B["2. 安装 FastMCP"]
    B --> C["3. 实现 Tool"]
    C --> D["4. 实现 Resource"]
    D --> E["5. 实现 Prompt"]
    E --> F["6. 编写测试"]
    F --> G["7. Inspector 调试"]
    G --> H["8. claude mcp add"]
    H --> I["9. 集成验证"]
    I --> J["10. Docker 部署"]
步骤 命令 预期结果
1 uv init && cd code-review-mcp 项目创建成功
2 uv add fastmcp 依赖安装完成
3 编写 server.py 中的 Tool 函数 函数可被 @mcp.tool() 注册
4 添加 Resource 装饰器 URI 可访问
5 添加 Prompt 模板 模板可触发
6 uv run pytest tests/ -v 全部测试通过
7 npx @modelcontextprotocol/inspector uv run python server.py 浏览器可交互测试
8 claude mcp add code-review -- uv run python server.py 服务器出现在列表
9 Claude Code 中调用 Tool 返回正确结果
10 docker compose up -d HTTP 模式正常监听

十一、TypeScript vs Python:如何选择

维度 Python (FastMCP) TypeScript (官方 SDK)
上手速度 极快(装饰器驱动) 较快(面向对象)
生态兼容 ML/AI/数据处理 Web 开发/Node.js 生态
类型安全 Pydantic 运行时 Zod + TS 编译时
性能 够用(I/O 密集型场景) 更优(CPU 密集型)
部署 Docker / Serverless Docker / Edge / Serverless
适用场景 数据分析、ML Pipeline、脚本工具 Web 服务、API 网关、前后端统一

建议:已有 Python 代码库或涉及数据/ML → 选 FastMCP;已有 TypeScript 项目或需要 Web 集成 → 选官方 SDK。


延伸阅读

参考来源

  1. Claude Code MCP Servers: The Complete Setup Guide for 2026 — Claude Code MCP 配置完整指南
  2. Build an MCP Server in Python: FastMCP Guide — FastMCP Python 开发教程
  3. MCP Python SDK GitHub — 官方 Python SDK 源码和示例
  4. FastMCP Python MCP Server Build Guide 2026 — FastMCP 3.x 实战指南
  5. Docker MCP Server Best Practices — Docker 官方 MCP 部署最佳实践

训练营适用性评估

项目 评估
适合训练营类型 AI 工具开发、Python 进阶、DevOps 自动化
教学时长 3-4 小时(含动手实验)
难度等级 中级(需要 Python 基础)
实验环境要求 Python 3.10+、Claude Code、Node.js(Inspector)
可拆分模块 基础篇(1-5节,2h)+ 进阶篇(6-10节,2h)

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入