diff --git a/client/src/components/ToolsTab.tsx b/client/src/components/ToolsTab.tsx index ee9a4f97d..82ebdb0b9 100644 --- a/client/src/components/ToolsTab.tsx +++ b/client/src/components/ToolsTab.tsx @@ -8,15 +8,15 @@ import { Textarea } from "@/components/ui/textarea"; import DynamicJsonForm, { JsonSchemaType, JsonValue } from "./DynamicJsonForm"; import { generateDefaultValue } from "@/utils/schemaUtils"; import { + CallToolResultSchema, + CompatibilityCallToolResult, ListToolsResult, Tool, - CallToolResultSchema, } from "@modelcontextprotocol/sdk/types.js"; import { AlertCircle, Send } from "lucide-react"; import { useEffect, useState } from "react"; import ListPane from "./ListPane"; - -import { CompatibilityCallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { escapeUnicode } from "@/utils/escapeUnicode"; const ToolsTab = ({ tools, @@ -54,7 +54,7 @@ const ToolsTab = ({ <>
- {JSON.stringify(toolResult, null, 2)}
+ {escapeUnicode(toolResult)}
- {JSON.stringify(item.resource, null, 2)}
+ {escapeUnicode(item.resource)}
))}
@@ -113,7 +113,7 @@ const ToolsTab = ({
<>
- {JSON.stringify(toolResult.toolResult, null, 2)}
+ {escapeUnicode(toolResult.toolResult)}
>
);
diff --git a/client/src/utils/__tests__/escapeUnicode.test.ts b/client/src/utils/__tests__/escapeUnicode.test.ts
new file mode 100644
index 000000000..b2eb130c5
--- /dev/null
+++ b/client/src/utils/__tests__/escapeUnicode.test.ts
@@ -0,0 +1,27 @@
+import { escapeUnicode } from "../escapeUnicode";
+
+describe("escapeUnicode", () => {
+ it("should escape Unicode characters in a string", () => {
+ const input = { text: "你好世界" };
+ const expected = '{\n "text": "\\\\u4f60\\\\u597d\\\\u4e16\\\\u754c"\n}';
+ expect(escapeUnicode(input)).toBe(expected);
+ });
+
+ it("should handle empty strings", () => {
+ const input = { text: "" };
+ const expected = '{\n "text": ""\n}';
+ expect(escapeUnicode(input)).toBe(expected);
+ });
+
+ it("should handle null and undefined values", () => {
+ const input = { text: null, value: undefined };
+ const expected = '{\n "text": null\n}';
+ expect(escapeUnicode(input)).toBe(expected);
+ });
+
+ it("should handle numbers and booleans", () => {
+ const input = { number: 123, boolean: true };
+ const expected = '{\n "number": 123,\n "boolean": true\n}';
+ expect(escapeUnicode(input)).toBe(expected);
+ });
+});
diff --git a/client/src/utils/escapeUnicode.ts b/client/src/utils/escapeUnicode.ts
new file mode 100644
index 000000000..ed6fbd930
--- /dev/null
+++ b/client/src/utils/escapeUnicode.ts
@@ -0,0 +1,16 @@
+// Utility function to escape Unicode characters
+export function escapeUnicode(obj: unknown): string {
+ return JSON.stringify(
+ obj,
+ (_key: string, value) => {
+ if (typeof value === "string") {
+ // Replace non-ASCII characters with their Unicode escape sequences
+ return value.replace(/[^\0-\x7F]/g, (char) => {
+ return "\\u" + ("0000" + char.charCodeAt(0).toString(16)).slice(-4);
+ });
+ }
+ return value;
+ },
+ 2,
+ );
+}
diff --git a/package-lock.json b/package-lock.json
index 21c9c3083..68929c522 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,6 +24,7 @@
"mcp-inspector": "bin/cli.js"
},
"devDependencies": {
+ "@types/jest": "^29.5.14",
"@types/node": "^22.7.5",
"@types/shell-quote": "^1.7.5",
"prettier": "3.3.3"
diff --git a/package.json b/package.json
index 3f40d2e6e..e3bce9216 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,7 @@
"ts-node": "^10.9.2"
},
"devDependencies": {
+ "@types/jest": "^29.5.14",
"@types/node": "^22.7.5",
"@types/shell-quote": "^1.7.5",
"prettier": "3.3.3"