diff --git a/financial-services/server/mock_mcp_server.py b/financial-services/server/mock_mcp_server.py index 9c561c2..2e46c27 100644 --- a/financial-services/server/mock_mcp_server.py +++ b/financial-services/server/mock_mcp_server.py @@ -75,6 +75,99 @@ def _risk_report_writer(args: dict) -> str: } +# Upstream definitions are independent of the gateway catalog used for drift checks. +TOOL_DEFINITIONS = [ + { + "name": "finance.document_reader", + "description": "Read filed annual financial statements for a corporate client from the secure " + "document vault", + "inputSchema": { + "type": "object", + "properties": { + "client_id": {"type": "string"}, + "document_id": {"type": "string"}, + }, + "required": ["client_id"], + }, + }, + { + "name": "finance.sanctions_screening", + "description": "Screen a corporate client and its beneficial owners against EU/UN sanctions and " + "PEP lists (CDD/AML)", + "inputSchema": { + "type": "object", + "properties": {"client_id": {"type": "string"}}, + "required": ["client_id"], + }, + }, + { + "name": "finance.credit_bureau_lookup", + "description": "Retrieve a commercial credit-bureau report for a client", + "inputSchema": { + "type": "object", + "properties": { + "client_id": {"type": "string"}, + "bureau": { + "type": "string", + "enum": [ + "creditreform", + "schufa", + "crif", + "banque-de-france-fiben", + ], + }, + }, + "required": ["client_id"], + }, + }, + { + "name": "finance.exposure_aggregation", + "description": "Aggregate existing group exposure with the proposed facility and test it against " + "the single-obligor concentration limit", + "inputSchema": { + "type": "object", + "properties": { + "client_id": {"type": "string"}, + "proposed_facility_eur": {"type": "number"}, + }, + "required": ["client_id", "proposed_facility_eur"], + }, + }, + { + "name": "finance.risk_model", + "description": "Compute PD/LGD/EAD, the internal rating grade and the IFRS 9 stage for a " + "proposed facility", + "inputSchema": { + "type": "object", + "properties": { + "client_id": {"type": "string"}, + "proposed_facility_eur": {"type": "number"}, + }, + "required": ["client_id", "proposed_facility_eur"], + }, + }, + { + "name": "finance.risk_report_writer", + "description": "Write the credit risk assessment to the core banking system", + "inputSchema": { + "type": "object", + "properties": { + "client_id": {"type": "string"}, + "internal_rating": {"type": "string"}, + "pd_1y": {"type": "number"}, + "ifrs9_stage": {"type": "number"}, + "amount_eur": {"type": "number"}, + "aggregate_exposure_eur": {"type": "number"}, + "breaches_concentration_limit": {"type": "boolean"}, + "cdd_cleared": {"type": "boolean"}, + "recommendation": {"type": "string"}, + }, + "required": ["client_id", "amount_eur", "recommendation", "cdd_cleared"], + }, + }, +] + + class Handler(BaseHTTPRequestHandler): def do_POST(self): # noqa: N802 if self.path != "/mcp": @@ -82,6 +175,21 @@ def do_POST(self): # noqa: N802 return length = int(self.headers.get("Content-Length", 0)) request = json.loads(self.rfile.read(length)) + method = request.get("method", "") + if method == "tools/list": + self._reply(200, { + "jsonrpc": "2.0", + "id": request.get("id"), + "result": {"tools": TOOL_DEFINITIONS}, + }) + return + if method != "tools/call": + self._reply(200, { + "jsonrpc": "2.0", + "id": request.get("id"), + "error": {"code": -32601, "message": f"unknown method: {method}"}, + }) + return params = request.get("params", {}) tool = params.get("name", "") handler = TOOLS.get(tool)