mirror of
https://github.com/samanhappy/mcphub.git
synced 2026-01-01 04:08:52 -05:00
enhance JSON schema conversion to Zod schema
This commit is contained in:
@@ -136,7 +136,7 @@ export const registerAllTools = async (server: McpServer, forceInit: boolean): P
|
|||||||
await server.tool(
|
await server.tool(
|
||||||
tool.name,
|
tool.name,
|
||||||
tool.description || '',
|
tool.description || '',
|
||||||
cast(tool.inputSchema.properties),
|
json2zod(tool.inputSchema.properties, tool.inputSchema.required),
|
||||||
async (params: Record<string, unknown>) => {
|
async (params: Record<string, unknown>) => {
|
||||||
const currentServer = getServerInfoByName(serverInfo.name)!;
|
const currentServer = getServerInfoByName(serverInfo.name)!;
|
||||||
console.log(`Calling tool: ${tool.name} with params: ${JSON.stringify(params)}`);
|
console.log(`Calling tool: ${tool.name} with params: ${JSON.stringify(params)}`);
|
||||||
@@ -258,28 +258,50 @@ export const createMcpServer = (name: string, version: string): McpServer => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Helper function: Convert JSON Schema to Zod Schema
|
// Helper function: Convert JSON Schema to Zod Schema
|
||||||
function cast(inputSchema: unknown): ZodRawShape {
|
function json2zod(inputSchema: unknown, required: unknown): ZodRawShape {
|
||||||
if (typeof inputSchema !== 'object' || inputSchema === null) {
|
if (typeof inputSchema !== 'object' || inputSchema === null) {
|
||||||
throw new Error('Invalid input schema');
|
throw new Error('Invalid input schema');
|
||||||
}
|
}
|
||||||
|
|
||||||
const properties = inputSchema as Record<
|
const properties = inputSchema as Record<string, any>;
|
||||||
string,
|
|
||||||
{ type: string; description?: string; items?: { type: string } }
|
|
||||||
>;
|
|
||||||
const processedSchema: ZodRawShape = {};
|
const processedSchema: ZodRawShape = {};
|
||||||
|
|
||||||
for (const key in properties) {
|
for (const key in properties) {
|
||||||
const prop = properties[key];
|
const prop = properties[key];
|
||||||
|
|
||||||
if (prop instanceof ZodType) {
|
if (prop instanceof ZodType) {
|
||||||
processedSchema[key] = prop.optional();
|
processedSchema[key] = prop;
|
||||||
} else if (typeof prop === 'object' && prop !== null) {
|
continue;
|
||||||
let zodType: ZodType;
|
}
|
||||||
|
|
||||||
|
if (typeof prop !== 'object' || prop === null) {
|
||||||
|
throw new Error(`Invalid property definition for ${key}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let zodType: ZodType;
|
||||||
|
|
||||||
|
if (prop.type === 'array' && prop.items) {
|
||||||
|
if (prop.items.type === 'string') {
|
||||||
|
zodType = z.array(z.string());
|
||||||
|
} else if (prop.items.type === 'number') {
|
||||||
|
zodType = z.array(z.number());
|
||||||
|
} else if (prop.items.type === 'integer') {
|
||||||
|
zodType = z.array(z.number().int());
|
||||||
|
} else if (prop.items.type === 'boolean') {
|
||||||
|
zodType = z.array(z.boolean());
|
||||||
|
} else if (prop.items.type === 'object' && prop.items.properties) {
|
||||||
|
zodType = z.array(z.object(json2zod(prop.items.properties, prop.items.required)));
|
||||||
|
} else {
|
||||||
|
zodType = z.array(z.any());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
switch (prop.type) {
|
switch (prop.type) {
|
||||||
case 'string':
|
case 'string':
|
||||||
zodType = z.string();
|
if (prop.enum && Array.isArray(prop.enum)) {
|
||||||
|
zodType = z.enum(prop.enum as [string, ...string[]]);
|
||||||
|
} else {
|
||||||
|
zodType = z.string();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'number':
|
case 'number':
|
||||||
zodType = z.number();
|
zodType = z.number();
|
||||||
@@ -290,32 +312,30 @@ function cast(inputSchema: unknown): ZodRawShape {
|
|||||||
case 'integer':
|
case 'integer':
|
||||||
zodType = z.number().int();
|
zodType = z.number().int();
|
||||||
break;
|
break;
|
||||||
case 'array':
|
|
||||||
zodType = z.array(z.any());
|
|
||||||
break;
|
|
||||||
case 'object':
|
case 'object':
|
||||||
zodType = z.record(z.any());
|
if (prop.properties) {
|
||||||
|
zodType = z.object(json2zod(prop.properties, prop.required));
|
||||||
|
} else {
|
||||||
|
zodType = z.record(z.any());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
zodType = z.any();
|
zodType = z.any();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (prop.description) {
|
if (prop.description) {
|
||||||
zodType = zodType.describe(prop.description);
|
zodType = zodType.describe(prop.description);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prop.items) {
|
if (prop.default !== undefined) {
|
||||||
if (prop.items.type === 'string') {
|
zodType = zodType.default(prop.default);
|
||||||
zodType = z.array(z.string());
|
}
|
||||||
} else if (prop.items.type === 'number') {
|
|
||||||
zodType = z.array(z.number());
|
|
||||||
} else if (prop.items.type === 'boolean') {
|
|
||||||
zodType = z.array(z.boolean());
|
|
||||||
} else {
|
|
||||||
zodType = z.array(z.any());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
required = Array.isArray(required) ? required : [];
|
||||||
|
if (Array.isArray(required) && required.includes(key)) {
|
||||||
|
processedSchema[key] = zodType;
|
||||||
|
} else {
|
||||||
processedSchema[key] = zodType.optional();
|
processedSchema[key] = zodType.optional();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user