Skip to content

Commit 5850953

Browse files
Add Dev mode auth to our MCP servers
- Update README.md and add CONTRIBUTING.md in Radar server Co-authored-by: Nevi <[email protected]>
1 parent cfc859f commit 5850953

File tree

23 files changed

+399
-219
lines changed

23 files changed

+399
-219
lines changed

CONTRIBUTING.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Developing
2+
We welcome contributions to all of our MCP servers! Here's a quick run down on how to get started.
3+
4+
## Architecture
5+
6+
This monorepo has two top-level directories: `/apps` and `/packages`.
7+
8+
- **/apps**: Containing directories for each server. Within each server, you'll find a `CONTRIBUTING.md` with any special instructions on how to get set up:
9+
- [apps/workers-observability](apps/workers-observability)
10+
- [apps/workers-bindings](apps/workers-bindings)
11+
- [apps/radar](apps/radar)
12+
- [apps/cloudflare-one-casb](apps/cloudflare-one-casb)
13+
- **/packages**: Containing shared packages used across our various apps.
14+
- packages/eslint-config: Eslint config used by all apps and packages.
15+
- packages/typescript-config: tsconfig used by all apps and packages.
16+
- packages/mcp-common: Shared common tools and scripts to help manage this repo.
17+
18+
We use [TurboRepo](https://turbo.build/) and [pnpm](https://pnpm.io/) to manage this repository. TurboRepo manages the monorepo by ensuring commands are run across all apps.
19+
20+
## Getting Started
21+
22+
This section will guide you through setting up your developer environment and running tests.
23+
24+
### Installation
25+
26+
Install dependencies:
27+
28+
```bash
29+
pnpm install
30+
```
31+
32+
### Testing
33+
34+
The project uses Vitest as the testing framework with [fetchMock](https://developers.cloudflare.com/workers/testing/vitest-integration/test-apis/) for API mocking.
35+
36+
#### Running Tests
37+
38+
To run all tests:
39+
40+
```bash
41+
pnpm test
42+
```
43+
44+
To run a specific test file:
45+
46+
```bash
47+
pnpm test -- tests/tools/queues.test.ts
48+
```
49+
50+
To run tests in watch mode (useful during development):
51+
52+
```bash
53+
pnpm test:watch
54+
```

README.md

Lines changed: 20 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,47 @@
11
# Cloudflare MCP Server
22

3-
Model Context Protocol (MCP) is a [new, standardized protocol](https://modelcontextprotocol.io/introduction) for managing context between large language models (LLMs) and external systems. In this repository, we provide an installer as well as an MCP Server for [Cloudflare's API](https://api.cloudflare.com).
3+
Model Context Protocol (MCP) is a [new, standardized protocol](https://modelcontextprotocol.io/introduction) for managing context between large language models (LLMs) and external systems. In this repository, you can find several MCP servers allowing you to connect to Cloudflare's service from an MCP client (e.g. Cursor, Claude) and use natural language to accomplish tasks through your Cloudflare account.
44

5-
This lets you use Claude Desktop, or any MCP Client, to use natural language to accomplish things on your Cloudflare account, e.g.:
5+
These MCP servers allow your [MCP Client](https://modelcontextprotocol.io/clients) to read configurations from your account, process information, make suggestions based on data, and even make those suggested changes for you. All of these actions can happen across cloudflare's many services including application development, security and performance.
66

7-
- `List all the Cloudflare workers on my <some-email>@gmail.com account.`
8-
- `Can you tell me about any potential issues on this particular worker '...'?`
7+
The following servers are included in this repository:
98

10-
## Access the remote MCP server from Claude Desktop
9+
| Server Name | Description | Server URL |
10+
| ----------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------- |
11+
| [**Documentation server**](/apps/docs-autorag) | Get up to date reference information on Cloudflare | `https://docs.mcp.cloudflare.com/sse` |
12+
| [**Workers Bindings server**](/apps/bindings) | Build Workers applications with storage, AI, and compute primitives | `https://bindings.mcp.cloudflare.com/sse` |
13+
| [**Observability server**](/apps/observability) | Debug and get insight into your application’s logs and analytics | `https://observability.mcp.cloudflare.com/sse` |
14+
| [**Radar server**](/apps/radar) | Get global Internet traffic insights, trends, URL scans, and other utilities | `https://radar.mcp.cloudflare.com/sse` |
1115

12-
Open Claude Desktop and navigate to Settings -> Developer -> Edit Config. This opens the configuration file that controls which MCP servers Claude can access.
16+
## Access the remote MCP server from any MCP client
1317

14-
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.
18+
If your MCP client has first class support for remote MCP servers, the client will provide a way to accept the server URL directly within its interface (e.g. [Cloudflare AI Playground](https://playground.ai.cloudflare.com/))
19+
20+
If your client does not yet support remote MCP servers, you will need to set up its resepective configuration file using mcp-remote (https://www.npmjs.com/package/mcp-remote) to specify which servers your client can access.
1521

1622
```json
1723
{
1824
"mcpServers": {
19-
"cloudflare": {
25+
"cloudflare-observability": {
2026
"command": "npx",
2127
"args": ["mcp-remote", "https://observability.mcp.cloudflare.com/sse"]
28+
},
29+
"cloudflare-bindings": {
30+
"command": "npx",
31+
"args": ["mcp-remote", "https://bindings.mcp.cloudflare.com/sse"]
2232
}
2333
}
2434
}
2535
```
2636

2737
## Need access to more Cloudflare tools?
2838

29-
We're gradually moving over functionality to this remote MCP server repo. In the meantime please take a look at the local only mcp-server-cloudflare package which currently has more tools available.
30-
31-
Visit <https://www.npmjs.com/package/@cloudflare/mcp-server-cloudflare>
39+
We're continuing to add more functionality to this remote MCP server repo. If you'd like to leave feedback, file a bug or provide a feature request, [please open an issue](https://github.com/cloudflare/mcp-server-cloudflare/issues/new/choose) on this repository
3240

3341
## Paid Features
3442

3543
Some features may require a paid Cloudflare Workers plan. Ensure your Cloudflare account has the necessary subscription level for the features you intend to use.
3644

37-
## Features
38-
39-
### Workers Management
40-
41-
- `worker_list`: List all Workers in your account
42-
- `worker_get_worker`: Get a Worker's script content
43-
44-
### Workers Logs
45-
46-
- `worker_logs_by_worker_name`: Analyze recent logs for a Cloudflare Worker by worker name
47-
- `worker_logs_by_ray_id`: Analyze recent logs across all workers for a specific request by Cloudflare Ray ID
48-
- `worker_logs_keys`: Get available telemetry keys for a Cloudflare Worker
49-
50-
## Developing
51-
52-
### Apps
53-
54-
- [workers-observability](apps/workers-observability): The Workers Observability MCP server
55-
- [radar](apps/radar): The Cloudflare Radar MCP server
56-
57-
### Packages
58-
59-
- eslint-config: Eslint config used by all apps and packages.
60-
- typescript-config: tsconfig used by all apps and packages.
61-
- mcp-common: Shared common tools and scripts to help manage this repo.
62-
63-
For more details on development in this monorepo, take a look at apps/workers-observability
64-
65-
## Testing
66-
67-
The project uses Vitest as the testing framework with MSW (Mock Service Worker) for API mocking.
68-
69-
### Running Tests
70-
71-
To run all tests:
72-
73-
```bash
74-
pnpm test
75-
```
76-
77-
To run a specific test file:
78-
79-
```bash
80-
pnpm test -- tests/tools/queues.test.ts
81-
```
82-
83-
To run tests in watch mode (useful during development):
84-
85-
```bash
86-
pnpm test:watch
87-
```
88-
8945
## Contributing
9046

91-
Contributions are welcome! Please feel free to submit a Pull Request.
47+
Interested in contributing, and running this server locally? See [CONTRIBUTING.md](CONTRIBUTING.md) to get started.

apps/cloudflare-one-casb/src/context.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ export interface Env {
77
MCP_OBJECT: DurableObjectNamespace<CASBMCP>
88
MCP_METRICS: AnalyticsEngineDataset
99
AI: Ai
10-
1110
CLOUDFLARE_CLIENT_ID: string
1211
CLOUDFLARE_CLIENT_SECRET: string
13-
1412
USER_DETAILS: DurableObjectNamespace<UserDetails>
13+
DEV_DISABLE_OAUTH: string
14+
DEV_CLOUDFLARE_API_TOKEN: string
15+
DEV_CLOUDFLARE_EMAIL: string
1516
}

apps/cloudflare-one-casb/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
} from '@repo/mcp-common/src/cloudflare-oauth-handler'
88
import { getUserDetails, UserDetails } from '@repo/mcp-common/src/durable-objects/user_details'
99
import { getEnv } from '@repo/mcp-common/src/env'
10+
import { RequiredScopes } from '@repo/mcp-common/src/scopes'
1011
import { CloudflareMCPServer } from '@repo/mcp-common/src/server'
1112
import { registerAccountTools } from '@repo/mcp-common/src/tools/account'
1213

@@ -86,10 +87,9 @@ export class CASBMCP extends McpAgent<Env, State, Props> {
8687
}
8788
}
8889
const CloudflareOneCasbScopes = {
90+
...RequiredScopes,
8991
'account:read': 'See your account info such as account details, analytics, and memberships.',
90-
'user:read': 'See your user info such as name, email address, and account memberships.',
9192
'teams:read': 'See Cloudflare One Resources',
92-
offline_access: 'Grants refresh tokens for long-lived access.',
9393
} as const
9494

9595
export default new OAuthProvider({

apps/dex-analysis/src/context.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@ export interface Env {
1111
MCP_OBJECT: DurableObjectNamespace<CloudflareDEXMCP>
1212
USER_DETAILS: DurableObjectNamespace<UserDetails>
1313
MCP_METRICS: AnalyticsEngineDataset
14+
DEV_DISABLE_OAUTH: string
15+
DEV_CLOUDFLARE_API_TOKEN: string
16+
DEV_CLOUDFLARE_EMAIL: string
1417
}

apps/dex-analysis/src/index.ts

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { McpAgent } from 'agents/mcp'
33

44
import {
55
createAuthHandlers,
6+
getUserAndAccounts,
67
handleTokenExchangeCallback,
78
} from '@repo/mcp-common/src/cloudflare-oauth-handler'
89
import { getUserDetails, UserDetails } from '@repo/mcp-common/src/durable-objects/user_details'
@@ -96,16 +97,42 @@ const DexScopes = {
9697
'dex:read': 'See Cloudflare Cloudflare DEX data for your account',
9798
} as const
9899

99-
export default new OAuthProvider({
100-
apiRoute: '/sse',
101-
apiHandler: CloudflareDEXMCP.mount('/sse'),
102-
// @ts-ignore
103-
defaultHandler: createAuthHandlers({ scopes: DexScopes, metrics }),
104-
authorizeEndpoint: '/oauth/authorize',
105-
tokenEndpoint: '/token',
106-
tokenExchangeCallback: (options) =>
107-
handleTokenExchangeCallback(options, env.CLOUDFLARE_CLIENT_ID, env.CLOUDFLARE_CLIENT_SECRET),
108-
// Cloudflare access token TTL
109-
accessTokenTTL: 3600,
110-
clientRegistrationEndpoint: '/register',
111-
})
100+
// TODO: Move this in to mcp-common
101+
async function handleDevMode(req: Request, env: Env, ctx: ExecutionContext) {
102+
const { user, accounts } = await getUserAndAccounts(env.DEV_CLOUDFLARE_API_TOKEN, {
103+
'X-Auth-Email': env.DEV_CLOUDFLARE_EMAIL,
104+
'X-Auth-Key': env.DEV_CLOUDFLARE_API_TOKEN,
105+
})
106+
ctx.props = {
107+
accessToken: env.DEV_CLOUDFLARE_API_TOKEN,
108+
user,
109+
accounts,
110+
} as Props
111+
return CloudflareDEXMCP.mount('/sse').fetch(req, env, ctx)
112+
}
113+
114+
export default {
115+
fetch: async (req: Request, env: Env, ctx: ExecutionContext) => {
116+
if (env.ENVIRONMENT === 'development' && env.DEV_DISABLE_OAUTH === 'true') {
117+
return await handleDevMode(req, env, ctx)
118+
}
119+
120+
return new OAuthProvider({
121+
apiRoute: '/sse',
122+
apiHandler: CloudflareDEXMCP.mount('/sse'),
123+
// @ts-ignore
124+
defaultHandler: createAuthHandlers({ scopes: DexScopes, metrics }),
125+
authorizeEndpoint: '/oauth/authorize',
126+
tokenEndpoint: '/token',
127+
tokenExchangeCallback: (options) =>
128+
handleTokenExchangeCallback(
129+
options,
130+
env.CLOUDFLARE_CLIENT_ID,
131+
env.CLOUDFLARE_CLIENT_SECRET
132+
),
133+
// Cloudflare access token TTL
134+
accessTokenTTL: 3600,
135+
clientRegistrationEndpoint: '/register',
136+
}).fetch(req, env, ctx)
137+
},
138+
}

apps/dex-analysis/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"extends": "@repo/typescript-config/workers.json",
3-
"include": ["*/**.ts"]
3+
"include": ["*/**.ts", "./vitest.config.ts", "./types.d.ts"]
44
}

apps/dex-analysis/vitest.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config'
2+
import type { Env } from './src/context'
23

34
export interface TestEnv extends Env {
45
CLOUDFLARE_MOCK_ACCOUNT_ID: string

apps/docs-autorag/.dev.vars.example

Whitespace-only changes.

apps/radar/.dev.vars.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
CLOUDFLARE_CLIENT_ID=
22
CLOUDFLARE_CLIENT_SECRET=
33
URL_SCANNER_API_TOKEN=
4+
DEV_DISABLE_OAUTH=
5+
DEV_CLOUDFLARE_API_TOKEN=
6+
DEV_CLOUDFLARE_EMAIL=

0 commit comments

Comments
 (0)