模型上下文协议工具集成标准

MCP(模型上下文协议)是一个开放标准,用于定义AI模型与外部工具、数据源和服务的标准化连接方式,简化AI工具集成并提高可重用性。

  • by shashipk
  • Python
  • 本地部署
  • 2 星标
  • 更新于
在 GitHub 查看 shashipk/mcp_explained

使用说明

MCP解析——通过代码理解模型上下文协议

一个动手学习项目,解释 MCP(模型上下文协议) 通过工作Python代码——它是什么,为什么存在,以及它如何使AI工具集成更简单、更强大。


目录


什么是MCP?

模型上下文协议(MCP) 是由Anthropic开发(现已广泛采用)的开放标准,定义了 人工智能模型连接到外部工具、数据源和服务的标准化方式.

把它想象成 用于AI工具的USB:

  • USB标准化了设备连接到计算机的方式——一个端口,无限兼容设备
  • MCP规范了工具如何连接到AI模型——一个协议、无限兼容的工具和AI模型

在MCP之前,每个开发人员都必须在他们的工具和每个AI模型之间构建自定义集成。在MCP之后,您只需构建一次工具服务器,它就可以与任何兼容MCP的AI一起工作。

简而言之

Without MCP: "I need to write code to make my tool work with Claude,
              then rewrite it for GPT, then again for Gemini..."

With MCP:    "I build an MCP server once. Claude, GPT, Gemini — they
              all connect to the same server using the same protocol."

为什么我们需要MCP?

问题:N×M积分

想象一下,你有 5工具 (计算器、数据库、文件系统、天气API、日历)和 4个AI模型 (克劳德,GPT-4,双子座,拉玛)。没有标准:

5 tools × 4 AI models = 20 custom integrations to build and maintain

每个集成都有自己的模式格式、调用约定、响应格式、身份验证机制和错误处理——所有这些都是不同的,都是重复的。

解决方案:N+M集成

使用MCP:

5 tools (each as an MCP server)  +  4 AI clients (each MCP-compatible)
= 9 total things to build

每个工具都是写的 一次 作为MCP服务器。每个AI客户端都是构建的 一次 作为MCP客户端。他们都通过标准协议相互交谈。

MCP解决的其他问题

问题 没有MCP 有MCP
工具重复使用 在应用程序之间复制粘贴代码 将任何应用程序指向同一服务器
可发现性 硬编码哪些工具存在 客户端在运行时发现工具
关注点分离 工具代码与AI逻辑混合 干净分割:服务器=工具,客户端=AI
生态系统 每个开发人员都在重新发明轮子 不断增长的可重用服务器库
更新 更新工具=更新每个AI应用程序 更新服务器=所有客户端都得到它
安全 工具代码在任何地方运行 工具代码在受控服务器中运行

MCP的工作原理

建筑

┌─────────────────────────────────────────────────────────────────┐
│                         YOUR APPLICATION                         │
│                                                                  │
│  ┌──────────────────┐            ┌─────────────────────────┐    │
│  │    MCP CLIENT     │           │      Claude API          │    │
│  │  (mcp_client.py) │◄─────────►│  (or GPT / Gemini / ...) │   │
│  └────────┬─────────┘            └─────────────────────────┘    │
│           │                                                      │
│     MCP Protocol                                                 │
│     (JSON-RPC over stdio / SSE / WebSocket)                     │
│           │                                                      │
│  ┌────────▼─────────┐                                           │
│  │    MCP SERVER     │                                           │
│  │  (mcp_server.py) │                                           │
│  │                  │                                           │
│  │  Tools exposed:  │                                           │
│  │   • calculate    │                                           │
│  │   • get_weather  │                                           │
│  │   • save_note    │                                           │
│  │   • get_note     │                                           │
│  │   • list_notes   │                                           │
│  │   • get_datetime │                                           │
│  │   • word_count   │                                           │
│  └──────────────────┘                                           │
└─────────────────────────────────────────────────────────────────┘

沟通流程(循序渐进)

User types: "What is sqrt(144) + 10^2?"
                    │
                    ▼
           MCP Client sends to Claude API
           (includes list of tools discovered from MCP server)
                    │
                    ▼
         Claude thinks: "I need the calculator tool"
         Claude responds: tool_use { name: "calculate", input: {...} }
                    │
                    ▼
         MCP Client routes to MCP Server via call_tool()
         Server executes the calculation
         Server returns: "Result: 112"
                    │
                    ▼
         MCP Client sends tool_result back to Claude
                    │
                    ▼
         Claude responds: "sqrt(144) is 12, and 10² is 100, so the answer is 112."
                    │
                    ▼
         User sees the final answer

协议:基于stdio的JSON-RPC

MCP使用 JSON-RPC 2.0 --简单的请求/响应格式。这是客户端和服务器之间实际流动的内容:

