mcpField
A
aiohttp-mcp

aiohttp-mcp

本地服务
github.com/kulapard开发工具812 周前更新

关于 aiohttp-mcp

aiohttp-mcp 是用于在 aiohttp 应用中构建 MCP 服务的 Python 库,提供原生协议支持、装饰器注册,并可配置无状态或有状态运行。

主要功能

  1. 01原生实现 MCP 协议
  2. 02支持带 SSE 流式传输的 Streamable HTTP
  3. 03注册工具、资源和提示词
  4. 04集成到 aiohttp 应用
  5. 05可选状态管理与事件续传
  6. 06异步优先并提供类型提示

适用场景

  1. 01在 aiohttp 应用中添加 MCP 端点
  2. 02注册工具、资源和提示词
  3. 03在单实例中启用可续传的 SSE 会话

MCP 相关

该库实现 MCP 服务端功能,通过带 SSE 流式传输的 Streamable HTTP 向 MCP 客户端公开已注册的工具、资源和提示词。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

aiohttp-mcp

GitHub Actions Workflow Status codecov pre-commit.ci status PyPI - Version PyPI Downloads PyPI - Python Version GitHub License

基于 aiohttp 构建 Model Context Protocol (MCP) 服务的工具。

原生实现 MCP 协议,无需依赖庞大的 SDK。仅有 3 个运行时依赖:aiohttp、aiohttp-sse、pydantic。

功能特性

  • 原生实现 MCP 协议(支持规范 2025-11-25、2025-06-18、2025-03-26)
  • 支持 SSE 流式传输的 Streamable HTTP 传输
  • 可轻松集成到 aiohttp Web 应用
  • 支持工具、资源和提示词,并通过装饰器注册
  • 通过 ctx.app 共享状态,并通过 ctx.request 获取每个请求的数据
  • 默认无状态,可选有状态模式,支持服务端推送和恢复
  • 支持用于恢复的事件存储
  • 异步优先设计,提供完整类型提示
  • 支持非流式部署的 JSON 响应模式

安装

使用 uv 包管理器:

uv add aiohttp-mcp

或使用 pip:

pip install aiohttp-mcp

快速开始

基本服务端设置

创建一个带有自定义工具的简单 MCP 服务:

import datetime
from zoneinfo import ZoneInfo

from aiohttp import web

from aiohttp_mcp import AiohttpMCP, build_mcp_app

# Initialize MCP
mcp = AiohttpMCP()


# Define a tool
@mcp.tool()
def get_time(timezone: str) -> str:
    """Get the current time in the specified timezone."""
    tz = ZoneInfo(timezone)
    return datetime.datetime.now(tz).isoformat()


# Create and run the application
app = build_mcp_app(mcp, path="/mcp")
web.run_app(app)
作为子应用使用

也可以将 aiohttp-mcp 作为子应用用于现有的 aiohttp 服务:

import datetime
from zoneinfo import ZoneInfo

from aiohttp import web

from aiohttp_mcp import AiohttpMCP, setup_mcp_subapp

mcp = AiohttpMCP()


# Define a tool
@mcp.tool()
def get_time(timezone: str) -> str:
    """Get the current time in the specified timezone."""
    tz = ZoneInfo(timezone)
    return datetime.datetime.now(tz).isoformat()


# Create your main application
app = web.Application()

# Add MCP as a sub-application
setup_mcp_subapp(app, mcp, prefix="/mcp")

web.run_app(app)
有状态模式与恢复

默认情况下,服务以无状态模式运行——每个请求都会创建一个全新的传输,因此适用于负载均衡和多实例部署。工具通知(ctx.info())通过 SSE POST 响应内联工作。

对于需要服务端主动推送(通过 GET SSE 流)或 SSE 恢复能力的单实例部署,可启用有状态模式。会话状态和事件存储在进程内存中——若未使用粘性会话,则不适用于多实例部署。

from aiohttp_mcp import AiohttpMCP, InMemoryEventStore, build_mcp_app

# Stateful with resumability (single instance only)
# If client disconnects, it can reconnect with Last-Event-ID to replay missed events
mcp = AiohttpMCP(event_store=InMemoryEventStore())
app = build_mcp_app(mcp, path="/mcp", stateless=False)

注意: InMemoryEventStore 仅限进程内使用。对于多实例有状态部署,请实现一个由共享存储(例如 Redis)支持的自定义 EventStore,并使用粘性会话。

访问上下文

在工具中访问 MCP 上下文有 3 种方式。它们都会返回同一个 Context 对象:

1. get_current_context() — 模块函数

from aiohttp_mcp import get_current_context

@mcp.tool()
async def my_tool(query: str) -> str:
    ctx = get_current_context()
    user_id = ctx.request.headers.get("X-User-ID", "anonymous")
    await ctx.info(f"Query by {user_id}")
    return f"Result for {user_id}"

2. mcp.get_context() — 实例方法

