Skip to content

Update README & add dev mode #89

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

Merged
merged 1 commit into from
Apr 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Developing

We welcome contributions to all of our MCP servers! Here's a quick run down on how to get started.

## Architecture

This monorepo has two top-level directories: `/apps` and `/packages`.

- **/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:
- [apps/workers-observability](apps/workers-observability)
- [apps/workers-bindings](apps/workers-bindings)
- [apps/radar](apps/radar)
- [apps/cloudflare-one-casb](apps/cloudflare-one-casb)
- **/packages**: Containing shared packages used across our various apps.
- packages/eslint-config: Eslint config used by all apps and packages.
- packages/typescript-config: tsconfig used by all apps and packages.
- packages/mcp-common: Shared common tools and scripts to help manage this repo.

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.

## Getting Started

This section will guide you through setting up your developer environment and running tests.

### Installation

Install dependencies:

```bash
pnpm install
```

### Testing

The project uses Vitest as the testing framework with [fetchMock](https://developers.cloudflare.com/workers/testing/vitest-integration/test-apis/) for API mocking.

#### Running Tests

To run all tests:

```bash
pnpm test
```

To run a specific test file:

```bash
pnpm test -- tests/tools/queues.test.ts
```

To run tests in watch mode (useful during development):

```bash
pnpm test:watch
```
84 changes: 20 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,91 +1,47 @@
# Cloudflare MCP Server

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).
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.

This lets you use Claude Desktop, or any MCP Client, to use natural language to accomplish things on your Cloudflare account, e.g.:
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.

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

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

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

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.
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/))

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.

```json
{
"mcpServers": {
"cloudflare": {
"cloudflare-observability": {
"command": "npx",
"args": ["mcp-remote", "https://observability.mcp.cloudflare.com/sse"]
},
"cloudflare-bindings": {
"command": "npx",
"args": ["mcp-remote", "https://bindings.mcp.cloudflare.com/sse"]
}
}
}
```

## Need access to more Cloudflare tools?

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.

Visit <https://www.npmjs.com/package/@cloudflare/mcp-server-cloudflare>
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

## Paid Features

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.

## Features

### Workers Management

- `worker_list`: List all Workers in your account
- `worker_get_worker`: Get a Worker's script content

### Workers Logs

- `worker_logs_by_worker_name`: Analyze recent logs for a Cloudflare Worker by worker name
- `worker_logs_by_ray_id`: Analyze recent logs across all workers for a specific request by Cloudflare Ray ID
- `worker_logs_keys`: Get available telemetry keys for a Cloudflare Worker

## Developing

### Apps

- [workers-observability](apps/workers-observability): The Workers Observability MCP server
- [radar](apps/radar): The Cloudflare Radar MCP server

### Packages

- eslint-config: Eslint config used by all apps and packages.
- typescript-config: tsconfig used by all apps and packages.
- mcp-common: Shared common tools and scripts to help manage this repo.

For more details on development in this monorepo, take a look at apps/workers-observability

## Testing

The project uses Vitest as the testing framework with MSW (Mock Service Worker) for API mocking.

### Running Tests

To run all tests:

```bash
pnpm test
```

To run a specific test file:

```bash
pnpm test -- tests/tools/queues.test.ts
```

To run tests in watch mode (useful during development):

```bash
pnpm test:watch
```

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.
Interested in contributing, and running this server locally? See [CONTRIBUTING.md](CONTRIBUTING.md) to get started.
1 change: 0 additions & 1 deletion apps/cloudflare-one-casb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
},
"devDependencies": {
"@cloudflare/vitest-pool-workers": "0.8.14",
"@cloudflare/workers-types": "4.20250410.0",
"@types/jsonwebtoken": "9.0.9",
"prettier": "3.5.3",
"typescript": "5.5.4",
Expand Down
5 changes: 3 additions & 2 deletions apps/cloudflare-one-casb/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ export interface Env {
MCP_OBJECT: DurableObjectNamespace<CASBMCP>
MCP_METRICS: AnalyticsEngineDataset
AI: Ai

CLOUDFLARE_CLIENT_ID: string
CLOUDFLARE_CLIENT_SECRET: string

USER_DETAILS: DurableObjectNamespace<UserDetails>
DEV_DISABLE_OAUTH: string
DEV_CLOUDFLARE_API_TOKEN: string
DEV_CLOUDFLARE_EMAIL: string
}
4 changes: 2 additions & 2 deletions apps/cloudflare-one-casb/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '@repo/mcp-common/src/cloudflare-oauth-handler'
import { getUserDetails, UserDetails } from '@repo/mcp-common/src/durable-objects/user_details'
import { getEnv } from '@repo/mcp-common/src/env'
import { RequiredScopes } from '@repo/mcp-common/src/scopes'
import { CloudflareMCPServer } from '@repo/mcp-common/src/server'
import { registerAccountTools } from '@repo/mcp-common/src/tools/account'

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

export default new OAuthProvider({
Expand Down
2 changes: 1 addition & 1 deletion apps/dex-analysis/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
module.exports = {
root: true,
extends: ['@repo/eslint-config/default.cjs'],
}
}
3 changes: 1 addition & 2 deletions apps/dex-analysis/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@
},
"devDependencies": {
"@cloudflare/vitest-pool-workers": "0.8.14",
"@cloudflare/workers-types": "4.20250410.0",
"@types/jsonwebtoken": "9.0.9",
"prettier": "3.5.3",
"typescript": "5.5.4",
"vitest": "3.0.9",
"wrangler": "4.10.0"
}
}
}
3 changes: 3 additions & 0 deletions apps/dex-analysis/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ export interface Env {
MCP_OBJECT: DurableObjectNamespace<CloudflareDEXMCP>
USER_DETAILS: DurableObjectNamespace<UserDetails>
MCP_METRICS: AnalyticsEngineDataset
DEV_DISABLE_OAUTH: string
DEV_CLOUDFLARE_API_TOKEN: string
DEV_CLOUDFLARE_EMAIL: string
}
53 changes: 40 additions & 13 deletions apps/dex-analysis/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { McpAgent } from 'agents/mcp'

import {
createAuthHandlers,
getUserAndAccounts,
handleTokenExchangeCallback,
} from '@repo/mcp-common/src/cloudflare-oauth-handler'
import { getUserDetails, UserDetails } from '@repo/mcp-common/src/durable-objects/user_details'
Expand Down Expand Up @@ -96,16 +97,42 @@ const DexScopes = {
'dex:read': 'See Cloudflare Cloudflare DEX data for your account',
} as const

export default new OAuthProvider({
apiRoute: '/sse',
apiHandler: CloudflareDEXMCP.mount('/sse'),
// @ts-ignore
defaultHandler: createAuthHandlers({ scopes: DexScopes, metrics }),
authorizeEndpoint: '/oauth/authorize',
tokenEndpoint: '/token',
tokenExchangeCallback: (options) =>
handleTokenExchangeCallback(options, env.CLOUDFLARE_CLIENT_ID, env.CLOUDFLARE_CLIENT_SECRET),
// Cloudflare access token TTL
accessTokenTTL: 3600,
clientRegistrationEndpoint: '/register',
})
// TODO: Move this in to mcp-common
async function handleDevMode(req: Request, env: Env, ctx: ExecutionContext) {
const { user, accounts } = await getUserAndAccounts(env.DEV_CLOUDFLARE_API_TOKEN, {
'X-Auth-Email': env.DEV_CLOUDFLARE_EMAIL,
'X-Auth-Key': env.DEV_CLOUDFLARE_API_TOKEN,
})
ctx.props = {
accessToken: env.DEV_CLOUDFLARE_API_TOKEN,
user,
accounts,
} as Props
return CloudflareDEXMCP.mount('/sse').fetch(req, env, ctx)
}

export default {
fetch: async (req: Request, env: Env, ctx: ExecutionContext) => {
if (env.ENVIRONMENT === 'development' && env.DEV_DISABLE_OAUTH === 'true') {
return await handleDevMode(req, env, ctx)
}

return new OAuthProvider({
apiRoute: '/sse',
apiHandler: CloudflareDEXMCP.mount('/sse'),
// @ts-ignore
defaultHandler: createAuthHandlers({ scopes: DexScopes, metrics }),
authorizeEndpoint: '/oauth/authorize',
tokenEndpoint: '/token',
tokenExchangeCallback: (options) =>
handleTokenExchangeCallback(
options,
env.CLOUDFLARE_CLIENT_ID,
env.CLOUDFLARE_CLIENT_SECRET
),
// Cloudflare access token TTL
accessTokenTTL: 3600,
clientRegistrationEndpoint: '/register',
}).fetch(req, env, ctx)
},
}
2 changes: 1 addition & 1 deletion apps/dex-analysis/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"extends": "@repo/typescript-config/workers.json",
"include": ["*/**.ts"]
"include": ["*/**.ts", "./vitest.config.ts", "./types.d.ts"]
}
2 changes: 1 addition & 1 deletion apps/dex-analysis/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ import type { TestEnv } from './vitest.config'

declare module 'cloudflare:test' {
interface ProvidedEnv extends TestEnv {}
}
}
4 changes: 3 additions & 1 deletion apps/dex-analysis/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config'

import type { Env } from './src/context'

export interface TestEnv extends Env {
CLOUDFLARE_MOCK_ACCOUNT_ID: string
CLOUDFLARE_MOCK_API_TOKEN: string
Expand All @@ -19,4 +21,4 @@ export default defineWorkersConfig({
},
},
},
})
})
6 changes: 3 additions & 3 deletions apps/dex-analysis/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* For more details on how to configure Wrangler, refer to:
* https://developers.cloudflare.com/workers/wrangler/configuration/
*/
{
{
"$schema": "node_modules/wrangler/config-schema.json",
"main": "src/index.ts",
"compatibility_date": "2025-03-10",
Expand Down Expand Up @@ -80,7 +80,7 @@
"binding": "MCP_METRICS",
"dataset": "mcp-metrics-staging"
}
],
]
},
"production": {
"name": "mcp-cloudflare-workers-dex-production",
Expand Down Expand Up @@ -113,7 +113,7 @@
"binding": "MCP_METRICS",
"dataset": "mcp-metrics-production"
}
],
]
}
}
}
Empty file.
3 changes: 3 additions & 0 deletions apps/radar/.dev.vars.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
CLOUDFLARE_CLIENT_ID=
CLOUDFLARE_CLIENT_SECRET=
URL_SCANNER_API_TOKEN=
DEV_DISABLE_OAUTH=
DEV_CLOUDFLARE_API_TOKEN=
DEV_CLOUDFLARE_EMAIL=
Loading