Skip to content

Commit 32b482e

Browse files
committed
Add sentry client to CloudflareMCPServer
1 parent 616322c commit 32b482e

File tree

17 files changed

+338
-53
lines changed

17 files changed

+338
-53
lines changed

apps/docs-autorag/src/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ export type Props = never
1515
export type State = never
1616

1717
export class CloudflareDocumentationMCP extends McpAgent<Env, State, Props> {
18-
server = new CloudflareMCPServer(undefined, env.MCP_METRICS, {
19-
name: env.MCP_SERVER_NAME,
20-
version: env.MCP_SERVER_VERSION,
18+
server = new CloudflareMCPServer({
19+
wae: env.MCP_METRICS,
20+
serverInfo: {
21+
name: env.MCP_SERVER_NAME,
22+
version: env.MCP_SERVER_VERSION,
23+
},
2124
})
2225

2326
constructor(

apps/sandbox-container/server/containerMcp.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ export class ContainerMcpAgent extends McpAgent<Env, {}, Props> {
5252

5353
async init() {
5454
this.props.user.id
55-
this.server = new CloudflareMCPServer(
56-
this.props.user.id,
57-
this.env.MCP_METRICS,
58-
{
55+
this.server = new CloudflareMCPServer({
56+
userId: this.props.user.id,
57+
wae: this.env.MCP_METRICS,
58+
serverInfo: {
5959
name: this.env.MCP_SERVER_NAME,
6060
version: this.env.MCP_SERVER_VERSION,
6161
},
62-
{ instructions: BASE_INSTRUCTIONS }
63-
)
62+
options: { instructions: BASE_INSTRUCTIONS },
63+
})
6464

6565
this.server.tool(
6666
'container_initialize',

apps/workers-bindings/src/index.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,13 @@ export class WorkersBindingsMCP extends McpAgent<Env, WorkersBindingsMCPState, P
5757
}
5858

5959
async init() {
60-
this.server = new CloudflareMCPServer(this.props.user.id, this.env.MCP_METRICS, {
61-
name: this.env.MCP_SERVER_NAME,
62-
version: this.env.MCP_SERVER_VERSION,
60+
this.server = new CloudflareMCPServer({
61+
userId: this.props.user.id,
62+
wae: this.env.MCP_METRICS,
63+
serverInfo: {
64+
name: this.env.MCP_SERVER_NAME,
65+
version: this.env.MCP_SERVER_VERSION,
66+
},
6367
})
6468

6569
registerAccountTools(this)

apps/workers-observability/src/context.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ export interface Env {
99
CLOUDFLARE_CLIENT_SECRET: 'PLACEHOLDER'
1010
MCP_OBJECT: DurableObjectNamespace<ObservabilityMCP>
1111
MCP_METRICS: AnalyticsEngineDataset
12+
SENTRY_ACCESS_CLIENT_ID: 'PLACEHOLDER'
13+
SENTRY_ACCESS_CLIENT_SECRET: 'PLACEHOLDER'
14+
GIT_HASH: 'OVERRIDEN_DURING_DEPLOYMENT'
15+
SENTRY_DSN: 'PLACEHOLDER'
1216
}

apps/workers-observability/src/index.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
handleTokenExchangeCallback,
77
} from '@repo/mcp-common/src/cloudflare-oauth-handler'
88
import { getEnv } from '@repo/mcp-common/src/env'
9+
import { initSentryWithUser } from '@repo/mcp-common/src/sentry'
910
import { CloudflareMCPServer } from '@repo/mcp-common/src/server'
1011
import { registerAccountTools } from '@repo/mcp-common/src/tools/account'
1112
import { registerWorkersTools } from '@repo/mcp-common/src/tools/worker'
@@ -38,7 +39,6 @@ export class ObservabilityMCP extends McpAgent<Env, State, Props> {
3839
set server(server: CloudflareMCPServer) {
3940
this._server = server
4041
}
41-
4242
get server(): CloudflareMCPServer {
4343
if (!this._server) {
4444
throw new Error('Tried to access server before it was initialized')
@@ -47,18 +47,19 @@ export class ObservabilityMCP extends McpAgent<Env, State, Props> {
4747
return this._server
4848
}
4949

50-
initialState: State = {
51-
activeAccountId: null,
52-
}
53-
5450
constructor(ctx: DurableObjectState, env: Env) {
5551
super(ctx, env)
5652
}
5753

5854
async init() {
59-
this.server = new CloudflareMCPServer(this.props.user.id, this.env.MCP_METRICS, {
60-
name: this.env.MCP_SERVER_NAME,
61-
version: this.env.MCP_SERVER_VERSION,
55+
this.server = new CloudflareMCPServer({
56+
userId: this.props.user.id,
57+
wae: this.env.MCP_METRICS,
58+
serverInfo: {
59+
name: this.env.MCP_SERVER_NAME,
60+
version: this.env.MCP_SERVER_VERSION,
61+
},
62+
sentry: initSentryWithUser(env, this.ctx, this.props.user.id),
6263
})
6364

6465
registerAccountTools(this)
@@ -75,6 +76,7 @@ export class ObservabilityMCP extends McpAgent<Env, State, Props> {
7576
try {
7677
return this.state.activeAccountId ?? null
7778
} catch (e) {
79+
this.server.recordError(e)
7880
return null
7981
}
8082
}
@@ -87,6 +89,7 @@ export class ObservabilityMCP extends McpAgent<Env, State, Props> {
8789
activeAccountId: accountId,
8890
})
8991
} catch (e) {
92+
this.server.recordError(e)
9093
return null
9194
}
9295
}

apps/workers-observability/src/tools/logs.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,14 @@ export function registerLogsTools(agent: ObservabilityMCP) {
161161
},
162162
],
163163
}
164-
} catch (error) {
164+
} catch (e) {
165+
agent.server.recordError(e)
165166
return {
166167
content: [
167168
{
168169
type: 'text',
169170
text: JSON.stringify({
170-
error: `Error analyzing worker logs: ${error instanceof Error && error.message}`,
171+
error: `Error analyzing worker logs: ${e instanceof Error && e.message}`,
171172
}),
172173
},
173174
],
@@ -225,13 +226,14 @@ export function registerLogsTools(agent: ObservabilityMCP) {
225226
},
226227
],
227228
}
228-
} catch (error) {
229+
} catch (e) {
230+
agent.server.recordError(e)
229231
return {
230232
content: [
231233
{
232234
type: 'text',
233235
text: JSON.stringify({
234-
error: `Error analyzing logs by Ray ID: ${error instanceof Error && error.message}`,
236+
error: `Error analyzing logs by Ray ID: ${e instanceof Error && e.message}`,
235237
}),
236238
},
237239
],
@@ -290,13 +292,14 @@ export function registerLogsTools(agent: ObservabilityMCP) {
290292
},
291293
],
292294
}
293-
} catch (error) {
295+
} catch (e) {
296+
agent.server.recordError(e)
294297
return {
295298
content: [
296299
{
297300
type: 'text',
298301
text: JSON.stringify({
299-
error: `Error retrieving worker telemetry keys: ${error instanceof Error && error.message}`,
302+
error: `Error retrieving worker telemetry keys: ${e instanceof Error && e.message}`,
300303
}),
301304
},
302305
],

apps/workers-observability/wrangler.jsonc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@
6969
}
7070
],
7171
"vars": {
72-
"ENVIRONMENT": "staging"
72+
"ENVIRONMENT": "staging",
73+
"GIT_HASH": "OVERRIDEN_DURING_DEPLOYMENT",
74+
"SENTRY_DSN": "https://[email protected]/1764",
75+
"MCP_SERVER_NAME": "workers-staging-observability",
76+
"MCP_SERVER_VERSION": "1.0.0"
7377
},
7478
"analytics_engine_datasets": [
7579
{
@@ -97,7 +101,11 @@
97101
}
98102
],
99103
"vars": {
100-
"ENVIRONMENT": "production"
104+
"ENVIRONMENT": "production",
105+
"GIT_HASH": "OVERRIDEN_DURING_DEPLOYMENT",
106+
"SENTRY_DSN": "https://[email protected]/1764",
107+
"MCP_SERVER_NAME": "workers-observability",
108+
"MCP_SERVER_VERSION": "1.0.0"
101109
},
102110
"analytics_engine_datasets": [
103111
{

packages/mcp-common/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"agents": "0.0.62",
1919
"cloudflare": "4.2.0",
2020
"hono": "4.7.6",
21+
"toucan-js": "^4.1.1",
2122
"zod": "3.24.2"
2223
},
2324
"devDependencies": {
@@ -26,6 +27,7 @@
2627
"@repo/tools": "workspace:*",
2728
"@repo/typescript-config": "workspace:*",
2829
"@types/node": "22.14.1",
30+
"@sentry/types": "8.9.2",
2931
"@vitest/ui": "3.0.9",
3032
"vitest": "3.0.9",
3133
"wrangler": "4.10.0"

packages/mcp-common/src/cloudflare-auth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export async function getAuthToken({
154154

155155
if (!resp.ok) {
156156
console.log(await resp.text())
157-
throw new McpError('Failed to get OAuth token', 500)
157+
throw new McpError('Failed to get OAuth token', 500, { reportToSentry: true })
158158
}
159159

160160
return AuthorizationToken.parse(await resp.json())
@@ -185,7 +185,7 @@ export async function refreshAuthToken({
185185
})
186186
if (!resp.ok) {
187187
console.log(await resp.text())
188-
throw new McpError('Failed to get OAuth token', 500)
188+
throw new McpError('Failed to get OAuth token', 500, { reportToSentry: true })
189189
}
190190

191191
return AuthorizationToken.parse(await resp.json())

packages/mcp-common/src/cloudflare-oauth-handler.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { z } from 'zod'
55
import { AuthUser } from '../../mcp-observability/src'
66
import { getAuthorizationURL, getAuthToken, refreshAuthToken } from './cloudflare-auth'
77
import { McpError } from './mcp-error'
8+
import { useSentry } from './sentry'
89

910
import type {
1011
OAuthHelpers,
@@ -13,14 +14,15 @@ import type {
1314
} from '@cloudflare/workers-oauth-provider'
1415
import type { Context } from 'hono'
1516
import type { MetricsTracker } from '../../mcp-observability/src'
17+
import type { BaseHonoContext } from './sentry'
1618

1719
type AuthContext = {
1820
Bindings: {
1921
OAUTH_PROVIDER: OAuthHelpers
2022
CLOUDFLARE_CLIENT_ID: string
2123
CLOUDFLARE_CLIENT_SECRET: string
2224
}
23-
}
25+
} & BaseHonoContext
2426

2527
const AuthRequestSchema = z.object({
2628
responseType: z.string(),
@@ -94,11 +96,11 @@ async function getTokenAndUser(
9496

9597
if (!userResponse.ok) {
9698
console.log(await userResponse.text())
97-
throw new McpError('Failed to fetch user', 500)
99+
throw new McpError('Failed to fetch user', 500, { reportToSentry: true })
98100
}
99101
if (!accountsResponse.ok) {
100102
console.log(await accountsResponse.text())
101-
throw new McpError('Failed to fetch accounts', 500)
103+
throw new McpError('Failed to fetch accounts', 500, { reportToSentry: true })
102104
}
103105

104106
// Fetch the user & accounts info from Cloudflare
@@ -153,6 +155,9 @@ export function createAuthHandlers({
153155
}) {
154156
{
155157
const app = new Hono<AuthContext>()
158+
app.use(useSentry)
159+
// TODO: Add useOnError middleware rather than handling errors in each handler
160+
// app.onError(useOnError)
156161
/**
157162
* OAuth Authorization Endpoint
158163
*
@@ -178,6 +183,7 @@ export function createAuthHandlers({
178183

179184
return Response.redirect(res.authUrl, 302)
180185
} catch (e) {
186+
c.var.sentry?.recordError(e)
181187
if (e instanceof Error) {
182188
metrics.logEvent(
183189
new AuthUser({
@@ -254,6 +260,7 @@ export function createAuthHandlers({
254260

255261
return Response.redirect(redirectTo, 302)
256262
} catch (e) {
263+
c.var.sentry?.recordError(e)
257264
if (e instanceof Error) {
258265
console.error(e)
259266
metrics.logEvent(

0 commit comments

Comments
 (0)