Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions client/jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,17 @@ module.exports = {
tsconfig: "tsconfig.jest.json",
},
],
"^.+\\.m?js$": [
"ts-jest",
{
tsconfig: "tsconfig.jest.json",
},
],
},
extensionsToTreatAsEsm: [".ts", ".tsx"],
transformIgnorePatterns: [
"node_modules/(?!(@modelcontextprotocol)/)",
],
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
// Exclude directories and files that don't need to be tested
testPathIgnorePatterns: [
Expand Down
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"cleanup:e2e": "node e2e/global-teardown.js"
},
"dependencies": {
"@modelcontextprotocol/ext-apps": "^1.0.0",
"@modelcontextprotocol/sdk": "^1.25.2",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-dialog": "^1.1.3",
Expand Down
55 changes: 51 additions & 4 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import {
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import {
AppWindow,
Bell,
Files,
FolderTree,
Expand All @@ -75,6 +76,7 @@ import SamplingTab, { PendingRequest } from "./components/SamplingTab";
import Sidebar from "./components/Sidebar";
import ToolsTab from "./components/ToolsTab";
import TasksTab from "./components/TasksTab";
import AppsTab from "./components/AppsTab";
import { InspectorConfig } from "./lib/configurationTypes";
import {
getMCPProxyAddress,
Expand Down Expand Up @@ -308,11 +310,13 @@ const App = () => {
...(serverCapabilities?.prompts ? ["prompts"] : []),
...(serverCapabilities?.tools ? ["tools"] : []),
...(serverCapabilities?.tasks ? ["tasks"] : []),
"apps",
"ping",
"sampling",
"elicitations",
"roots",
"auth",
"metadata",
];

if (!validTabs.includes(originatingTab)) return;
Expand Down Expand Up @@ -440,11 +444,13 @@ const App = () => {
...(serverCapabilities?.prompts ? ["prompts"] : []),
...(serverCapabilities?.tools ? ["tools"] : []),
...(serverCapabilities?.tasks ? ["tasks"] : []),
"apps",
"ping",
"sampling",
"elicitations",
"roots",
"auth",
"metadata",
];

const isValidTab = validTabs.includes(hash);
Expand Down Expand Up @@ -473,6 +479,13 @@ const App = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mcpClient, activeTab]);

useEffect(() => {
if (mcpClient && activeTab === "apps" && serverCapabilities?.tools) {
void listTools();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mcpClient, activeTab, serverCapabilities?.tools]);

useEffect(() => {
localStorage.setItem("lastCommand", command);
}, [command]);
Expand Down Expand Up @@ -757,11 +770,13 @@ const App = () => {
...(serverCapabilities?.prompts ? ["prompts"] : []),
...(serverCapabilities?.tools ? ["tools"] : []),
...(serverCapabilities?.tasks ? ["tasks"] : []),
"apps",
"ping",
"sampling",
"elicitations",
"roots",
"auth",
"metadata",
];

if (validTabs.includes(originatingTab)) {
Expand Down Expand Up @@ -851,6 +866,7 @@ const App = () => {
};

const readResource = async (uri: string) => {
console.log("[App] Reading resource:", uri);
lastToolCallOriginTabRef.current = currentTabRef.current;

const response = await sendMCPRequest(
Expand All @@ -861,12 +877,25 @@ const App = () => {
ReadResourceResultSchema,
"resources",
);
console.log("[App] Resource read response:", {
uri,
responseLength: JSON.stringify(response).length,
hasContents: !!(response as { contents?: unknown[] }).contents,
});
const content = JSON.stringify(response, null, 2);
setResourceContent(content);
setResourceContentMap((prev) => ({
...prev,
[uri]: content,
}));
setResourceContentMap((prev) => {
const updated = {
...prev,
[uri]: content,
};
console.log("[App] Updated resourceContentMap:", {
uri,
contentLength: content.length,
mapKeys: Object.keys(updated),
});
return updated;
});
};

const subscribeToResource = async (uri: string) => {
Expand Down Expand Up @@ -1308,6 +1337,10 @@ const App = () => {
<ListTodo className="w-4 h-4 mr-2" />
Tasks
</TabsTrigger>
<TabsTrigger value="apps">
<AppWindow className="w-4 h-4 mr-2" />
Apps
</TabsTrigger>
<TabsTrigger value="ping">
<Bell className="w-4 h-4 mr-2" />
Ping
Expand Down Expand Up @@ -1497,6 +1530,20 @@ const App = () => {
error={errors.tasks}
nextCursor={nextTaskCursor}
/>
<AppsTab
tools={tools}
listTools={() => {
clearError("tools");
listTools();
}}
error={errors.tools}
mcpClient={mcpClient}
onReadResource={(uri: string) => {
clearError("resources");
readResource(uri);
}}
resourceContentMap={resourceContentMap}
/>
<ConsoleTab />
<PingTab
onPingClick={() => {
Expand Down
Loading
Loading