fix types, eliminate client/server
This commit is contained in:
@@ -7,6 +7,8 @@ import {
|
|||||||
ReadResourceResultSchema,
|
ReadResourceResultSchema,
|
||||||
CallToolResultSchema,
|
CallToolResultSchema,
|
||||||
ListPromptsResultSchema,
|
ListPromptsResultSchema,
|
||||||
|
Tool,
|
||||||
|
ClientRequest,
|
||||||
} from "mcp-typescript/types.js";
|
} from "mcp-typescript/types.js";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
@@ -28,8 +30,9 @@ import RequestsTab from "./components/RequestsTabs";
|
|||||||
import ResourcesTab, { Resource } from "./components/ResourcesTab";
|
import ResourcesTab, { Resource } from "./components/ResourcesTab";
|
||||||
import NotificationsTab from "./components/NotificationsTab";
|
import NotificationsTab from "./components/NotificationsTab";
|
||||||
import PromptsTab, { Prompt } from "./components/PromptsTab";
|
import PromptsTab, { Prompt } from "./components/PromptsTab";
|
||||||
import ToolsTab, { Tool as ToolType } from "./components/ToolsTab";
|
import ToolsTab from "./components/ToolsTab";
|
||||||
import History from "./components/History";
|
import History from "./components/History";
|
||||||
|
import { AnyZodObject } from "node_modules/zod/lib";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [connectionStatus, setConnectionStatus] = useState<
|
const [connectionStatus, setConnectionStatus] = useState<
|
||||||
@@ -39,7 +42,7 @@ const App = () => {
|
|||||||
const [resourceContent, setResourceContent] = useState<string>("");
|
const [resourceContent, setResourceContent] = useState<string>("");
|
||||||
const [prompts, setPrompts] = useState<Prompt[]>([]);
|
const [prompts, setPrompts] = useState<Prompt[]>([]);
|
||||||
const [promptContent, setPromptContent] = useState<string>("");
|
const [promptContent, setPromptContent] = useState<string>("");
|
||||||
const [tools, setTools] = useState<ToolType[]>([]);
|
const [tools, setTools] = useState<Tool[]>([]);
|
||||||
const [toolResult, setToolResult] = useState<string>("");
|
const [toolResult, setToolResult] = useState<string>("");
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [command, setCommand] = useState<string>(
|
const [command, setCommand] = useState<string>(
|
||||||
@@ -57,7 +60,7 @@ const App = () => {
|
|||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
const [selectedPrompt, setSelectedPrompt] = useState<Prompt | null>(null);
|
const [selectedPrompt, setSelectedPrompt] = useState<Prompt | null>(null);
|
||||||
const [selectedTool, setSelectedTool] = useState<ToolType | null>(null);
|
const [selectedTool, setSelectedTool] = useState<Tool | null>(null);
|
||||||
|
|
||||||
const pushHistory = (request: object, response: object) => {
|
const pushHistory = (request: object, response: object) => {
|
||||||
setRequestHistory((prev) => [
|
setRequestHistory((prev) => [
|
||||||
@@ -66,10 +69,10 @@ const App = () => {
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeRequest = async (
|
const makeRequest = async <T extends AnyZodObject>(
|
||||||
request: Parameters<Client["request"]>[0],
|
request: ClientRequest,
|
||||||
schema: Parameters<Client["request"]>[1],
|
schema: T,
|
||||||
): Promise<ReturnType<Client["request"]>> => {
|
) => {
|
||||||
if (!mcpClient) {
|
if (!mcpClient) {
|
||||||
throw new Error("MCP client not connected");
|
throw new Error("MCP client not connected");
|
||||||
}
|
}
|
||||||
@@ -114,9 +117,7 @@ const App = () => {
|
|||||||
},
|
},
|
||||||
ListPromptsResultSchema,
|
ListPromptsResultSchema,
|
||||||
);
|
);
|
||||||
if (response.prompts) {
|
setPrompts(response.prompts);
|
||||||
setPrompts(response.prompts);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPrompt = async (name: string, args: Record<string, string> = {}) => {
|
const getPrompt = async (name: string, args: Record<string, string> = {}) => {
|
||||||
@@ -137,9 +138,7 @@ const App = () => {
|
|||||||
},
|
},
|
||||||
ListToolsResultSchema,
|
ListToolsResultSchema,
|
||||||
);
|
);
|
||||||
if (response.tools) {
|
setTools(response.tools);
|
||||||
setTools(response.tools);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const callTool = async (name: string, params: Record<string, unknown>) => {
|
const callTool = async (name: string, params: Record<string, unknown>) => {
|
||||||
|
|||||||
@@ -3,19 +3,11 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Send, AlertCircle } from "lucide-react";
|
import { Send, AlertCircle } from "lucide-react";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Tool } from "mcp-typescript/types.js";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import ListPane from "./ListPane";
|
import ListPane from "./ListPane";
|
||||||
|
|
||||||
export type Tool = {
|
|
||||||
name: string;
|
|
||||||
description?: string | undefined;
|
|
||||||
inputSchema: {
|
|
||||||
type: string;
|
|
||||||
properties?: Record<string, { type: string; description: string }>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const ToolsTab = ({
|
const ToolsTab = ({
|
||||||
tools,
|
tools,
|
||||||
listTools,
|
listTools,
|
||||||
|
|||||||
@@ -1,48 +1,32 @@
|
|||||||
import cors from "cors";
|
import cors from "cors";
|
||||||
|
|
||||||
import { Server } from "mcp-typescript/server/index.js";
|
|
||||||
import { SSEServerTransport } from "mcp-typescript/server/sse.js";
|
import { SSEServerTransport } from "mcp-typescript/server/sse.js";
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import { Client } from "mcp-typescript/client/index.js";
|
|
||||||
import { StdioClientTransport } from "mcp-typescript/client/stdio.js";
|
import { StdioClientTransport } from "mcp-typescript/client/stdio.js";
|
||||||
import mcpProxy from "./mcpProxy.js";
|
import mcpProxy from "./mcpProxy.js";
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
|
|
||||||
let servers: Server[] = [];
|
let transports: SSEServerTransport[] = [];
|
||||||
|
|
||||||
app.get("/sse", async (req, res) => {
|
app.get("/sse", async (req, res) => {
|
||||||
console.log("New SSE connection");
|
console.log("New SSE connection");
|
||||||
const command = decodeURIComponent(req.query.command as string);
|
const command = decodeURIComponent(req.query.command as string);
|
||||||
const args = decodeURIComponent(req.query.args as string).split(",");
|
const args = decodeURIComponent(req.query.args as string).split(",");
|
||||||
const mcpClient = new Client({ name: "MyApp", version: "1.0.0" });
|
|
||||||
const backingServerTransport = new StdioClientTransport();
|
const backingServerTransport = new StdioClientTransport();
|
||||||
await backingServerTransport.spawn({ command, args });
|
await backingServerTransport.spawn({ command, args });
|
||||||
await mcpClient.connect(backingServerTransport);
|
|
||||||
|
|
||||||
const webAppTransport = new SSEServerTransport("/message");
|
const webAppTransport = new SSEServerTransport("/message");
|
||||||
const server = new Server({
|
transports.push(webAppTransport);
|
||||||
name: "mcp-server-inspector",
|
|
||||||
version: "0.0.1",
|
|
||||||
});
|
|
||||||
servers.push(server);
|
|
||||||
|
|
||||||
server.onclose = async () => {
|
|
||||||
console.log("SSE connection closed");
|
|
||||||
servers = servers.filter((s) => s !== server);
|
|
||||||
await mcpClient.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
await webAppTransport.connectSSE(req, res);
|
await webAppTransport.connectSSE(req, res);
|
||||||
await server.connect(webAppTransport);
|
|
||||||
|
|
||||||
mcpProxy({
|
mcpProxy({
|
||||||
transportToClient: webAppTransport,
|
transportToClient: webAppTransport,
|
||||||
transportToServer: backingServerTransport,
|
transportToServer: backingServerTransport,
|
||||||
onerror: (error) => {
|
onerror: (error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
server.close();
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -50,9 +34,7 @@ app.get("/sse", async (req, res) => {
|
|||||||
app.post("/message", async (req, res) => {
|
app.post("/message", async (req, res) => {
|
||||||
console.log("Received message");
|
console.log("Received message");
|
||||||
|
|
||||||
const transport = servers
|
const transport = transports.find((t) => true);
|
||||||
.map((s) => s.transport as SSEServerTransport)
|
|
||||||
.find((t) => true);
|
|
||||||
if (!transport) {
|
if (!transport) {
|
||||||
res.status(404).send("Session not found");
|
res.status(404).send("Session not found");
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user