Skip to main content
Glama
mhamzanadeem

mcp-demo-server

by mhamzanadeem

MCP 演示 — 从零构建 Python 智能体工具


什么是 MCP?

MCP(模型上下文协议) 是一种标准化协议,让 AI 应用能够通过一个一致的接口发现并使用外部的工具、资源和提示

与其让每个 AI 框架为每个数据库、API、文件系统或内部服务发明不同的集成方式,MCP 主机可以连接到 MCP 服务器并使用相同的协议表面。

MCP 解决的问题

问题

MCP 解决方案

供应商锁定

集成通过 MCP 暴露能力,而不是绑定到某个模型提供商或智能体框架

工具调用不一致

工具具有机器可读的模式和标准化的发现/调用语义

无上下文持久化

MCP 将上下文/工具提供者与模型分离,支持长连接

动态数据源

数据库、API、文件和内部系统被封装为 MCP 资源/工具,而无需将实现嵌入模型运行时

在传输层,MCP 使用 JSON-RPC 2.0 消息,通过 stdio 和基于 HTTP 的传输(SSE/Streamable HTTP)等传输方式。本仓库使用 stdio:客户端将服务器作为子进程启动,通过 stdin 发送协议消息,并通过 stdout 接收响应。


Related MCP server: Weather MCP Server

架构

flowchart TD
    A[User: "What's the weather in London?"] --> B[AI Agent<br/>OpenAI Responses API]
    B --> C[1. Discovers MCP tools]
    B --> D[2. Decides whether to call]
    B --> E[3. Emits function call]
    E --> F[MCP Client<br/>ClientSession + stdio]
    F --> G[initialize]
    F --> H[tools/list]
    F --> I[tools/call]
    I --> J[JSON-RPC 2.0<br/>stdin/stdout]
    J --> K[MCP Server subprocess]
    K --> L[get_current_weather tool]
    K --> M[greeting://{name} resource]

为什么使用官方 SDK?

本仓库使用官方 Python MCP SDK,而不是重新实现协议。SDK 提供:

  • 协议生命周期与验证

  • 传输抽象(stdio、HTTP/SSE)

  • 类型化的客户端/服务器 API

应用代码仍然明确体现了重要的 MCP 概念:服务器注册、工具模式、initializetools/listtools/call、资源读取以及 stdio 进程管理。

当前 SDK 的稳定 v2 API 使用 MCPServer 构建服务器,并使用 ClientSession/stdio_client 作为 stdio 客户端。


项目结构

mcp-demo/
├── README.md
├── requirements.txt
├── .env.example
├── pyproject.toml
├── src/
│   ├── mcp_server/
│   │   ├── __init__.py
│   │   ├── server.py      # MCP server entry point
│   │   ├── tools.py       # Tool implementations
│   │   ├── handlers.py    # Request handlers
│   │   └── utils.py       # Shared utilities
│   ├── mcp_client/
│   │   ├── __init__.py
│   │   ├── client.py      # MCP client wrapper
│   │   ├── agent.py       # OpenAI agent integration
│   │   └── runner.py      # Demo runner
│   └── shared/
│       ├── __init__.py
│       └── types.py       # Shared Pydantic models
├── tests/
│   ├── test_server.py
│   └── test_client.py
├── examples/
│   └── demo.ipynb
└── scripts/
    └── run_demo.sh

环境要求

  • Python 3.10+

  • OpenAI API 密钥(用于 AI 智能体演示)

  • 无需天气 API 密钥 — 天气工具使用确定性的示例数据,因此 MCP 路径可以离线工作


快速开始

1. 创建虚拟环境

python -m venv .venv
source .venv/bin/activate        # Linux/macOS
.venv\Scripts\Activate.ps1       # Windows PowerShell

2. 安装依赖

python -m pip install --upgrade pip
pip install -r requirements.txt

3. 配置 OpenAI

cp .env.example .env

使用你的凭据编辑 .env

OPENAI_API_KEY=your_api_key_here
OPENAI_MODEL=gpt-4.1-mini

服务器本身不需要 OpenAI 密钥。


运行演示

从仓库根目录

python src/mcp_client/runner.py

运行器执行的操作:

步骤

描述

1️⃣

src/mcp_server/server.py 作为子进程启动

2️⃣

执行 MCP 初始化握手

3️⃣

调用 tools/list

4️⃣

将发现的 MCP 模式转换为 OpenAI 函数工具

5️⃣

让模型回答自然语言问题

6️⃣

当模型选择 get_current_weather 时,通过 MCP 发送 tools/call

7️⃣

将 MCP 结果发送回模型

8️⃣

打印最终答案

9️⃣

干净地关闭服务器

备选:Shell 包装器

bash scripts/run_demo.sh

预期输出

具体措辞因模型而异,但日志流程如下:

INFO mcp_client.client: -> MCP initialize
INFO mcp_client.client: <- MCP initialize: server=mcp-demo-server
INFO mcp_client.client: -> MCP tools/list
INFO mcp_client.client: <- MCP tools/list: ["get_current_weather"]
INFO mcp_client.agent: User: What's the weather in London?
INFO mcp_client.agent: OpenAI requested tool: get_current_weather {"city":"London","units":"metric"}
INFO mcp_client.client: -> MCP tools/call name=get_current_weather arguments={"city":"London","units":"metric"}
INFO mcp_server.tools: weather lookup city=London units=metric
INFO mcp_client.client: <- MCP tools/call result={"city":"London","temperature":18.0,...}
INFO mcp_client.agent: Final: London is 18°C and partly cloudy.

日志特意在应用边界显示 MCP 语义消息。SDK 在内部处理 JSON-RPC 帧。


独立运行 MCP 服务器

python src/mcp_server/server.py

stdio MCP 服务器看起来像“挂起”——这是预期行为。它等待 stdin 上的协议消息。主机/客户端应启动它并拥有 stdio 管道。

交互式协议检查

pip install "mcp[cli]"
mcp dev src/mcp_server/server.py

演示的 MCP 方法

官方 SDK 处理 JSON-RPC 生命周期:

方法

方向

用途

initialize

客户端 → 服务器

握手与能力协商

tools/list

客户端 → 服务器

发现可用工具

tools/call

客户端 → 服务器

调用工具

resources/list

客户端 → 服务器

发现可用资源

resources/read

客户端 → 服务器

读取资源

客户端在列出或调用能力之前显式调用 initialize()。服务器的装饰器根据 Python 类型注解生成工具/资源模式。


工具:get_current_weather

get_current_weather(
    city: str,
    units: Literal["metric", "imperial"] = "metric"
) -> WeatherResponse

返回基于 Pydantic 的结构化负载:

{
  "city": "London",
  "temperature": 18.0,
  "units": "metric",
  "condition": "partly cloudy",
  "humidity_percent": 72
}

未知城市会以受控的 MCP 工具错误失败,而不是导致服务器崩溃。


智能体集成流程

智能体使用纯 OpenAI 函数调用(无额外框架)以保持演示聚焦:

flowchart LR
    A[MCP Tool Schema] --> B[OpenAI Function Tool]
    B --> C[Model Chooses Function]
    C --> D[MCP ClientSession.call_tool]
    D --> E[MCP Server Executes Tool]
    E --> F[Function Call Output]
    F --> G[Final Model Answer]

这与智能体框架包装的模式相同:发现 MCP 工具 → 向模型暴露模式 → 将选定的调用路由回 MCP → 将结果输入下一轮模型。


测试

pytest -q

测试套件涵盖:

  • ✅ 工具执行(公制天气)

  • ✅ 工具执行(英制天气)

  • ✅ 验证/错误行为(未知城市)

  • ✅ 进程内 MCP 客户端发现与工具调用

测试尽可能使用 SDK 的内存客户端——避免子进程不稳定,同时锻炼真实的 MCP 协议层。


格式与代码检查

本项目使用 Ruff

# Check
ruff check .
ruff format --check .

# Format
ruff format .

生产注意事项

此演示刻意保持小巧,但代表了几个生产关注点:

关注点

实现

stdout 纪律

服务器从不将应用日志打印到 stdout(属于 MCP);日志通过 logging 输出到 stderr

类型化 I/O

Pydantic 模型在应用边界验证工具输入/输出

受控失败

工具异常 → MCP 错误结果(SDK),而不是进程崩溃

子进程生命周期

SDK 的 stdio 上下文管理器负责进程启动/关闭

最小权限环境

MCP stdio 客户端显式传递子进程所需的环境变量

动态发现

智能体不硬编码天气工具模式;通过 tools/list 发现

对于真实的外部数据源:用经过身份验证的 API/数据库调用替换确定性天气,添加超时、重试、速率限制、可观测性和密钥管理。


协议心智模型

简化的 JSON-RPC 序列:

// Client -> Server
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}