// Client → Server: "What tools do you have?"
{ "jsonrpc": "2.0", "method": "tools/list", "id": 1 }

// Server → Client: "Here are my tools"
{ "jsonrpc": "2.0", "result": { "tools": [...] }, "id": 1 }

// Client → Server: "Run the calculator"
{ "jsonrpc": "2.0", "method": "tools/call",
  "params": { "name": "calculate", "arguments": { "expression": "sqrt(144)" } },
  "id": 2 }

// Server → Client: "Here's the result"
{ "jsonrpc": "2.0", "result": { "content": [{ "type": "text", "text": "Result: 12" }] }, "id": 2 }

所有这些都是自动发生的—— mcp Python库处理它。你只需编写工具逻辑,库就可以进行消息传递。


本项目

MCP服务器内置的工具

工具 它做什么 它展示了什么
calculate 安全地评估数学表达式 工具可以包装现有的Python库
get_weather 返回任何城市的模拟天气 工具可以调用外部API
save_note 留一张便条给 data/notes.json 工具可以读/写文件(有状态)
get_note 按键检索笔记 工具可以返回存储的数据
list_notes 列出所有已保存的笔记键 工具不能有必需的参数
get_datetime 返回当前UTC日期/时间 简单实用工具
word_count 统计文本中的单词/字符/句子 文本处理工具

文件及其目的

文件 目的
server/mcp_server.py MCP服务器--定义并运行所有7个工具
client/mcp_client.py MCP客户端连接到服务器,使用Claude回答问题
examples/01_without_mcp.py 传统方法——人工智能客户端中硬编码的工具
examples/02_with_mcp.py MCP方法——结果相同,客户端无工具代码

项目结构

mcp_explained/
│
├── README.md                    ← You are here
├── pyproject.toml               ← Project dependencies (uv)
├── requirements.txt             ← Same deps for pip users
├── .env.example                 ← API key template
├── .gitignore
│
├── server/
│   └── mcp_server.py            ← THE MCP SERVER
│                                   Exposes 7 tools via stdio transport
│                                   Any MCP-compatible AI can connect to this
│
├── client/
│   └── mcp_client.py            ← THE MCP CLIENT
│                                   Connects to server, uses Claude + MCP
│                                   Interactive CLI + scripted demo mode
│
├── examples/
│   ├── 01_without_mcp.py        ← Traditional approach (hardcoded tools)
│   └── 02_with_mcp.py           ← MCP approach (dynamic discovery)
│
└── data/
    └── notes.json               ← Persisted notes (created at runtime)

快速开始

📖 需要更多细节吗? 请参阅 完整的分步安装指南 它涵盖了uv和pip方法、验证步骤、所有运行命令以及完整的故障排除部分。

先决条件

账单备注: 此项目使用 claude-haiku-4-5-20251001 例如(最便宜的型号)。 完整的演示课程费用低于 $0.01.在以下位置添加至少5美元的信用额度 console.anthropic.com/settings/billion.


步骤1——克隆仓库

git clone https://github.com/shashipk/mcp_explained.git
cd mcp_explained

步骤2——安装依赖项

紫外线(推荐):

uv sync

使用pip:

python3 -m venv .venv
source .venv/bin/activate      # macOS/Linux
pip install -r requirements.txt

步骤3-添加您的API密钥

cp .env.example .env

打开 .env 在任何编辑器中,替换占位符:

ANTHROPIC_API_KEY=sk-ant-api03-your-actual-key-here

如何获取密钥:

  1. 首选 console.anthropic.com/settings/keys
  2. 点击 创建密钥,随便命名(例如。 mcp-learning)
  3. 复制密钥——它以开头 sk-ant-...
  4. 将其粘贴到 .env (值周围没有引号)

第4步——验证一切正常

# Check that all packages are importable
uv run python -c "import mcp, anthropic, dotenv, rich; print('All OK')"
# Expected: All OK

# Confirm your API key loads
uv run python -c "
from dotenv import load_dotenv; import os
load_dotenv('.env', override=True)
key = os.environ.get('ANTHROPIC_API_KEY', '')
print('Key OK' if key.startswith('sk-ant') else 'Key missing — check your .env')
"

建议学习路径

如果您是MCP的新手,请按以下顺序操作:

1. Read "What is MCP?" and "Why Do We Need MCP?" above
         ↓
2. Run Example 1 (without MCP) — see the problem
   uv run python examples/01_without_mcp.py
         ↓
3. Run Example 2 (with MCP) — see the solution
   uv run python examples/02_with_mcp.py
         ↓
4. Compare the two files side by side in your editor
   Open: examples/01_without_mcp.py  vs  examples/02_with_mcp.py
         ↓
