1515from collections .abc import Awaitable , Callable
1616
1717from mcp import ClientSession # pyright: ignore[reportMissingImports]
18- from mcp .client .stdio import stdio_client # pyright: ignore[reportMissingImports]
18+ from mcp .client .stdio import (
19+ stdio_client , # pyright: ignore[reportMissingImports]
20+ )
1921
2022from arcp import ARCPError , Envelope , ErrorCode , new_message_id
2123
@@ -52,9 +54,7 @@ async def call_via_mcp(
5254 raise ARCPError (ErrorCode .INTERNAL , str (exc )) from exc
5355
5456 if result .isError :
55- text = "\n " .join (
56- getattr (c , "text" , "" ) for c in result .content
57- )
57+ text = "\n " .join (getattr (c , "text" , "" ) for c in result .content )
5858 # MCP doesn't carry a typed error code; FAILED_PRECONDITION is
5959 # the right canonical mapping for "tool ran, said no".
6060 raise ARCPError (ErrorCode .FAILED_PRECONDITION , text or "tool error" )
@@ -74,19 +74,23 @@ async def handle_invoke(
7474 """One inbound ARCP `tool.invoke` → MCP call → ARCP job lifecycle."""
7575 job_id = f"job_{ new_message_id ()[- 10 :]} "
7676
77- await send (Envelope (
78- id = new_message_id (),
79- type = "job.accepted" ,
80- correlation_id = request .id ,
81- job_id = job_id ,
82- payload = {"job_id" : job_id , "state" : "accepted" },
83- ))
84- await send (Envelope (
85- id = new_message_id (),
86- type = "job.started" ,
87- job_id = job_id ,
88- payload = {"job_id" : job_id },
89- ))
77+ await send (
78+ Envelope (
79+ id = new_message_id (),
80+ type = "job.accepted" ,
81+ correlation_id = request .id ,
82+ job_id = job_id ,
83+ payload = {"job_id" : job_id , "state" : "accepted" },
84+ )
85+ )
86+ await send (
87+ Envelope (
88+ id = new_message_id (),
89+ type = "job.started" ,
90+ job_id = job_id ,
91+ payload = {"job_id" : job_id },
92+ )
93+ )
9094
9195 try :
9296 result = await call_via_mcp (
@@ -95,26 +99,32 @@ async def handle_invoke(
9599 arguments = dict (request .payload .get ("arguments" , {})),
96100 )
97101 except ARCPError as exc :
98- await send (Envelope (
99- id = new_message_id (),
100- type = "job.failed" ,
101- job_id = job_id ,
102- payload = exc .to_payload (),
103- ))
102+ await send (
103+ Envelope (
104+ id = new_message_id (),
105+ type = "job.failed" ,
106+ job_id = job_id ,
107+ payload = exc .to_payload (),
108+ )
109+ )
104110 return
105111
106- await send (Envelope (
107- id = new_message_id (),
108- type = "job.completed" ,
109- job_id = job_id ,
110- payload = {"result" : result },
111- ))
112+ await send (
113+ Envelope (
114+ id = new_message_id (),
115+ type = "job.completed" ,
116+ job_id = job_id ,
117+ payload = {"result" : result },
118+ )
119+ )
112120
113121
114122async def run_bridge (send : SendEnvelope , inbound ) -> None :
115123 """Wire one MCP session as the upstream for one ARCP runtime."""
116- async with stdio_client (upstream_params ()) as (read , write ), \
117- ClientSession (read , write ) as mcp :
124+ async with (
125+ stdio_client (upstream_params ()) as (read , write ),
126+ ClientSession (read , write ) as mcp ,
127+ ):
118128 await mcp .initialize ()
119129 extensions = await advertise_from_mcp (mcp )
120130 # In production this list would feed `Capabilities.extensions`
0 commit comments