1+ """ASGI entrypoint for the OpenAPI MCP server."""
2+
13import os
24import re
35import sys
1012from starlette .types import ASGIApp , Scope , Receive , Send , Message
1113from .mcp_audit import McpAuditMiddleware
1214from .storage_backend import read_file
15+ from .memory_store import get_callback_result , set_callback_result
16+ from .mcp_core import mcp
17+ from .apis import (
18+ async_tool ,
19+ automotive ,
20+ cap ,
21+ company ,
22+ docuengine ,
23+ exchange ,
24+ geocoding ,
25+ info ,
26+ pec ,
27+ risk ,
28+ sms ,
29+ trust ,
30+ visurecamerali ,
31+ )
1332
1433# ---------------------------------------------------------------------------
1534# Bootstrap package logger early — before uvicorn configures its own logging.
@@ -59,12 +78,8 @@ def format(self, record: logging.LogRecord) -> str:
5978 # Fallback: at least mask tokens
6079 return self ._TOKEN_RE .sub (r'\1token=***' , result )
6180
62- # Delegate everything else to the inner formatter
6381 def __getattr__ (self , name ):
6482 return getattr (self ._inner , name )
65- from .memory_store import get_callback_result , set_callback_result
66- from .mcp_core import mcp # Import MCP instance with tools already registered in mcp_core.py
67- from .apis import async_tool , company , cap , trust , visurecamerali , sms , risk , geocoding ,automotive ,exchange , pec , docuengine , info # Import tool modules (side-effect: triggers @mcp.tool registration)
6883
6984# Create the MCP ASGI app mounted at root
7085mcp_app = mcp .http_app (path = '/' )
@@ -168,19 +183,31 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
168183 client_ip = (scope .get ("client" ) or ("?" , 0 ))[0 ]
169184 async with registration_lock :
170185 if not getattr (app .state , "dynamic_tools_registered" , False ):
171- _logger .info ('%s %s "Initializing dynamic tools (token: %s...)"' , "[JIT]" , client_ip , token [:8 ])
186+ _logger .info (
187+ '%s %s "Initializing dynamic tools (token: %s...)"' ,
188+ "[JIT]" ,
189+ client_ip ,
190+ token [:8 ],
191+ )
172192 success = await asyncio .to_thread (docuengine .init_dynamic_tools , token )
173193 if success :
174194 app .state .dynamic_tools_registered = True
175195 else :
176- _logger .warning ('%s %s "Registration failed — will retry on next request"' , "[JIT]" , client_ip )
196+ _logger .warning (
197+ '%s %s "Registration failed — will retry on next request"' ,
198+ "[JIT]" ,
199+ client_ip ,
200+ )
177201
178202 await self .app (scope , receive , send )
179203
180204
181205_OAUTH_NOT_SUPPORTED_BODY = json .dumps ({
182206 "error" : "oauth_not_supported" ,
183- "message" : "This server does not support OAuth. Use a pre-configured Bearer token in the Authorization header."
207+ "message" : (
208+ "This server does not support OAuth. Use a pre-configured Bearer "
209+ "token in the Authorization header."
210+ ),
184211}).encode ()
185212
186213_OAUTH_DISCOVERY_PATHS = {
@@ -190,18 +217,25 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
190217}
191218
192219class RejectOAuthDiscoveryMiddleware :
193- """Return a JSON 404 for OAuth discovery endpoints so MCP clients fall back to Bearer auth ."""
220+ """Return a JSON 404 for OAuth discovery endpoints."""
194221 def __init__ (self , app : ASGIApp ) -> None :
195222 self .app = app
196223
197224 async def __call__ (self , scope : Scope , receive : Receive , send : Send ) -> None :
198- if scope ["type" ] == "http" and scope ["path" ].rstrip ("/" ) in {p .rstrip ("/" ) for p in _OAUTH_DISCOVERY_PATHS }:
225+ if (
226+ scope ["type" ] == "http"
227+ and scope ["path" ].rstrip ("/" ) in {p .rstrip ("/" ) for p in _OAUTH_DISCOVERY_PATHS }
228+ ):
199229 await send ({
200230 "type" : "http.response.start" ,
201231 "status" : 404 ,
202232 "headers" : [(b"content-type" , b"application/json" )],
203233 })
204- await send ({"type" : "http.response.body" , "body" : _OAUTH_NOT_SUPPORTED_BODY , "more_body" : False })
234+ await send ({
235+ "type" : "http.response.body" ,
236+ "body" : _OAUTH_NOT_SUPPORTED_BODY ,
237+ "more_body" : False ,
238+ })
205239 return
206240 await self .app (scope , receive , send )
207241
@@ -214,7 +248,7 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
214248app .add_middleware (McpAuditMiddleware ) # innermost — logs MCP JSON-RPC actions
215249app .add_middleware (Enrich404Middleware ) # wraps 404s in JSON
216250app .add_middleware (TokenQuerystringMiddleware ) # injects auth header + JIT registration
217- app .add_middleware (RejectOAuthDiscoveryMiddleware ) # short-circuits OAuth discovery paths
251+ app .add_middleware (RejectOAuthDiscoveryMiddleware ) # short-circuits OAuth discovery paths
218252# CORS must be outermost so it runs before anything else on every request,
219253# including pre-flight OPTIONS. expose_headers exposes Mcp-Session-Id to browsers.
220254# allow_credentials must NOT be True when allow_origins=["*"].
@@ -243,7 +277,9 @@ async def callbacks_endpoint(request: Request):
243277 return {"status" : "error" , "message" : "Body not a valid JSON" }
244278
245279 cb_obj = callback .get ("callback" )
246- custom = callback .get ("custom" ) or (cb_obj .get ("data" ) if isinstance (cb_obj , dict ) else None )
280+ custom = callback .get ("custom" ) or (
281+ cb_obj .get ("data" ) if isinstance (cb_obj , dict ) else None
282+ )
247283 if not custom :
248284 _logger .warning ('%s %s "Missing callback.custom field"' , "[CB]" , client_ip )
249285 return {"status" : "error" , "message" : "'callback.custom' missing from received data" }
0 commit comments