Skip to content

Commit 10ff032

Browse files
committed
Fix up wrangler.json, add dev handler, and new createApiHandler for dealing with SSE + Streamable HTTP
1 parent 1f0b186 commit 10ff032

File tree

4 files changed

+46
-35
lines changed

4 files changed

+46
-35
lines changed

apps/logpush/src/context.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ export interface Env {
66
ENVIRONMENT: 'development' | 'staging' | 'production'
77
MCP_SERVER_NAME: string
88
MCP_SERVER_VERSION: string
9-
CLOUDFLARE_ACCESS_TOKEN: string
109
CLOUDFLARE_CLIENT_ID: string
1110
CLOUDFLARE_CLIENT_SECRET: string
1211
MCP_OBJECT: DurableObjectNamespace<LogsMCP>
1312
USER_DETAILS: DurableObjectNamespace<UserDetails>
1413
MCP_METRICS: AnalyticsEngineDataset
14+
DEV_DISABLE_OAUTH: string
15+
DEV_CLOUDFLARE_API_TOKEN: string
16+
DEV_CLOUDFLARE_EMAIL: string
1517
}

apps/logpush/src/index.ts

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import OAuthProvider from '@cloudflare/workers-oauth-provider'
22
import { McpAgent } from 'agents/mcp'
33

4+
import { createApiHandler } from '@repo/mcp-common/src/api-handler'
45
import {
56
createAuthHandlers,
67
handleTokenExchangeCallback,
78
} from '@repo/mcp-common/src/cloudflare-oauth-handler'
9+
import { handleDevMode } from '@repo/mcp-common/src/dev-mode'
810
import { getUserDetails, UserDetails } from '@repo/mcp-common/src/durable-objects/user_details'
911
import { getEnv } from '@repo/mcp-common/src/env'
1012
import { RequiredScopes } from '@repo/mcp-common/src/scopes'
@@ -14,7 +16,7 @@ import { registerAccountTools } from '@repo/mcp-common/src/tools/account'
1416
import { MetricsTracker } from '../../../packages/mcp-observability/src'
1517
import { registerLogsTools } from './tools/logs'
1618

17-
import type { AccountSchema, UserSchema } from '@repo/mcp-common/src/cloudflare-oauth-handler'
19+
import type { AuthProps } from '@repo/mcp-common/src/cloudflare-oauth-handler'
1820
import type { Env } from './context'
1921

