<!-- title: 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） |

安装核心依赖：

```bash
# 推荐 uv（更快）
uv pip install fastmcp

# 或传统 pip
pip install fastmcp
```

验证安装：

```bash
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 三大原语对比

```mermaid
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 两种传输方式

```mermaid
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 以子进程启动你的服务器，通过 stdin/stdout 通信。最简单，适合本地开发。
- **Streamable HTTP**：服务器独立运行，通过 HTTP 端点通信。适合远程部署和多客户端。

本教程使用 stdio 模式（最常用的 Claude Code 集成方式），最后介绍 HTTP 模式。

---

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

### 3.1 创建项目结构

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

编辑 `pyproject.toml`：

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

### 3.2 最小服务器代码

创建 `server.py`：

```python
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 本地测试

```bash
# 安装依赖
uv sync

# 启动服务器（stdio 模式）
uv run python server.py
```

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

### 3.4 接入 Claude Code

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

验证：

```bash
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 整体架构

```mermaid
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。

```python
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：编码规范检查

```python
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：生成审查报告

```python
@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 访问。适合提供上下文信息。

```python
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 的选择原则**：

```mermaid
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 触发预定义的交互流程。

```python
@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`：

```python
#!/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 三种配置范围

```mermaid
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（推荐）

```bash
# 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`（推荐纳入版本控制）：

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

带环境变量的配置：

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

### 5.4 管理命令速查

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

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

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

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

---

## 六、调试与测试

### 6.1 MCP Inspector：可视化调试利器

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

```bash
# 安装并启动 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 编写单元测试

```python
# 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
```

运行测试：

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

### 6.3 直接调用调试

无需 Claude Code，直接在 Python 中测试：

```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 常见调试排查

```mermaid
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 修改启动方式

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

启动：

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

### 7.2 Claude Code 配置远程服务器

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

### 7.3 Docker 部署

```dockerfile
# 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"]
```

```yaml
# docker-compose.yml
services:
  code-review-mcp:
    build: .
    ports:
      - "8080:8080"
    environment:
      - REVIEW_STRICTNESS=high
    restart: unless-stopped
```

```bash
docker compose up -d
```

---

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

### 8.1 端到端工作流

```mermaid
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 支持不同语言的复杂度分析：

```python
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 通知：

```python
@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 访问日志

```python
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 错误处理策略

```python
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 性能优化

```python
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 安全考量

```python
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 项目级配置
```

### 十步交付清单

```mermaid
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。

---

## 延伸阅读

- [FastMCP 官方文档](https://gofastmcp.com) — FastMCP 框架完整 API 参考
- [MCP 规范文档](https://modelcontextprotocol.io/specification/2025-03-26) — 协议规范的权威来源
- [MCP Inspector GitHub](https://github.com/modelcontextprotocol/inspector) — 调试工具源码和使用指南
- [Anthropic MCP 工程博客](https://www.anthropic.com/engineering/code-execution-with-mcp) — 官方 MCP 工程实践
- [Claude Code MCP 配置文档](https://code.claude.com/docs/en/mcp) — Claude Code MCP 集成官方指南

## 参考来源

1. [Claude Code MCP Servers: The Complete Setup Guide for 2026](https://thepromptshelf.dev/blog/claude-code-mcp-setup-guide/) — Claude Code MCP 配置完整指南
2. [Build an MCP Server in Python: FastMCP Guide](https://tech-insider.org/how-to-build-mcp-server-python-fastmcp-tutorial/) — FastMCP Python 开发教程
3. [MCP Python SDK GitHub](https://github.com/modelcontextprotocol/python-sdk) — 官方 Python SDK 源码和示例
4. [FastMCP Python MCP Server Build Guide 2026](https://jangwook.net/en/blog/en/fastmcp-python-mcp-server-build-guide-2026/) — FastMCP 3.x 实战指南
5. [Docker MCP Server Best Practices](https://www.docker.com/blog/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学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
