feat(settings): add MCP tools introspection endpoint

This commit is contained in:
2026-05-04 06:34:19 +00:00
parent 69bdf7b30a
commit 272e49b6b0
2 changed files with 64 additions and 0 deletions

View File

@@ -2806,6 +2806,18 @@ async def api_mcp_env_redeploy():
}
@app.get("/api/settings/mcp/tools")
async def api_mcp_tools():
"""List all MCP tools registered in legal_mcp."""
from web.mcp_introspection import list_mcp_tools
try:
tools = await list_mcp_tools()
except Exception as e:
logger.exception("mcp_tools_introspection_failed")
raise HTTPException(500, f"Tools introspection failed: {e}")
return {"tools": tools, "count": len(tools)}
# ── Settings: Tag → Company Mappings ──────────────────────────────
@app.get("/api/settings/paperclip-companies")

52
web/mcp_introspection.py Normal file
View File

@@ -0,0 +1,52 @@
# web/mcp_introspection.py
"""Introspect MCP tools from the FastMCP instance."""
from __future__ import annotations
import inspect
from typing import Any
async def list_mcp_tools() -> list[dict[str, Any]]:
"""List all registered MCP tools with metadata."""
from legal_mcp.server import mcp
tools = await mcp.list_tools()
out: list[dict[str, Any]] = []
for t in tools:
# Resolve underlying callable for source location
fn = _resolve_callable(t.name)
source_location = ""
module = ""
if fn is not None:
try:
file = inspect.getfile(fn)
_, line = inspect.getsourcelines(fn)
source_location = f"{file}:{line}"
module = fn.__module__
except Exception:
pass
out.append({
"name": t.name,
"description": t.description or "",
"params_schema": getattr(t, "inputSchema", None),
"module": module,
"source_location": source_location,
})
return sorted(out, key=lambda r: (r["module"], r["name"]))
def _resolve_callable(tool_name: str):
"""Find the python function backing a registered tool name."""
from legal_mcp.tools import (
cases, documents, drafting, precedent_library,
precedents, search, workflow,
)
for mod in (
cases, documents, drafting, precedent_library,
precedents, search, workflow,
):
fn = getattr(mod, tool_name, None)
if callable(fn):
return fn
return None