Skip to content

hub-mcp Phase 6: distribution and remote access (bd-8iv9jty5) - #799

Open
shikokuchuo wants to merge 6 commits into
braid/bd-rpra6kpq-hub-mcp-phase-5-mcp-native-surfacesfrom
braid/bd-8iv9jty5-hub-mcp-phase-6-distribution
Open

shikokuchuo wants to merge 6 commits into
braid/bd-rpra6kpq-hub-mcp-phase-5-mcp-native-surfacesfrom
braid/bd-8iv9jty5-hub-mcp-phase-6-distribution

Conversation

@shikokuchuo

Copy link
Copy Markdown
Member

What this PR does

Phase 6 of the quarto-hub-mcp plan: distribution and remote access. It stacks on the Phase 5 branch (bd-rpra6kpq).

Packaging (CAP-15). The server now packs as a real npm package. scripts/pack-npm.mjs builds the bundle from a clean tree and makes a tarball with one runtime dependency. A smoke test packs the tarball, installs it into an empty prefix, and runs the installed server against the test hub. The .mcpb one-click bundle for Claude Desktop works the same way, with the keyring addon for all eight platforms inside. Two public manifests ship: server.json for the MCP Registry and mcpb/manifest.json for the one-click install. The install dialog shows the exact command. Secrets come from prompted user config, never from baked defaults.

Official conformance suite. The MCP project's conformance suite now runs as a test against a test-only HTTP listener. All 37 required scenarios pass at the frozen 2026-07-28 requirement set. The list of allowed failures is empty. The suite drives a test_* fixture surface that never appears in the normal tool list.

Design docs. The CAP-16 design doc covers hub-served MCP over HTTP: tokens, consent, scopes, and the per-user connection pool. It answers open question Q-5. A one-page note covers MCP Apps: worth doing, not yet.

Docs. The q2 mcp docs page and the README now list the three channels: q2 mcp, npm, and .mcpb.

What this PR does not do

It does not publish anything to npm. The workflow .github/workflows/publish-hub-mcp.yml packs and validates on every run, but publishes only on an explicit non-dry-run dispatch. That decision stays with bd-3tak0lyy.

Test evidence

  • npm run test -w ts-packages/quarto-hub-mcp: 62 files, 545 passed.
  • cargo xtask verify: green, all legs.
  • Conformance suite: 37 of 37 required scenarios, 146 checks, exit 0.
  • Agent-task eval suite: 15 of 15 PASS. Transcripts are in the commits.

Notes for reviewers

Two bugs were found and fixed on the way. A listener leak in the resource bridge only appears under per-request HTTP serving. A race between the packaging tests and the bundle tests rebuilt a shared file while a test ran it. Both have regression tests.

@posit-snyk-bot

posit-snyk-bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@shikokuchuo
shikokuchuo added this pull request to stack #792 October 7, 2026 13:12
…l conformance green (CAP-15; bd-8iv9jty5, bd-3tak0lyy)

Packaging (CAP-15):
- scripts/pack-npm.mjs: clean-build bundle → publish-shaped staging
  (bin, minimal deps: @napi-rs/keyring only, LICENSE/README/NOTICE,
  npmVersion stamp) → npm pack; server.json drift check
- scripts/pack-mcpb.mjs: same payload + all-platform vendored keyring
  + mcpb/manifest.json, validated and packed with @anthropic-ai/mcpb
- server.json (registry listing, io.github.quarto-dev/hub-mcp) +
  vendored registry schema; mcpb/manifest.json with consent-forward
  user_config (exact command visible, secrets only via sensitive
  prompts)
- version 0.0.1 → 0.1.0; Implementation version now reports
  build-info.json npmVersion when installed from npm

Official conformance suite (deferred from Phase 0):
- @modelcontextprotocol/conformance@0.2.0-alpha.12 as devDep;
  --requirements 2026-07-28, empty expected-failures baseline
- src/http-loopback.ts: test-only loopback HTTP listener (SDK
  createMcpHandler, per-request serving, Host/Origin guards) — the
  CAP-16 rehearsal
- src/conformance-fixtures.ts: the test_* surface the suite drives,
  gated behind CreateServerOptions.conformanceFixtures (never in the
  default listing; ERG-5 budget untouched); MRTR fixtures use the SDK's
  HMAC requestState codec shared across per-request instances
- responseMode 'auto' is load-bearing: -32021 → HTTP 400 mapping dies
  under forced SSE; async execFile (not execFileSync) so the in-process
  loopback's event loop survives the suite run
