Skip to content

@contentrain/mcp 1.4.0: multi-tenant HTTP + App auth + published conformance fixtures#49

Merged
ABB65 merged 1 commit intomainfrom
feat/mcp-1-4-multi-tenant-app-auth-fixtures
Apr 18, 2026
Merged

@contentrain/mcp 1.4.0: multi-tenant HTTP + App auth + published conformance fixtures#49
ABB65 merged 1 commit intomainfrom
feat/mcp-1-4-multi-tenant-app-auth-fixtures

Conversation

@ABB65
Copy link
Copy Markdown
Member

@ABB65 ABB65 commented Apr 18, 2026

Covers every MCP-side item surfaced in the Studio S2-S8 handoff audit, in a single release.

Headline: multi-tenant HTTP MCP

startHttpMcpServerWith now accepts a per-request provider resolver:

await startHttpMcpServerWith({
  resolveProvider: async (req) => {
    const projectId = req.headers['x-project-id']
    const { repo, auth } = await lookupProject(projectId)
    return createGitHubProvider({ auth, repo })
  },
  authToken: workspaceBearerToken,
  port: 3333,
  sessionTtlMs: 15 * 60 * 1000,
})

Resolver invoked once per MCP session; subsequent requests with the same Mcp-Session-Id header reuse the resolved server + transport pair. Idle sessions disposed after sessionTtlMs. Single-provider shape fully backward compatible. Unblocks Studio S6 (MCP Cloud).

Also shipping

GitHub App auth in createGitHubProvider

New auth: { type: 'app', appId, privateKey, installationId } factory mode: signs a JWT, exchanges for installation token, returns Octokit-backed client. Removes the old Phase 5.2 throw.

Public exports:

  • exchangeInstallationToken — standalone helper, custom baseUrl for GHES
  • signAppJwt — pure RS256 JWT signer
  • Types: AppAuthConfig, InstallationTokenResult

Conformance fixtures published

@contentrain/mcp/testing/conformance subpath exposes the byte-parity scenarios the package tests itself against. External tools (Studio, alt-provider harnesses) can assert matching output without symlinking tests/.

Fixtures moved from tests/fixtures/conformance/testing/conformance/, shipped in the tarball via files[]. Helpers: fixturesDir, listConformanceScenarios, loadConformanceScenario.

validateProject(reader, options) overload pinned

New dedicated test exercises the Phase 5.5b overload: pure RepoReader, error surfacing, OverlayReader composition. Pins the contract Studio S3 depends on.

Docs

docs/guides/embedding-mcp.md Recipe 3 now shows three GitHub App auth patterns with a trade-off table — (a) factory auth.type:'app', (b) exchangeInstallationToken + external cache, (c) Octokit injection with @octokit/auth-app (Studio's pattern). New Recipe 3a documents the multi-tenant resolver.

Package description updated from "13 deterministic tools" to the current 17-tool surface.

Test plan

  • oxlint monorepo → 0 warnings on 424 files
  • @contentrain/mcp typecheck → 0 errors
  • MCP fast suite → 471 passed / 2 skipped / 34 files (21 new tests beyond 1.3.0 baseline)
    • 4 app-auth (JWT + exchange + baseUrl + error)
    • 3 multi-tenant resolver (session isolation, 500 on resolver throw, single-provider handle.mcp)
    • 5 conformance subpath smoke tests
    • 3 validateProject reader overload
  • vitepress build docs → success

Version

@contentrain/mcp: 1.3.0 → 1.4.0 (minor — new public exports, no breaking changes).

🤖 Generated with Claude Code

@netlify
Copy link
Copy Markdown

netlify bot commented Apr 18, 2026

Deploy Preview for contentrain-ai ready!

Name Link
🔨 Latest commit cc066fe
🔍 Latest deploy log https://app.netlify.com/projects/contentrain-ai/deploys/69e36f7398702f000868cd1a
😎 Deploy Preview https://deploy-preview-49--contentrain-ai.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

…d conformance fixtures

### Multi-tenant HTTP MCP — per-request provider resolver

startHttpMcpServerWith now accepts resolveProvider(req) — every new
MCP session resolves its own RepoProvider from the inbound request.
Studio's MCP Cloud and similar hosted agents can serve many projects
from one endpoint without N server instances. Resolver invoked
exactly once per session; subsequent requests with Mcp-Session-Id
reuse the resolved server + transport pair. Idle sessions disposed
after sessionTtlMs (default 15m). Single-provider shape fully
backward compatible.

### GitHub App installation auth in the factory

createGitHubProvider({ auth: { type: 'app', appId, privateKey,
installationId } }) now mints a JWT, exchanges it for an installation
token, and returns an Octokit-backed client. Removes the legacy
"coming in Phase 5.2" throw.

New public exports under @contentrain/mcp/providers/github:
- exchangeInstallationToken(config, opts?) — standalone helper;
  supports custom baseUrl for GHES; useful for external token
  caching across workers
- signAppJwt(config) — pure RS256 JWT signer (10-min TTL)
- Types: AppAuthConfig, InstallationTokenResult

Factory-minted tokens are ~1 hour and don't auto-refresh — for long-
lived hosted providers, inject your own Octokit with
@octokit/auth-app's auth strategy (Studio's pattern).

### Conformance fixtures published

New subpath @contentrain/mcp/testing/conformance exposes the byte-
parity scenarios the package tests itself against. External tools
(Studio, alt-provider harnesses, third-party reimplementations) can
assert matching output without symlinking the tests directory.

Fixtures moved from tests/fixtures/conformance/ to
testing/conformance/ and included in the published tarball via
files[].

Helpers: fixturesDir, listConformanceScenarios,
loadConformanceScenario + ConformanceScenario type.

### validateProject(reader, options) overload pinned

New tests/core/validator/reader-overload.test.ts exercises the
Phase 5.5b overload:
- validation through a pure RepoReader
- error surfacing from reader-backed content
- OverlayReader composition (Studio's pre-commit validation shape)

Pins the contract against silent regressions.

### Docs

docs/guides/embedding-mcp.md Recipe 3 shows 3 GitHub App auth
patterns with a trade-off table:
1. Factory auth.type: 'app' — simple, 1-hour TTL
2. exchangeInstallationToken + external cache — manual refresh
3. Octokit injection with @octokit/auth-app — auto-refresh
   (recommended for Studio-style hosted providers)

New Recipe 3a shows the multi-tenant resolver pattern.

Package description updated from "13 deterministic tools" to
accurately describe the current 17-tool surface.

### Verification

- oxlint monorepo → 0 warnings on 424 files
- @contentrain/mcp typecheck → 0 errors
- MCP fast suite → 471 passed / 2 skipped / 34 files (21 new tests
  beyond 1.3.0 baseline: 4 app-auth, 3 resolver, 5 conformance
  subpath, 3 validateProject reader + conformance test adjustments
  for the fixture move)
- vitepress build → success
@ABB65 ABB65 force-pushed the feat/mcp-1-4-multi-tenant-app-auth-fixtures branch from 2a63678 to cc066fe Compare April 18, 2026 11:48
@ABB65 ABB65 merged commit 6e5a3cf into main Apr 18, 2026
6 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Apr 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant