Skip to content

Commit 25668da

Browse files
committed
improve README.md
1 parent 0f07c12 commit 25668da

File tree

6 files changed

+117
-17
lines changed

6 files changed

+117
-17
lines changed

apps/radar/README.md

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,71 @@
22

33
This is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) server that supports remote MCP connections, with Cloudflare OAuth built-in.
44

5+
It features tools powered by the [Cloudflare Radar API](https://developers.cloudflare.com/radar/).
6+
7+
## Tools
8+
9+
Currently available tools:
10+
11+
- `list_autonomous_systems`: Lists autonomous systems (filterable by location and sortable by population size)
12+
- `get_as_details`: Retrieves details of an autonomous system by ASN
13+
- `get_ip_details`: Provides information about a specific IP address
14+
- `get_traffic_anomalies`: Lists traffic anomalies (filterable by AS, location, start date, and end date)
15+
16+
This MCP server is still a work in progress, and we plan to add more tools in the future.
17+
518
## Getting Started
619

7-
- Set secrets via Wrangler (ask in the `Cloudflare's Own MCP Servers` internal channel to get credentials)
20+
#### Secrets
21+
22+
Set secrets via Wrangler (ask in the `Cloudflare's Own MCP Servers` internal channel to get credentials)
823

924
```bash
10-
wrangler secret put CLOUDFLARE_CLIENT_ID
11-
wrangler secret put CLOUDFLARE_CLIENT_SECRET
25+
npx wrangler secret put CLOUDFLARE_CLIENT_ID -e <ENVIRONMENT>
26+
npx wrangler secret put CLOUDFLARE_CLIENT_SECRET -e <ENVIRONMENT>
1227
```
1328

1429
#### Set up a KV namespace
1530

16-
- Create the KV namespace:
17-
`wrangler kv:namespace create "OAUTH_KV"`
18-
- Update the Wrangler file with the KV ID
31+
Create the KV namespace:
32+
33+
```bash
34+
npx wrangler kv namespace create "OAUTH_KV"
35+
```
36+
37+
Then, update the Wrangler file with the generated KV namespace ID.
1938

2039
#### Deploy & Test
2140

22-
Deploy the MCP server to make it available on your workers.dev domain
23-
` wrangler deploy`
41+
Deploy the MCP server to make it available on your workers.dev domain:
42+
43+
```bash
44+
npx wrangler deploy -e <ENVIRONMENT>
45+
```
2446

2547
Test the remote server using [Inspector](https://modelcontextprotocol.io/docs/tools/inspector):
2648

2749
```
2850
npx @modelcontextprotocol/inspector@latest
2951
```
52+
53+
## Local Development
54+
55+
If you'd like to iterate and test your MCP server, you can do so in local development.
56+
This will require you to create another OAuth App on Cloudflare:
57+
58+
1. Create a `.dev.vars` file in your project root with:
59+
60+
```
61+
CLOUDFLARE_CLIENT_ID=your_development_cloudflare_client_id
62+
CLOUDFLARE_CLIENT_SECRET=your_development_cloudflare_client_secret
63+
```
64+
65+
2. Start the local development server:
66+
67+
```bash
68+
npx wrangler dev
69+
```
70+
71+
3. To test locally, open Inspector, and connect to `http://localhost:8788/sse`.
72+
Once you follow the prompts, you'll be able to "List Tools".

apps/radar/src/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
33
import { McpAgent } from 'agents/mcp'
44
import { env } from 'cloudflare:workers'
55

6-
import { createAuthHandlers, handleTokenExchangeCallback, } from '@repo/mcp-common/src/cloudflare-oauth-handler'
6+
import {
7+
createAuthHandlers,
8+
handleTokenExchangeCallback,
9+
} from '@repo/mcp-common/src/cloudflare-oauth-handler'
710

811
import { registerRadarTools } from './tools/radar'
912

13+
// TODO import { registerUrlScannerTools } from "./tools/url-scanner";
14+
1015
// Context from the auth process, encrypted & stored in the auth token
1116
// and provided to the DurableMCP as this.props
1217
export type Props = {
@@ -17,7 +22,7 @@ export type State = never
1722

1823
export class RadarMCP extends McpAgent<Env, State, Props> {
1924
server = new McpServer({
20-
name: 'Remote MCP Server with Cloudflare Radar Data',
25+
name: 'Cloudflare Radar Remote MCP Server',
2126
version: '1.0.0',
2227
})
2328

@@ -30,6 +35,7 @@ export class RadarMCP extends McpAgent<Env, State, Props> {
3035

3136
async init() {
3237
registerRadarTools(this)
38+
// TODO registerUrlScannerTools(this)
3339
}
3440
}
3541

apps/radar/src/tools/radar.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import {
99
IpParam,
1010
SingleLocationParam,
1111
} from '../types/radar'
12-
import type { RadarMCP } from "../index";
12+
13+
import type { RadarMCP } from '../index'
1314

1415
export function registerRadarTools(agent: RadarMCP) {
1516
agent.server.tool(
16-
'radar_ases_list',
17+
'list_autonomous_systems',
1718
'List Autonomous Systems',
1819
{
1920
limit: PaginationLimitParam,
@@ -55,7 +56,7 @@ export function registerRadarTools(agent: RadarMCP) {
5556
)
5657

5758
agent.server.tool(
58-
'radar_as_details',
59+
'get_as_details',
5960
'Get Autonomous System details by ASN',
6061
{
6162
asn: AsnParam,
@@ -89,7 +90,7 @@ export function registerRadarTools(agent: RadarMCP) {
8990
)
9091

9192
agent.server.tool(
92-
'radar_ip_details',
93+
'get_ip_details',
9394
'Get IP address information',
9495
{
9596
ip: IpParam,
@@ -123,7 +124,7 @@ export function registerRadarTools(agent: RadarMCP) {
123124
)
124125

125126
agent.server.tool(
126-
'radar_get_traffic_anomalies',
127+
'get_traffic_anomalies',
127128
'Get traffic anomalies',
128129
{
129130
limit: PaginationLimitParam,
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { getCloudflareClient } from '@repo/mcp-common/src/cloudflare-api'
2+
3+
import { UrlParam } from '../types/url-scanner'
4+
5+
import type { RadarMCP } from '../index'
6+
7+
export function registerUrlScannerTools(agent: RadarMCP) {
8+
agent.server.tool(
9+
'scan_url',
10+
'Submit a URL to scan',
11+
{
12+
url: UrlParam,
13+
},
14+
async ({ url }) => {
15+
try {
16+
const accountId = '' // TODO agent.getActiveAccountId()
17+
const client = getCloudflareClient(agent.props.accessToken)
18+
const scanId = await client.urlScanner.scans.create({ account_id: accountId, url })
19+
20+
// TODO get scan...
21+
22+
return {
23+
content: [
24+
{
25+
type: 'text',
26+
text: JSON.stringify({
27+
result: scanId,
28+
}),
29+
},
30+
],
31+
}
32+
} catch (error) {
33+
return {
34+
content: [
35+
{
36+
type: 'text',
37+
text: `Error scanning URL: ${error instanceof Error && error.message}`,
38+
},
39+
],
40+
}
41+
}
42+
}
43+
)
44+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/**
2+
* This file contains the validators for the URL scanner tools.
3+
*/
4+
import { z } from 'zod'
5+
6+
export const UrlParam = z.string().url()

apps/radar/wrangler.jsonc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"kv_namespaces": [
5656
{
5757
"binding": "OAUTH_KV",
58-
"id": "a6ad24203a244d248f2fe1acfeb7b3a3"
58+
"id": "51342186c2f54c1d82946ffc35e74143"
5959
}
6060
],
6161
"vars": {
@@ -77,7 +77,7 @@
7777
"kv_namespaces": [
7878
{
7979
"binding": "OAUTH_KV",
80-
"id": "753f27a19ef94d7dbd49de05588ca890"
80+
"id": "5193d970c2cb43a28cc38d4d839b102e"
8181
}
8282
],
8383
"vars": {

0 commit comments

Comments
 (0)