Give bots tools and MCP servers per bot and workspace, with status and tests
- Bots and workspaces get tools and MCP servers from their settings pages; bots also from chips under the chat composer, removable there - "Every bot" now gives one to every bot now and every new bot; each can still drop it (attach-every-bot-extensions.ts moves old installs over) - Status lines: MCP servers record whether they connect, tools whether their last run worked - Test connection in the MCP form and a Test panel in the tool form check the form as it is, without saving - Hide Google sign-in on the login form Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
||||
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import { SiteData } from "@/src/data/site-data";
|
||||
import type { McpServerRecord } from "@/src/types";
|
||||
import grabMcpDir from "./grab-mcp-dir";
|
||||
import hostShell from "./host-shell";
|
||||
import runMcpSetup from "./run-mcp-setup";
|
||||
|
||||
type Params = {
|
||||
server: McpServerRecord;
|
||||
/**
|
||||
* Its environment (`grabMcpStdioEnv`).
|
||||
*/
|
||||
env: Record<string, string>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts a stdio MCP server after its setup (`runMcpSetup`), with the
|
||||
* host's shell in its directory, and connects to it. A failed start
|
||||
* throws with the last lines it wrote to stderr. Closing the client stops
|
||||
* it.
|
||||
*/
|
||||
export default async function startStdioMcpClient({ server, env }: Params) {
|
||||
await runMcpSetup({ server, env });
|
||||
|
||||
const transport = new StdioClientTransport({
|
||||
command: hostShell(),
|
||||
args: ["-c", server.command],
|
||||
cwd: await grabMcpDir({ server_id: server.id }),
|
||||
env,
|
||||
stderr: "pipe",
|
||||
});
|
||||
let stderr = "";
|
||||
|
||||
transport.stderr?.on("data", (chunk: Buffer) => {
|
||||
stderr = `${stderr}${chunk.toString()}`.slice(-4000);
|
||||
});
|
||||
|
||||
const client = new Client({ name: SiteData["SiteSlug"], version: "1.0.0" });
|
||||
|
||||
try {
|
||||
await client.connect(transport, { timeout: AppData.McpConnectTimeoutMs * 4 });
|
||||
} catch (error) {
|
||||
await client.close().catch(() => {});
|
||||
throw new Error(
|
||||
`Couldn't start ${server.name}: ${error instanceof Error ? error.message : String(error)}${
|
||||
stderr.trim() ? `\n${stderr.trim().slice(-2000)}` : ""
|
||||
}`,
|
||||
);
|
||||
}
|
||||
|
||||
return { client, transport };
|
||||
}
|
||||
Reference in New Issue
Block a user