From 429cfcc7c0d22280d09215210b4be402fc5f6b5c Mon Sep 17 00:00:00 2001 From: er1c-cartman Date: Thu, 28 May 2026 08:30:45 +0900 Subject: [PATCH] Add arbitrary MCP server toolkit --- src/toolkits/toolkits/client.ts | 2 + src/toolkits/toolkits/mcp/base.ts | 25 +++++++ src/toolkits/toolkits/mcp/client.tsx | 25 +++++++ src/toolkits/toolkits/mcp/form.tsx | 65 +++++++++++++++++++ src/toolkits/toolkits/mcp/server.ts | 19 ++++++ .../toolkits/mcp/tools/call_tool/base.ts | 16 +++++ .../toolkits/mcp/tools/call_tool/client.tsx | 25 +++++++ .../toolkits/mcp/tools/call_tool/server.ts | 29 +++++++++ .../toolkits/mcp/tools/list_tools/base.ts | 17 +++++ .../toolkits/mcp/tools/list_tools/client.tsx | 32 +++++++++ .../toolkits/mcp/tools/list_tools/server.ts | 27 ++++++++ src/toolkits/toolkits/mcp/tools/tools.ts | 4 ++ src/toolkits/toolkits/mcp/transport.ts | 59 +++++++++++++++++ src/toolkits/toolkits/server.ts | 2 + src/toolkits/toolkits/shared.ts | 5 ++ 15 files changed, 352 insertions(+) create mode 100644 src/toolkits/toolkits/mcp/base.ts create mode 100644 src/toolkits/toolkits/mcp/client.tsx create mode 100644 src/toolkits/toolkits/mcp/form.tsx create mode 100644 src/toolkits/toolkits/mcp/server.ts create mode 100644 src/toolkits/toolkits/mcp/tools/call_tool/base.ts create mode 100644 src/toolkits/toolkits/mcp/tools/call_tool/client.tsx create mode 100644 src/toolkits/toolkits/mcp/tools/call_tool/server.ts create mode 100644 src/toolkits/toolkits/mcp/tools/list_tools/base.ts create mode 100644 src/toolkits/toolkits/mcp/tools/list_tools/client.tsx create mode 100644 src/toolkits/toolkits/mcp/tools/list_tools/server.ts create mode 100644 src/toolkits/toolkits/mcp/tools/tools.ts create mode 100644 src/toolkits/toolkits/mcp/transport.ts diff --git a/src/toolkits/toolkits/client.ts b/src/toolkits/toolkits/client.ts index 29087577..efc45b56 100644 --- a/src/toolkits/toolkits/client.ts +++ b/src/toolkits/toolkits/client.ts @@ -19,6 +19,7 @@ import { spotifyClientToolkit } from "./spotify/client"; import { etsyClientToolkit } from "./etsy/client"; import { videoClientToolkit } from "./video/client"; import { twitterClientToolkit } from "./twitter/client"; +import { mcpClientToolkit } from "./mcp/client"; export type ClientToolkits = { [K in Toolkits]: ClientToolkit< @@ -42,6 +43,7 @@ export const clientToolkits: ClientToolkits = { [Toolkits.Etsy]: etsyClientToolkit, [Toolkits.Video]: videoClientToolkit, [Toolkits.Twitter]: twitterClientToolkit, + [Toolkits.Mcp]: mcpClientToolkit, }; export function getClientToolkit( diff --git a/src/toolkits/toolkits/mcp/base.ts b/src/toolkits/toolkits/mcp/base.ts new file mode 100644 index 00000000..ee3f42de --- /dev/null +++ b/src/toolkits/toolkits/mcp/base.ts @@ -0,0 +1,25 @@ +import type { ToolkitConfig } from "@/toolkits/types"; +import { z } from "zod"; +import { baseCallMcpTool } from "./tools/call_tool/base"; +import { baseListMcpToolsTool } from "./tools/list_tools/base"; +import { McpTools } from "./tools/tools"; + +export const mcpParameters = z.object({ + url: z.string().url(), + transport: z.enum(["http", "sse"]).default("http"), + headers: z + .string() + .optional() + .describe("Optional JSON object of HTTP headers for the MCP server"), +}); + +export const baseMcpToolkitConfig: ToolkitConfig< + McpTools, + typeof mcpParameters.shape +> = { + tools: { + [McpTools.ListTools]: baseListMcpToolsTool, + [McpTools.CallTool]: baseCallMcpTool, + }, + parameters: mcpParameters, +}; diff --git a/src/toolkits/toolkits/mcp/client.tsx b/src/toolkits/toolkits/mcp/client.tsx new file mode 100644 index 00000000..35774fb4 --- /dev/null +++ b/src/toolkits/toolkits/mcp/client.tsx @@ -0,0 +1,25 @@ +import { Network } from "lucide-react"; + +import { createClientToolkit } from "@/toolkits/create-toolkit"; +import { ToolkitGroups } from "@/toolkits/types"; +import { baseMcpToolkitConfig } from "./base"; +import { McpForm } from "./form"; +import { mcpCallToolConfigClient } from "./tools/call_tool/client"; +import { mcpListToolsToolConfigClient } from "./tools/list_tools/client"; +import { McpTools } from "./tools/tools"; + +export const mcpClientToolkit = createClientToolkit( + baseMcpToolkitConfig, + { + name: "MCP Server", + description: "Connect to a hosted MCP server by URL", + icon: Network, + form: McpForm, + type: ToolkitGroups.DataSource, + envVars: [], + }, + { + [McpTools.ListTools]: mcpListToolsToolConfigClient, + [McpTools.CallTool]: mcpCallToolConfigClient, + }, +); diff --git a/src/toolkits/toolkits/mcp/form.tsx b/src/toolkits/toolkits/mcp/form.tsx new file mode 100644 index 00000000..659bd2f0 --- /dev/null +++ b/src/toolkits/toolkits/mcp/form.tsx @@ -0,0 +1,65 @@ +"use client"; + +import type React from "react"; +import type { z, ZodObject } from "zod"; + +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Textarea } from "@/components/ui/textarea"; +import type { mcpParameters } from "./base"; + +export const McpForm: React.ComponentType<{ + parameters: z.infer>; + setParameters: ( + parameters: z.infer>, + ) => void; +}> = ({ parameters, setParameters }) => { + const setParameter = ( + key: K, + value: (typeof parameters)[K], + ) => { + setParameters({ + ...parameters, + transport: parameters.transport ?? "http", + [key]: value, + }); + }; + + return ( +
+
+ + setParameter("url", event.target.value)} + /> +
+
+ + +
+
+ +