- resources.ts: fixtures branches (test:// statics/template) + the
  per-request listener-leak fix (bridge unhooks on server close; the
  loopback would otherwise leak one manager listener per request)
- connection-manager: projectEventListenerCount() conformance seam

Result: 37/37 required scenarios pass (146 checks); all failures
confined to the not-scored roster (tasks extension, pending).
…e (bd-8iv9jty5)

- docs/tools/q2-mcp.qmd: npm (npx @quarto/hub-mcp, MCP Registry) and
  .mcpb one-click channels; remote HTTP noted as designed-not-shipped
- README: the three distribution channels up front
- .github/workflows/publish-hub-mcp.yml: dry-run-by-default dispatch —
  pack + validate via the packaging tests, artifacts; real publish
  (npm + registry via mcp-publisher GitHub OIDC) gated on the
  npm-publish environment and NPM_TOKEN
- claude-notes/plans/2026-10-07-hub-mcp-streamable-http-design.md:
  CAP-16 design — hub-minted tokens (no passthrough), RFC 9728 PRM,
  CIMD not DCR, capability scopes, per-user ConnectionManager pool
  (Q-5 resolved: 500-entry LRU / 20 projects / 15 min TTL / 8 req),
  render + authenticate omitted over HTTP; CAP-3 registry confirmed
  needed
- claude-notes/research/2026-10-07-mcp-apps-feasibility.md: worth
  doing, not yet — revisit on host GA or scored requirements
…st-bundle race (bd-8iv9jty5)

- Plan: Phase 6 items checked off, completion record (packaging,
  conformance, loopback, CAP-16 design, eval table, phase-close gate),
  Q-5 marked resolved (design doc §7 numbers)
- Eval results committed (15/15 PASS, eval/results/2026-10-07T11-42-20)
- Race fix (caught by cargo xtask verify running the full suite):
  packaging tests rebuilt the shared dist-bundle while bundle.test.ts
  spawned it. bundle.mjs honors HUB_MCP_BUNDLE_OUT; pack-npm/pack-mcpb
  build into private staging dirs. verify now green end to end
@shikokuchuo
shikokuchuo force-pushed the braid/bd-8iv9jty5-hub-mcp-phase-6-distribution branch from ce9080c to 786d69b Compare October 7, 2026 13:45
…oolchain leg (bd-8iv9jty5)

npm-pack.test.ts and mcpb-pack.test.ts invoke the pack scripts, which
rebuild dist-bundle and therefore stage the wasm-qmd-parser pkg — they
need the wasm toolchain. But they ran ungated in the full 'npm test' on
the deliberately toolchain-free workspace-ts-suites legs, failing both
(no Homebrew LLVM / wasm-pack there). Gate both files with
describe.skipIf(PARSER_UNAVAILABLE), the same marker mechanism
bundle.test.ts and the qmd-* tier use, and add them to the test-suite
job's explicit parser-tier vitest list so they still gate in CI.
Verified locally: files run and pass with the parser pkg present
(8 tests), and skip cleanly (exit 0) with the pkg and wasm-pack
hidden to simulate the toolchain-free leg.
buildShareUrl omitted server= on the default hub and file=/name= when
callers didn't supply them, but hub-client's share route treats all
three as required and rejects such links as "incomplete" on the invite
landing — every shareUrl embedded by create_project, connect_project,
get_project_info, and list_projects was refused by the web client.

- buildShareUrl always emits server=/file=/name=; ShareUrlParts fields
  are now required, matching hub-client's buildShareableUrl contract.
- normalizeArgs stashes an incoming share URL's name= (args.shareName;
  file= already arrived as args.path), so connect_project and
  get_project_info propagate both into the link they hand back.
  Fallbacks: file = index.qmd, else first .qmd, else first file; name =
  'Untitled project' (hub-client's own display fallback).
- list_projects uses the project-set summary's topFiles when cached;
  create_project points at the created files.
- Tests: buildShareUrl unit tests; rewritten embed tests incl.
  name/file propagation; strengthened list_projects round-trip; and a
  cross-package contract test (hub-client/src/utils/
  shareUrlContract.test.ts) that parses MCP-built URLs with hub-client's
  own parseHashRoute and asserts the App.tsx completeness predicate.

Full quarto-hub-mcp suite (547 tests) and hub-client tsc -b + vite
build green; TS-only change, cargo nextest not run. Also regenerates
.braid/snapshot.jsonl (adds bd-jtl4o0pt, created and closed here).

This branch has not been deployed

No deployments
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.

2 participants