初始化提交
This commit is contained in:
commit
887c1f449e
963 files changed
+166869
No files matched your search
@@ -0,0 +1,82 @@
|
||||
"""MCP 工具转 ToolSpec(executor 绑定 http_client 调 MCP server tools/call)。
|
||||
|
||||
MCP 工具命名 ``mcp_{server_name}_{tool_name}``(下划线分隔,冒号不含 OpenAI 命名规范),``risk_level`` 缺省 L2(外部工具),
|
||||
``permission_policy`` 由 risk 经 ``default_policy`` 推导。executor 闭包捕获
|
||||
http_client + server endpoint + auth_token。
|
||||
|
||||
协议:标准 MCP Streamable HTTP(JSON-RPC 2.0 over POST /message)
|
||||
"""
|
||||
|
||||
from app.integrations.mcp.client import call_tool
|
||||
from app.modules.safety.governor import default_policy
|
||||
from app.modules.tool_runtime.definition import ToolSpec
|
||||
|
||||
|
||||
def make_mcp_tool_specs(
|
||||
server,
|
||||
tools: list[dict],
|
||||
http_client,
|
||||
meta: dict | None = None,
|
||||
transport=None,
|
||||
) -> list[ToolSpec]:
|
||||
"""把 MCP server 工具清单(list[dict])转为 ToolSpec 列表。
|
||||
|
||||
Args:
|
||||
meta: 可选业务上下文
|
||||
transport: 可选传输层实例(stdio 用,传给 executor 替代 HTTP call_tool)
|
||||
"""
|
||||
specs: list[ToolSpec] = []
|
||||
for tool in tools:
|
||||
name = tool.get("name")
|
||||
if not name:
|
||||
continue
|
||||
risk_level = tool.get("risk_level", "L2")
|
||||
input_schema = tool.get("inputSchema") or tool.get("input_schema")
|
||||
specs.append(
|
||||
ToolSpec(
|
||||
name=f"mcp_{server.name}_{name}",
|
||||
description=tool.get("description", ""),
|
||||
risk_level=risk_level,
|
||||
permission_policy=default_policy(risk_level),
|
||||
executor=_make_mcp_executor(
|
||||
http_client,
|
||||
server.endpoint_url,
|
||||
name,
|
||||
server.auth_token,
|
||||
meta=meta,
|
||||
transport=transport,
|
||||
),
|
||||
input_schema=input_schema,
|
||||
)
|
||||
)
|
||||
return specs
|
||||
|
||||
|
||||
def _make_mcp_executor(
|
||||
http_client,
|
||||
endpoint_url,
|
||||
tool_name,
|
||||
auth_token,
|
||||
meta: dict | None = None,
|
||||
transport=None,
|
||||
):
|
||||
async def executor(input, context): # noqa: ARG001
|
||||
call_meta = dict(meta or {})
|
||||
if context:
|
||||
user_role = context.get("user_role") or "free"
|
||||
call_meta.setdefault("user_role", user_role)
|
||||
call_meta.setdefault("caller", "hunjing")
|
||||
if context.get("trace_id"):
|
||||
call_meta["trace_id"] = context["trace_id"]
|
||||
if transport is not None:
|
||||
return await transport.call_tool(tool_name, input)
|
||||
return await call_tool(
|
||||
http_client,
|
||||
endpoint_url,
|
||||
tool_name,
|
||||
input,
|
||||
auth_token,
|
||||
meta=call_meta or None,
|
||||
)
|
||||
|
||||
return executor
|
||||
Reference in new issue
Block a user