107 lines
3.4 KiB
Python
107 lines
3.4 KiB
Python
"""MCP 协议:JSON-RPC 消息定义"""
|
||
"""
|
||
mcp/mcp_protocol.py
|
||
MCP (Model Context Protocol) 协议数据结构定义
|
||
基于 JSON-RPC 2.0 规范封装请求/响应消息体
|
||
"""
|
||
|
||
import uuid
|
||
from dataclasses import dataclass, field
|
||
from typing import Any
|
||
|
||
|
||
# ── MCP 方法常量 ───────────────────────────────────────────────
|
||
class MCPMethod:
|
||
TOOLS_LIST = "tools/list" # 列出所有可用工具
|
||
TOOLS_CALL = "tools/call" # 调用指定工具
|
||
RESOURCES_READ = "resources/read" # 读取资源
|
||
|
||
|
||
# ── 请求消息 ───────────────────────────────────────────────────
|
||
@dataclass
|
||
class MCPRequest:
|
||
"""
|
||
MCP 工具调用请求(JSON-RPC 2.0 格式)
|
||
|
||
示例:
|
||
{
|
||
"jsonrpc": "2.0",
|
||
"id": "abc-123",
|
||
"method": "tools/call",
|
||
"params": {
|
||
"name": "calculator",
|
||
"arguments": {"expression": "1+1"}
|
||
}
|
||
}
|
||
"""
|
||
method: str
|
||
params: dict[str, Any] = field(default_factory=dict)
|
||
jsonrpc: str = "2.0"
|
||
id: str = field(default_factory=lambda: str(uuid.uuid4())[:8])
|
||
|
||
def to_dict(self) -> dict:
|
||
return {
|
||
"jsonrpc": self.jsonrpc,
|
||
"id": self.id,
|
||
"method": self.method,
|
||
"params": self.params,
|
||
}
|
||
|
||
|
||
# ── 响应消息 ───────────────────────────────────────────────────
|
||
@dataclass
|
||
class MCPResponse:
|
||
"""
|
||
MCP 工具调用响应(JSON-RPC 2.0 格式)
|
||
|
||
成功示例:
|
||
{"jsonrpc": "2.0", "id": "abc-123", "result": {"content": [...]}}
|
||
|
||
失败示例:
|
||
{"jsonrpc": "2.0", "id": "abc-123", "error": {"code": -32601, "message": "..."}}
|
||
"""
|
||
id: str
|
||
result: dict[str, Any] | None = None
|
||
error: dict[str, Any] | None = None
|
||
jsonrpc: str = "2.0"
|
||
|
||
@property
|
||
def success(self) -> bool:
|
||
return self.error is None
|
||
|
||
@property
|
||
def content(self) -> str:
|
||
"""提取响应中的文本内容"""
|
||
if not self.success or not self.result:
|
||
return self.error.get("message", "Unknown error") if self.error else ""
|
||
items = self.result.get("content", [])
|
||
return "\n".join(item.get("text", "") for item in items if item.get("type") == "text")
|
||
|
||
def to_dict(self) -> dict:
|
||
base = {"jsonrpc": self.jsonrpc, "id": self.id}
|
||
if self.success:
|
||
base["result"] = self.result
|
||
else:
|
||
base["error"] = self.error
|
||
return base
|
||
|
||
|
||
# ── 工具描述 ───────────────────────────────────────────────────
|
||
@dataclass
|
||
class ToolSchema:
|
||
"""
|
||
工具的元数据描述,用于 LLM 识别和选择工具
|
||
"""
|
||
name: str
|
||
description: str
|
||
parameters: dict[str, Any] # JSON Schema 格式的参数定义
|
||
|
||
def to_dict(self) -> dict:
|
||
return {
|
||
"name": self.name,
|
||
"description": self.description,
|
||
"inputSchema": {
|
||
"type": "object",
|
||
"properties": self.parameters,
|
||
},
|
||
} |