- capabilities/{manifests,registry,providers,install_manager}.py + tool_runner.py:
三层机制(注册层/调用层/安装管理层),四 Provider,热加载差分刷新
- configs/capabilities.yaml: 唯一注册入口(明文热加载面)
- api.py: QARequest+history/capabilities, /capabilities/install loopback 路由
- llm_client.py: complete() tools 透传 + complete_raw_messages() 工具调用循环支持
- pipeline.py/answer_composer.py: history 线程化(只进 Dialogue Context,检索零回归)
- sdk: services/history.py(3轮/16k预算) + routers/qa.py session_id 剥离注入
- compile_qa.sh: rsync 允许子目录 + capabilities.yaml 入 install 清单
- tooling/cap/: fake_mcp_server.py + cap_selfcheck.py 机制自检
- requirements.lock: mcp 2.1.1 + 依赖 12 包
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
132 lines
4.3 KiB
Python
132 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
||
"""fake_mcp_server.py —— 自检用假 MCP server(stdio,一个 echo 工具)。
|
||
|
||
用官方 mcp SDK 2.x 的 lowlevel Server + add_request_handler 实现;
|
||
若 mcp SDK 未安装则退化为纯 stdio JSON-RPC 手工实现(保底)。
|
||
S1 端到端自检用它验证「热加载 + 工具调用」全链。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
import sys
|
||
|
||
|
||
def _serve_manual() -> int:
|
||
"""无 mcp SDK 保底:JSON-RPC over stdio(initialize/tools-list/tools-call)。"""
|
||
for line in sys.stdin:
|
||
try:
|
||
message = json.loads(line)
|
||
except Exception:
|
||
continue
|
||
method = message.get("method")
|
||
msg_id = message.get("id")
|
||
if method == "initialize":
|
||
reply = {
|
||
"jsonrpc": "2.0",
|
||
"id": msg_id,
|
||
"result": {
|
||
"protocolVersion": "2024-11-05",
|
||
"capabilities": {"tools": {}},
|
||
"serverInfo": {"name": "fake-echo", "version": "0.1.0"},
|
||
},
|
||
}
|
||
elif method == "notifications/initialized":
|
||
continue
|
||
elif method == "tools/list":
|
||
reply = {
|
||
"jsonrpc": "2.0",
|
||
"id": msg_id,
|
||
"result": {
|
||
"tools": [
|
||
{
|
||
"name": "echo",
|
||
"description": "回显文本",
|
||
"inputSchema": {
|
||
"type": "object",
|
||
"properties": {
|
||
"text": {"type": "string", "description": "要回显的文本"}
|
||
},
|
||
"required": ["text"],
|
||
},
|
||
}
|
||
]
|
||
},
|
||
}
|
||
elif method == "tools/call":
|
||
params = message.get("params") or {}
|
||
arguments = params.get("arguments") or {}
|
||
text = str(arguments.get("text", ""))
|
||
reply = {
|
||
"jsonrpc": "2.0",
|
||
"id": msg_id,
|
||
"result": {
|
||
"content": [{"type": "text", "text": f"echo: {text}"}],
|
||
"isError": False,
|
||
},
|
||
}
|
||
else:
|
||
reply = {
|
||
"jsonrpc": "2.0",
|
||
"id": msg_id,
|
||
"error": {"code": -32601, "message": f"unknown method {method}"},
|
||
}
|
||
sys.stdout.write(json.dumps(reply, ensure_ascii=False) + "\n")
|
||
sys.stdout.flush()
|
||
return 0
|
||
|
||
|
||
def _serve_mcp() -> int:
|
||
from mcp.server.lowlevel import Server
|
||
from mcp.server.stdio import stdio_server
|
||
import mcp.types as types
|
||
import anyio
|
||
|
||
server = Server("fake-echo")
|
||
|
||
async def handle_list_tools(ctx, params: types.PaginatedRequestParams):
|
||
return types.ListToolsResult(
|
||
tools=[
|
||
types.Tool(
|
||
name="echo",
|
||
description="回显文本",
|
||
inputSchema={
|
||
"type": "object",
|
||
"properties": {
|
||
"text": {"type": "string", "description": "要回显的文本"}
|
||
},
|
||
"required": ["text"],
|
||
},
|
||
)
|
||
]
|
||
)
|
||
|
||
async def handle_call_tool(ctx, params: types.CallToolRequestParams):
|
||
arguments = params.arguments or {}
|
||
text = str(arguments.get("text", ""))
|
||
return types.CallToolResult(
|
||
content=[types.TextContent(type="text", text=f"echo: {text}")],
|
||
is_error=False,
|
||
)
|
||
|
||
server.add_request_handler("tools/list", types.PaginatedRequestParams, handle_list_tools)
|
||
server.add_request_handler("tools/call", types.CallToolRequestParams, handle_call_tool)
|
||
|
||
async def run() -> None:
|
||
async with stdio_server() as (read_stream, write_stream):
|
||
await server.run(read_stream, write_stream, server.create_initialization_options())
|
||
|
||
anyio.run(run)
|
||
return 0
|
||
|
||
|
||
def main() -> int:
|
||
try:
|
||
import mcp # noqa: F401
|
||
except ImportError:
|
||
return _serve_manual()
|
||
return _serve_mcp()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main())
|