Skip to content

Export a safe public MCP tool contract - #15

Merged
aviyashchin merged 8 commits into
mainfrom
codex/13-mcp-safe-contract
Jul 28, 2026
Merged

Export a safe public MCP tool contract#15
aviyashchin merged 8 commits into
mainfrom
codex/13-mcp-safe-contract

Conversation

@aviyashchin

@aviyashchin aviyashchin commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Closes #13

Customer outcome

Agents can discover Ghostshell’s 15 public MCP tools and connect through the supported stdio transport without copying unsafe credentials into URLs.

What changed

  • export a source-owned public MCP manifest with immutable provenance across every tool implementation, including shared _core modules
  • validate the exact tool registry, safe transport, and environment-based bearer auth
  • remove the stale query-token example from REPO-MAP.md
  • bound the executable stdio smoke to 10 seconds
  • keep the runtime on the supported MCP 1.x API and reject unsupported major-version drift
  • make CI reject any return of query-token setup guidance and avoid persisting checkout credentials
  • align the new tests with the repository’s class-based pytest convention

Validation

  • clean Python 3.11 environment installed MCP 1.29.0 and passed 75 tests
  • Ruff and mypy passed
  • manifest regeneration produced no committed diff
  • a real stdio initialize plus tools/list returned 15 tools
  • CI lint, test, MCP validation, CodeRabbit, Seer, and both preview checks passed at 017733ffc855713bab729e5e026d719b5dbc0dd4
  • CodeRabbit approved the addressed functional findings
  • manifest SHA-256: b653818071c082574749a8617b7229b8b6a40a086b4fd2fd5fccdb3d548247c6

Boundary

No merge, deployment, or credential change was performed. Ready for an independent human reviewer.

@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ghostshell Ready Ready Preview, Comment Jul 28, 2026 3:44pm
ghostshell-runi Ready Ready Preview, Comment Jul 28, 2026 3:44pm

@aviyashchin

Copy link
Copy Markdown
Contributor Author

Readiness check at 1f754461711fa82c62508e01951815c87c14c392:

  • pytest tests/ -q: 70 passed
  • Ruff: passed
  • mypy: passed
  • stdio protocol smoke: initialized server and listed 15 tools
  • deterministic manifest SHA-256: b653818071c082574749a8617b7229b8b6a40a086b4fd2fd5fccdb3d548247c6
  • hosted auth proof remains intentionally out of scope in Prove hosted MCP SSE authentication before supporting it #14

PR remains draft; no merge or deployment performed.

@aviyashchin

Copy link
Copy Markdown
Contributor Author

CI repair pushed and PR head read-back confirms 35e5c2f7d50f2015398ac00600d899903bd51ce8. GitHub’s shallow synthetic merge checkout hid the manifest’s immutable source commit; the workflow now fetches full history and the exporter ignores merge commits. Regression coverage is included; 71 tests, Ruff, mypy, and the stdio smoke pass locally. CI rerun is in progress.

@aviyashchin

Copy link
Copy Markdown
Contributor Author

Final check read-back: all CI, Vercel preview, and CodeRabbit checks pass at exact head 35e5c2f7d50f2015398ac00600d899903bd51ce8. PR remains draft; hosted SSE remains experimental pending #14.

@aviyashchin

Copy link
Copy Markdown
Contributor Author

Ready for draft review at ddea125cb939e1f44cb7a3b0270a3ccb168560f3: 71 tests pass, Ruff/mypy pass, stdio lists all 15 tools, and two manifest exports are byte-identical. Exact-head CI is green. Safe supported path is local stdio; hosted SSE remains experimental/header-only. No merge or deployment.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The PR replaces query-string MCP authentication with Authorization-header-only handling, adds a deterministic 15-tool manifest exporter and artifact, introduces local stdio protocol smoke tests, updates CI validation, and revises connection documentation and examples.

Changes

MCP contract and validation