2022
const env = getEnv<Env>()
@@ -28,14 +30,8 @@ const metrics = new MetricsTracker(env.MCP_METRICS, {
2830

2931
// Context from the auth process, encrypted & stored in the auth token
3032
// and provided to the DurableMCP as this.props
31-
export type Props = {
32-
accessToken: string
33-
apiToken: string
34-
user: UserSchema['result']
35-
accounts: AccountSchema['result']
36-
}
37-
38-
export type State = { activeAccountId: string | null }
33+
type Props = AuthProps
34+
type State = { activeAccountId: string | null }
3935

4036
export class LogsMCP extends McpAgent<Env, State, Props> {
4137
_server: CloudflareMCPServer | undefined
@@ -67,7 +63,7 @@ export class LogsMCP extends McpAgent<Env, State, Props> {
6763
registerAccountTools(this)
6864

6965
// Register Cloudflare Log Push tools
70-
registerLogsTools(this, env.CLOUDFLARE_ACCESS_TOKEN)
66+
registerLogsTools(this)
7167
}
7268

7369
async getActiveAccountId() {
@@ -99,16 +95,28 @@ const LogPushScopes = {
9995
'Grants read and write access to Logpull and Logpush, and read access to Instant Logs. Note that all Logpush API operations require Logs: Write permission because Logpush jobs contain sensitive information.',
10096
} as const
10197

102-
export default new OAuthProvider({
103-
apiRoute: '/sse',
104-
apiHandler: LogsMCP.mount('/sse'),
105-
// @ts-ignore
106-
defaultHandler: createAuthHandlers({ scopes: LogPushScopes, metrics }),
107-
authorizeEndpoint: '/oauth/authorize',
108-
tokenEndpoint: '/token',
109-
tokenExchangeCallback: (options) =>
110-
handleTokenExchangeCallback(options, env.CLOUDFLARE_CLIENT_ID, env.CLOUDFLARE_CLIENT_SECRET),
111-
// Cloudflare access token TTL
112-
accessTokenTTL: 3600,
113-
clientRegistrationEndpoint: '/register',
114-
})
98+
export default {
99+
fetch: async (req: Request, env: Env, ctx: ExecutionContext) => {
100+
if (env.ENVIRONMENT === 'development' && env.DEV_DISABLE_OAUTH === 'true') {
101+
return await handleDevMode(LogsMCP, req, env, ctx)
102+
}
103+
104+
return new OAuthProvider({
105+
apiRoute: ['/mcp', '/sse'],
106+
apiHandler: createApiHandler(LogsMCP),
107+
// @ts-ignore
108+
defaultHandler: createAuthHandlers({ scopes: LogPushScopes, metrics }),
109+
authorizeEndpoint: '/oauth/authorize',
110+
tokenEndpoint: '/token',
111+
tokenExchangeCallback: (options) =>
112+
handleTokenExchangeCallback(
113+
options,
114+
env.CLOUDFLARE_CLIENT_ID,
115+
env.CLOUDFLARE_CLIENT_SECRET
116+
),
117+
// Cloudflare access token TTL
118+
accessTokenTTL: 3600,
119+
clientRegistrationEndpoint: '/register',
120+
}).fetch(req, env, ctx)
121+
},
122+
}

apps/logpush/src/tools/logs.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ const zJobIdentifier = z.number().int().min(1).optional().describe('Unique id of
88
const zEnabled = z.boolean().optional().describe('Flag that indicates if the job is enabled.')
99
const zName = z
1010
.string()
11-
.regex(/^[a-zA-Z0-9\-\.]*$/)
11+
.regex(/^[a-zA-Z0-9\-.]*$/)
1212
.max(512)
1313
.nullable()
1414
.optional()
1515
.describe('Optional human readable job name. Not unique.')
1616
const zDataset = z
1717
.string()
18-
.regex(/^[a-zA-Z0-9_\-]*$/)
18+
.regex(/^[a-zA-Z0-9_-]*$/)
1919
.max(256)
2020
.nullable()
2121
.optional()
@@ -90,7 +90,7 @@ export async function handleGetAccountLogPushJobs(
9090
})
9191

9292
const res = data as z.infer<typeof zLogpushJobResponseCollection>
93-
return res.result?.slice(0, 100) || []
93+
return (res.result ?? []).slice(0, 100)
9494
}
9595

9696
/**
@@ -99,7 +99,7 @@ export async function handleGetAccountLogPushJobs(
9999
* @param accountId Cloudflare account ID
100100
* @param apiToken Cloudflare API token
101101
*/
102-
export function registerLogsTools(agent: LogsMCP, devToken: string) {
102+
export function registerLogsTools(agent: LogsMCP) {
103103
// Register the worker logs analysis tool by worker name
104104
agent.server.tool(
105105
'logpush_jobs_by_account_id',
@@ -125,8 +125,7 @@ export function registerLogsTools(agent: LogsMCP, devToken: string) {
125125
}
126126
}
127127
try {
128-
const token = devToken.length > 0 ? devToken : agent.props.accessToken
129-
const result = await handleGetAccountLogPushJobs(accountId, token)
128+
const result = await handleGetAccountLogPushJobs(accountId, agent.props.accessToken)
130129
return {
131130
content: [
132131
{

apps/logpush/wrangler.jsonc

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"name": "mcp-cloudflare-logpush-dev",
1111
"migrations": [
1212
{
13-
"new_sqlite_classes": ["UserDetails", "LogsMCP"],
13+
"new_sqlite_classes": ["LogsMCP"],
1414
"tag": "v1"
1515
}
1616
],
@@ -66,13 +66,14 @@
6666
},
6767
{
6868
"class_name": "UserDetails",
69-
"name": "USER_DETAILS"
69+
"name": "USER_DETAILS",
70+
"script_name": "mcp-cloudflare-workers-observability-staging"
7071
}
7172
]
7273
},
7374
"kv_namespaces": [
7475
{
75-
"binding": "OAUTH_KV_LOGPUSH_STAGING",
76+
"binding": "OAUTH_KV",
7677
"id": "3804747ed31344cca8e4ebecd255e417"
7778
}
7879
],
@@ -100,13 +101,14 @@
100101
},
101102
{
102103
"class_name": "UserDetails",
103-
"name": "USER_DETAILS"
104+
"name": "USER_DETAILS",
105+
"script_name": "mcp-cloudflare-workers-observability-production"
104106
}
105107
]
106108
},
107109
"kv_namespaces": [
108110
{
109-
"binding": "OAUTH_KV_LOGPUSH_PRODUCTION",
111+
"binding": "OAUTH_KV",
110112
"id": "400ff7a67c824f9698f9e5c25bf51a1c"
111113
}
112114
],

0 commit comments

Comments
 (0)