Skip to content

Commit 9dbd5cc

Browse files
committed
* Remove handling of out-of-spec 'notification/stderr' messages. It's not a thing. See modelcontextprotocol/servers#2469
* Inspect the stderr output of STDIO servers and attempt to assign an appropriate RFC 5424 Syslog Protocol level before sending a leveled logging message to the client
1 parent 8a5a4e5 commit 9dbd5cc

File tree

5 files changed

+49
-77
lines changed

5 files changed

+49
-77
lines changed

client/src/App.tsx

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import {
3434
useDraggablePane,
3535
useDraggableSidebar,
3636
} from "./lib/hooks/useDraggablePane";
37-
import { StdErrNotification } from "./lib/notificationTypes";
3837

3938
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
4039
import { Button } from "@/components/ui/button";
@@ -106,9 +105,6 @@ const App = () => {
106105
>(getInitialTransportType);
107106
const [logLevel, setLogLevel] = useState<LoggingLevel>("debug");
108107
const [notifications, setNotifications] = useState<ServerNotification[]>([]);
109-
const [stdErrNotifications, setStdErrNotifications] = useState<
110-
StdErrNotification[]
111-
>([]);
112108
const [roots, setRoots] = useState<Root[]>([]);
113109
const [env, setEnv] = useState<Record<string, string>>({});
114110

@@ -224,12 +220,6 @@ const App = () => {
224220
onNotification: (notification) => {
225221
setNotifications((prev) => [...prev, notification as ServerNotification]);
226222
},
227-
onStdErrNotification: (notification) => {
228-
setStdErrNotifications((prev) => [
229-
...prev,
230-
notification as StdErrNotification,
231-
]);
232-
},
233223
onPendingRequest: (request, resolve, reject) => {
234224
setPendingSampleRequests((prev) => [
235225
...prev,
@@ -757,10 +747,6 @@ const App = () => {
757747
setLogLevel(level);
758748
};
759749

760-
const clearStdErrNotifications = () => {
761-
setStdErrNotifications([]);
762-
};
763-
764750
const AuthDebuggerWrapper = () => (
765751
<TabsContent value="auth">
766752
<AuthDebugger
@@ -829,11 +815,9 @@ const App = () => {
829815
setOauthScope={setOauthScope}
830816
onConnect={connectMcpServer}
831817
onDisconnect={disconnectMcpServer}
832-
stdErrNotifications={stdErrNotifications}
833818
logLevel={logLevel}
834819
sendLogLevelRequest={sendLogLevelRequest}
835820
loggingSupported={!!serverCapabilities?.logging || false}
836-
clearStdErrNotifications={clearStdErrNotifications}
837821
/>
838822
<div
839823
onMouseDown={handleSidebarDragStart}

client/src/components/Sidebar.tsx

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import {
2424
SelectTrigger,
2525
SelectValue,
2626
} from "@/components/ui/select";
27-
import { StdErrNotification } from "@/lib/notificationTypes";
2827
import {
2928
LoggingLevel,
3029
LoggingLevelSchema,
@@ -62,8 +61,6 @@ interface SidebarProps {
6261
setOauthScope: (scope: string) => void;
6362
onConnect: () => void;
6463
onDisconnect: () => void;
65-
stdErrNotifications: StdErrNotification[];
66-
clearStdErrNotifications: () => void;
6764
logLevel: LoggingLevel;
6865
sendLogLevelRequest: (level: LoggingLevel) => void;
6966
loggingSupported: boolean;
@@ -93,8 +90,6 @@ const Sidebar = ({
9390
setOauthScope,
9491
onConnect,
9592
onDisconnect,
96-
stdErrNotifications,
97-
clearStdErrNotifications,
9893
logLevel,
9994
sendLogLevelRequest,
10095
loggingSupported,
@@ -760,36 +755,6 @@ const Sidebar = ({
760755
</Select>
761756
</div>
762757
)}
763-
764-
{stdErrNotifications.length > 0 && (
765-
<>
766-
<div className="mt-4 border-t border-gray-200 pt-4">
767-
<div className="flex justify-between items-center">
768-
<h3 className="text-sm font-medium">
769-
Error output from MCP server
770-
</h3>
771-
<Button
772-
variant="outline"
773-
size="sm"
774-
onClick={clearStdErrNotifications}
775-
className="h-8 px-2"
776-
>
777-
Clear
778-
</Button>
779-
</div>
780-
<div className="mt-2 max-h-80 overflow-y-auto">
781-
{stdErrNotifications.map((notification, index) => (
782-
<div
783-
key={index}
784-
className="text-sm text-red-500 font-mono py-2 border-b border-gray-200 last:border-b-0"
785-
>
786-
{notification.params.content}
787-
</div>
788-
))}
789-
</div>
790-
</div>
791-
</>
792-
)}
793758
</div>
794759
</div>
795760
</div>

client/src/lib/hooks/useConnection.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import { useEffect, useState } from "react";
3636
import { useToast } from "@/lib/hooks/useToast";
3737
import { z } from "zod";
3838
import { ConnectionStatus } from "../constants";
39-
import { Notification, StdErrNotificationSchema } from "../notificationTypes";
39+
import { Notification } from "../notificationTypes";
4040
import {
4141
auth,
4242
discoverOAuthProtectedResourceMetadata,
@@ -92,7 +92,6 @@ export function useConnection({
9292
oauthScope,
9393
config,
9494
onNotification,
95-
onStdErrNotification,
9695
onPendingRequest,
9796
onElicitationRequest,
9897
getRoots,
@@ -505,13 +504,6 @@ export function useConnection({
505504
};
506505
}
507506

508-
if (onStdErrNotification) {
509-
client.setNotificationHandler(
510-
StdErrNotificationSchema,
511-
onStdErrNotification,
512-
);
513-
}
514-
515507
let capabilities;
516508
try {
517509
const transport =

client/src/lib/notificationTypes.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,8 @@ import {
55
} from "@modelcontextprotocol/sdk/types.js";
66
import { z } from "zod";
77

8-
export const StdErrNotificationSchema = BaseNotificationSchema.extend({
9-
method: z.literal("notifications/stderr"),
10-
params: z.object({
11-
content: z.string(),
12-
}),
13-
});
14-
158
export const NotificationSchema = ClientNotificationSchema.or(
16-
StdErrNotificationSchema,
17-
)
18-
.or(ServerNotificationSchema)
19-
.or(BaseNotificationSchema);
9+
ServerNotificationSchema,
10+
).or(BaseNotificationSchema);
2011

21-
export type StdErrNotification = z.infer<typeof StdErrNotificationSchema>;
2212
export type Notification = z.infer<typeof NotificationSchema>;

server/src/index.ts

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -401,24 +401,65 @@ app.get(
401401

402402
(serverTransport as StdioClientTransport).stderr!.on("data", (chunk) => {
403403
if (chunk.toString().includes("MODULE_NOT_FOUND")) {
404+
// Server command not found, remove transports
405+
const message = "Command not found, transports removed";
404406
webAppTransport.send({
405407
jsonrpc: "2.0",
406-
method: "notifications/stderr",
408+
method: "notifications/message",
407409
params: {
408-
content: "Command not found, transports removed",
410+
level: "alert",
411+
data: {
412+
error: message,
413+
},
409414
},
410415
});
411416
webAppTransport.close();
412417
serverTransport.close();
413418
webAppTransports.delete(webAppTransport.sessionId);
414419
serverTransports.delete(webAppTransport.sessionId);
415-
console.error("Command not found, transports removed");
420+
console.error(message);
416421
} else {
422+
// Inspect message and attempt to assign a RFC 5424 Syslog Protocol level
423+
let level;
424+
let message = chunk.toString();
425+
let ucMsg = chunk.toString().toUpperCase();
426+
if (ucMsg.includes("DEBUG")) {
427+
level = "debug";
428+
} else if (ucMsg.includes("INFO")) {
429+
level = "info";
430+
} else if (ucMsg.includes("NOTICE")) {
431+
level = "notice";
432+
} else if (ucMsg.includes("WARN")) {
433+
level = "warning";
434+
} else if (ucMsg.includes("ERROR")) {
435+
level = "error";
436+
} else if (ucMsg.includes("CRITICAL")) {
437+
level = "critical";
438+
} else if (ucMsg.includes("ALERT")) {
439+
level = "alert";
440+
} else if (ucMsg.includes("EMERGENCY")) {
441+
level = "emergency";
442+
} else if (ucMsg.includes("SIGINT")) {
443+
level = "alert";
444+
message = "SIGINT received. Server shutdown.";
445+
} else if (ucMsg.includes("SIGHUP")) {
446+
level = "alert";
447+
message = "SIGHUP received. Server shutdown.";
448+
} else if (ucMsg.includes("SIGTERM")) {
449+
level = "alert";
450+
message = "SIGTERM received. Server shutdown.";
451+
} else {
452+
level = "info";
453+
}
417454
webAppTransport.send({
418455
jsonrpc: "2.0",
419-
method: "notifications/stderr",
456+
method: "notifications/message",
420457
params: {
421-
content: chunk.toString(),
458+
level,
459+
logger: "stdio",
460+
data: {
461+
error: message,
462+
},
422463
},
423464
});
424465
}

0 commit comments

Comments
 (0)