Layer / File(s) Summary
Authentication and transport contract
api/index.py, REPO-MAP.md, tests/test_integration.py, examples/*
Authentication now uses only Bearer headers; server metadata, integration tests, and local process configurations reflect the updated transport contract.
Deterministic manifest generation
scripts/export_mcp_manifest.py, mcp-tools.public.json, tests/test_mcp_manifest.py
A normalized, checksummed 15-tool manifest is generated from the registry, tied to source revision metadata, validated for drift, and covered by deterministic and integrity tests.
Stdio smoke test and CI enforcement
.github/workflows/ci.yml, scripts/smoke_stdio_mcp.py, tests/test_mcp_stdio.py
CI exports and verifies the committed manifest, runs the stdio initialize/tools-list probe, preserves Git history, and uploads the manifest artifact.
Public connection guidance
README.md, CLAUDE.md
Documentation identifies local stdio as supported, hosted SSE as experimental, and credentials as Authorization-header-only while documenting the new scripts and manifest.

Sequence Diagram(s)

sequenceDiagram
  participant CI
  participant ManifestExporter
  participant ToolRegistry
  participant StdioSmokeTest
  participant MCPServer
  CI->>ManifestExporter: Export and validate manifest
  ManifestExporter->>ToolRegistry: Read 15 registered tools
  ToolRegistry-->>ManifestExporter: Tool definitions
  CI->>CI: Compare committed manifest
  CI->>StdioSmokeTest: Run protocol smoke test
  StdioSmokeTest->>MCPServer: initialize and tools/list over stdio
  MCPServer-->>StdioSmokeTest: Server metadata and tool inventory
Loading

Possibly related PRs

Poem

I’m a rabbit guarding the tools,
No tokens tucked in URL jewels.
Stdio hops through the gate,
Fifteen tools enumerate.
Manifests bloom, checksums gleam—
CI keeps watch on every dream.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR satisfies #13 by adding a deterministic manifest, drift checks, stdio smoke tests, and removing query-token guidance.
Out of Scope Changes check ✅ Passed No clear unrelated code changes stand out; the edits are all aligned with the manifest, docs, tests, and CI objectives.
Title check ✅ Passed The title clearly summarizes the main change: exporting a safe public MCP tool contract.
Description check ✅ Passed The description is directly related to the manifest, stdio transport, auth cleanup, and CI checks in this changeset.
✨ 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 codex/13-mcp-safe-contract

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
.github/workflows/ci.yml (1)

40-43: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Disable credential persistence on checkout.

Neither the test nor validate-mcp job pushes or authenticates via git afterward, yet both checkouts leave the GITHUB_TOKEN credential persisted in the local git config for the remainder of the job (default persist-credentials: true). Any subsequent step in the job (e.g. a compromised transitive pip dependency during pip install) could use it to push/exfiltrate.

🔒 Proposed fix
       - uses: actions/checkout@v4
         with:
           # Manifest tests read back the exact registry-owning commit.
           fetch-depth: 0
+          persist-credentials: false
       - uses: actions/checkout@v4
         with:
           # Ignore GitHub's synthetic PR merge and retain source history.
           fetch-depth: 0
+          persist-credentials: false

Also applies to: 64-67

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 40 - 43, Update the checkout steps in
both the test and validate-mcp jobs to disable credential persistence by setting
persist-credentials to false, while retaining the existing full fetch-depth
required by manifest tests.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/export_mcp_manifest.py`:
- Around line 18-24: Update SOURCE_PATHS in the export manifest script to
include Python files under server/tools/_core, either by changing the existing
server/tools glob to recursive rglob("*.py") or by explicitly adding the shared
_core modules. Preserve the existing repository-relative sorting and inclusion
of api/index.py so validate_source_revision covers all exported tool metadata
sources.

In `@scripts/smoke_stdio_mcp.py`:
- Around line 42-44: Update the main function’s asyncio.run call around
probe_stdio to enforce a 10-second timeout, matching the existing test behavior,
so a hung server causes the CI entrypoint to fail promptly.

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 40-43: Update the checkout steps in both the test and validate-mcp
jobs to disable credential persistence by setting persist-credentials to false,
while retaining the existing full fetch-depth required by manifest tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 954c3079-3a6a-4d95-af76-539f9b8ce911

📥 Commits

Reviewing files that changed from the base of the PR and between 6cbc5ec and a597b2c.

📒 Files selected for processing (14)
  • .github/workflows/ci.yml
  • CLAUDE.md
  • README.md
  • REPO-MAP.md
  • api/index.py
  • examples/claude/config.json
  • examples/cursor/mcp.json
  • examples/local/config.json
  • mcp-tools.public.json
  • scripts/export_mcp_manifest.py
  • scripts/smoke_stdio_mcp.py
  • tests/test_integration.py
  • tests/test_mcp_manifest.py
  • tests/test_mcp_stdio.py

Comment thread scripts/export_mcp_manifest.py
Comment thread scripts/smoke_stdio_mcp.py
@aviyashchin

Copy link
Copy Markdown
Contributor Author

Addressed every actionable review finding in 6cf88dd: recursive provenance now covers shared server/tools/_core modules, the executable stdio probe has a 10-second protocol timeout, and both full-history checkouts disable persisted credentials. Fresh local proof: manifest regeneration clean; 74 pytest tests passed; Ruff passed; mypy passed; real stdio initialization listed all 15 tools. @coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@aviyashchin: I’ll review the updated draft, including the provenance recursion, stdio timeout, and CI credential-handling changes.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/test_mcp_stdio.py (1)

8-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Align these tests with the repository’s pytest conventions.

Make test_stdio_initialize_and_tools_list an async def test that awaits asyncio.wait_for(...) instead of calling asyncio.run(...). Also place both tests in a PascalCase test class.

Proposed structure
-def test_stdio_initialize_and_tools_list():
-    result = asyncio.run(asyncio.wait_for(smoke.probe_stdio(), timeout=10))
+class TestMcpStdio:
+    async def test_stdio_initialize_and_tools_list(self):
+        result = await asyncio.wait_for(smoke.probe_stdio(), timeout=10)

- def test_cli_entrypoint_enforces_the_protocol_timeout(monkeypatch, capsys):
+    def test_cli_entrypoint_enforces_the_protocol_timeout(self, monkeypatch, capsys):

As per coding guidelines, tests/**/*.py must use pytest with pytest-asyncio, and tests/test_*.py must organize tests as class-based tests.

