Skip to content

Commit 988aa8d

Browse files
nficanoclaude
andcommitted
ci: fix lint and restore client.py coverage above 90%
Ruff was failing on examples/mcp/main.py import sort; applied auto-fix and format. Coverage had drifted to 88.56% after recent client refactors — added tests/unit/test_client.py covering the handshake error paths (rejected, challenge, unexpected type, out-of-band envelopes), envelope() factory, send/request before open, close idempotency, and reader-loop routing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent deac826 commit 988aa8d

2 files changed

Lines changed: 412 additions & 31 deletions

File tree

examples/mcp/main.py

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
from collections.abc import Awaitable, Callable
1616

1717
from 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

2022
from 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

114122
async 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

Comments
 (0)