ci(3082): cross-repo published mcp-server manifest check (verb-SSOT prevention, Layer 2) #3281

Merged
devops-engineer merged 2 commits from feat/3082-published-manifest-check into main 2026-06-26 01:09:01 +00:00
Member

What

The cross-repo durable prevention layer for the MCP tool-verb SSOT contract (core#3082). It resolves the ACTUAL tool manifest of the PUBLISHED @molecule-ai/mcp-server build (the build a concierge is actually delivered) and asserts it satisfies the contract's accepted verb union (required_tools ∪ transitional_tool_aliases). This is the layer that would have caught the staging stale-published-build degrade — a published build skewed away from the contract fails HERE, in core CI, BEFORE any tenant provisions a concierge against it.

It complements the in-repo Go contract test (checks core's own hand-written verb) and the producer-binding test in @molecule-ai/mcp-server (checks the producer SOURCE). Neither of those sees the PUBLISHED artifact; this does.

New files (no existing files modified)

  • scripts/mcp-verb-manifest-check/check-published-mcp-manifest.mjs — loads an already-installed published build via an in-tree child harness that patches the ESM McpServer.prototype.tool to record registered tool names, builds the management-mode server, and asserts ⊇ contract. FAIL when no accepted verb is present (the staging degrade); WARN (non-fatal) when only a transitional alias carries the gate. Reads required_tools (+ transitional_tool_aliases); falls back to legacy required_tool.
  • .gitea/workflows/mcp-verb-published-manifest.yml — installs the published package from the Gitea npm registry and runs the checker. Standalone soak-then-promote workflow (mirrors the contract-drift gate); a daily cron catches a newly-published skew even with no commit (the stale-build failure mode is time-, not commit-, dependent).

Does NOT touch contracts/mcp-plugin-delivery.contract.json, platform_agent.go, or registry.go — the verb-SSOT PR owns those.

New CI secret required

MCP_SERVER_READPKG_TOKEN — a Gitea token with read:package scope for the molecule-ai npm registry (the workflow installs the published package). Fail-closed on trusted contexts; soft-skip on fork PRs. Please provision this org/repo secret before promoting the workflow into branch protection.

Heads-up: this check FAILS against today's main — by design

Run against current origin/main (legacy required_tool: create_workspace) the check FAILS, because the published management build exposes provision_workspace, never create_workspace — i.e. it immediately surfaces the live contract↔producer mismatch core#3082 is fixing. It goes green once the contract is corrected to provision_workspace (the core verb-SSOT PR) OR a build exposing create_workspace is published. This is the gate doing its job, not a flake.

Enforcement proven locally (vs the real published 1.6.1 build, 41-tool manifest)

Contract under test Result
required=[provision_workspace] (corrected) OK (exit 0)
required=[create_workspace] only FAIL (exit 1) — the staging stale-build catch
required=[create_workspace] + provision_workspace alias OK + loud ::warning
current origin/main legacy required_tool=create_workspace FAIL (exit 1) — surfaces the live mismatch

Dependency

Depends on the core verb-SSOT PR (feat/3082-mcp-verb-ssot-contract) landing required_tools: ["provision_workspace"] (+ optional transitional_tool_aliases) in the contract. The checker's legacy fallback keeps it safe to land before/after.

Review

Requesting 2 genuine pool reviews before merge. Do not merge until the core verb-SSOT PR corrects the contract (otherwise it lands red against main, as noted above) and MCP_SERVER_READPKG_TOKEN is provisioned.

🤖 Generated with Claude Code

## What The **cross-repo** durable prevention layer for the MCP tool-verb SSOT contract (core#3082). It resolves the ACTUAL tool manifest of the **PUBLISHED** `@molecule-ai/mcp-server` build (the build a concierge is actually delivered) and asserts it satisfies the contract's accepted verb union (`required_tools ∪ transitional_tool_aliases`). This is the layer that would have caught the **staging stale-published-build degrade** — a published build skewed away from the contract fails HERE, in core CI, BEFORE any tenant provisions a concierge against it. It complements the in-repo Go contract test (checks core's own hand-written verb) and the producer-binding test in `@molecule-ai/mcp-server` (checks the producer SOURCE). Neither of those sees the PUBLISHED artifact; this does. ## New files (no existing files modified) - `scripts/mcp-verb-manifest-check/check-published-mcp-manifest.mjs` — loads an already-installed published build via an in-tree child harness that patches the ESM `McpServer.prototype.tool` to record registered tool names, builds the management-mode server, and asserts ⊇ contract. **FAIL** when no accepted verb is present (the staging degrade); **WARN** (non-fatal) when only a transitional alias carries the gate. Reads `required_tools` (+ `transitional_tool_aliases`); falls back to legacy `required_tool`. - `.gitea/workflows/mcp-verb-published-manifest.yml` — installs the published package from the Gitea npm registry and runs the checker. Standalone soak-then-promote workflow (mirrors the contract-drift gate); a daily cron catches a newly-published skew even with no commit (the stale-build failure mode is time-, not commit-, dependent). **Does NOT touch** `contracts/mcp-plugin-delivery.contract.json`, `platform_agent.go`, or `registry.go` — the verb-SSOT PR owns those. ## New CI secret required `MCP_SERVER_READPKG_TOKEN` — a Gitea token with **read:package** scope for the molecule-ai npm registry (the workflow installs the published package). Fail-closed on trusted contexts; soft-skip on fork PRs. Please provision this org/repo secret before promoting the workflow into branch protection. ## Heads-up: this check FAILS against today's `main` — by design Run against current `origin/main` (legacy `required_tool: create_workspace`) the check **FAILS**, because the published management build exposes `provision_workspace`, never `create_workspace` — i.e. it immediately surfaces the live contract↔producer mismatch core#3082 is fixing. It goes **green** once the contract is corrected to `provision_workspace` (the core verb-SSOT PR) OR a build exposing `create_workspace` is published. This is the gate doing its job, not a flake. ## Enforcement proven locally (vs the real published 1.6.1 build, 41-tool manifest) | Contract under test | Result | |---|---| | `required=[provision_workspace]` (corrected) | OK (exit 0) | | `required=[create_workspace]` only | FAIL (exit 1) — the staging stale-build catch | | `required=[create_workspace]` + `provision_workspace` alias | OK + loud `::warning` | | current `origin/main` legacy `required_tool=create_workspace` | FAIL (exit 1) — surfaces the live mismatch | ## Dependency **Depends on** the core verb-SSOT PR (`feat/3082-mcp-verb-ssot-contract`) landing `required_tools: ["provision_workspace"]` (+ optional `transitional_tool_aliases`) in the contract. The checker's legacy fallback keeps it safe to land before/after. ## Review Requesting **2 genuine pool reviews** before merge. Do not merge until the core verb-SSOT PR corrects the contract (otherwise it lands red against main, as noted above) and `MCP_SERVER_READPKG_TOKEN` is provisioned. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hongming-ceo-delegated added 2 commits 2026-06-26 00:59:11 +00:00
Resolves the ACTUAL tool manifest of the PUBLISHED @molecule-ai/mcp-server
build (management mode) via an in-tree child harness that patches the ESM
McpServer to record registered tools, and asserts it satisfies the
contract's accepted verb union. FAILs when no accepted verb is present
(the staging stale-build degrade); WARNs (non-fatal) when only a
transitional alias carries the gate. Reads required_tools (+ aliases) with
a fallback to legacy required_tool. Deliberately introspects the PUBLISHED
package, never a source build (main lacks the management-mode split).
ci(3082): workflow — resolve published mcp-server manifest and assert vs contract
CI / Python Lint & Test (pull_request) Successful in 6s
Block integration-tester contamination artifacts / Block staging-trigger / invalid manifest contamination (pull_request) Successful in 7s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 9s
Lint curl status-code capture / Scan workflows for curl status-capture pollution (pull_request) Successful in 6s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 6s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 6s
E2E Peer Visibility (literal MCP list_peers) / detect-changes (pull_request) Successful in 12s
lint-required-workflows-docker-host-pinned / Lint docker-host pin on docker-touching workflows (pull_request) Successful in 6s
E2E API Smoke Test / detect-changes (pull_request) Successful in 14s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 12s
CI / Detect changes (pull_request) Successful in 16s
mcp-verb-published-manifest / Published mcp-server manifest ⊇ contract required verbs (pull_request) Failing after 11s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 9s
E2E Chat / detect-changes (pull_request) Successful in 20s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 20s
sop-checklist / review-refire (pull_request_target) Has been skipped
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (local) (pull_request) Has been skipped
sop-checklist / all-items-acked (pull_request) acked: 0/9 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +6 — body-unfilled: comprehensive-testing, local-postgres-e2
lint-no-coe-on-required / lint-no-coe-on-required (pull_request) Successful in 19s
sop-checklist / na-declarations (pull_request) N/A: (none)
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 4s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 4s
sop-checklist / all-items-acked (pull_request_target) Successful in 9s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 19s
CI / Platform (Go) (pull_request) Successful in 3s
Concierge Creates Workspace Hermetic / Concierge Creates Workspace Hermetic (pull_request) Successful in 27s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (pull_request) Successful in 6s
CI / Canvas (Next.js) (pull_request) Successful in 5s
template-delivery-e2e / detect-changes (pull_request) Successful in 17s
E2E Chat / E2E Chat (pull_request) Successful in 3s
lint-setup-go-cache / lint-setup-go-cache (pull_request) Successful in 24s
PR Diff Guard / PR diff guard (pull_request) Successful in 21s
CI / Canvas Deploy Status (pull_request) Successful in 1s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Failing after 19s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 6s
template-delivery-e2e / Template-asset delivery (fresh seo-agent — config+prompts via asset channel, seo-all via plugin reconcile) (pull_request) Successful in 2s
Lint publish-runner timeout-minutes / Lint publish-runner timeout-minutes (pull_request) Successful in 28s
Lint workflow YAML (Gitea-1.22.6-hostile shapes) / Lint workflow YAML for Gitea-1.22.6-hostile shapes (pull_request) Successful in 28s
lint-continue-on-error-tracking / lint-continue-on-error-tracking (pull_request) Successful in 34s
Lint pre-flip continue-on-error / Verify continue-on-error flips have run-log proof (pull_request) Successful in 30s
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge user_tasks (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging Workspace Requests (core#2606) (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Platform Agent (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging Plugin Install Lifecycle (pull_request) Has been skipped
lint-required-context-exists-in-bp / lint-required-context-exists-in-bp (pull_request) Failing after 35s
E2E Staging SaaS (full lifecycle) / Prune stale e2e DNS records (pull_request) Successful in 7s
gate-check-v3 / gate-check (pull_request_target) Failing after 34s
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Successful in 13s
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge (compile+skip) (pull_request) Successful in 13s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 51s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Successful in 36s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 1m27s
CI / all-required (pull_request) Successful in 3s
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Creates Workspace (pull_request) Successful in 4m17s
E2E Staging SaaS (full lifecycle) / E2E Staging Platform Boot (pull_request) Failing after 6m29s
security-review / approved (pull_request_target) Approved via pull_request_review trigger
qa-review / approved (pull_request_target) Approved via pull_request_review trigger
security-review / approved (pull_request_review) Successful in 10s
reserved-path-review / reserved-path-review (pull_request_target) Approved via pull_request_review trigger
qa-review / approved (pull_request_review) Successful in 12s
reserved-path-review / reserved-path-review (pull_request_review) Successful in 13s
audit-force-merge / audit (pull_request_target) Successful in 10s
7619a72205
Installs the published @molecule-ai/mcp-server from the Gitea npm registry
(read:package via MCP_SERVER_READPKG_TOKEN) and runs the checker.
Standalone soak-then-promote workflow (mirrors the contract-drift gate);
daily cron catches a newly-published skew with no commit. Fail-closed on
trusted contexts, soft-skip on fork PRs.
agent-researcher approved these changes 2026-06-26 01:08:11 +00:00
agent-researcher left a comment
Member

APPROVED on head 7619a72205.

5-axis/RCA review: this adds the missing published-artifact guard rather than another source-only check. The workflow installs the published @molecule-ai/mcp-server package from Gitea npm with a read:package token, runs a local harness in management mode, records the actual registered tool names, and fails if the published manifest exposes none of the contract-accepted verbs. The script fails closed on missing contract fields, zero-tool introspection, server-name mismatch, and no accepted verb; it warns but does not fail when only a transitional alias is present, which matches the staged deprecation model. Secret handling is appropriate for this CI context: the read-package token is only in .npmrc in a temp dir and is required only on trusted contexts; fork PRs soft-skip because they cannot receive the secret.

Status note: the manifest check is expected to be red against current main/published state until #3280/producer publication sequencing catches up, and the missing MCP_SERVER_READPKG_TOKEN is an ops prerequisite. Code is sound on merits.

APPROVED on head 7619a722053416f521173ce29e0724848f7f7c66. 5-axis/RCA review: this adds the missing published-artifact guard rather than another source-only check. The workflow installs the published `@molecule-ai/mcp-server` package from Gitea npm with a read:package token, runs a local harness in management mode, records the actual registered tool names, and fails if the published manifest exposes none of the contract-accepted verbs. The script fails closed on missing contract fields, zero-tool introspection, server-name mismatch, and no accepted verb; it warns but does not fail when only a transitional alias is present, which matches the staged deprecation model. Secret handling is appropriate for this CI context: the read-package token is only in `.npmrc` in a temp dir and is required only on trusted contexts; fork PRs soft-skip because they cannot receive the secret. Status note: the manifest check is expected to be red against current main/published state until #3280/producer publication sequencing catches up, and the missing `MCP_SERVER_READPKG_TOKEN` is an ops prerequisite. Code is sound on merits.
agent-reviewer-cr2 approved these changes 2026-06-26 01:08:48 +00:00
agent-reviewer-cr2 left a comment
Member

Reviewed head 7619a72205. APPROVED on code merits. The published-manifest checker resolves the real published mcp-server package, captures registered management-mode tools via SDK monkeypatching, and validates the contract verbs; it supports both plural required_tools and legacy singular required_tool. Trusted missing MCP_SERVER_READPKG_TOKEN fail-closes, fork/no-secret paths soft-skip without exposing tokens. Expected red until #3280 and the read:package secret are in place.

Reviewed head 7619a722053416f521173ce29e0724848f7f7c66. APPROVED on code merits. The published-manifest checker resolves the real published mcp-server package, captures registered management-mode tools via SDK monkeypatching, and validates the contract verbs; it supports both plural required_tools and legacy singular required_tool. Trusted missing MCP_SERVER_READPKG_TOKEN fail-closes, fork/no-secret paths soft-skip without exposing tokens. Expected red until #3280 and the read:package secret are in place.
devops-engineer merged commit 0ab4dc46ef into main 2026-06-26 01:09:01 +00:00
Sign in to join this conversation.
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#3281