Skip to content

feat(mcp-cloud): enforce tool allowlist, fix quota semantics, improve onboarding#57

Merged
ABB65 merged 6 commits into
mainfrom
feat/mcp-cloud-hardening
Jun 12, 2026
Merged

feat(mcp-cloud): enforce tool allowlist, fix quota semantics, improve onboarding#57
ABB65 merged 6 commits into
mainfrom
feat/mcp-cloud-hardening

Conversation

@ABB65

@ABB65 ABB65 commented Jun 12, 2026

Copy link
Copy Markdown
Member

Summary

Hardens and completes the MCP Cloud flow based on an end-to-end review of the proxy route, key management, and panel UX.

Proxy route (/api/mcp/v1/{projectId}/...)

  • Per-key tool allowlist is now enforced. allowed_tools was stored and displayed but never checked — every key had the full tool surface. A non-empty list now 403s disallowed tools/call requests before quota consumption (enables read-only / CI-scoped keys).
  • Quota semantics fixed: only tools/call requests consume the monthly quota and produce overage meter events. Protocol traffic (initialize, tools/list, SSE GET, session DELETE) is rate-limited but free — previously a client burned ~3 quota units before its first real call.
  • WRITE_TOOL_NAMES derived from MCP TOOL_ANNOTATIONS (readOnlyHint: false) minus the Studio-owned merge/review lifecycle tools, so a future MCP release that opens e.g. contentrain_bulk to remote providers gets brain-cache invalidation + auto-merge reconciliation without a Studio change.
  • Retry-After header on rate-limit 429s.

Key management

  • Create endpoint validates input: allowedTools against MCP TOOL_NAMES, rateLimitPerMinute integer 1–600, monthlyCallLimit positive integer or null. Previously negative/huge values were written to the DB unchecked.
  • Key list endpoint enriches each key with calls_this_month (new DatabaseProvider.getMcpCloudKeyUsage, reads mcp_cloud_usage per key).

Panel UX

  • Plan gate now goes through useFeature('api.mcp_cloud') instead of a hardcoded ['starter','pro','enterprise'] array (CLAUDE.md rule).
  • Canonical /mcp-suffixed endpoint URL, copyable per key.
  • Key reveal dialog now shows ready-to-paste connect snippets: a claude mcp add command and a generic mcpServers JSON config (Cursor, VS Code, others).
  • Per-key monthly usage shown in the key list.

Docs

  • CLAUDE.md MCP Cloud section corrected: init/bulk/scaffold/doctor/scan/apply/validate(fix) are localWorktree-gated and unavailable remotely; documented quota semantics, allowlist behavior, and the session-affinity scaling note.

Tests

  • New integration suites for proxy gating (quota-only-on-tools-call, allowlist, Retry-After, write detection, header stripping) and key route validation — 26 new tests, full suite 659 passing, build green.

Not in this PR

  • The context.json-on-feature-branch conflict (MCP remote write path) is being fixed in @contentrain/mcp separately.

🤖 Generated with Claude Code

Contentrain added 6 commits June 11, 2026 14:10
… onboarding

- Enforce per-key allowed_tools in the proxy (empty = unrestricted);
  denied calls return 403 before consuming quota
- Only tools/call requests consume the monthly quota and meter events;
  protocol traffic (initialize, tools/list, SSE, DELETE) stays free but
  rate-limited
- Derive WRITE_TOOL_NAMES from MCP TOOL_ANNOTATIONS (readOnlyHint) minus
  Studio-owned lifecycle tools; add Retry-After header on 429
- Validate key create inputs (allowedTools against TOOL_NAMES,
  rateLimitPerMinute 1-600, monthlyCallLimit positive integer)
- Panel: feature-gated via useFeature('api.mcp_cloud'), canonical /mcp
  endpoint URLs per key, Claude Code + JSON connect snippets in the
  key reveal dialog, per-key monthly usage column
- New DatabaseProvider.getMcpCloudKeyUsage + usage enrichment on key list
- Integration tests for proxy gating and key route validation
@ABB65 ABB65 merged commit 4f28b4b into main Jun 12, 2026
1 check passed
@ABB65 ABB65 deleted the feat/mcp-cloud-hardening branch June 12, 2026 10:30
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.

1 participant