-
Notifications
You must be signed in to change notification settings - Fork 7
feat(mcp): add OAuth-protected server #297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mscolnick
wants to merge
15
commits into
main
Choose a base branch
from
ms/mcp-server-support
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
377087e
feat(mcp): add OAuth-protected server
mscolnick 353bc35
test(mcp): cover OAuth and kernel failure paths
mscolnick 186a5d6
fix(deps): pin patched fast-uri
mscolnick f87262a
docs(mcp): tighten setup and security guidance
mscolnick b5d1f2a
fix(mcp): harden OAuth and tool boundaries
mscolnick edc179d
test(mcp): cover remaining OAuth regressions
mscolnick 52220ea
fix(mcp): bind OAuth tokens to resource
mscolnick 10c6094
docs(mcp): tighten OAuth guidance
mscolnick 4a3f029
fix(mcp): close OAuth and execution edge cases
mscolnick 681db36
ci(schemas): allow additive OAuth token binding
mscolnick e925a4d
fix(mcp): parse marimo kernel session maps
mscolnick c179621
fix(mcp): fall back to sandbox kernel session
mscolnick 1cdcfb7
feat(mcp): add create notebook tool
mscolnick e41a3fd
perf(api): parallelize independent work
mscolnick 3d5721c
fix(mcp): clarify and simplify tool inputs
mscolnick File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| --- | ||
| description: Connect Claude, Cursor, and other MCP clients to marimohub notebooks. | ||
| --- | ||
|
|
||
| # MCP server | ||
|
|
||
| Marimohub exposes notebooks that a user can access through the Model Context | ||
| Protocol (MCP). OAuth 2.1 opens a browser consent page. There, the user selects | ||
| actions, projects, and token lifetime. The client receives a scoped | ||
| [personal access token](./api-tokens.md). | ||
|
|
||
| ## Enable MCP | ||
|
|
||
| MCP is off by default and runs only on the Node server. Set these variables: | ||
|
|
||
| ```dotenv | ||
| MARIMOHUB_MCP=on | ||
| MARIMOHUB_APP_BASE_URL=https://hub.example.com | ||
| ``` | ||
|
|
||
| `MARIMOHUB_APP_BASE_URL` must include the public origin and any path prefix. | ||
| The MCP server URL adds `/mcp` to this value: | ||
|
|
||
| ```text | ||
| https://hub.example.com/mcp | ||
| ``` | ||
|
|
||
| OAuth discovery uses the base URL to publish stable, absolute URLs. The API | ||
| tokens dialog shows the MCP URL. | ||
|
|
||
| ## Connect a client | ||
|
|
||
| For Claude Code, run: | ||
|
|
||
| ```bash | ||
| claude mcp add --transport http marimohub https://hub.example.com/mcp | ||
| ``` | ||
|
|
||
| For Claude.ai, add a custom connector and enter the MCP server URL. For Cursor, | ||
| add a remote HTTP MCP server. The client discovers the authorization server, | ||
| registers itself, and opens the marimohub consent page. | ||
|
|
||
| Before approval, verify the client name and redirect URL. The default grant | ||
| permits notebook editing and execution. Use the smallest practical set of | ||
| actions and projects. The token lifetime defaults to 7 days and cannot exceed | ||
| 90 days. Revoke a token from the API tokens dialog. Marimohub does not issue | ||
| refresh tokens. Expiry or revocation requires a new authorization. | ||
|
|
||
| ## Tools | ||
|
|
||
| ### `list_catalog` | ||
|
|
||
| Lists accessible projects and notebooks. Filters by project, notebook status, | ||
| tag, or text. Includes active sessions by default. | ||
|
|
||
| ### `create_notebook` | ||
|
|
||
| Creates a local notebook from Python source. Set `launch` to `true` to start an | ||
| edit session and return its session details. | ||
|
|
||
| ### `launch_notebook` | ||
|
|
||
| Starts or reuses an edit or app session. The first launch can take about two | ||
| minutes. Later calls reuse an eligible session. | ||
|
|
||
| ### `execute_code` | ||
|
|
||
| Runs code in the scratchpad of a live edit session. Open the notebook URL in a | ||
| browser before you call this tool. The kernel remains available while a tab is | ||
| connected and during marimo's short grace period. If no tab is connected, the | ||
| tool returns the URL to open. Pass the project and session ID returned by | ||
| `launch_notebook`; the tool automatically uses the first connected kernel. | ||
|
|
||
| The scratchpad shares the notebook's live variables. For durable cell changes, | ||
| first inspect marimo code mode: | ||
|
|
||
| ```python | ||
| import marimo._code_mode as cm | ||
| help(cm) | ||
| ``` | ||
|
|
||
| ## OAuth and security | ||
|
|
||
| Dynamic registration creates public clients that use authorization code and | ||
| PKCE S256. Redirect URIs must use HTTPS, loopback HTTP, or a private-use | ||
| application scheme. Marimohub supports `cursor:` and reverse-domain, | ||
| single-slash application schemes. Authorization codes expire after ten minutes | ||
| and can be used once. Authorization requests, token exchanges, and issued tokens | ||
| must target the configured MCP URL. Each token also stores the registered client | ||
| ID. Other marimohub PATs cannot access `/mcp`. | ||
|
|
||
| The `mcp:tools` OAuth scope permits MCP access. The consent grant restricts Hub | ||
| actions and projects for each tool call. | ||
|
|
||
| Within the configured app base path, MCP reserves these paths: | ||
|
|
||
| - `/mcp` | ||
| - `/authorize` | ||
| - `/oauth/consent` | ||
| - `/token` | ||
| - `/register` | ||
| - `/revoke` | ||
| - `/.well-known/oauth-authorization-server` | ||
| - `/.well-known/oauth-protected-resource` | ||
| - `/.well-known/oauth-protected-resource/mcp` | ||
|
|
||
| The grant does not restrict kernel code or injected credentials. Use a short | ||
| token lifetime. | ||
|
|
||
| Dynamic registration is anonymous. Marimohub verifies client metadata, enforces | ||
| deployment-wide rate limits, and expires registrations after 90 days. Each | ||
| successful registration emits an `oauth_client_registered` event without | ||
| client-supplied names or URIs. Deployments that require client vetting must add | ||
| trusted registration controls before enabling MCP. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.