Add UI for viewing and configuring environment variables
This commit is contained in:
@@ -93,6 +93,7 @@ const App = () => {
|
|||||||
const [mcpClient, setMcpClient] = useState<Client | null>(null);
|
const [mcpClient, setMcpClient] = useState<Client | null>(null);
|
||||||
const [notifications, setNotifications] = useState<ServerNotification[]>([]);
|
const [notifications, setNotifications] = useState<ServerNotification[]>([]);
|
||||||
const [roots, setRoots] = useState<Root[]>([]);
|
const [roots, setRoots] = useState<Root[]>([]);
|
||||||
|
const [env, setEnv] = useState<Record<string, string>>({});
|
||||||
|
|
||||||
const [pendingSampleRequests, setPendingSampleRequests] = useState<
|
const [pendingSampleRequests, setPendingSampleRequests] = useState<
|
||||||
Array<
|
Array<
|
||||||
@@ -145,6 +146,15 @@ const App = () => {
|
|||||||
localStorage.setItem("lastArgs", args);
|
localStorage.setItem("lastArgs", args);
|
||||||
}, [args]);
|
}, [args]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch("http://localhost:3000/default-environment")
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => setEnv(data))
|
||||||
|
.catch((error) =>
|
||||||
|
console.error("Error fetching default environment:", error),
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const pushHistory = (request: object, response: object) => {
|
const pushHistory = (request: object, response: object) => {
|
||||||
setRequestHistory((prev) => [
|
setRequestHistory((prev) => [
|
||||||
...prev,
|
...prev,
|
||||||
@@ -284,6 +294,7 @@ const App = () => {
|
|||||||
if (transportType === "stdio") {
|
if (transportType === "stdio") {
|
||||||
backendUrl.searchParams.append("command", command);
|
backendUrl.searchParams.append("command", command);
|
||||||
backendUrl.searchParams.append("args", args);
|
backendUrl.searchParams.append("args", args);
|
||||||
|
backendUrl.searchParams.append("env", JSON.stringify(env));
|
||||||
} else {
|
} else {
|
||||||
backendUrl.searchParams.append("url", url);
|
backendUrl.searchParams.append("url", url);
|
||||||
}
|
}
|
||||||
@@ -371,6 +382,50 @@ const App = () => {
|
|||||||
Connect
|
Connect
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
{transportType === "stdio" && (
|
||||||
|
<div className="mt-4">
|
||||||
|
<h3 className="text-md font-semibold mb-2">
|
||||||
|
Environment Variables
|
||||||
|
</h3>
|
||||||
|
{Object.entries(env).map(([key, value]) => (
|
||||||
|
<div key={key} className="flex space-x-2 mb-2">
|
||||||
|
<Input
|
||||||
|
placeholder="Key"
|
||||||
|
value={key}
|
||||||
|
onChange={(e) =>
|
||||||
|
setEnv((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[e.target.value]: value,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
placeholder="Value"
|
||||||
|
value={value}
|
||||||
|
onChange={(e) =>
|
||||||
|
setEnv((prev) => ({ ...prev, [key]: e.target.value }))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
onClick={() =>
|
||||||
|
setEnv((prev) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const { [key]: _, ...rest } = prev;
|
||||||
|
return rest;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Remove
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<Button
|
||||||
|
onClick={() => setEnv((prev) => ({ ...prev, "": "" }))}
|
||||||
|
>
|
||||||
|
Add Environment Variable
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{mcpClient ? (
|
{mcpClient ? (
|
||||||
<Tabs defaultValue="resources" className="w-full p-4">
|
<Tabs defaultValue="resources" className="w-full p-4">
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ import cors from "cors";
|
|||||||
import EventSource from "eventsource";
|
import EventSource from "eventsource";
|
||||||
|
|
||||||
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
||||||
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
import {
|
||||||
|
StdioClientTransport,
|
||||||
|
getDefaultEnvironment,
|
||||||
|
} from "@modelcontextprotocol/sdk/client/stdio.js";
|
||||||
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import mcpProxy from "./mcpProxy.js";
|
import mcpProxy from "./mcpProxy.js";
|
||||||
@@ -24,8 +27,11 @@ const createTransport = async (query: express.Request["query"]) => {
|
|||||||
if (transportType === "stdio") {
|
if (transportType === "stdio") {
|
||||||
const command = query.command as string;
|
const command = query.command as string;
|
||||||
const args = (query.args as string).split(/\s+/);
|
const args = (query.args as string).split(/\s+/);
|
||||||
console.log(`Stdio transport: command=${command}, args=${args}`);
|
const env = query.env ? JSON.parse(query.env as string) : undefined;
|
||||||
const transport = new StdioClientTransport({ command, args });
|
console.log(
|
||||||
|
`Stdio transport: command=${command}, args=${args}, env=${JSON.stringify(env)}`,
|
||||||
|
);
|
||||||
|
const transport = new StdioClientTransport({ command, args, env });
|
||||||
await transport.start();
|
await transport.start();
|
||||||
console.log("Spawned stdio transport");
|
console.log("Spawned stdio transport");
|
||||||
return transport;
|
return transport;
|
||||||
@@ -79,6 +85,10 @@ app.post("/message", async (req, res) => {
|
|||||||
await transport.handlePostMessage(req, res);
|
await transport.handlePostMessage(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get("/default-environment", (req, res) => {
|
||||||
|
res.json(getDefaultEnvironment());
|
||||||
|
});
|
||||||
|
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`Server is running on port ${PORT}`);
|
console.log(`Server is running on port ${PORT}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user