| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- """FastMCP transport wrapper for virtuoso tool logic.
- This module keeps the existing Virtuoso tool implementations untouched
- and exposes them through the MCP SDK transport.
- """
- from fastapi import FastAPI
- from fastapi import HTTPException
- from pydantic import BaseModel
- from mcp.server.fastmcp import FastMCP
- from mcp.server.transport_security import TransportSecuritySettings
- from virtuoso_mcp import (
- TOOLS,
- TOOL_DOCS,
- VIRTUOSO_ENDPOINT,
- SPARQL_DEFAULT_LIMIT,
- SPARQL_MAX_LIMIT,
- ALLOW_EXAMPLE_LOAD,
- )
- mcp = FastMCP(
- "virtuoso",
- transport_security=TransportSecuritySettings(
- enable_dns_rebinding_protection=False
- ),
- )
- def _wrap_tool(tool_name: str):
- def _tool(input: dict | None = None):
- payload = input or {}
- return TOOLS[tool_name](payload)
- _tool.__name__ = f"tool_{tool_name}"
- _tool.__doc__ = TOOL_DOCS.get(tool_name, "")
- return _tool
- for _name in sorted(TOOLS.keys()):
- mcp.add_tool(
- _wrap_tool(_name),
- name=_name,
- description=TOOL_DOCS.get(_name, ""),
- )
- app = FastAPI(title="Virtuoso MCP Server")
- app.mount("/mcp", mcp.sse_app())
- class LegacyToolRequest(BaseModel):
- tool: str
- input: dict = {}
- @app.post("/rpc")
- def legacy_rpc(req: LegacyToolRequest):
- if req.tool not in TOOLS:
- raise HTTPException(status_code=400, detail=f"Unknown tool: {req.tool}")
- try:
- result = TOOLS[req.tool](req.input or {})
- return {
- "status": "ok",
- "tool": req.tool,
- "description": TOOL_DOCS.get(req.tool, ""),
- "result": result,
- }
- except HTTPException:
- raise
- except Exception as exc:
- raise HTTPException(status_code=500, detail=str(exc))
- @app.get("/")
- def root():
- return {
- "status": "MCP server running",
- "transport": "fastmcp+sse",
- "mount": "/mcp",
- "tools": sorted(TOOLS.keys()),
- "virtuoso": VIRTUOSO_ENDPOINT,
- "guardrails": {
- "default_limit": SPARQL_DEFAULT_LIMIT,
- "max_limit": SPARQL_MAX_LIMIT,
- "allow_example_load": ALLOW_EXAMPLE_LOAD,
- },
- }
- @app.get("/health")
- def health():
- return root()
|