// Server -> Client
{"jsonrpc":"2.0","id":1,"result":{...}}

// Client -> Server
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}

// Server -> Client
{"jsonrpc":"2.0","id":2,"result":{"tools":[...]}}

// Client -> Server
{"jsonrpc":"2.0","id":3,"method":"tools/call",
 "params":{"name":"get_current_weather","arguments":{"city":"London"}}}

// Server -> Client
{"jsonrpc":"2.0","id":3,"result":{"content":[...],"structuredContent":{...}}}

确切的协议模式由 MCP 规范 和 SDK 维护。以上内容为教学目的而刻意简化。


参考


F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    Enables AI agents to retrieve real-time weather conditions and forecasts via OpenWeatherMap API. Supports interactive weather queries and travel planning through MCP tools, resources, and prompts.
    2
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides weather data from OpenWeatherMap API through MCP tools and a REST API with OpenAPI support. Enables LLM agents to retrieve current weather, forecasts, and temperature ranges by city or coordinates.
    21
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Wraps the OpenWeatherMap API to provide weather data through MCP, enabling AI agents to query current conditions, forecasts, and other weather information via natural language.
    10
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides weather data from WeatherAPI.com through MCP, enabling AI agents to query current conditions and forecasts via natural language.
    11
    MIT

View all related MCP servers

Related MCP Connectors

  • Pocket Agent (aipocketagent.com) MCP server — read tools for personas, apps, and product info.

  • OpenWeather MCP — wraps the OpenWeatherMap API (openweathermap.org)

  • NOAA and ECMWF weather forecast MCP for discovery, validation, and GribStream OAuth queries.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mhamzanadeem/mcp-playground'

If you have feedback or need assistance with the MCP directory API, please join our Discord server