Skip to content

Commit 22bf787

Browse files
committed
show server stderr in inspector UI
1 parent 9196c1d commit 22bf787

File tree

4 files changed

+85
-4
lines changed

4 files changed

+85
-4
lines changed

client/src/App.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,26 @@ import {
1212
ListPromptsResultSchema,
1313
ListResourcesResultSchema,
1414
ListResourceTemplatesResultSchema,
15+
Request,
1516
ListRootsRequestSchema,
1617
ListToolsResultSchema,
1718
ProgressNotificationSchema,
1819
ReadResourceResultSchema,
1920
Resource,
2021
ResourceTemplate,
22+
Result,
2123
Root,
2224
ServerNotification,
2325
Tool,
2426
} from "@modelcontextprotocol/sdk/types.js";
2527
import { useCallback, useEffect, useRef, useState } from "react";
28+
29+
import {
30+
StderrNotificationSchema,
31+
StdErrNotification,
32+
Notification,
33+
} from "./lib/notificationTypes";
34+
2635
// Add dark mode class based on system preference
2736
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
2837
document.documentElement.classList.add("dark");
@@ -87,6 +96,9 @@ const App = () => {
8796
>([]);
8897
const [mcpClient, setMcpClient] = useState<Client | null>(null);
8998
const [notifications, setNotifications] = useState<ServerNotification[]>([]);
99+
const [stdErrNotifications, setStdErrNotifications] = useState<
100+
StdErrNotification[]
101+
>([]);
90102
const [roots, setRoots] = useState<Root[]>([]);
91103
const [env, setEnv] = useState<Record<string, string>>({});
92104

@@ -383,7 +395,7 @@ const App = () => {
383395

384396
const connectMcpServer = async () => {
385397
try {
386-
const client = new Client(
398+
const client = new Client<Request, Notification, Result>(
387399
{
388400
name: "mcp-inspector",
389401
version: "0.0.1",
@@ -411,8 +423,6 @@ const App = () => {
411423
}
412424

413425
const clientTransport = new SSEClientTransport(backendUrl);
414-
await client.connect(clientTransport);
415-
416426
client.setNotificationHandler(
417427
ProgressNotificationSchema,
418428
(notification) => {
@@ -423,6 +433,18 @@ const App = () => {
423433
},
424434
);
425435

436+
client.setNotificationHandler(
437+
StderrNotificationSchema,
438+
(notification) => {
439+
setStdErrNotifications((prevErrorNotifications) => [
440+
...prevErrorNotifications,
441+
notification,
442+
]);
443+
},
444+
);
445+
446+
await client.connect(clientTransport);
447+
426448
client.setRequestHandler(CreateMessageRequestSchema, (request) => {
427449
return new Promise<CreateMessageResult>((resolve, reject) => {
428450
setPendingSampleRequests((prev) => [
@@ -459,6 +481,7 @@ const App = () => {
459481
env={env}
460482
setEnv={setEnv}
461483
onConnect={connectMcpServer}
484+
stdErrNotifications={stdErrNotifications}
462485
/>
463486
<div className="flex-1 flex flex-col overflow-hidden">
464487
<div className="flex-1 overflow-auto">

client/src/components/Sidebar.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
SelectTrigger,
1111
SelectValue,
1212
} from "@/components/ui/select";
13+
import { StdErrNotification } from "@/lib/notificationTypes";
1314

1415
interface SidebarProps {
1516
connectionStatus: "disconnected" | "connected" | "error";
@@ -24,6 +25,7 @@ interface SidebarProps {
2425
env: Record<string, string>;
2526
setEnv: (env: Record<string, string>) => void;
2627
onConnect: () => void;
28+
stdErrNotifications: StdErrNotification[];
2729
}
2830

2931
const Sidebar = ({
@@ -39,6 +41,7 @@ const Sidebar = ({
3941
env,
4042
setEnv,
4143
onConnect,
44+
stdErrNotifications,
4245
}: SidebarProps) => {
4346
const [showEnvVars, setShowEnvVars] = useState(false);
4447

@@ -187,6 +190,25 @@ const Sidebar = ({
187190
: "Disconnected"}
188191
</span>
189192
</div>
193+
{stdErrNotifications.length > 0 && (
194+
<>
195+
<div className="mt-4 border-t border-gray-200 pt-4">
196+
<h3 className="text-sm font-medium">
197+
Error output from MCP server
198+
</h3>
199+
<div className="mt-2 max-h-80 overflow-y-auto">
200+
{stdErrNotifications.map((notification, index) => (
201+
<div
202+
key={index}
203+
className="text-sm text-red-500 font-mono py-2 border-b border-gray-200 last:border-b-0"
204+
>
205+
{notification.params.content}
206+
</div>
207+
))}
208+
</div>
209+
</div>
210+
</>
211+
)}
190212
</div>
191213
</div>
192214
</div>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {
2+
ClientNotificationSchema,
3+
NotificationSchema as BaseNotificationSchema,
4+
} from "@modelcontextprotocol/sdk/types.js";
5+
import { z } from "zod";
6+
7+
export const StderrNotificationSchema = BaseNotificationSchema.extend({
8+
method: z.literal("notifications/stderr"),
9+
params: z.object({
10+
content: z.string(),
11+
}),
12+
});
13+
14+
export const NotificationSchema = ClientNotificationSchema.or(
15+
StderrNotificationSchema,
16+
);
17+
18+
export type StdErrNotification = z.infer<typeof StderrNotificationSchema>;
19+
export type Notification = z.infer<typeof NotificationSchema>;

server/src/index.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ const createTransport = async (query: express.Request["query"]) => {
4242
console.log(
4343
`Stdio transport: command=${command}, args=${args}, env=${JSON.stringify(env)}`,
4444
);
45-
const transport = new StdioClientTransport({ command, args, env });
45+
const transport = new StdioClientTransport({
46+
command,
47+
args,
48+
env,
49+
stderr: "pipe",
50+
});
4651
await transport.start();
4752
console.log("Spawned stdio transport");
4853
return transport;
@@ -75,6 +80,18 @@ app.get("/sse", async (req, res) => {
7580

7681
await webAppTransport.start();
7782

83+
if (backingServerTransport.stderr) {
84+
backingServerTransport.stderr.on("data", (chunk) => {
85+
webAppTransport.send({
86+
jsonrpc: "2.0",
87+
method: "notifications/stderr",
88+
params: {
89+
content: chunk.toString(),
90+
},
91+
});
92+
});
93+
}
94+
7895
mcpProxy({
7996
transportToClient: webAppTransport,
8097
transportToServer: backingServerTransport,

0 commit comments

Comments
 (0)