v1.0.0 feat(mcp-registry): #201 PR 5 of 5 HTTP install/uninstall + spec/36 LOCK#334
Merged
Merged
Conversation
…ion handler Wires the HTTPMCPServerRegistryBackend write paths against a tier-2+ catalog server: install(spec) posts to /mcp-servers (returning 201 with MCPServerRef projection from input spec), uninstall(name) deletes (204 on success or absence per MUST 9 idempotency). _handle_tier_regression() catches 405 on either POST or DELETE, calls refresh_capabilities() outside the cache lock, and raises NotImplementedError with operator-readable tier-change wording. install() now REJECTS literal env values with ValueError before any I/O. The load_mcp_server -> install pipeline would otherwise send resolved secrets in the POST body. Callers MUST pass unresolved $VAR refs. MCPServerSpec.__repr__ redacts env contents (defense-in-depth for any future log site). MCPServerRef.source preserves the raw catalog URL per spec/36 line 228 with an operator-facing docstring warning to redact before logging. CLI mcp-registry handler catches NotImplementedError so tier-1 / tier regression surfaces as readable output rather than an unhandled exception. Tests: +18 net (16 in http_backend covering POST 201/409/405-with-three re-probe outcomes, DELETE 204/absent/405, capability gate, auth headers, env validation x3, MUST 4 redaction, regression-guard C-F7; +2 in conformance for MUST 4 parametrized credential redaction across both backends). MockTransport upgraded to tier-2 with POST 201 + 409 simulation + DELETE 204 + servers-list mirroring for MUST 10.
… versioning policy spec/36 LOCKED at PR 5: removes DRAFT marker, adds the missing Install/uninstall semantics (HTTP) subsection mirroring the PR 3 filesystem section, extends the exception table with POST 409 / 405 and DELETE 204 / 405 rows, corrects Decision 5 wording so the 'static class default' phrase no longer contradicts Decision 6's dynamic-per-tier contract, corrects baseline test counts (the prior 3,078 / 3,088 numbers were 219 off from reality), removes the inline TODO comment, documents the new install() env-var input contract (callers MUST pass unresolved $VAR refs), documents the tier-2 re-probe-after-405 inconsistent-server contract, and adds an operator note for the MCPServerRef.source raw URL. spec/19 cross-link updated from DRAFT to LOCKED at #201 PR 5; brief addendum documents the resolve_env=False parameter on parse_mcp_md_text for backend implementers. release-runbook.md gains a pre-publish smoke pipeline (uv build + twine check + clean-venv install + version assertion), a TestPyPI smoke step (first publish ever for this project), and a rollback contract (yank semantics) section. versioning.md gains a Protocol surface breaking-change policy. _locks.py deprecation shim sunset deferred from v1.0 to v1.1 per the PR 5 release decision: sunset markers, docstrings, and warning messages all updated. spec/21 + disaster-recovery.md text refreshed to match. Lock integration test assertion updated to v1.1.
…pped) Cuts the v1.0.0 release after twelve consecutive backend protocols shipped across the protocol-pattern series. Spec/36 LOCKED in the prior commit closes the v1.0 Protocol surface. pyproject.toml: version 0.13.0 -> 1.0.0, classifier Alpha -> Production/Stable, twine>=6.0 added to dev deps, [tool.hatch.build .targets.sdist] excludes tests/ + docs/ + extras/ + .claude/ + .github/ so the published sdist stays clean. atomic_agents/__init__.py version bumped in lockstep. README.md: version badge 0.13.0 -> 1.0.0 (alpha -> stable); backend protocols table flips MCPServerRegistryBackend row to Shipped; status block flips "Eleven of twelve" to "Twelve of twelve"; Quick Start gains pip install + uv add paths above the git clone path; 45 relative-to-absolute GitHub URL rewrites across spec list, backend table, and image refs so the README renders cleanly on PyPI (it bakes into the wheel at build time and is not patchable post-publish). CLAUDE.md: architecture diagram MCPServerRegistry emoji flips yellow to green; 12th backend lock-paragraph added mirroring the CorpusBackend precedent shape (covers Decision 1-9, the 10 MUSTs, capability evolution table, tier negotiation, what it closes); where-things-live spec count flips from "31 locked + 4 drafts" to "32 locked + 3 drafts" with spec/36 dropped from the draft enumeration; "Eleven backend protocols shipped" string flipped to "Twelve" in two locations. CHANGELOG.md: renames [Unreleased] section to [1.0.0] - 2026-06-04; prepends the PR 5 entry above the existing PR 4 entry under the shared [1.0.0] header; adds a fresh empty [Unreleased] section above for post-1.0 work; documents the install() env-var contract upgrade under Changed; documents the _locks.py deprecation shim deferral under Deprecated. Uses "1.0.0" no v prefix per the existing convention. .github/workflows/publish-to-pypi.yml NEW: triggers on strict 3-component v[0-9]+.[0-9]+.[0-9]+ semver tag (rejects v1.0.0-rc1 and similar pre-release tags that would otherwise match a v1.* wildcard); runs uv build + twine check + uv publish via UV_PUBLISH_TOKEN secret. First publish stays manual (PyPI account token bootstrap); subsequent releases automated. .github/workflows/test.yml: adds --extra http to the uv sync command so CI installs httpx explicitly per the [http] optional dependency. httpx arrives transitively via mcp>=1.0.0 today, but the explicit declaration validates the operator install path and guards against a future mcp release dropping the dep. Closes #201. Twelve of twelve backend protocols shipped. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- docs/methodology.md: "eleven are shipped" → "twelve are shipped"; add MCPServerRegistryBackend to the protocol list; 2937+ → 3270+ test count - CONTRIBUTING.md: 2937 → 3270+ test count - docs/getting-started.md: stale "296 passed" → "3270 passed" (was written at v0.1.0 era; reflects the current full-suite count at v1.0.0) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Final PR of the MCPServerRegistryBackend arc (#201) and the v1.0.0 release candidate. Closes the v1.0 Protocol surface: twelve of twelve backend protocols shipped.
Feature (commit 4464c2b):
HTTPMCPServerRegistryBackend.install(spec)posts to/mcp-serverswith the spec body, projectsMCPServerReffrom input, maps 409 toMCPServerAlreadyInstalled, 405 to_handle_tier_regressionraisingNotImplementedErrorwith operator-readable tier-change wording.HTTPMCPServerRegistryBackend.uninstall(name)deletes via/mcp-servers/<name>, 204 on success or absence per MUST 9 idempotency, 405 to tier regression handler._handle_tier_regression(operation)re-probes outside the cache lock, updates capabilities, raisesNotImplementedError. Re-probe failure raisesMCPRegistryUnavailableinstead of swallowing.install()rejects literal env values withValueErrorBEFORE any network call so theload_mcp_server -> installpipeline cannot exfiltrate resolved secrets via the POST body. Callers MUST pass unresolved$VARrefs.MCPServerSpec.__repr__redacts env contents defensively.MCPServerRef.sourcekeeps the raw catalog URL per spec/36 line 228 with an operator-facing docstring warning.NotImplementedErrorfrom tier-1 / tier-regression so it surfaces as readable output.Spec + docs (commit df59918):
spec/36-mcp-server-registry-backend.mdLOCKED at v1.0: DRAFT marker removed; Install/uninstall semantics (HTTP) section added; exception table extended with POST 409 / 405 and DELETE 204 / 405; Decision 5 wording corrected; baseline test counts corrected; inline TODO removed; env-var input contract documented; tier-2 re-probe-after-405 inconsistent-server contract documented.spec/19-mcp.mdcross-link updated DRAFT to LOCKED at [backend] MCPServerRegistryBackend — unify MCP server discovery across agents #201 PR 5; addendum forresolve_env=False.release-runbook.mdgains pre-publish smoke pipeline + TestPyPI smoke + rollback contract (yank semantics).versioning.mdgains a Protocol-surface breaking-change policy._locks.pyshim sunset deferred from v1.0 to v1.1; markers + docstrings + warning text updated; spec/21 + disaster-recovery.md refreshed.Release ceremony (commit 4319f1e):
pyproject.tomlversion 0.13.0 to 1.0.0; classifier Alpha to Production/Stable;twine>=6.0in dev deps; sdist excludes for tests/docs/extras/.claude/.github.atomic_agents/__init__.pyversion bumped in lockstep..github/workflows/publish-to-pypi.ymlNEW: strict 3-component SemVer tag trigger only; uv build + twine check + uv publish viaUV_PUBLISH_TOKEN..github/workflows/test.yml:--extra httpadded so CI validates the [http] optional dependency declaratively.Doc drift sweep (commit 9706692):
docs/methodology.md: eleven to twelve; MCPServerRegistryBackend added to shipped list; 2937+ to 3270+ tests.CONTRIBUTING.md: test count 2937 to 3270+.docs/getting-started.md: stale install-verify step 296 passed (v0.1.0 era) to 3270 passed.Test Coverage
87% on PR 5 surface (13 of 15 tracepoints covered with dedicated tests; 2 known gaps documented).
Test delta: 3,307 to 3,326 collected (+19 net; 3,270 passing + 56 skipped, 0 regressions, 0 failures).
Pre-Landing Review
Ran a 10-reviewer army (5 specialists, 2 single-purpose subagents, 1 Claude adversarial, 1 Codex adversarial, 1 Codex structured). 60 findings total; 8 P1 + 3 em-dash project-rule violations + 2 user-decision items resolved inline before push.
P1 auto-fixes applied:
_handle_tier_regressionexcept clause extended to catchMCPRegistryDescriptorInvalid(was bypassing the stale-cache path on malformed/capabilitiesre-probe responses)._handle_http_error409 branch now namesspec.namein theMCPServerAlreadyInstalledmessage via the newinstalled_server_nameparameter (was returning bare URL only).threading.Lockaround the check-and-set on theinstalleddict so the MUST 9 concurrent test is race-free (was relying on GIL behavior)..github/workflows/publish-to-pypi.ymltag pattern tightened fromv1.*to strict 3-component SemVer (was matchingv1.0.0-rc1and similar)..github/workflows/test.ymladds--extra httpto CI uv sync (was relying on transitivemcp>=1.0.0for httpx)._locks.pyshim deferral decision).if resp.status_code != 201/!= 204checks afterraise_for_status()so non-contract 2xx responses (200 HTML interstitial, 202 async queue) fail loudly instead of silently reporting success.User-decision items resolved:
install()rejects literal env values with ValueError (upgraded from warn + proceed). Both adversarial reviewers BLOCKED on the warn-only design because it lets resolved secrets reach the catalog server's request body. Refusal at the API boundary is the v1.0 contract.MCPServerRef.sourcekeeps the raw catalog URL per spec/36 line 228, with operator-facing docstring warnings added to types.py and install() return docs.Adversarial Review
Both Codex (
codex review+codex exec) and Claude (subagent) ran in parallel.Codex structured review: GATE PASS (0 P1 markers); 2 P2 findings on non-contract 2xx responses (silently treated as success). Both addressed inline with explicit status code checks.
Codex adversarial: BLOCK recommendation on env exfiltration path. 8 findings: env exfiltration via warn-only design (addressed: upgraded to refuse), MCPServerRef.source raw URL (addressed: docstring warnings), MCPServerSpec.repr command/args not redacted (out of scope for v1.0; documented as intentional), tier regression DescriptorInvalid catch (addressed), 409 message missing spec.name (addressed), PyPI workflow OIDC (deferred to v1.1 as documented), list_mcp_servers spec vs HTTP behavior carve-out (spec already documents this), spec validation gap (addressed with status checks).
Claude adversarial: BLOCK on Findings 1 (env exfiltration) and 3 (PyPI wildcard tag trigger). Both addressed inline. 10 findings total; all addressed or documented.
Cross-model synthesis: High-confidence findings (env exfiltration, MCPServerRef.source, tier regression catch, 409 message, PyPI wildcard, em-dashes, non-contract 2xx) all caught by 2+ reviewers and addressed before push.
Plan Completion
48 of 51 plan items DONE; 0 NOT DONE; 3 UNVERIFIABLE at PR-merge time (PyPI/TestPyPI publish, v1.0.0 git tag, GitHub Release creation; these execute post-merge per the release ceremony in
docs/deployment/release-runbook.md).All 6 pre-dispatch corrections applied (exception table rows, HTTP install/uninstall semantics section, Decision 5 wording, test count corrections, inline TODO removal, tier-2-still-supports clarification). All 13 D-PR5 implementation decisions applied. All 4 user-decision items resolved with Dan's prep-time picks (one PR shape, _locks deferred to v1.1, TestPyPI first, repr env redacted).
Documentation
Files updated post-PR-5-implementation
docs/methodology.md: backend protocol count corrected eleven to twelve; MCPServerRegistryBackend added to the shipped-protocols list in the intro paragraph; test count corrected 2937+ to 3270+.CONTRIBUTING.md: test count corrected 2937 to 3270+ in the Tests section.docs/getting-started.md: stale install-verify step corrected from 296 passed (written at v0.1.0) to 3270 passed.Files already current (updated by PR 5)
README.md,CLAUDE.md,CHANGELOG.md,docs/spec/36-mcp-server-registry-backend.md,docs/spec/19-mcp.md,docs/spec/21-lock-backend.md,docs/deployment/release-runbook.md,docs/deployment/versioning.md,docs/deployment/disaster-recovery.md.Documentation coverage
All shipped features (HTTP install/uninstall, 409 collision mapping, 405 mid-session tier regression handler, tier negotiation) are fully documented in spec/36, CHANGELOG, README, and CLAUDE.md. No critical gaps.
Version
Already bumped to 1.0.0 by PR 5; covers all changes in this branch.
Test plan
test_legacy_agentlock_emits_deprecation_warningassertion updated v1.0 to v1.1Closes #201. Extends
/shipstreak to 12 consecutive clean ships.🤖 Generated with Claude Code