Skip to content

Commit eaa8055

Browse files
authored
Merge branch 'main' into fix-214
2 parents 1d4ca43 + 75537c7 commit eaa8055

File tree

10 files changed

+330
-111
lines changed

10 files changed

+330
-111
lines changed

client/src/App.tsx

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,6 @@ const PROXY_SERVER_URL = `http://${window.location.hostname}:${PROXY_PORT}`;
5252

5353
const App = () => {
5454
// Handle OAuth callback route
55-
if (window.location.pathname === "/oauth/callback") {
56-
const OAuthCallback = React.lazy(
57-
() => import("./components/OAuthCallback"),
58-
);
59-
return (
60-
<Suspense fallback={<div>Loading...</div>}>
61-
<OAuthCallback />
62-
</Suspense>
63-
);
64-
}
6555
const [resources, setResources] = useState<Resource[]>([]);
6656
const [resourceTemplates, setResourceTemplates] = useState<
6757
ResourceTemplate[]
@@ -114,22 +104,6 @@ const App = () => {
114104
const nextRequestId = useRef(0);
115105
const rootsRef = useRef<Root[]>([]);
116106

117-
const handleApproveSampling = (id: number, result: CreateMessageResult) => {
118-
setPendingSampleRequests((prev) => {
119-
const request = prev.find((r) => r.id === id);
120-
request?.resolve(result);
121-
return prev.filter((r) => r.id !== id);
122-
});
123-
};
124-
125-
const handleRejectSampling = (id: number) => {
126-
setPendingSampleRequests((prev) => {
127-
const request = prev.find((r) => r.id === id);
128-
request?.reject(new Error("Sampling request rejected"));
129-
return prev.filter((r) => r.id !== id);
130-
});
131-
};
132-
133107
const [selectedResource, setSelectedResource] = useState<Resource | null>(
134108
null,
135109
);
@@ -224,7 +198,7 @@ const App = () => {
224198
// Connect to the server
225199
connectMcpServer();
226200
}
227-
}, []);
201+
}, [connectMcpServer]);
228202

229203
useEffect(() => {
230204
fetch(`${PROXY_SERVER_URL}/config`)
@@ -253,6 +227,22 @@ const App = () => {
253227
}
254228
}, []);
255229

230+
const handleApproveSampling = (id: number, result: CreateMessageResult) => {
231+
setPendingSampleRequests((prev) => {
232+
const request = prev.find((r) => r.id === id);
233+
request?.resolve(result);
234+
return prev.filter((r) => r.id !== id);
235+
});
236+
};
237+
238+
const handleRejectSampling = (id: number) => {
239+
setPendingSampleRequests((prev) => {
240+
const request = prev.find((r) => r.id === id);
241+
request?.reject(new Error("Sampling request rejected"));
242+
return prev.filter((r) => r.id !== id);
243+
});
244+
};
245+
256246
const clearError = (tabKey: keyof typeof errors) => {
257247
setErrors((prev) => ({ ...prev, [tabKey]: null }));
258248
};
@@ -425,6 +415,17 @@ const App = () => {
425415
setLogLevel(level);
426416
};
427417

