Skip to content

Commit 20d10a2

Browse files
authored
Add forced approval flow for MCP intermediary (#164)
Address vulnerability where an attacker can effectively bypass authorization once you've already approved a primary client. modelcontextprotocol/modelcontextprotocol#265 This also takes the opportunity to bump up the oauth worker bindings, which addresses another security vulnerability (missing verification of redirect_uri). Note: mcp-remote@latest is required to resolve a bug customers may experience with the oauth change above.
1 parent 42af9e1 commit 20d10a2

File tree

14 files changed

+808
-59
lines changed

14 files changed

+808
-59
lines changed

.vscode/mcp.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
"sentry-dev": {
44
"type": "stdio",
55
"command": "npx",
6-
"args": ["-y", "mcp-remote", "http://localhost:5173/sse"]
6+
"args": ["-y", "mcp-remote@latest", "http://localhost:5173/sse"]
77
},
88
"sentry": {
99
"type": "stdio",
1010
"command": "npx",
11-
"args": ["-y", "mcp-remote", "https://mcp.sentry.dev/sse"]
11+
"args": ["-y", "mcp-remote@latest", "https://mcp.sentry.dev/sse"]
1212
}
1313
}
1414
}

README.md

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -51,31 +51,9 @@ MCP includes an [Inspector](https://modelcontextprotocol.io/docs/tools/inspector
5151
pnpm inspector
5252
```
5353

54-
Enter `https://[domain].workers.dev/sse` (TODO) and hit connect. Once you go through the authentication flow, you'll see the Tools working:
54+
Enter the MCP server URL (http://localhost:5173) and hit connect. This should trigger the authentication flow for you.
5555

56-
<img width="640" alt="image" src="https://github.com/user-attachments/assets/7973f392-0a9d-4712-b679-6dd23f824287" />
57-
58-
### Access the remote MCP server from Claude Desktop
59-
60-
Open Claude Desktop and navigate to Settings, press `⌘ + ,` (comma) -> Developer -> Edit Config. This opens the configuration file that controls which MCP servers Claude can access.
61-
62-
Replace the content with the following configuration. Once you restart Claude Desktop, a browser window will open showing your OAuth login page. Complete the authentication flow to grant Claude access to your MCP server. After you grant access, the tools will become available for you to use.
63-
64-
```json
65-
{
66-
"mcpServers": {
67-
"math": {
68-
"command": "npx",
69-
"args": [
70-
"mcp-remote",
71-
"https://mcp-github-oauth.<your-subdomain>.workers.dev/sse"
72-
]
73-
}
74-
}
75-
}
76-
```
77-
78-
Once the Tools (under 🔨) show up in the interface, you can ask Claude to use them. For example: "Could you use the math tool to add 23 and 19?". Claude should invoke the tool and show the result generated by the MCP server.
56+
Note: If you have issues with your OAuth flow when accessing the inspector on `127.0.0.1`, try using `localhost` instead by visiting `http://localhost:6274`.
7957

8058
## Local Development
8159

@@ -131,7 +109,7 @@ When using Claude to connect to your remote MCP server, you may see some error m
131109

132110
### Using Cursor and other MCP Clients
133111

134-
To connect Cursor with your MCP server, choose `Type`: "Command" and in the `Command` field, combine the command and args fields into one (e.g. `npx mcp-remote https://<your-worker-name>.<your-subdomain>.workers.dev/sse`).
112+
To connect Cursor with your MCP server, choose `Type`: "Command" and in the `Command` field, combine the command and args fields into one (e.g. `npx mcp-remote@latest https://<your-worker-name>.<your-subdomain>.workers.dev/sse`).
135113

136114
Note that while Cursor supports HTTP+SSE servers, it doesn't support authentication, so you still need to use `mcp-remote` (and to use a STDIO server, not an HTTP one).
137115

packages/mcp-cloudflare/package.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
"private": true,
55
"type": "module",
66
"license": "FSL-1.1-ALv2",
7-
"files": [
8-
"./dist/*"
9-
],
7+
"files": ["./dist/*"],
108
"exports": {
119
".": {
1210
"types": "./dist/index.ts",
@@ -41,7 +39,7 @@
4139
"wrangler": "~4.13.2"
4240
},
4341
"dependencies": {
44-
"@cloudflare/workers-oauth-provider": "^0.0.3",
42+
"@cloudflare/workers-oauth-provider": "^0.0.5",
4543
"@modelcontextprotocol/sdk": "^1.10.2",
4644
"@radix-ui/react-accordion": "^1.2.8",
4745
"@radix-ui/react-slot": "^1.2.0",

packages/mcp-cloudflare/src/client/components/fragments/remote-setup.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,22 @@ const mcpServerName = import.meta.env.DEV ? "sentry-dev" : "sentry";
88
export default function RemoteSetup() {
99
const sseUrl = new URL("/sse", window.location.href).href;
1010

11-
const mcpRemoteSnippet = `npx mcp-remote ${sseUrl}`;
11+
const mcpRemoteSnippet = `npx mcp-remote@latest ${sseUrl}`;
1212

1313
// https://code.visualstudio.com/docs/copilot/chat/mcp-servers
1414
const vsCodeHandler = `code:mcp/install?${encodeURIComponent(
1515
JSON.stringify({
1616
name: mcpServerName,
1717
command: "npx",
18-
args: ["-y", "mcp-remote", sseUrl],
18+
args: ["-y", "mcp-remote@latest", sseUrl],
1919
}),
2020
)}`;
2121
const zedInstructions = JSON.stringify(
2222
{
2323
context_servers: {
2424
[mcpServerName]: {
2525
command: "npx",
26-
args: ["-y", "mcp-remote", sseUrl],
26+
args: ["-y", "mcp-remote@latest", sseUrl],
2727
},
2828
settings: {},
2929
},
@@ -61,7 +61,7 @@ export default function RemoteSetup() {
6161
mcpServers: {
6262
sentry: {
6363
command: "npx",
64-
args: ["-y", "mcp-remote", sseUrl],
64+
args: ["-y", "mcp-remote@latest", sseUrl],
6565
},
6666
},
6767
},

packages/mcp-cloudflare/src/client/index.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,11 @@
8484

8585
body {
8686
@apply bg-background text-foreground;
87-
background: linear-gradient(to bottom, #2d1b69, #171717, #000000);
87+
background: linear-gradient(
88+
oklch(0.13 0.028 261.692) 0%,
89+
oklch(0.21 0.034 264.665) 50%,
90+
oklch(0.13 0.028 261.692) 100%
91+
);
8892
min-height: 100vh;
8993
}
9094

packages/mcp-cloudflare/src/server/app.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Hono } from "hono";
2-
import authHandler from "./routes/oauth";
32
import type { Env } from "./types";
3+
import sentryOauth from "./routes/sentry-oauth";
44

55
export default new Hono<{
66
Bindings: Env;
@@ -20,4 +20,4 @@ export default new Hono<{
2020
].join("\n"),
2121
);
2222
})
23-
.route("/", authHandler);
23+
.route("/oauth", sentryOauth);

packages/mcp-cloudflare/src/server/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const oAuthProvider = new OAuthProvider({
1414
apiHandler: SentryMCP.mount("/sse"),
1515
// @ts-ignore
1616
defaultHandler: app,
17+
// must match the routes registered in `app.ts`
1718
authorizeEndpoint: "/oauth/authorize",
1819
tokenEndpoint: "/oauth/token",
1920
clientRegistrationEndpoint: "/oauth/register",

0 commit comments

Comments
 (0)