"""MCP 协议常量与纯函数。 本模块**不含任何 IO**,只做版本协商、信封构造与方法路由判定,便于单独测试。 """ from . import __version__ as SERVER_VERSION # 本桥支持的协议版本,从新到旧。initialize 时按客户端请求协商。 PROTOCOL_VERSIONS = ("2025-06-18", "2025-03-26", "2024-11-05") DEFAULT_VERSION = PROTOCOL_VERSIONS[0] SERVER_NAME = "cad-mcp-bridge" # classify() 的四种路由结果 LOCAL = "local" # 由桥自己应答(基座没有实现) FORWARD = "forward" # 原样转发给 CAD 基座 NOTIFY = "notify" # 通知,按规范不回包 UNKNOWN = "unknown" # 未知方法,回 -32601 _LOCAL_METHODS = frozenset({"initialize", "ping"}) _FORWARD_METHODS = frozenset({"tools/list", "tools/call"}) def negotiate_version(requested): """协议版本协商:客户端请求的版本受支持则回显,否则回本桥支持的最新版本。 依据 MCP 规范:服务端支持的版本必须原样返回;不支持时回退到自己支持的版本, 由客户端决定是否继续。 """ return requested if requested in PROTOCOL_VERSIONS else DEFAULT_VERSION def classify(method): """把方法名映射到路由动作。""" if method in _LOCAL_METHODS: return LOCAL if method in _FORWARD_METHODS: return FORWARD if method.startswith("notifications/"): return NOTIFY return UNKNOWN def ok(msg_id, result): """构造 JSON-RPC 成功响应。""" return {"jsonrpc": "2.0", "id": msg_id, "result": result} def err(msg_id, code, message): """构造 JSON-RPC 错误响应。""" return {"jsonrpc": "2.0", "id": msg_id, "error": {"code": code, "message": message}} def initialize_result(params): """合成 initialize 的 result(基座未实现生命周期,由桥代答)。""" requested = "" if isinstance(params, dict): requested = params.get("protocolVersion") or "" return { "protocolVersion": negotiate_version(requested), "capabilities": {"tools": {"listChanged": False}}, "serverInfo": {"name": SERVER_NAME, "version": SERVER_VERSION}, "instructions": ( "本服务器通过 stdio 桥接本机 AutoCAD 的 cad_mcp_frame 基座。" "工具仅在 CAD 已启动且已加载插件时可用;未启动时调用会返回连接错误。" ), }