418+
if (window.location.pathname === "/oauth/callback") {
419+
const OAuthCallback = React.lazy(
420+
() => import("./components/OAuthCallback"),
421+
);
422+
return (
423+
<Suspense fallback={<div>Loading...</div>}>
424+
<OAuthCallback />
425+
</Suspense>
426+
);
427+
}
428+
428429
return (
429430
<div className="flex h-screen bg-background">
430431
<Sidebar

client/src/components/DynamicJsonForm.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,21 @@ const DynamicJsonForm = ({
108108
}
109109
};
110110

111+
const formatJson = () => {
112+
try {
113+
const jsonStr = rawJsonValue.trim();
114+
if (!jsonStr) {
115+
return;
116+
}
117+
const formatted = JSON.stringify(JSON.parse(jsonStr), null, 2);
118+
setRawJsonValue(formatted);
119+
debouncedUpdateParent(formatted);
120+
setJsonError(undefined);
121+
} catch (err) {
122+
setJsonError(err instanceof Error ? err.message : "Invalid JSON");
123+
}
124+
};
125+
111126
const renderFormFields = (
112127
propSchema: JsonSchemaType,
113128
currentValue: JsonValue,
@@ -353,7 +368,12 @@ const DynamicJsonForm = ({
353368

354369
return (
355370
<div className="space-y-4">
356-
<div className="flex justify-end">
371+
<div className="flex justify-end space-x-2">
372+
{isJsonMode && (
373+
<Button variant="outline" size="sm" onClick={formatJson}>
374+
Format JSON
375+
</Button>
376+
)}
357377
<Button variant="outline" size="sm" onClick={handleSwitchToFormMode}>
358378
{isJsonMode ? "Switch to Form" : "Switch to JSON"}
359379
</Button>

client/src/components/History.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ServerNotification } from "@modelcontextprotocol/sdk/types.js";
22
import { Copy } from "lucide-react";
33
import { useState } from "react";
4+
import JsonView from "./JsonView";
45

56
const HistoryAndNotifications = ({
67
requestHistory,
@@ -74,9 +75,9 @@ const HistoryAndNotifications = ({
7475
<Copy size={16} />
7576
</button>
7677
</div>
77-
<pre className="whitespace-pre-wrap break-words bg-background p-2 rounded">
78-
{JSON.stringify(JSON.parse(request.request), null, 2)}
79-
</pre>
78+
<div className="bg-background p-2 rounded">
79+
<JsonView data={request.request} />
80+
</div>
8081
</div>
8182
{request.response && (
8283
<div className="mt-2">
@@ -91,13 +92,9 @@ const HistoryAndNotifications = ({
9192
<Copy size={16} />
9293
</button>
9394
</div>
94-
<pre className="whitespace-pre-wrap break-words bg-background p-2 rounded">
95-
{JSON.stringify(
96-
JSON.parse(request.response),
97-
null,
98-
2,
99-
)}
100-
</pre>
95+
<div className="bg-background p-2 rounded">
96+
<JsonView data={request.response} />
97+
</div>
10198
</div>
10299
)}
103100
</>
@@ -146,9 +143,11 @@ const HistoryAndNotifications = ({
146143
<Copy size={16} />
147144
</button>
148145
</div>
149-
<pre className="whitespace-pre-wrap break-words bg-background p-2 rounded">
150-
{JSON.stringify(notification, null, 2)}
151-
</pre>
146+
<div className="bg-background p-2 rounded">
147+
<JsonView
148+
data={JSON.stringify(notification, null, 2)}
149+
/>
150+
</div>
152151
</div>
153152
)}
154153
</li>

client/src/components/JsonEditor.tsx

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import Editor from "react-simple-code-editor";
33
import Prism from "prismjs";
44
import "prismjs/components/prism-json";
55
import "prismjs/themes/prism.css";
6-
import { Button } from "@/components/ui/button";
76

87
interface JsonEditorProps {
98
value: string;
@@ -16,49 +15,25 @@ const JsonEditor = ({
1615
onChange,
1716
error: externalError,
1817
}: JsonEditorProps) => {
19-
const [editorContent, setEditorContent] = useState(value);
18+
const [editorContent, setEditorContent] = useState(value || "");
2019
const [internalError, setInternalError] = useState<string | undefined>(
2120
undefined,
2221
);
2322

2423
useEffect(() => {
25-
setEditorContent(value);
24+
setEditorContent(value || "");
2625
}, [value]);
2726

28-
const formatJson = (json: string): string => {
29-
try {
30-
return JSON.stringify(JSON.parse(json), null, 2);
31-
} catch {
32-
return json;
33-
}
34-
};
35-
3627
const handleEditorChange = (newContent: string) => {
3728
setEditorContent(newContent);
3829
setInternalError(undefined);
3930
onChange(newContent);
4031
};
4132

42-
const handleFormatJson = () => {
43-
try {
44-
const formatted = formatJson(editorContent);
45-
setEditorContent(formatted);
46-
onChange(formatted);
47-
setInternalError(undefined);
48-
} catch (err) {
49-
setInternalError(err instanceof Error ? err.message : "Invalid JSON");
50-
}
51-
};
52-
5333
const displayError = internalError || externalError;
5434

5535
return (
56-
<div className="relative space-y-2">
57-
<div className="flex justify-end">
58-
<Button variant="outline" size="sm" onClick={handleFormatJson}>
59-
Format JSON
60-
</Button>
61-
</div>
36+
<div className="relative">
6237
<div
6338
className={`border rounded-md ${
6439
displayError

0 commit comments

Comments
 (0)