Skip to content

Commit 7f3f206

Browse files
seer-by-sentry[bot]cursoragentkentcdodds
authored
fix(mcp): Notification API (#486)
* Notification API refactor * fix: update notification calls to match MCP logging schema - Changed notification method signature from topic/payload to object with method/params - Added required 'level' field to all notifications/message calls - Set appropriate log levels: warning for timeout, error for failures, info for success - Fixed TypeScript errors by using correct notification object structure Co-authored-by: me <me@kentcdodds.com> --------- Co-authored-by: seer-by-sentry[bot] <157164994+seer-by-sentry[bot]@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: me <me@kentcdodds.com>
1 parent e87a578 commit 7f3f206

1 file changed

Lines changed: 41 additions & 37 deletions

File tree

packages/workshop-mcp/src/tools.ts

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -252,16 +252,17 @@ export function initTools(server: McpServer) {
252252
name: z.string().nullable().optional(),
253253
})
254254

255-
const timeout = setTimeout(() => {
256-
void server.server
257-
.notification({
258-
method: 'notification',
259-
params: {
260-
message: 'Device authorization timed out',
261-
},
262-
})
263-
.catch(() => {})
264-
}, deviceResponse.expires_in * 1000)
255+
const timeout = setTimeout(() => {
256+
void server.server
257+
.notification({
258+
method: 'notifications/message',
259+
params: {
260+
level: 'warning',
261+
data: 'Device authorization timed out',
262+
},
263+
})
264+
.catch(() => {})
265+
}, deviceResponse.expires_in * 1000)
265266

266267
try {
267268
const tokenSet = await client.pollDeviceAuthorizationGrant(
@@ -270,15 +271,16 @@ export function initTools(server: McpServer) {
270271
)
271272
clearTimeout(timeout)
272273

273-
if (!tokenSet) {
274-
await server.server.notification({
275-
method: 'notification',
276-
params: {
277-
message: 'No token set',
278-
},
279-
})
280-
return
281-
}
274+
if (!tokenSet) {
275+
await server.server.notification({
276+
method: 'notifications/message',
277+
params: {
278+
level: 'error',
279+
data: 'No token set',
280+
},
281+
})
282+
return
283+
}
282284

283285
const protectedResourceResponse = await client.fetchProtectedResource(
284286
config,
@@ -287,16 +289,17 @@ export function initTools(server: McpServer) {
287289
'GET',
288290
)
289291
const userinfoRaw = await protectedResourceResponse.json()
290-
const userinfoResult = UserInfoSchema.safeParse(userinfoRaw)
291-
if (!userinfoResult.success) {
292-
await server.server.notification({
293-
method: 'notification',
294-
params: {
295-
message: `Failed to parse user info: ${userinfoResult.error.message}`,
296-
},
297-
})
298-
return
299-
}
292+
const userinfoResult = UserInfoSchema.safeParse(userinfoRaw)
293+
if (!userinfoResult.success) {
294+
await server.server.notification({
295+
method: 'notifications/message',
296+
params: {
297+
level: 'error',
298+
data: `Failed to parse user info: ${userinfoResult.error.message}`,
299+
},
300+
})
301+
return
302+
}
300303
const userinfo = userinfoResult.data
301304

302305
await setAuthInfo({
@@ -306,15 +309,16 @@ export function initTools(server: McpServer) {
306309
name: userinfo.name,
307310
})
308311

309-
await getUserInfo({ forceFresh: true })
312+
await getUserInfo({ forceFresh: true })
310313

311-
await server.server.notification({
312-
method: 'notification',
313-
params: {
314-
message: 'Authentication successful',
315-
},
316-
})
317-
} catch (error) {
314+
await server.server.notification({
315+
method: 'notifications/message',
316+
params: {
317+
level: 'info',
318+
data: 'Authentication successful',
319+
},
320+
})
321+
} catch (error) {
318322
clearTimeout(timeout)
319323
throw error
320324
}

0 commit comments

Comments
 (0)