Also applies to: 17-34

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_mcp_stdio.py` around lines 8 - 14, Update
test_stdio_initialize_and_tools_list to be an async def test and await
asyncio.wait_for(smoke.probe_stdio(), timeout=10) directly, removing
asyncio.run. Organize this test and the related tests in the file within a
PascalCase pytest test class, preserving their existing assertions and behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/test_mcp_stdio.py`:
- Around line 8-14: Update test_stdio_initialize_and_tools_list to be an async
def test and await asyncio.wait_for(smoke.probe_stdio(), timeout=10) directly,
removing asyncio.run. Organize this test and the related tests in the file
within a PascalCase pytest test class, preserving their existing assertions and
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 41067ba4-d8f4-4c5a-965d-b40e2367c64c

📥 Commits

Reviewing files that changed from the base of the PR and between a597b2c and 6cf88dd.

📒 Files selected for processing (5)
  • .github/workflows/ci.yml
  • scripts/export_mcp_manifest.py
  • scripts/smoke_stdio_mcp.py
  • tests/test_mcp_manifest.py
  • tests/test_mcp_stdio.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • .github/workflows/ci.yml
  • tests/test_mcp_manifest.py
  • scripts/export_mcp_manifest.py

@aviyashchin

Copy link
Copy Markdown
Contributor Author

Final review handoff at 9ce1fcf1568ae28757d10a56e40b7eeca5ade13e: clean Python 3.11 proof passed 75 tests, Ruff, mypy, deterministic manifest regeneration, and the real 15-tool stdio handshake with MCP 1.29.0. All GitHub CI jobs and previews are green, and CodeRabbit approved the addressed findings. This PR is review-ready and remains unmerged.

@aviyashchin

Copy link
Copy Markdown
Contributor Author

Addressed the remaining valid style review on the existing tests: both MCP test modules now follow the repository-required class-based pytest convention, and the protocol smoke test awaits the probe natively under pytest-asyncio. No production behavior changed. Clean Python 3.11 proof remains green: 75 tests, Ruff, mypy, deterministic manifest regeneration, and real 15-tool stdio handshake with MCP 1.29.0. @coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@aviyashchin I’ll review the updated test conventions and native async smoke-test coverage.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@aviyashchin

Copy link
Copy Markdown
Contributor Author

Closeout review: source-owned export, deterministic 15-tool registry, executable stdio handshake, MCP 1.x bound, environment-based bearer auth, and the query-token documentation regression guard are all green. CodeRabbit approved the addressed findings and all eight checks pass at exact head 017733f. The important product boundary is explicit: stdio is supported now; hosted transport remains a separate authenticated follow-up. Proceeding with the authorized squash merge.

@aviyashchin
aviyashchin merged commit c445240 into main Jul 28, 2026
9 checks passed
@aviyashchin
aviyashchin deleted the codex/13-mcp-safe-contract branch July 28, 2026 20:40
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.

Replace query-token MCP setup with a safe supported contract and tool export

1 participant