feat: Handle MCP server notification messages (#2613)

Co-authored-by: Michael Neale <michael.neale@gmail.com>
This commit is contained in:
Jack Amadeo
2025-05-30 11:50:14 -04:00
committed by GitHub
parent eeb61ace22
commit 03e5549b54
40 changed files with 1186 additions and 443 deletions
+28 -1
View File
@@ -6,11 +6,25 @@ import { Message, createUserMessage, hasCompletedToolCalls } from '../types/mess
// Ensure TextDecoder is available in the global scope
const TextDecoder = globalThis.TextDecoder;
type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };
export interface NotificationEvent {
type: 'Notification';
request_id: string;
message: {
method: string;
params: {
[key: string]: JsonValue;
};
};
}
// Event types for SSE stream
type MessageEvent =
| { type: 'Message'; message: Message }
| { type: 'Error'; error: string }
| { type: 'Finish'; reason: string };
| { type: 'Finish'; reason: string }
| NotificationEvent;
export interface UseMessageStreamOptions {
/**
@@ -124,6 +138,8 @@ export interface UseMessageStreamHelpers {
/** Modify body (session id and/or work dir mid-stream) **/
updateMessageStreamBody?: (newBody: object) => void;
notifications: NotificationEvent[];
}
/**
@@ -151,6 +167,8 @@ export function useMessageStream({
fallbackData: initialMessages,
});
const [notifications, setNotifications] = useState<NotificationEvent[]>([]);
// expose a way to update the body so we can update the session id when CLE occurs
const updateMessageStreamBody = useCallback((newBody: object) => {
extraMetadataRef.current.body = {
@@ -247,6 +265,14 @@ export function useMessageStream({
break;
}
case 'Notification': {
const newNotification = {
...parsedEvent,
};
setNotifications((prev) => [...prev, newNotification]);
break;
}
case 'Error':
throw new Error(parsedEvent.error);
@@ -516,5 +542,6 @@ export function useMessageStream({
isLoading: isLoading || false,
addToolResult,
updateMessageStreamBody,
notifications,
};
}