feat(settings): add MCP tools introspection endpoint
This commit is contained in:
12
web/app.py
12
web/app.py
@@ -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
52
web/mcp_introspection.py
Normal 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
|
||||
Reference in New Issue
Block a user