模型上下文协议SDK

MCP Python SDK是一个让AI模型通过标准化协议与外部工具和数据源交互的开发工具包,适用于构建智能笔记应用和自动化工作流。

  • by Dev-Pradeep-NS
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 Dev-Pradeep-NS/mcp-server

使用说明

MCP Python SDK——概念与示例


目录

  1. 概述
  2. 安装
  3. 项目结构
  4. 用作笔记应用程序
  5. 服务器
  6. 资源
  7. 工具
  8. 结构化输出
  9. 提示
  10. 图像
  11. 上下文
  12. 补全
  13. 引出
  14. 采样
  15. 日志记录和通知
  16. 认证
  17. 会话
  18. 请求上下文
  19. 运行服务器
  20. HTTP传输
  21. ASGI集成
  22. SSE服务器
  23. 编写MCP客户端
  24. 解析工具结果
  25. MCP图元
  26. 服务器能力

概述

MCP(模型上下文协议) 是一个开放标准,允许人工智能模型(LLM)以一致的方式与外部工具、数据源和服务进行交互。MCP定义了客户端和服务器之间的通信方式,而不是每个应用程序构建自己的集成。

流量:

User/App → LLM → MCP Client → MCP Server → Tools / Resources / Data

LLM决定何时调用工具或读取资源;MCP客户端与MCP服务器对话;服务器运行实际的逻辑(读取文件、调用API等)。


安装

安装官方的MCP Python SDK,以便您可以构建服务器和客户端。

使用pip:

pip install mcp

使用uv(推荐用于现代Python项目):

uv add mcp

项目结构

一个典型的基于MCP的Python项目看起来像这样:

project/
├── mcp_server.py    # Defines tools, resources, prompts
├── mcp_client.py    # Connects to the server and calls it
└── docs/            # Optional: folder for document resources
  • mcp_server.py –您的MCP服务器:注册工具、资源和提示。
  • mcp_client.py –连接到服务器(例如通过stdio或HTTP),并代表LLM调用工具/资源。

用作笔记应用程序

这个项目兼作 笔记应用程序:服务器将笔记作为文件存储在 ./docs (或由设置的目录 DOCUMENTS_DIR),客户可以列出它们或与LLM聊天,LLM可以通过MCP工具创建、读取、编辑和删除笔记。

快速启动:

# List all notes (uses list_documents tool)
uv run python mcp_client.py mcp_server.py --list-notes

# Chat with the notes assistant (Ollama required; uses create_document, read_document, edit_document, etc.)
uv run python mcp_client.py mcp_server.py --chat --model qwen3:1.7b

Notes应用程序功能(所有功能都可以在聊天室和MCP工具中使用):

你想要什么 工具 示例
写便条 create_document(doc_name, content) “保存这个:…”/“创建一个名为ideas.md的笔记”
看看我有什么笔记 list_documents() 或客户 --list-notes “我有什么笔记?”/ python mcp_client.py mcp_server.py --list-notes
读便条 read_document(doc_id) “阅读会议笔记.md”/“显示我的待办事项列表”
更新注释 update_document(doc_id, content) “用以下内容更新shopping.txt:…”/“重写该注释”
注释中的小编辑 edit_document(doc_id, old_text, new_text) “在shopping.txt中将‘买牛奶’改为‘买燕麦奶’”
删除注释 delete_document(doc_id) “删除旧笔记.txt”(要求确认)
总结/审查/改进笔记 read_document(doc_id) 然后助理响应 “总结会议笔记.md”/“审阅草稿.txt”/“改进此笔记”

提示(总结_文件、审查_文件、改进_文件):

服务器暴露了三个 提示 (消息模板)用于调用的客户端 get_prompt():

  • summarize_文件(doc_id)--要求LLM在以下位置汇总文档的模板 file://documents/{doc_id}.
  • review_文档(doc_id)——请求文档反馈的模板。
  • 改进文档(doc_id)——要求提高清晰度、语法和结构的模板。

在 聊天模式,助手不直接调用这些提示;使用 read_document(doc_id) 获取内容,然后在对话中回复摘要、评论或改进版本。因此,您可以说“总结会议笔记.md”、“审阅草稿.txt”或“改进想法.md的措辞”,助理将阅读笔记并做出相应回应(并可以提供用 update_document).

