@@ -243,6 +243,47 @@ async def handle_tool_call_request(mcp_request: JSONRPCRequest, request: Request
243243 )
244244 # For Canton payments, return standard MCP error (not 402)
245245 if payment_handler .canton_enabled :
246+ # Register pending payment with facilitator (async, non-blocking)
247+ try :
248+ party_id = request .headers .get ("X-Canton-Party-ID" , "" )
249+ if not party_id :
250+ party_id = request .query_params .get ("payerParty" , "" )
251+ if not party_id :
252+ from canton_mcp_server .env import get_env
253+ party_id = get_env ("CANTON_DEFAULT_PAYER_PARTY" , "" )
254+
255+ if party_id and e .payment_requirements :
256+ # Find Canton payment requirement
257+ canton_req = next (
258+ (req for req in e .payment_requirements
259+ if isinstance (req , dict ) and req .get ("scheme" ) == "exact-canton" ),
260+ None
261+ )
262+ if canton_req :
263+ import httpx
264+ import asyncio
265+
266+ async def register_pending_payment ():
267+ try :
268+ async with httpx .AsyncClient (timeout = 5.0 ) as client :
269+ await client .post (
270+ f"{ payment_handler .canton_facilitator_url } /pending-payments" ,
271+ json = {
272+ "party" : party_id ,
273+ "payee" : canton_req .get ("payTo" , "" ),
274+ "amount" : canton_req .get ("maxAmountRequired" , "" ),
275+ "resource" : canton_req .get ("resource" , "" ),
276+ },
277+ )
278+ logger .info (f"📝 Registered pending payment for '{ tool_name } ' with facilitator" )
279+ except Exception as reg_error :
280+ logger .warning (f"Failed to register pending payment: { reg_error } " )
281+
282+ # Fire and forget - don't block error response
283+ asyncio .create_task (register_pending_payment ())
284+ except Exception as reg_error :
285+ logger .warning (f"Failed to register pending payment: { reg_error } " )
286+
246287 return error_response (
247288 mcp_request .id ,
248289 ErrorCodes .INVALID_REQUEST , # Use -32600 for payment required
0 commit comments