Skip to content

feat(mcp): add OAuth-protected server - #297

Open
mscolnick wants to merge 15 commits into
mainfrom
ms/mcp-server-support
Open

feat(mcp): add OAuth-protected server#297
mscolnick wants to merge 15 commits into
mainfrom
ms/mcp-server-support

Conversation

@mscolnick

@mscolnick mscolnick commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Adds an OAuth 2.1-protected MCP endpoint for discovering, creating, launching, and executing code in marimohub notebooks.

Includes dynamic public-client registration with PKCE, browser consent and project-scoped PAT grants, exact MCP resource binding, the mcp:tools scope, short-lived tokens, client-bound revocation, deployment-wide OAuth rate limits, structured registration auditing, path-prefixed discovery metadata, configuration, and documentation.

@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
marimohub-docs Ready Ready Preview Sep 3, 2026 9:09pm UTC

Request Review

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 3d5721c.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 issues found across 47 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/api/src/mcp/server.ts">

<violation number="1" location="packages/api/src/mcp/server.ts:256">
P2: `execute_code` accepts unbounded code on a route with no body limiter, so an authenticated caller can submit oversized payloads before Zod validation and consume API memory or kernel capacity. Add an MCP request/body limit and a maximum code size.</violation>
</file>

<file name="packages/api/src/mcp/createMcpApp.test.ts">

<violation number="1" location="packages/api/src/mcp/createMcpApp.test.ts:341">
P3: The rate-limit test asserts on the module-level `authorizationBudget` (shared with every other test in this file via `createMcpApp`), so its 429 count and record bound depend on how many authorize calls the other tests in the file already made. It passes today only because the other tests consume few slots. Add `beforeEach`/`afterEach` isolation (e.g. re-import fresh budgets or use an injectable budget) so this test does not silently break when a future test also hits `/authorize`.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/api/src/mcp/auth.ts
Comment thread packages/api/src/createApi.ts
Comment thread packages/api/src/routes/sessions.ts Outdated
Comment thread packages/config/src/index.ts Outdated
Comment thread packages/web/src/components/Account/OAuthConsentPage.tsx Outdated
Comment thread packages/api/src/mcp/createMcpApp.ts Outdated
Comment thread packages/api/src/mcp/server.ts Outdated
Comment thread packages/api/src/mcp/server.ts Outdated
project: z.string(),
session_id: z.string().optional(),
notebook: z.string().optional(),
code: z.string(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: execute_code accepts unbounded code on a route with no body limiter, so an authenticated caller can submit oversized payloads before Zod validation and consume API memory or kernel capacity. Add an MCP request/body limit and a maximum code size.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/api/src/mcp/server.ts, line 256:

<comment>`execute_code` accepts unbounded code on a route with no body limiter, so an authenticated caller can submit oversized payloads before Zod validation and consume API memory or kernel capacity. Add an MCP request/body limit and a maximum code size.</comment>

<file context>
@@ -0,0 +1,364 @@
+					project: z.string(),
+					session_id: z.string().optional(),
+					notebook: z.string().optional(),
+					code: z.string(),
+					timeout_seconds: z.number().int().min(1).max(300).default(60),
+					kernel_session_id: z.string().optional(),
</file context>

Comment thread packages/api/src/mcp/oauthProvider.ts Outdated
}).toString();

const statuses: number[] = [];
for (let index = 0; index < 105; index += 1) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: The rate-limit test asserts on the module-level authorizationBudget (shared with every other test in this file via createMcpApp), so its 429 count and record bound depend on how many authorize calls the other tests in the file already made. It passes today only because the other tests consume few slots. Add beforeEach/afterEach isolation (e.g. re-import fresh budgets or use an injectable budget) so this test does not silently break when a future test also hits /authorize.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/api/src/mcp/createMcpApp.test.ts, line 341:

<comment>The rate-limit test asserts on the module-level `authorizationBudget` (shared with every other test in this file via `createMcpApp`), so its 429 count and record bound depend on how many authorize calls the other tests in the file already made. It passes today only because the other tests consume few slots. Add `beforeEach`/`afterEach` isolation (e.g. re-import fresh budgets or use an injectable budget) so this test does not silently break when a future test also hits `/authorize`.</comment>

<file context>
@@ -0,0 +1,354 @@
+		}).toString();
+
+		const statuses: number[] = [];
+		for (let index = 0; index < 105; index += 1) {
+			statuses.push((await app.request(authorizeUrl, { redirect: 'manual' })).status);
+		}
</file context>

@mscolnick

Copy link
Copy Markdown
Contributor Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review

@mscolnick I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 54 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/api/src/mcp/createMcpApp.ts Outdated
Comment thread packages/api/src/mcp/server.ts Outdated
Comment thread packages/core/src/services/oauth/OAuthAuthorizationService.ts
Comment thread packages/core/src/services/oauth/OAuthClientStore.ts Outdated
Comment thread packages/core/src/services/oauth/OAuthRateLimitService.ts Outdated
Comment thread packages/api/src/mcp/oauthProvider.ts Outdated
Comment thread pnpm-workspace.yaml
Comment thread docs/mcp.md
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