服务器行为:

  • 笔记存储在 ./docs 默认情况下;集 DOCUMENTS_DIR 使用另一个文件夹。如果目录不存在,则会自动创建。
  • 文档ID(文件名)已验证:否 ..、路径分隔符或不安全字符(仅限字母、数字、, -, _, .).
  • 工具: list_documents, read_document, create_document, edit_document, update_document, delete_document.提示: summarize_document, review_document, improve_document (适用于使用 get_prompt;在聊天中,助手使用 read_document +其答复)。

客户行为:

  • 无标志:连接并打印服务器功能(工具、资源、提示)。
  • --list-notes:呼叫 list_documents 并打印钞票名称。
  • --chat:启动一个交互式笔记助手,系统提示鼓励创建和管理笔记;该模型使用MCP工具来读/写文档存储。

激励(用户确认):

服务器使用MCP 引出 在一个地方: 删除文档在删除笔记之前,服务器会调用 ctx.elicit(message="Are you sure...?", schema=DeleteConfirm)。这会向客户端发送一个请求:“工具需要用户确认。”客户端应该提示用户(例如“删除注释'x'?[y/N]”),然后发回 接受 或 下降如果客户端发送accept,则服务器删除该文件;否则,它将返回 deleted: false.

  • 在 光标 (或支持启发的其他MCP主机),UI将显示确认并允许您批准或取消。
  • 在 CLI聊天客户端 (--chat),行为取决于MCP Python SDK:如果 call_tool 在启发的块上,客户端可能需要处理启发响应并提示用户。如果SDK尚不支持工具调用流中的启发,则删除可能会在此客户端中完成,无需确认。

完成(文档ID自动完成):

