UNPKG

@hashgraphonline/conversational-agent

Version:

Hashgraph Online conversational AI agent implementing HCS-10 communication, HCS-2 registries, and content inscription on Hedera

156 lines (153 loc) 5.18 kB
import { DynamicStructuredTool } from "@langchain/core/tools"; import { z } from "zod"; import { shouldUseReference, ContentStoreService } from "@hashgraphonline/standards-sdk"; function convertMCPToolToLangChain(tool, mcpManager, serverConfig) { const zodSchema = jsonSchemaToZod(tool.inputSchema); const sanitizedName = `${tool.serverName}_${tool.name}`.replace( /[^a-zA-Z0-9_]/g, "_" ); let description = tool.description || `MCP tool ${tool.name} from ${tool.serverName}`; if (serverConfig?.toolDescriptions?.[tool.name]) { description = `${description} ${serverConfig.toolDescriptions[tool.name]}`; } if (serverConfig?.additionalContext) { description = `${description} Context: ${serverConfig.additionalContext}`; } return new DynamicStructuredTool({ name: sanitizedName, description, schema: zodSchema, func: async (input) => { try { const result = await mcpManager.executeTool( tool.serverName, tool.name, input ); let responseText = ""; if (typeof result === "string") { responseText = result; } else if (result && typeof result === "object" && "content" in result) { const content = result.content; if (Array.isArray(content)) { const textParts = content.filter( (item) => typeof item === "object" && item !== null && "type" in item && item.type === "text" && "text" in item ).map((item) => item.text); responseText = textParts.join("\n"); } else { responseText = JSON.stringify(content); } } else { responseText = JSON.stringify(result); } const responseBuffer = Buffer.from(responseText, "utf8"); const MCP_REFERENCE_THRESHOLD = 10 * 1024; const shouldStoreMCPContent = responseBuffer.length > MCP_REFERENCE_THRESHOLD; if (shouldStoreMCPContent || shouldUseReference(responseBuffer)) { const contentStore = ContentStoreService.getInstance(); if (contentStore) { try { const referenceId = await contentStore.storeContent(responseBuffer, { contentType: "text", source: "mcp", mcpToolName: `${tool.serverName}_${tool.name}`, originalSize: responseBuffer.length }); return `content-ref:${referenceId}`; } catch (storeError) { } } } return responseText; } catch (error) { const errorMessage = error instanceof Error ? error.message : "Unknown error"; return `Error executing MCP tool ${tool.name}: ${errorMessage}`; } } }); } function jsonSchemaToZod(schema) { if (!schema || typeof schema !== "object") { return z.object({}); } const schemaObj = schema; if (schemaObj.type && schemaObj.type !== "object") { return convertType(schemaObj); } if (!schemaObj.properties || typeof schemaObj.properties !== "object") { return z.object({}); } const shape = {}; for (const [key, value] of Object.entries(schemaObj.properties)) { let zodType = convertType(value); const isRequired = Array.isArray(schemaObj.required) && schemaObj.required.includes(key); if (!isRequired) { zodType = zodType.optional(); } shape[key] = zodType; } return z.object(shape); } function convertType(schema) { if (!schema || typeof schema !== "object" || !("type" in schema)) { return z.unknown(); } const schemaObj = schema; let zodType; switch (schemaObj.type) { case "string": zodType = z.string(); if (schemaObj.enum && Array.isArray(schemaObj.enum)) { zodType = z.enum(schemaObj.enum); } break; case "number": zodType = z.number(); if ("minimum" in schemaObj && typeof schemaObj.minimum === "number") { zodType = zodType.min(schemaObj.minimum); } if ("maximum" in schemaObj && typeof schemaObj.maximum === "number") { zodType = zodType.max(schemaObj.maximum); } break; case "integer": zodType = z.number().int(); if ("minimum" in schemaObj && typeof schemaObj.minimum === "number") { zodType = zodType.min(schemaObj.minimum); } if ("maximum" in schemaObj && typeof schemaObj.maximum === "number") { zodType = zodType.max(schemaObj.maximum); } break; case "boolean": zodType = z.boolean(); break; case "array": if (schemaObj.items) { zodType = z.array(convertType(schemaObj.items)); } else { zodType = z.array(z.unknown()); } break; case "object": if ("properties" in schemaObj) { zodType = jsonSchemaToZod(schemaObj); } else { zodType = z.object({}).passthrough(); } break; default: zodType = z.unknown(); } if ("description" in schemaObj && typeof schemaObj.description === "string") { zodType = zodType.describe(schemaObj.description); } return zodType; } export { convertMCPToolToLangChain }; //# sourceMappingURL=index23.js.map