Skip to content

fix(mcp): make the conformance harness survive a bad server, and tighten two claims - #376

Merged
caezium merged 1 commit into
mainfrom
fix/mcp-conformance-harness
Aug 10, 2026
Merged

fix(mcp): make the conformance harness survive a bad server, and tighten two claims#376
caezium merged 1 commit into
mainfrom
fix/mcp-conformance-harness

Conversation

@caezium

@caezium caezium commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Re-lands four review findings from #369. They were fixed there, then reverted because my push conflicted with unpushed local work on that branch, and the revert pair got dropped during the restack — so #369 merged without them. The four threads on #369 are still open; this closes them.

The harness could die before printing its verdict

next(t for t in tools if t["name"] == ...) raises StopIteration when a server omits a tool — so the single condition most worth reporting killed the run instead of failing a check. Now looked up through a by_name dict with .get, so a missing tool registers a failure and the run still reaches its verdict.

The tasks section is wrapped in try/finally with both clients closed there. Without it, any unexpected payload left spawned Burrow processes running and swallowed the verdict at the same time. tc is initialised to None before the try, so a failure inside Client() itself can't turn the cleanup into a NameError.

A missing argument failed unhelpfully

No binary path meant None reached subprocess.Popen, raising a TypeError naming neither the script nor the argument. It now exits with usage text. Verified by running it with no arguments.

An assertion twelve times looser than the thing it checked

testResourceRead_isPrivateAndShortLived compared the TTL against digestTTL (60s), but burrow://info declares liveTTL (5s) in MCPResources.swift. The bound would have held even if the resource regressed to caching live machine state for a full minute. Now pinned to liveTTL; the private cache-scope assertion is unchanged.

A documented command that couldn't run

socketfilterfw isn't on the default PATHwhich socketfilterfw finds nothing; it lives at /usr/libexec/ApplicationFirewall/. Anyone pasting the documented command got "command not found". Now absolute. The other three status commands resolve fine and are untouched.

Verification

Python compiles and the new usage guard was exercised directly. The Swift change is a one-line constant swap against MCPProtocol.Cache.liveTTL; CI covers the build.

Summary by CodeRabbit

  • Documentation

    • Updated the documented macOS firewall status command with its full system path.
  • Bug Fixes

    • Corrected resource caching validation to respect the resource’s maximum lifetime.
    • Improved conformance checks by reporting missing tools clearly instead of stopping unexpectedly.
    • Ensured spawned processes are cleaned up when validation or task polling encounters errors.

…ten two claims

The harness could die before printing the verdict it exists to produce.
`next(t for t in tools if ...)` raises StopIteration when a server omits a
tool, so the one condition most worth reporting -- a missing tool -- killed
the run instead of failing a check. Looked up by name with .get now, so an
absent tool registers a failure and the run still reaches its verdict.

The tasks section is wrapped in try/finally with both clients closed there.
Without it any unexpected payload left spawned Burrow processes running and
swallowed the verdict at the same time. `tc` is initialised to None first, so
a failure inside Client() itself cannot turn the cleanup into a NameError.

A missing binary argument now exits with usage text. It previously reached
subprocess.Popen as None and failed with a TypeError that named neither the
script nor the missing argument.

testResourceRead_isPrivateAndShortLived compared the TTL against digestTTL
(60s) when burrow://info declares liveTTL (5s) -- a bound twelve times looser
than the thing it was checking, which would have held even if the resource
regressed to minute-long caching of live machine state.

`socketfilterfw` is not on the default PATH; it lives in
/usr/libexec/ApplicationFirewall, so the documented command failed for anyone
who pasted it.
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a2d91dec-6c2a-437a-af96-59aeaca74cc1

📥 Commits

Reviewing files that changed from the base of the PR and between d5a457b and 13d61d6.

📒 Files selected for processing (3)
  • docs/agent-tools.md
  • macos/Tests/MCPConformanceTests.swift
  • macos/scripts/mcp-conformance.py

📝 Walkthrough

Walkthrough

The conformance harness now validates required inputs and tools, closes clients during failures, and updates cache and firewall command expectations.

Changes

Conformance harness robustness

Layer / File(s) Summary
Harness input and tool validation
macos/scripts/mcp-conformance.py
The harness reports a usage error when no binary path is supplied. Missing tools become explicit failures instead of raising lookup exceptions.
Guaranteed client cleanup
macos/scripts/mcp-conformance.py
Task and primary clients close through try/finally paths when setup, polling, or assertions fail.
Conformance expectations and command documentation
macos/Tests/MCPConformanceTests.swift, docs/agent-tools.md
The cache test uses MCPProtocol.Cache.liveTTL as the maximum duration. The firewall example uses the full socketfilterfw path.

Estimated code review effort: 3 (Moderate) | ~20 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/mcp-conformance-harness

Comment @coderabbitai help to get the list of available commands.

@caezium
caezium merged commit dbc650d into main Aug 10, 2026
4 of 5 checks passed
@caezium
caezium deleted the fix/mcp-conformance-harness branch August 10, 2026 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant