Skip to content

Commit 3e1f73e

Browse files
committed
Lint
1 parent 3dbca1d commit 3e1f73e

30 files changed

+1699
-748
lines changed

.eslintrc.cjs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
// This configuration only applies to the package manager root.
22
/** @type {import("eslint").Linter.Config} */
33
module.exports = {
4-
ignorePatterns: [
5-
'apps/**',
6-
'packages/**',
7-
],
8-
extends: ['@repo/eslint-config/default.cjs']
4+
ignorePatterns: ['apps/**', 'packages/**'],
5+
extends: ['@repo/eslint-config/default.cjs'],
96
}

.vscode/extensions.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
44

55
// List of extensions which should be recommended for users of this workspace.
6-
"recommendations": [
7-
"esbenp.prettier-vscode",
8-
"dbaeumer.vscode-eslint",
9-
],
6+
"recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"],
107
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
118
"unwantedRecommendations": []
129
}

.vscode/settings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
"**/packages/tools/bin/*": "shellscript",
1414
"**/*.css": "tailwindcss",
1515
"turbo.json": "jsonc",
16-
"**/packages/typescript-config/*.json": "jsonc",
16+
"**/packages/typescript-config/*.json": "jsonc"
1717
},
1818
"eslint.workingDirectories": [
1919
{
2020
"mode": "auto"
2121
}
22-
],
22+
]
2323
}

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ Model Context Protocol (MCP) is a [new, standardized protocol](https://modelcont
44

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

1010
## Access the remote MCP server from Claude Desktop
1111

1212
Open Claude Desktop and navigate to Settings -> Developer -> Edit Config. This opens the configuration file that controls which MCP servers Claude can access.
1313

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

1616
```
1717
{
@@ -44,17 +44,20 @@ Ensure your Cloudflare account has the necessary subscription level for the feat
4444
## Features
4545

4646
### Workers Management
47+
4748
- `worker_list`: List all Workers in your account
4849
- `worker_get_worker`: Get a Worker's script content
4950

5051
### Workers Logs
52+
5153
- `worker_logs_by_worker_name`: Analyze recent logs for a Cloudflare Worker by worker name
5254
- `worker_logs_by_ray_id`: Analyze recent logs across all workers for a specific request by Cloudflare Ray ID
5355
- `worker_logs_keys`: Get available telemetry keys for a Cloudflare Worker
5456

5557
## Developing
5658

5759
### Apps
60+
5861
- [workers-observability](apps/workers-observability/): The Workers Observability MCP server
5962

6063
### Packages

apps/sandbox-container/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ TODO: replace locally running server with the real docker container.
1212

1313
1. Make sure the docker daemon is running
1414

15-
2. Disable WARP and run
15+
2. Disable WARP and run
1616

1717
```
1818
npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/14387504770/npm-package-wrangler-8740 deploy

apps/sandbox-container/server/containerHelpers.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
export const MAX_CONTAINERS = 8
22
export async function startAndWaitForPort(
3-
environment: "dev" | "prod",
3+
environment: 'dev' | 'prod',
44
container: Container | undefined,
55
portToAwait: number,
66
maxTries = 10
77
): Promise<boolean> {
8-
if (environment === "dev") {
9-
console.log("Running in dev, assuming locally running container")
10-
return true
11-
}
8+
if (environment === 'dev') {
9+
console.log('Running in dev, assuming locally running container')
10+
return true
11+
}
1212

1313
if (!container) {
1414
throw new Error('Error: ctx.container is undefined. Does this DO support containers?')
@@ -62,15 +62,17 @@ export async function startAndWaitForPort(
6262
}
6363

6464
export async function proxyFetch(
65-
environment: "dev" | "prod",
65+
environment: 'dev' | 'prod',
6666
container: Container | undefined,
6767
request: Request,
6868
portNumber: number
6969
): Promise<Response> {
70-
if (environment === "dev") {
71-
const url = request.url.replace('https://', 'http://').replace("http://host", "http://localhost")
72-
return fetch(url, request.clone() as Request)
73-
}
70+
if (environment === 'dev') {
71+
const url = request.url
72+
.replace('https://', 'http://')
73+
.replace('http://host', 'http://localhost')
74+
return fetch(url, request.clone() as Request)
75+
}
7476

7577
if (!container) {
7678
throw new Error('Error: ctx.container is undefined. Does this DO support containers?')

apps/sandbox-container/server/containerMcp.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,11 @@ export class ContainerMcpAgent extends McpAgent<Env, Props> {
166166
// start container
167167
let startedContainer = false
168168
await this.ctx.blockConcurrencyWhile(async () => {
169-
startedContainer = await startAndWaitForPort(this.env.ENVIRONMENT, this.ctx.container, OPEN_CONTAINER_PORT)
169+
startedContainer = await startAndWaitForPort(
170+
this.env.ENVIRONMENT,
171+
this.ctx.container,
172+
OPEN_CONTAINER_PORT
173+
)
170174
})
171175
if (!startedContainer) {
172176
throw new Error('Failed to start container')

apps/sandbox-container/server/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ export { ContainerManager, ContainerMcpAgent }
1313
export type Env = {
1414
CONTAINER_MCP_AGENT: DurableObjectNamespace<ContainerMcpAgent>
1515
CONTAINER_MANAGER: DurableObjectNamespace<ContainerManager>
16-
ENVIRONMENT: "dev" | "prod"
16+
ENVIRONMENT: 'dev' | 'prod'
1717
}
1818

1919
// TODO: add user specific props
2020
export type Props = {}
2121

2222
const app = new Hono<{ Bindings: Env }>()
2323

24-
export default ContainerMcpAgent.mount('/sse', { binding: 'CONTAINER_MCP_AGENT' })
24+
export default ContainerMcpAgent.mount('/sse', { binding: 'CONTAINER_MCP_AGENT' })

apps/workers-observability/README.md

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,50 @@ You can deploy it to your own Cloudflare account, and after you create your own
66

77
You can use this as a reference example for how to integrate other OAuth providers with an MCP server deployed to Cloudflare, using the [`workers-oauth-provider` library](https://github.com/cloudflare/workers-oauth-provider).
88

9-
The MCP server (powered by [Cloudflare Workers](https://developers.cloudflare.com/workers/)):
9+
The MCP server (powered by [Cloudflare Workers](https://developers.cloudflare.com/workers/)):
1010

11-
* Acts as OAuth _Server_ to your MCP clients
12-
* Acts as OAuth _Client_ to your _real_ OAuth server (in this case, Cloudflare)
11+
- Acts as OAuth _Server_ to your MCP clients
12+
- Acts as OAuth _Client_ to your _real_ OAuth server (in this case, Cloudflare)
1313

1414
## Getting Started
1515

1616
### For Production
17+
1718
- Set secrets via Wrangler
19+
1820
```bash
1921
wrangler secret put CLOUDFLARE_CLIENT_ID
2022
wrangler secret put CLOUDFLARE_CLIENT_SECRET
2123
```
24+
2225
#### Set up a KV namespace
23-
- Create the KV namespace:
24-
`wrangler kv:namespace create "OAUTH_KV"`
26+
27+
- Create the KV namespace:
28+
`wrangler kv:namespace create "OAUTH_KV"`
2529
- Update the Wrangler file with the KV ID
2630

2731
#### Deploy & Test
28-
Deploy the MCP server to make it available on your workers.dev domain
32+
33+
Deploy the MCP server to make it available on your workers.dev domain
2934
` wrangler deploy`
3035

31-
Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector):
36+
Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector):
3237

3338
```
3439
npx @modelcontextprotocol/inspector@latest
3540
```
36-
Enter `https://mcp-cloudflare-staging.<your-subdomain>.workers.dev/sse` and hit connect. Once you go through the authentication flow, you'll see the Tools working:
41+
42+
Enter `https://mcp-cloudflare-staging.<your-subdomain>.workers.dev/sse` and hit connect. Once you go through the authentication flow, you'll see the Tools working:
3743

3844
<img width="640" alt="image" src="https://github.com/user-attachments/assets/7973f392-0a9d-4712-b679-6dd23f824287" />
3945

40-
You now have a remote MCP server deployed!
46+
You now have a remote MCP server deployed!
4147

4248
#### Access the remote MCP server from Claude Desktop
4349

4450
Open Claude Desktop and navigate to Settings -> Developer -> Edit Config. This opens the configuration file that controls which MCP servers Claude can access.
4551

46-
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.
52+
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.
4753

4854
```
4955
{
@@ -62,21 +68,25 @@ Replace the content with the following configuration. Once you restart Claude De
6268
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.
6369

6470
### For Local Development
65-
If you'd like to iterate and test your MCP server, you can do so in local development. This will require you to create another OAuth App on GitHub:
71+
72+
If you'd like to iterate and test your MCP server, you can do so in local development. This will require you to create another OAuth App on GitHub:
73+
6674
- For the Homepage URL, specify `http://localhost:8788`
6775
- For the Authorization callback URL, specify `http://localhost:8788/callback`
68-
- Note your Client ID and generate a Client secret.
69-
- Create a `.dev.vars` file in your project root with:
76+
- Note your Client ID and generate a Client secret.
77+
- Create a `.dev.vars` file in your project root with:
78+
7079
```
7180
CLOUDFLARE_CLIENT_ID=your_development_cloudflare_client_id
7281
CLOUDFLARE_CLIENT_SECRET=your_development_cloudflare_client_secret
7382
```
7483

7584
#### Develop & Test
85+
7686
Run the server locally to make it available at `http://localhost:8788`
7787
`wrangler dev`
7888

79-
To test the local server, enter `http://localhost:8788/sse` into Inspector and hit connect. Once you follow the prompts, you'll be able to "List Tools".
89+
To test the local server, enter `http://localhost:8788/sse` into Inspector and hit connect. Once you follow the prompts, you'll be able to "List Tools".
8090

8191
#### Using Claude and other MCP Clients
8292

@@ -90,25 +100,30 @@ Note that while Cursor supports HTTP+SSE servers, it doesn't support authenticat
90100

91101
You can connect your MCP server to other MCP clients like Windsurf by opening the client's configuration file, adding the same JSON that was used for the Claude setup, and restarting the MCP client.
92102

93-
## How does it work?
103+
## How does it work?
94104

95105
#### OAuth Provider
106+
96107
The OAuth Provider library serves as a complete OAuth 2.1 server implementation for Cloudflare Workers. It handles the complexities of the OAuth flow, including token issuance, validation, and management. In this project, it plays the dual role of:
97108

98109
- Authenticating MCP clients that connect to your server
99110
- Managing the connection to GitHub's OAuth services
100111
- Securely storing tokens and authentication state in KV storage
101112

102113
#### Durable MCP
114+
103115
Durable MCP extends the base MCP functionality with Cloudflare's Durable Objects, providing:
116+
104117
- Persistent state management for your MCP server
105118
- Secure storage of authentication context between requests
106119
- Access to authenticated user information via `this.props`
107120
- Support for conditional tool availability based on user identity
108121

109122
#### MCP Remote
123+
110124
The MCP Remote library enables your server to expose tools that can be invoked by MCP clients like the Inspector. It:
125+
111126
- Defines the protocol for communication between clients and your server
112127
- Provides a structured way to define tools
113128
- Handles serialization and deserialization of requests and responses
114-
- Maintains the Server-Sent Events (SSE) connection between clients and your server
129+
- Maintains the Server-Sent Events (SSE) connection between clients and your server
Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,58 @@
1-
import OAuthProvider from "@cloudflare/workers-oauth-provider";
2-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3-
import { McpAgent } from "agents/mcp";
4-
import type { Env } from "../worker-configuration";
5-
import { registerAccountTools } from "./tools/account";
6-
import { registerLogsTools } from "./tools/logs";
7-
import { registerWorkersTools } from "./tools/workers";
1+
import OAuthProvider from '@cloudflare/workers-oauth-provider'
2+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
3+
import { McpAgent } from 'agents/mcp'
4+
85
import {
9-
type AccountSchema,
106
CloudflareAuthHandler,
11-
type UserSchema,
127
handleTokenExchangeCallback,
13-
} from "@repo/mcp-common/src/cloudflare-oauth-handler";
8+
} from '@repo/mcp-common/src/cloudflare-oauth-handler'
9+
10+
import { registerAccountTools } from './tools/account'
11+
import { registerLogsTools } from './tools/logs'
12+
import { registerWorkersTools } from './tools/workers'
13+
14+
import type { AccountSchema, UserSchema } from '@repo/mcp-common/src/cloudflare-oauth-handler'
15+
import type { Env } from '../worker-configuration'
1416

1517
// Context from the auth process, encrypted & stored in the auth token
1618
// and provided to the DurableMCP as this.props
1719
export type Props = {
18-
accessToken: string;
19-
user: UserSchema["result"];
20-
accounts: AccountSchema["result"];
21-
};
20+
accessToken: string
21+
user: UserSchema['result']
22+
accounts: AccountSchema['result']
23+
}
2224

23-
export type State = { activeAccountId: string | null };
25+
export type State = { activeAccountId: string | null }
2426

2527
export class MyMCP extends McpAgent<Env, State, Props> {
2628
server = new McpServer({
27-
name: "Remote MCP Server with Workers Observability",
28-
version: "1.0.0",
29-
});
29+
name: 'Remote MCP Server with Workers Observability',
30+
version: '1.0.0',
31+
})
3032
// TOOO: Why does this type need to be declared again on MyMCP?
3133
// @ts-ignore
32-
env!: Env;
34+
env!: Env
3335

3436
initialState: State = {
3537
activeAccountId: null,
36-
};
38+
}
3739

3840
async init() {
39-
registerAccountTools(this);
41+
registerAccountTools(this)
4042

4143
// Register Cloudflare Workers tools
42-
registerWorkersTools(this);
44+
registerWorkersTools(this)
4345

4446
// Register Cloudflare Workers logs tools
45-
registerLogsTools(this);
47+
registerLogsTools(this)
4648
}
4749

4850
getActiveAccountId() {
4951
// TODO: Figure out why this fail sometimes, and why we need to wrap this in a try catch
5052
try {
51-
return this.state.activeAccountId ?? null;
53+
return this.state.activeAccountId ?? null
5254
} catch (e) {
53-
return null;
55+
return null
5456
}
5557
}
5658

@@ -60,23 +62,23 @@ export class MyMCP extends McpAgent<Env, State, Props> {
6062
this.setState({
6163
...this.state,
6264
activeAccountId: accountId,
63-
});
65+
})
6466
} catch (e) {
65-
return null;
67+
return null
6668
}
6769
}
6870
}
6971

7072
export default new OAuthProvider({
71-
apiRoute: "/workers/observability/sse",
73+
apiRoute: '/workers/observability/sse',
7274
// @ts-ignore
73-
apiHandler: MyMCP.mount("/workers/observability/sse"),
75+
apiHandler: MyMCP.mount('/workers/observability/sse'),
7476
// @ts-ignore
7577
defaultHandler: CloudflareAuthHandler,
76-
authorizeEndpoint: "/oauth/authorize",
77-
tokenEndpoint: "/token",
78+
authorizeEndpoint: '/oauth/authorize',
79+
tokenEndpoint: '/token',
7880
tokenExchangeCallback: handleTokenExchangeCallback,
7981
// Cloudflare access token TTL
8082
accessTokenTTL: 3600,
81-
clientRegistrationEndpoint: "/register",
82-
});
83+
clientRegistrationEndpoint: '/register',
84+
})

0 commit comments

Comments
 (0)