5. Read the server code with comments
   Open: server/mcp_server.py
         ↓
6. Read the client code with comments
   Open: client/mcp_client.py
         ↓
7. Run the interactive client and experiment
   uv run python client/mcp_client.py

运行示例

pip用户注意事项: 如果您使用pip而不是uv,请先激活您的venv: source .venv/bin/activate (macOS/Linux)或 .venv\Scripts\activate (Windows) 然后使用 python 而不是 uv run python.


示例1:没有MCP(旧方法)

uv run python examples/01_without_mcp.py

在输出中要注意什么:

  • 工具模式在文件中定义(搜索 TOOLS_HARDCODED_IN_THIS_FILE)
  • 工具逻辑在文件中运行(请参见 execute_tool_locally())
  • 要添加新工具,您必须修改此文件

尝试一个自定义问题:

uv run python examples/01_without_mcp.py "What is 15 squared plus sqrt(81)?"

示例2:使用MCP(正确的方式)

uv run python examples/02_with_mcp.py

注意事项:

  • 此文件中没有工具模式-- session.list_tools() 从服务器获取它们
  • 此文件中没有工具逻辑-- session.call_tool() 在服务器中运行它
  • 此文件将自动获得您添加到的任何新工具 server/mcp_server.py

尝试相同的自定义问题:

uv run python examples/02_with_mcp.py "What is 15 squared plus sqrt(81)?"

同样的答案。完全不同的架构。


交互式客户端(完整体验)

# Interactive mode — ask Claude anything
uv run python client/mcp_client.py

# Pass a question directly
uv run python client/mcp_client.py "What is the area of a circle with radius 5?"

# Scripted demo — automatically shows all 7 tools
uv run python client/mcp_client.py --demo

尝试涵盖所有7个工具的问题:

# Calculator
"What is log base 2 of 1024, and what is 15 factorial?"

# Weather
"Compare the weather in Tokyo, Mumbai, and New York."

# Notes — try these in sequence
"Save a note called 'mcp-insight' with this text: MCP lets you build tools once and reuse them with any AI."
"What notes do I have saved?"
"Read the note called 'mcp-insight'"

# Word count
"How many words are in: Four score and seven years ago our fathers brought forth on this continent a new nation."

# Date / Time
"What day of the week is it today, and what is the Unix timestamp right now?"

关键概念深度学习

1.MCP服务器(server/mcp_server.py)

MCP服务器是一个带有两个处理程序的Python脚本:

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types

app = Server("my-server")

# Handler 1: Tell clients what tools exist
@app.list_tools()
async def list_tools() -> list[types.Tool]:
    return [
        types.Tool(
            name="my_tool",
            description="Does something useful",  # Claude reads this to decide when to use the tool
            inputSchema={"type": "object", "properties": {...}}
        )
    ]

# Handler 2: Execute a tool when called
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
    if name == "my_tool":
        result = do_something(arguments)
        return [types.TextContent(type="text", text=result)]

2.MCP客户端(client/mcp_client.py)

MCP客户端连接到服务器并将其与AI桥接:

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

# 1. Define how to launch the server
server_params = StdioServerParameters(command="python", args=["server/mcp_server.py"])

# 2. Connect
async with stdio_client(server_params) as (read, write):
    async with ClientSession(read, write) as session:
        await session.initialize()                    # MCP handshake

        tools = await session.list_tools()            # discover tools dynamically
        result = await session.call_tool(name, args)  # execute a tool in the server

3.传输层

MCP支持客户端和服务器的多种通信方式:

运输 用例 工作原理
标准 本地工具(同一台机器) 客户端将服务器作为子进程启动;通过stdin/stdout进行通信
SSE(HTTP) 远程工具(不同的机器) 服务器作为HTTP端点运行;客户端通过服务器发送的事件进行连接
WebSocket 双向远程工具 全双工连接

此项目使用 标准 --最容易在本地设置和运行。在生产环境中,您可以使用SSE或WebSocket通过网络公开服务器,以便多个客户端可以连接。

4.工具模式(JSON模式)

每个工具都用JSON模式描述。Claude使用它来了解要发送哪些参数:

types.Tool(
    name="calculate",
    description="Evaluate a math expression",   # ← Claude reads this to decide WHEN to use the tool
    inputSchema={
        "type": "object",
        "properties": {
            "expression": {
                "type": "string",
                "description": "e.g. 'sqrt(144)', '2 + 2 * 10'"  # ← Claude reads this to format its call
            }
        },
        "required": ["expression"]
    }
)

5.代理循环

Claude并没有预先调用所有工具——它一步一步地推理:

Turn 1  →  User: "What is sqrt(144)?"
Turn 2  →  Claude: tool_use { name: "calculate", input: { "expression": "sqrt(144)" } }
Turn 3  →  User:   tool_result { content: "Result: 12.0" }
Turn 4  →  Claude: "The square root of 144 is 12."   [stop_reason: "end_turn"]

