38 lines
1.3 KiB
Python
38 lines
1.3 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from mcp.server.fastmcp import FastMCP
|
||
|
|
from starlette.applications import Starlette
|
||
|
|
|
||
|
|
from qonto_assistant import __version__
|
||
|
|
from qonto_assistant.config import Settings
|
||
|
|
|
||
|
|
|
||
|
|
def create_mcp_server(*, settings: Settings) -> FastMCP:
|
||
|
|
"""Build the MCP adapter on the same capability core as the REST surface.
|
||
|
|
|
||
|
|
Phase 2 (QONTO-WP-0003) scope note: this skeleton exposes only a smoke
|
||
|
|
tool. Real read tools (`qonto_org_summary`, `qonto_list_transactions`,
|
||
|
|
`qonto_cost_run_rate_hints`) land in QONTO-WP-0003-T02, routed through the
|
||
|
|
same `CapabilityRequest` -> `PolicyEngine.decide()` path REST already
|
||
|
|
uses -- no policy fork between transports.
|
||
|
|
"""
|
||
|
|
server = FastMCP(
|
||
|
|
name=settings.service_name,
|
||
|
|
instructions=(
|
||
|
|
"Governed read-only Qonto finance awareness for Binky. "
|
||
|
|
"No spend, transfer, card, or volume-cost tools are exposed here."
|
||
|
|
),
|
||
|
|
stateless_http=True,
|
||
|
|
)
|
||
|
|
|
||
|
|
@server.tool()
|
||
|
|
def qonto_ping() -> dict[str, str]:
|
||
|
|
"""Smoke tool confirming the MCP adapter is reachable. No bank call."""
|
||
|
|
return {"status": "ok", "service": settings.service_name, "version": __version__}
|
||
|
|
|
||
|
|
return server
|
||
|
|
|
||
|
|
|
||
|
|
def mcp_asgi_app(*, settings: Settings) -> Starlette:
|
||
|
|
return create_mcp_server(settings=settings).streamable_http_app()
|