@xynehq/jaf
Version:
Juspay Agent Framework - A purely functional agent framework with immutable state and composable tools
111 lines • 3.71 kB
JavaScript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { z } from 'zod';
export async function makeMCPClient(command, args = []) {
const transport = new StdioClientTransport({
command,
args,
});
const client = new Client({
name: "jaf-client",
version: "2.0.0",
});
await client.connect(transport);
return {
async listTools() {
try {
const response = await client.listTools();
return response.tools.map(tool => ({
name: tool.name,
description: tool.description,
inputSchema: tool.inputSchema
}));
}
catch (error) {
console.error('Failed to list MCP tools:', error);
return [];
}
},
async callTool(name, args) {
try {
const response = await client.callTool({
name,
arguments: args
});
if (response.content && Array.isArray(response.content) && response.content.length > 0) {
return response.content.map((c) => {
if (c.type === 'text') {
return c.text;
}
return JSON.stringify(c);
}).join('\n');
}
return JSON.stringify(response);
}
catch (error) {
return JSON.stringify({
error: 'mcp_tool_error',
message: error instanceof Error ? error.message : String(error),
tool_name: name
});
}
},
async close() {
await client.close();
}
};
}
export function mcpToolToJAFTool(mcpClient, mcpToolDef) {
const zodSchema = jsonSchemaToZod(mcpToolDef.inputSchema || {});
const baseTool = {
schema: {
name: mcpToolDef.name,
description: mcpToolDef.description ?? mcpToolDef.name,
parameters: zodSchema,
},
execute: (args, _) => mcpClient.callTool(mcpToolDef.name, args),
};
return baseTool;
}
function jsonSchemaToZod(schema) {
if (!schema || typeof schema !== 'object') {
return z.any();
}
if (schema.type === 'object') {
const shape = {};
if (schema.properties) {
for (const [key, prop] of Object.entries(schema.properties)) {
let fieldSchema = jsonSchemaToZod(prop);
if (!schema.required || !schema.required.includes(key)) {
fieldSchema = fieldSchema.optional();
}
if (prop.description) {
fieldSchema = fieldSchema.describe(prop.description);
}
shape[key] = fieldSchema;
}
}
return z.object(shape);
}
if (schema.type === 'string') {
let stringSchema = z.string();
if (schema.description) {
stringSchema = stringSchema.describe(schema.description);
}
if (schema.enum) {
return z.enum(schema.enum);
}
return stringSchema;
}
if (schema.type === 'number' || schema.type === 'integer') {
return z.number();
}
if (schema.type === 'boolean') {
return z.boolean();
}
if (schema.type === 'array') {
return z.array(jsonSchemaToZod(schema.items));
}
return z.any();
}
//# sourceMappingURL=mcp.js.map