对于复杂的问题,克劳德可能会在给出最终答案之前,在多个回合中调用多个工具。

6.MCP与本地工具使用

您可能会想:“Claude已经原生支持工具使用——为什么要在上面添加MCP?”

特性 本机工具使用(无MCP) 使用MCP
工具模式 在应用程序中硬编码 在可重用服务器中定义
工具逻辑 在应用程序中运行 在服务器中运行
可重用性 零--每个应用程序复制粘贴 完全--任何MCP客户端都可以连接
多模型 每个模型都必须重写 一台服务器适用于所有模型
发现 静态--您预先定义它 动态--客户端在运行时询问服务器
生态系统 无-你构建一切 数百个可用的社区服务器

MCP是一种 标准化层 除了原生工具的使用。客户端仍然发送本机Anthropic格式的工具调用——MCP只是定义了如何在单独的服务器中发现和执行这些工具。


并排理解代码

同样的问题,两种架构:

无MCP (examples/01_without_mcp.py):

# ❌ Tool schemas defined HERE (in the AI client)
TOOLS = [{"name": "calculate", "description": "...", "input_schema": {...}}]

# ❌ Tool logic runs HERE (in the AI client)
def execute_tool_locally(name, args):
    if name == "calculate":
        return str(eval(args["expression"], ...))

# ❌ Reuse = copy-paste this entire file into every new app

使用MCP (examples/02_with_mcp.py):

# ✅ Tool schemas come FROM the server (zero hardcoding here)
tools_response = await session.list_tools()
anthropic_tools = [{"name": t.name, ...} for t in tools_response.tools]

# ✅ Tool logic runs IN the server (zero implementation code here)
result = await session.call_tool(block.name, block.input)

# ✅ Reuse = point any new app at the same server

MCP生态系统

MCP已被所有主要AI平台采用:

  • Anthropic -Claude Desktop,Claude API
  • 开放人工智能 --ChatGPT(2025年宣布支持MCP)
  • 谷歌 --Gemini(社区MCP客户)
  • 微软 --GitHub Copilot,VS Code AI扩展

社区MCP服务器

社区已经构建了数百台即用型MCP服务器:

服务器 它连接到什么
mcp-server-filesystem 本地文件系统(读/写文件)
mcp-server-git Git仓库
mcp-server-github GitHub API(问题、PR、转发)
mcp-server-postgres PostgreSQL数据库
mcp-server-brave-search 勇敢的网络搜索
mcp-server-puppeteer 浏览器自动化
mcp-server-slack Slack消息

更多信息请访问: github/modelcontextprotocol/servers


故障排除

API密钥未加载(ANTHROPIC_API_KEY not set)

如果您在设置密钥后仍看到此错误 .env,您的shell可能已经 ANTHROPIC_API_KEY 设置为空字符串-- load_dotenv 默认情况下不会覆盖现有的shell变量。

此项目中的所有文件都已包含 override=True 要处理此问题:

load_dotenv(Path(__file__).parent.parent / ".env", override=True)

如果您仍然有问题,请验证:

# Does the .env file exist and contain the key?
cat .env | grep ANTHROPIC_API_KEY

# Does it load correctly?
uv run python -c "
from dotenv import load_dotenv; import os
load_dotenv('.env', override=True)
key = os.environ.get('ANTHROPIC_API_KEY', '')
print('OK' if key.startswith('sk-ant') else 'Missing or wrong format')
"

credit balance is too low

anthropic.BadRequestError: Your credit balance is too low to access the Anthropic API.

在以下位置添加学分 console.anthropic.com/settings/billion5美元的充值足以完成这个项目的数百次运行。


ModuleNotFoundError: No module named 'mcp'

你在虚拟环境之外运行Python。使用 uv run python 而不是 python:

uv run python examples/01_without_mcp.py    # ✓ uses venv
python examples/01_without_mcp.py           # ✗ uses system Python

或者使用pip,先激活venv:

source .venv/bin/activate
python examples/01_without_mcp.py

服务器似乎挂起,没有输出

server/mcp_server.py 被设计为 由客户端作为子流程启动 --它等待stdin上的JSON-RPC输入。直接运行它不会显示任何输出(这是正确的——它正在等待客户端)。始终运行客户端:

uv run python client/mcp_client.py    # ✓ the client launches the server automatically

许可证

麻省理工学院——见 许可证


作者

作为一个学习项目,通过工作代码了解MCP。如果这对你有帮助,给它一个⭐ 在GitHub上!


用途 claude-opus-4-6 对于交互式客户端和 claude-haiku-4-5-20251001 例如(演示更快、更便宜)。