@mcp.tool()
async def my_tool(query: str) -> str:
    ctx = mcp.get_context()
    user_id = ctx.request.headers.get("X-User-ID", "anonymous")
    return f"Result for {user_id}"

3. ctx: Context — 参数注入

将 ctx: Context 声明为参数,即可自动注入,并从工具的输入架构中排除:

from aiohttp_mcp import Context

@mcp.tool()
async def my_tool(query: str, ctx: Context) -> str:
    user_id = ctx.request.headers.get("X-User-ID", "anonymous")
    return f"Result for {user_id}"

上下文功能:

  • ctx.request — aiohttp Request(标头、Cookie、客户端 IP)
  • ctx.app — aiohttp Application,用于共享状态(ctx.app["db_pool"])
  • ctx.request_id — JSON-RPC 请求 ID
  • await ctx.info(msg) / debug() / warning() / error() — 向客户端发送日志
  • await ctx.report_progress(progress, total) — 报告进度
  • await ctx.read_resource(uri) — 读取已注册的资源

通过 ctx.app 共享状态:

from collections.abc import AsyncIterator

from aiohttp import web

from aiohttp_mcp import AiohttpMCP, build_mcp_app, get_current_context

mcp = AiohttpMCP()


@mcp.tool()
async def secure_query(sql: str) -> str:
    """Run a database query with auth validation."""
    ctx = get_current_context()
    db_pool = ctx.app["db_pool"]
    return await db_pool.query(sql)


async def startup(app: web.Application) -> AsyncIterator[None]:
    app["db_pool"] = await create_db_pool()
    yield
    await app["db_pool"].close()


app = build_mcp_app(mcp, path="/mcp")
app.cleanup_ctx.append(startup)
资源组合

工具可以在执行期间通过 ctx.read_resource(uri) 读取已注册的资源,避免逻辑重复:

from aiohttp_mcp import AiohttpMCP, get_current_context

mcp = AiohttpMCP()


@mcp.resource("config://{service}")
async def get_config(service: str) -> str:
    """Service configuration exposed as a resource."""
    return load_config(service)


@mcp.tool()
async def deploy(service: str) -> str:
    """Deploy a service using its registered config."""
    ctx = get_current_context()
    config = await ctx.read_resource(f"config://{service}")
    return f"Deployed {service} with {config}"

该调用会使用 MCP 客户端所用的同一 URI 回调资源注册表——工具只需 URI,无需直接引用资源函数。

结构化返回类型

工具可以返回 Pydantic BaseModel 或 dataclass 实例——这些实例会自动序列化为 JSON,并在 tools/list 响应中生成 outputSchema:

import dataclasses
from pydantic import BaseModel
from aiohttp_mcp import AiohttpMCP

mcp = AiohttpMCP()


@dataclasses.dataclass
class UserData:
    name: str
    email: str
    age: int = 25


class UserResult(BaseModel):
    id: str
    name: str
    email: str


@mcp.tool()
async def create_user(data: UserData) -> UserResult:
    """Create a new user."""
    # Input: dataclass validated from dict/JSON automatically
    # Output: BaseModel serialized to JSON, outputSchema auto-generated
    return UserResult(id="123", name=data.name, email=data.email)

普通类型(str、dict、list)仍按原样序列化。任何返回类型注解都会生成 outputSchema;对于 BaseModel 和 dataclass 返回值,还会通过 Pydantic 的 TypeAdapter 进行适当的 JSON 序列化,而不是使用 str()。

客户端示例

以下示例展示了如何使用 mcp 客户端库创建与 MCP 服务交互的客户端:

import asyncio

from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client


async def main():
    # Connect to the MCP server
    async with streamablehttp_client("http://localhost:8080/mcp") as (
        read_stream,
        write_stream,
        _,
    ):
        async with ClientSession(read_stream, write_stream) as session:
            # Initialize the session
            await session.initialize()

            # List available tools
            tools = await session.list_tools()
            print("Available tools:", [tool.name for tool in tools.tools])

            # Call a tool
            result = await session.call_tool("get_time", {"timezone": "UTC"})
            print("Current time in UTC:", result.content)


if __name__ == "__main__":
    asyncio.run(main())
更多示例

如需了解更多示例,请查看 examples 目录。

开发

设置开发环境
  1. 克隆仓库:
git clone https://github.com/kulapard/aiohttp-mcp.git
cd aiohttp-mcp
  1. 创建并激活虚拟环境:
uv venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
  1. 安装开发依赖项:
uv sync --all-extras
运行测试
uv run pytest

要求

  • Python 3.11 或更高版本
  • aiohttp >= 3.9.0,< 4.0.0
  • aiohttp-sse >= 2.2.0,< 3.0.0
  • pydantic >= 2.0.0,< 3.0.0

许可证

本项目采用 MIT 许可证授权——详情请参阅 LICENSE 文件。

贡献

欢迎贡献!欢迎随时提交 Pull Request。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。