服务器实现 文件完成: @mcp.completion() 给定一个处理程序 部分 字符串(例如。 "meet" 或 "file://documents/meet"),返回匹配的笔记名称作为补全(例如。 file://documents/meeting-notes.md 与善良 "file" 以及描述)。因此,当客户端(例如Cursor或带有“文档”或“资源”字段的自定义UI)支持MCP完成时,它可以在用户键入时调用完成端点,并在中显示实际注释中的自动完成建议 ./docsThe CLI客户端 在这个repo中不使用补全;它主要用于聊天和 --list-notes.


服务器

一 MCP服务器 是向客户端公开功能(工具、资源、提示)的过程。你用以下方式创建它 FastMCP 然后为其添加工具和资源。

示例–最小服务器:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP('DocumentServer')
# Add tools and resources here, then run the server

'DocumentServer' 向客户端显示的服务器名称。然后,您可以在上注册工具和资源 mcp 最后运行它(例如。 mcp.run()).


资源

资源 是服务器通过URI公开的只读数据。客户端(以及LLM)可以在不改变状态的情况下“读取”它们。典型用途:文档、配置或任何静态/半静态数据。

示例–文档资源:

@mcp.resource('file://documents/{doc_id}')
def read_document(doc_id: str):
    with open(f'./docs/{doc_id}', encoding='utf-8') as f:
        return f.read()
  • URI模板: file://documents/{doc_id} –例如。 file://documents/notes.txt → doc_id = "notes.txt".
  • 该函数返回文档正文(例如字符串)。客户端可以将其作为上下文传递给LLM。

工具

工具 执行操作(副作用):删除文件、发送电子邮件、运行脚本等。当LLM决定使用它们时,客户端会调用它们。

示例–删除文档工具:

import os

@mcp.tool()
def delete_document(doc_id: str) -> str:
    path = f'./docs/{doc_id}'
    if os.path.exists(path):
        os.remove(path)
        return 'deleted'
    return 'file not found'
  • @mcp.tool() 将该功能注册为工具;客户端可以使用参数按名称调用它(例如。 doc_id).
  • 返回值被发送回客户端/LLM(例如,用于确认操作)。

结构化输出

工具和资源可以归还 结构化数据 (例如JSON),以便客户端或LLM能够可靠地解析它。

示例–返回一个dict:

@mcp.tool()
def save_document(doc_id: str, content: str):
    path = f'./docs/{doc_id}'
    with open(path, 'w', encoding='utf-8') as f:
        f.write(content)
    return {'status': 'success', 'file': doc_id}

客户端接收此结构,并可以将其传递给LLM或以编程方式使用它(例如。 result['file']).


提示

提示 是服务器公开的可重用提示模板。当客户端按名称(和参数)请求提示时,服务器会返回客户端可以发送给LLM的消息列表(例如系统+用户)。可用于“总结此”、“解释此文档”等。

示例–总结文档提示:

from mcp.types import UserMessage

@mcp.prompt()
def summarize_document(doc_id: str):
    return [
        UserMessage(content=f'Summarize the document at file://documents/{doc_id}')
    ]

当用户选择“摘要文档”并选择 doc_id,客户端请求此提示,获取消息列表,并将其发送到LLM,以便它可以使用相应的资源(例如。 file://documents/notes.txt)为了上下文。


图像

工具和资源可以归还 图像数据 (例如PNG、JPEG)以及文本。用例:图表、屏幕截图、生成的图表。客户可以显示它们或将它们传递给具有视觉能力的LLM。

示例想法:

  • 一种生成图表并将其作为base64或blob返回的工具。
  • URI为的资源 image://reports/chart.png 它返回图像字节。

确切的返回格式(例如JSON中的base64,或特定MCP内容类型中的二进制)取决于MCP版本和客户端支持。


上下文

这 上下文 对象(经常 ctx)传递给工具(和一些其他处理程序),并提供有关当前请求和与会话交互的方式的信息(例如日志记录)。

示例–在工具中使用上下文:

from mcp.server.context import Context

@mcp.tool()
def my_tool(ctx: Context, query: str):
    ctx.log('Running tool with query: %s', query)
    # ... do work ...
    return {'result': 'done'}
  • ctx.log() –向客户端发送进度或调试消息(对长时间运行的工具很有用)。
  • 你也可以得到 request_id 或来自的其他元数据 ctx 这取决于SDK版本。

补全

补全 让服务器建议参数的可能值(例如文件名、文档ID)。当用户键入部分输入时,客户端可以向服务器征求建议并显示自动完成。

示例想法:

  • 用户类型 doc 在“文档id”字段中。
  • 客户端使用部分输入调用完成端点 doc.
  • 服务器返回建议: doc1.txt, doc2.txt, notes.doc.

因此,服务器拥有有效或推荐选项的列表(例如,来自 docs/ 文件夹)。


引出

引出 意味着服务器(或客户端流)在运行工具之前会要求用户提供缺失或模糊的输入。例如,“删除文档”工具可能需要 doc_id;如果用户没有指定,系统可以提示:“我应该删除哪个文档?”并提供一个列表。这使工具变得简单,同时仍然指导用户。


采样

采样 当客户要求LLM 生成 内容(例如文本、代码)。例如:“在以下位置生成文档摘要file://documents/notes.txt.“客户端将提示(以及任何资源内容)发送到LLM,并返回模型的响应。因此,“采样”是使用模型来产生响应的行为。


日志记录和通知

服务器可以发送 进度或状态消息 在长时间运行的工具中,用户界面可以显示“正在处理…”、“步骤2/5”等。

例子:

@mcp.tool()
def long_task(ctx: Context):
    ctx.log('Processing...')
    # ... step 1 ...
    ctx.log('Halfway there...')
    # ... step 2 ...
    ctx.log('Done.')
    return 'completed'

客户端可以在日志面板或状态栏中显示这些消息。


认证

MCP服务器可以 已保护 因此,只有授权的客户端才能连接。常见方法:

  • API密钥 –客户端在headers或config中发送密钥;服务器验证它。
  • OAuth –客户端获得令牌并发送;服务器验证令牌。

配置通常在传输层完成(例如HTTP中间件或环境变量),而不是在单个工具中完成。


会话

A. 会话 是一个MCP客户端和一个MCP服务器之间的活动连接。在会话中,客户端可以多次调用工具、读取资源和请求提示。

示例–客户端在会话中调用工具:

# Pseudo-code on the client side
result = session.call_tool('read_document', {'doc_id': 'notes.txt'})

客户端保持会话打开,并将其重新用于许多请求,而不是每次重新连接。


请求上下文

对服务器的每个请求都可以携带 元数据 (例如请求ID、用户ID)。这通常可以在 请求上下文 (例如。 ctx)因此,工具可以记录或跟踪请求。

例子:

@mcp.tool()
def my_tool(ctx: Context):
    request_id = getattr(ctx, 'request_id', None)
    ctx.log('Request ID: %s', request_id)
    return 'ok'

确切的属性名称取决于MCP Python SDK版本(例如。 ctx.request_id 如果提供)。


运行服务器

定义服务器并注册工具/资源后,您 跑 当地最常用的交通工具是 标准:服务器在标准流上读取输入并写入输出,客户端将其作为子进程生成。

示例–使用stdio运行:

if __name__ == '__main__':
    mcp.run(transport='stdio')

对于其他传输(例如HTTP),您将使用适当的方法或集成(见下文)。


HTTP传输

您可以通过以下方式运行MCP服务器 超文本传输协议 因此远程客户端可以在不共享进程的情况下进行连接。

示例–服务器URL:

http://localhost:8000/mcp

服务器将使用HTTP传输(例如uvicorn或SDK的HTTP运行器)启动,并可能在以下位置暴露MCP端点 /mcp。然后,客户端连接到此URL,而不是使用stdio。


ASGI集成

你可以 安装 MCP服务器内部 ASGI 服务器网关接口 应用程序(例如FastAPI),因此相同的流程为您的API和MCP提供服务。

示例–FastAPI:

from fastapi import FastAPI
from mcp.server.fastmcp import FastMCP

mcp = FastMCP('MyServer')
# ... register tools, resources ...

app = FastAPI()
mcp_app = mcp.get_asgi_app()  # or equivalent in your SDK version
app.mount('/mcp', mcp_app)

然后,MCP端点在以下位置可用 http://localhost:8000/mcp (或您使用的任何端口)。


SSE服务器

服务器发送事件(SSE) 让服务器通过长期HTTP连接向客户端推送更新。可用于流式传输进度、日志或部分结果。MCP服务器可以支持SSE传输,以便客户端在工具执行期间接收实时更新。


编写MCP客户端

MCP客户端 在您的应用程序中运行(或在像Cursor这样的AI助手主机中运行)。它们连接到MCP服务器,将LLM决策转换为工具/资源调用,然后将结果传递回LLM。

流量:

User → LLM → MCP Client → MCP Server (tools/resources)
                ↑___________________________|

客户端负责:连接(stdio子进程或HTTP)、发送请求(例如。 call_tool, read_resource),并将服务器的响应返回给LLM。


解析工具结果

当客户端调用工具时,服务器返回一个结果。客户端通常会解析此内容并将其传递给LLM或您的应用程序。结果往往有 内容 字段(文本或结构化)。

示例–客户端解析:

# After session.call_tool('read_document', {'doc_id': 'notes.txt'})
result = response  # from server
content = result.get('content', [])
# content might be a list of parts, e.g. [{'type': 'text', 'text': '...'}]
text = content[0]['text'] if content else ''

具体形状取决于MCP SDK和版本;这个想法是读取结构化的结果(例如。 result['content'])并提取LLM的文本或数据。


MCP图元

MCP的核心构建块是:

原始 目的
工具 采取行动(副作用)。
资源 按URI公开只读数据
提示 可重用的提示模板(消息列表)。
采样 让模型生成内容。
引出 要求用户提供缺失或澄清的输入。

服务器实现其中的一个或多个;客户端使用它们让LLM访问您的后端和数据。


服务器能力

当客户端连接时,服务器 声明 它支持什么(工具、资源、提示等)。这叫做 能力客户端使用它来知道它可以调用什么(例如,存在哪些工具名称,哪些资源URI模板可用)。在MCP Python SDK中,注册一个工具/资源/提示符 mcp 自动在服务器的功能中通告它。


本指南总结了MCP的主要概念,并给出了最少的示例。有关API的全部详细信息和更改,请参阅官方网站 MCP文件 和那个 MCP Python SDK 在GitHub上。