Skip to content

Commit 3fb1f11

Browse files
committed
feat: remove zod deps
1 parent e7480c8 commit 3fb1f11

File tree

9 files changed

+82
-201
lines changed

9 files changed

+82
-201
lines changed

deno.lock

Lines changed: 1 addition & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cli/tests/config_loader_test.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Deno.test("Config Loader - load from MCPC_CONFIG env var", async () => {
2929

3030
Deno.test("Config Loader - environment variable substitution", async () => {
3131
// Setup
32-
process.env.TEST_API_KEY = "secret123";
32+
process.env.TEST_COMMAND = "npx";
3333
process.env.TEST_URL = "https://test.com";
3434

3535
const testConfig = {
@@ -38,15 +38,13 @@ Deno.test("Config Loader - environment variable substitution", async () => {
3838
agents: [
3939
{
4040
name: "agent",
41-
description: "API key: $TEST_API_KEY",
41+
description: "Command: $TEST_COMMAND",
4242
deps: {
4343
mcpServers: {
4444
server: {
45-
smitheryConfig: {
46-
type: "http",
47-
deploymentUrl: "$TEST_URL",
48-
config: { key: "$TEST_API_KEY" },
49-
},
45+
command: "$TEST_COMMAND",
46+
args: ["-y", "test"],
47+
transportType: "stdio",
5048
},
5149
},
5250
},
@@ -60,19 +58,13 @@ Deno.test("Config Loader - environment variable substitution", async () => {
6058

6159
// Verify
6260
assertExists(config);
63-
assertEquals(config.agents[0].description, "API key: secret123");
64-
assertEquals(
65-
config.agents[0].deps?.mcpServers?.server?.smitheryConfig?.deploymentUrl,
66-
"https://test.com",
67-
);
68-
assertEquals(
69-
config.agents[0].deps?.mcpServers?.server?.smitheryConfig?.config?.key,
70-
"secret123",
71-
);
61+
assertEquals(config.agents[0].description, "Command: npx");
62+
const serverConfig = config.agents[0].deps?.mcpServers?.server as any;
63+
assertEquals(serverConfig?.command, "npx");
7264

7365
// Cleanup
7466
delete process.env.MCPC_CONFIG;
75-
delete process.env.TEST_API_KEY;
67+
delete process.env.TEST_COMMAND;
7668
delete process.env.TEST_URL;
7769
});
7870

packages/cli/tests/wrap_mode_test.ts

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,13 @@ Deno.test("wrap mode - parse single server command correctly", async () => {
3232
config?.agents[0].name,
3333
"_wonderwhy-er_desktop-commander--orchestrator",
3434
);
35-
assertEquals(
36-
config?.agents[0].deps?.mcpServers?.["_wonderwhy-er_desktop-commander"]
37-
?.command,
38-
"npx",
39-
);
40-
assertEquals(
41-
config?.agents[0].deps?.mcpServers?.["_wonderwhy-er_desktop-commander"]
42-
?.args,
43-
["-y", "@wonderwhy-er/desktop-commander"],
44-
);
35+
const desktopConfig = config?.agents[0].deps?.mcpServers
36+
?.["_wonderwhy-er_desktop-commander"] as any;
37+
assertEquals(desktopConfig?.command, "npx");
38+
assertEquals(desktopConfig?.args, [
39+
"-y",
40+
"@wonderwhy-er/desktop-commander",
41+
]);
4542
assertEquals(
4643
config?.agents[0].deps?.mcpServers?.["_wonderwhy-er_desktop-commander"]
4744
?.transportType,
@@ -99,11 +96,10 @@ Deno.test("wrap mode - parse multiple servers with different transports", async
9996
assertEquals(Object.keys(mcpServers || {}).length, 3);
10097

10198
// Check first server (stdio)
102-
assertEquals(
103-
mcpServers?.["_wonderwhy-er_desktop-commander"]?.command,
104-
"npx",
105-
);
106-
assertEquals(mcpServers?.["_wonderwhy-er_desktop-commander"]?.args, [
99+
const desktopCmdConfig = mcpServers
100+
?.["_wonderwhy-er_desktop-commander"] as any;
101+
assertEquals(desktopCmdConfig?.command, "npx");
102+
assertEquals(desktopCmdConfig?.args, [
107103
"-y",
108104
"@wonderwhy-er/desktop-commander",
109105
]);
@@ -113,22 +109,18 @@ Deno.test("wrap mode - parse multiple servers with different transports", async
113109
);
114110

115111
// Check second server (http)
116-
assertEquals(
117-
mcpServers?.["https___api_github_com_mcp"]?.command,
118-
"https://api.github.com/mcp",
119-
);
120-
assertEquals(mcpServers?.["https___api_github_com_mcp"]?.args, []);
112+
const githubMcpConfig = mcpServers?.["https___api_github_com_mcp"] as any;
113+
assertEquals(githubMcpConfig?.command, "https://api.github.com/mcp");
114+
assertEquals(githubMcpConfig?.args, []);
121115
assertEquals(
122116
mcpServers?.["https___api_github_com_mcp"]?.transportType,
123117
"streamable-http",
124118
);
125119

126120
// Check third server (sse)
127-
assertEquals(
128-
mcpServers?.["https___api_example_com_sse"]?.command,
129-
"https://api.example.com/sse",
130-
);
131-
assertEquals(mcpServers?.["https___api_example_com_sse"]?.args, []);
121+
const sseConfig = mcpServers?.["https___api_example_com_sse"] as any;
122+
assertEquals(sseConfig?.command, "npx");
123+
assertEquals(sseConfig?.args, []);
132124
assertEquals(
133125
mcpServers?.["https___api_example_com_sse"]?.transportType,
134126
"sse",

packages/core/deno.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131
"ajv": "npm:ajv@^8.17.1",
3232
"ajv-formats": "npm:ajv-formats@^3.0.1",
3333
"cheerio": "npm:cheerio@^1.0.0",
34-
"json-schema-to-zod": "npm:json-schema-to-zod@^2.6.1",
35-
"jsonrepair": "npm:jsonrepair@^3.13.0",
36-
"zod": "npm:zod@^3.24.2"
34+
"jsonrepair": "npm:jsonrepair@^3.13.0"
3735
}
3836
}

packages/core/src/compose.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ import {
77
type Tool,
88
} from "@modelcontextprotocol/sdk/types.js";
99
import { extractJsonSchema, jsonSchema, type Schema } from "./utils/schema.ts";
10-
import type { McpSettingsSchema } from "./service/tools.ts";
10+
import type { MCPSetting } from "./service/tools.ts";
1111
import {
1212
Server,
1313
type ServerOptions,
1414
} from "@modelcontextprotocol/sdk/server/index.js";
15-
import type z from "zod";
1615
import { parseTags } from "@mcpc/utils";
1716
import { composeMcpDepTools } from "./utils/common/mcp.ts";
1817
import type { ComposeDefinition } from "./set-up-mcp-compose.ts";
@@ -368,7 +367,7 @@ export class ComposableMCPServer extends Server {
368367
async compose(
369368
name: string | null,
370369
description: string,
371-
depsConfig: z.infer<typeof McpSettingsSchema> = { mcpServers: {} },
370+
depsConfig: MCPSetting = { mcpServers: {} },
372371
options: ComposeDefinition["options"] = { mode: "agentic" },
373372
) {
374373
const refDesc = options.refs?.join("") ?? "";

packages/core/src/service/tools.ts

Lines changed: 41 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,42 @@
1-
import { z } from "zod";
2-
3-
const AutoApproveSchema: z.ZodDefault<z.ZodArray<z.ZodString, "many">> = z
4-
.array(z.string()).default([]);
5-
6-
const BaseConfigSchema: z.ZodObject<Record<string, z.ZodTypeAny>> = z.object({
7-
autoApprove: AutoApproveSchema.optional(),
8-
disabled: z.boolean().optional(),
9-
disabledReason: z.string().optional(),
10-
toolCallTimeout: z.number().optional(),
11-
});
12-
13-
export const SseConfigSchema: z.ZodObject<Record<string, z.ZodTypeAny>> =
14-
BaseConfigSchema.extend({
15-
url: z.string().url(),
16-
transportType: z.literal("sse").optional(),
17-
headers: z.record(z.string()).optional(),
18-
});
19-
20-
export const StreamableHTTPSchema: z.ZodObject<Record<string, z.ZodTypeAny>> =
21-
BaseConfigSchema.extend({
22-
url: z.string().url(),
23-
transportType: z.literal("streamable-http").optional(),
24-
headers: z.record(z.string()).optional(),
25-
});
26-
27-
export const StdioConfigSchema: z.ZodObject<Record<string, z.ZodTypeAny>> =
28-
BaseConfigSchema.extend({
29-
command: z.string(),
30-
args: z.array(z.string()).optional(),
31-
env: z.record(z.string()).optional(),
32-
transportType: z.literal("stdio").optional(),
33-
});
34-
35-
export const InMemoryConfigSchema: z.ZodObject<Record<string, z.ZodTypeAny>> =
36-
BaseConfigSchema.extend({
37-
transportType: z.literal("memory"),
38-
server: z.any(), // Server instance from @modelcontextprotocol/sdk
39-
});
40-
41-
export const ServerConfigSchema: z.ZodTypeAny = z.union([
42-
StdioConfigSchema,
43-
SseConfigSchema,
44-
StreamableHTTPSchema,
45-
InMemoryConfigSchema,
46-
]);
47-
48-
export const McpSettingsSchema: z.ZodObject<Record<string, z.ZodTypeAny>> = z
49-
.object({
50-
mcpServers: z.record(ServerConfigSchema),
51-
});
52-
53-
// Use the input types (pre-transform) so plain config objects in examples
54-
// that don't include the added `transportType` property still type-check.
55-
// Allow either the raw input (what users write in examples/configs) or the
56-
// transformed/inferred type (which includes the added `transportType` fields).
1+
// Pure TypeScript type definitions - no Zod dependency needed
2+
interface BaseServerConfig {
3+
autoApprove?: string[];
4+
disabled?: boolean;
5+
disabledReason?: string;
6+
toolCallTimeout?: number;
7+
}
8+
9+
export interface StdioServerConfig extends BaseServerConfig {
10+
command: string;
11+
args?: string[];
12+
env?: Record<string, string>;
13+
transportType?: "stdio";
14+
}
15+
16+
export interface SseServerConfig extends BaseServerConfig {
17+
url: string;
18+
transportType?: "sse";
19+
headers?: Record<string, string>;
20+
}
21+
22+
export interface StreamableHTTPServerConfig extends BaseServerConfig {
23+
url: string;
24+
transportType?: "streamable-http";
25+
headers?: Record<string, string>;
26+
}
27+
28+
export interface InMemoryServerConfig extends BaseServerConfig {
29+
transportType: "memory";
30+
server: any; // Server instance from @modelcontextprotocol/sdk
31+
}
32+
33+
// Use explicit union type for better type inference
5734
export type McpServerConfig =
58-
| z.input<typeof ServerConfigSchema>
59-
| z.infer<typeof ServerConfigSchema>;
60-
export type MCPSetting =
61-
| z.input<typeof McpSettingsSchema>
62-
| z.infer<typeof McpSettingsSchema>;
35+
| StdioServerConfig
36+
| SseServerConfig
37+
| StreamableHTTPServerConfig
38+
| InMemoryServerConfig;
39+
40+
export type MCPSetting = {
41+
mcpServers: Record<string, McpServerConfig>;
42+
};

packages/core/src/set-up-mcp-compose.ts

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { ComposableMCPServer } from "../mod.ts";
2-
import { connectToSmitheryServer } from "./utils/common/registory.ts";
32
import type { MCPCStep } from "./utils/state.ts";
43
import type { MCPSetting } from "./service/tools.ts";
54
import type { SamplingConfig } from "./types.ts";
@@ -89,26 +88,7 @@ export interface ComposibleMCPConfig {
8988
export function parseMcpcConfigs(
9089
conf?: ComposeDefinition[],
9190
): ComposeDefinition[] {
92-
const mcpcConfigs = conf ?? [];
93-
const newMcpcConfigs = [];
94-
95-
for (const mcpcConfig of mcpcConfigs) {
96-
if (mcpcConfig?.deps?.mcpServers) {
97-
for (
98-
const [name, config] of Object.entries<any>(
99-
mcpcConfig.deps.mcpServers,
100-
)
101-
) {
102-
if (config.smitheryConfig) {
103-
const streamConfig = connectToSmitheryServer(config.smitheryConfig);
104-
mcpcConfig.deps.mcpServers[name] = streamConfig;
105-
}
106-
}
107-
}
108-
newMcpcConfigs.push(mcpcConfig);
109-
}
110-
111-
return newMcpcConfigs;
91+
return conf ?? [];
11292
}
11393

11494
/**

packages/core/src/utils/common/mcp.ts

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"
33
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
44
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
55
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
6-
import type {
7-
McpSettingsSchema,
8-
ServerConfigSchema,
9-
} from "../../service/tools.ts";
10-
import type z from "zod";
11-
import { smitheryToolNameCompatibale } from "./registory.ts";
6+
import type { McpServerConfig, MCPSetting } from "../../service/tools.ts";
7+
128
import { sanitizePropertyKey } from "./provider.ts";
139
import { cwd } from "node:process";
1410
import process from "node:process";
@@ -25,9 +21,7 @@ const mcpClientConnecting = new Map<string, Promise<Client>>();
2521
const shortHash = (s: string) =>
2622
createHash("sha256").update(s).digest("hex").slice(0, 8);
2723

28-
function defSignature(
29-
def: z.input<typeof ServerConfigSchema> | z.infer<typeof ServerConfigSchema>,
30-
) {
24+
function defSignature(def: McpServerConfig) {
3125
// KISS: stringify full definition for a stable signature
3226
// Handle circular references from InMemoryTransport or other objects
3327
const defCopy = { ...def };
@@ -51,9 +45,7 @@ function defSignature(
5145
* - VSCode/Cursor: explicit "type" field
5246
* - Cline/Claude Desktop: implicit detection (command → stdio, url → http/sse)
5347
*/
54-
function createTransport(
55-
def: z.input<typeof ServerConfigSchema> | z.infer<typeof ServerConfigSchema>,
56-
):
48+
function createTransport(def: McpServerConfig):
5749
| StdioClientTransport
5850
| StreamableHTTPClientTransport
5951
| SSEClientTransport
@@ -122,7 +114,7 @@ function createTransport(
122114

123115
async function getOrCreateMcpClient(
124116
defKey: string,
125-
def: z.input<typeof ServerConfigSchema> | z.infer<typeof ServerConfigSchema>,
117+
def: McpServerConfig,
126118
): Promise<Client> {
127119
const pooled = mcpClientPool.get(defKey);
128120
if (pooled) {
@@ -196,9 +188,7 @@ process.once?.("SIGINT", () => {
196188
});
197189

198190
export async function composeMcpDepTools(
199-
mcpConfig:
200-
| z.input<typeof McpSettingsSchema>
201-
| z.infer<typeof McpSettingsSchema>,
191+
mcpConfig: MCPSetting,
202192
filterIn?: (params: {
203193
action: string;
204194
tool: any;
@@ -213,7 +203,7 @@ export async function composeMcpDepTools(
213203
const acquiredKeys: string[] = [];
214204

215205
for (const [name, definition] of Object.entries(mcpConfig.mcpServers)) {
216-
const def = definition as unknown as z.infer<typeof ServerConfigSchema>;
206+
const def = definition as McpServerConfig;
217207
if (def.disabled) continue;
218208

219209
const defKey = shortHash(defSignature(def));
@@ -227,8 +217,9 @@ export async function composeMcpDepTools(
227217
const { tools } = await client.listTools();
228218

229219
tools.forEach((tool) => {
230-
const { toolNameWithScope, toolName: internalToolName } =
231-
smitheryToolNameCompatibale(tool.name, name);
220+
const toolNameWithScope = `${name}.${tool.name}`;
221+
const internalToolName = tool.name;
222+
232223
// Sanitize toolId to ensure it only contains valid characters
233224
const rawToolId = `${serverId}_${internalToolName}`;
234225
const toolId = sanitizePropertyKey(rawToolId);

0 commit comments

Comments
 (0)