n8n
Version:
n8n Workflow Automation Tool
85 lines • 3.53 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildSearchMcpServersTool = buildSearchMcpServersTool;
const tool_1 = require("@n8n/agents/tool");
const change_case_1 = require("change-case");
const zod_1 = require("zod");
const node_description_transform_1 = require("../../../modules/mcp-registry/node-description-transform");
const builder_tool_names_1 = require("./builder-tool-names");
const searchMcpServersInputSchema = zod_1.z.object({
queries: zod_1.z
.array(zod_1.z.string())
.min(1)
.describe('Search queries for MCP servers (e.g., ["github"], ["slack"])'),
});
function getMcpRegistryCredentialTypeName(server) {
return `${(0, change_case_1.camelCase)(server.slug)}McpOAuth2Api`;
}
function pickPreferredRemote(server) {
const streamable = server.remotes.find((remote) => remote.type === 'streamable-http');
if (streamable)
return { type: 'streamableHttp', url: streamable.url };
const sse = server.remotes.find((remote) => remote.type === 'sse');
if (sse)
return { type: 'sse', url: sse.url };
return null;
}
function registryServerToMcpConfig(server) {
const remote = pickPreferredRemote(server);
if (!remote)
return null;
const credentialType = getMcpRegistryCredentialTypeName(server);
const nodeTypeName = `${node_description_transform_1.MCP_REGISTRY_PACKAGE_NAME}.${(0, change_case_1.camelCase)(server.slug)}`;
return {
name: (0, change_case_1.camelCase)(server.slug),
title: server.title,
description: server.tagline,
url: remote.url,
transport: remote.type,
authentication: credentialType,
credentialType,
tools: server.tools.map((tool) => ({
name: tool.name,
...(tool.title ? { title: tool.title } : {}),
})),
metadata: {
nodeTypeName,
},
};
}
function normalizeQueries(queries) {
return queries.map((query) => query.trim().toLowerCase()).filter((query) => query.length > 0);
}
function matchesServerQuery(server, normalizedQueries) {
const fields = [
server.slug,
(0, change_case_1.camelCase)(server.slug),
server.title,
server.description,
server.tagline,
]
.map((field) => (typeof field === 'string' ? field.toLowerCase() : null))
.filter((field) => field !== null);
return normalizedQueries.some((query) => fields.some((field) => field.includes(query)));
}
function buildSearchMcpServersTool(deps) {
return new tool_1.Tool(builder_tool_names_1.BUILDER_TOOLS.SEARCH_MCP_SERVERS)
.description('Search the MCP registry for available MCP servers. Returns MCP config-ready server details, ' +
'including credentialType for ask_credential and server metadata needed for patch_config.')
.input(searchMcpServersInputSchema)
.handler(async ({ queries }) => {
const normalizedQueries = normalizeQueries(queries);
if (normalizedQueries.length === 0)
return { results: [] };
const servers = await deps.mcpRegistryService.getAll();
const results = servers.flatMap((server) => {
if (!matchesServerQuery(server, normalizedQueries))
return [];
const transformed = registryServerToMcpConfig(server);
return transformed ? [transformed] : [];
});
return { results };
})
.build();
}
//# sourceMappingURL=search-mcp-servers.tool.js.map