n8n
Version:
n8n Workflow Automation Tool
211 lines • 8.15 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MCP_BASE_OAUTH2_CREDENTIAL_NAME = exports.MCP_REGISTRY_BASE_NODE_NAME = exports.LANGCHAIN_PACKAGE_NAME = exports.MCP_REGISTRY_PACKAGE_NAME = void 0;
exports.getMcpRegistryCredentialTypeName = getMcpRegistryCredentialTypeName;
exports.serverToCredentialDescription = serverToCredentialDescription;
exports.serverToNodeDescription = serverToNodeDescription;
const change_case_1 = require("change-case");
const mcp_registry_types_1 = require("./registry/mcp-registry.types");
exports.MCP_REGISTRY_PACKAGE_NAME = '@n8n/mcp-registry';
exports.LANGCHAIN_PACKAGE_NAME = '@n8n/n8n-nodes-langchain';
exports.MCP_REGISTRY_BASE_NODE_NAME = 'mcpRegistryClientTool';
exports.MCP_BASE_OAUTH2_CREDENTIAL_NAME = 'mcpOAuth2Api';
function getMcpRegistryNodeTypeName(server) {
return (0, change_case_1.camelCase)(server.slug);
}
function getMcpRegistryCredentialTypeName(server) {
return `${(0, change_case_1.camelCase)(server.slug)}McpOAuth2Api`;
}
function getMcpRegistryCredentialHeader(server) {
return {
name: getMcpRegistryCredentialTypeName(server),
icon: `node:${exports.MCP_REGISTRY_PACKAGE_NAME}.${getMcpRegistryNodeTypeName(server)}`,
displayName: `${server.title} MCP OAuth2`,
};
}
function resolveCredentialRemote(server) {
const remote = pickRemote(server);
if (!remote)
return null;
try {
return { endpointUrl: remote.endpointUrl, hostname: new URL(remote.endpointUrl).hostname };
}
catch {
return null;
}
}
function buildDomainRestrictionProperties(hostname) {
return [
{
displayName: 'Allowed HTTP Request Domains',
name: 'allowedHttpRequestDomains',
type: 'hidden',
default: 'domains',
},
{
displayName: 'Allowed Domains',
name: 'allowedDomains',
type: 'hidden',
default: hostname,
},
];
}
function serverToOAuth2CredentialDescription(server) {
const remote = resolveCredentialRemote(server);
if (!remote)
return null;
return {
...getMcpRegistryCredentialHeader(server),
extends: [exports.MCP_BASE_OAUTH2_CREDENTIAL_NAME],
properties: [
{
displayName: 'Use Dynamic Client Registration',
name: 'useDynamicClientRegistration',
type: 'hidden',
default: true,
},
{
displayName: 'Server URL',
name: 'serverUrl',
type: 'hidden',
default: remote.endpointUrl,
},
{
displayName: 'Resource URL',
name: 'resourceUrl',
type: 'hidden',
default: '',
},
...buildDomainRestrictionProperties(remote.hostname),
],
};
}
function getValidatedExtendsCredential(server, isKnownCredentialType) {
if (!server.extendsCredential)
return null;
const parseResult = mcp_registry_types_1.mcpRegistryExtendsCredentialSchema.safeParse(server.extendsCredential);
if (!parseResult.success)
return null;
const { extends: parentType, ...rawOverrides } = parseResult.data;
if (!isKnownCredentialType(parentType))
return null;
const overrides = Object.fromEntries(Object.entries(rawOverrides).filter(([, value]) => value !== null && value !== undefined));
return { parentType, overrides };
}
function serverToExtendedCredentialDescription(server, isKnownCredentialType) {
const validated = getValidatedExtendsCredential(server, isKnownCredentialType);
if (!validated)
return null;
const remote = resolveCredentialRemote(server);
if (!remote)
return null;
const overrideProperties = Object.entries(validated.overrides).map(([name, value]) => ({
displayName: name,
name,
type: 'hidden',
default: value,
}));
return {
...getMcpRegistryCredentialHeader(server),
extends: [validated.parentType],
properties: [...overrideProperties, ...buildDomainRestrictionProperties(remote.hostname)],
};
}
function getNodeDescriptionCredentials(server, isKnownCredentialType) {
switch (server.authType) {
case 'oauth2':
return [{ name: getMcpRegistryCredentialTypeName(server), required: true }];
case 'extendsCredential': {
const validated = getValidatedExtendsCredential(server, isKnownCredentialType);
if (!validated)
return [];
return [{ name: getMcpRegistryCredentialTypeName(server), required: true }];
}
default:
return [];
}
}
function pickRemote(server) {
const streamable = server.remotes.find((r) => r.type === 'streamable-http');
if (streamable)
return { transport: 'httpStreamable', endpointUrl: streamable.url };
const sse = server.remotes.find((r) => r.type === 'sse');
if (sse)
return { transport: 'sse', endpointUrl: sse.url };
return null;
}
const ICON_MIME_PREFERENCE = [
'image/svg+xml',
'image/webp',
'image/png',
'image/jpeg',
'image/jpg',
];
function preferredIcon(icons) {
for (const mimeType of ICON_MIME_PREFERENCE) {
const match = icons.find((icon) => icon.mimeType === mimeType);
if (match)
return match;
}
return icons[0];
}
function pickIconUrl(icons) {
const light = preferredIcon(icons.filter((icon) => icon.theme === 'light'));
const dark = preferredIcon(icons.filter((icon) => icon.theme === 'dark'));
if (light && dark)
return { light: light.src, dark: dark.src };
return preferredIcon(icons)?.src;
}
function withRemoteDefaults(properties, transport, endpointUrl) {
return properties.map((prop) => {
if (prop.name === 'endpointUrl')
return { ...prop, default: endpointUrl };
if (prop.name === 'serverTransport')
return { ...prop, default: transport };
return prop;
});
}
function serverToCredentialDescription(server, isKnownCredentialType) {
switch (server.authType) {
case 'oauth2':
return serverToOAuth2CredentialDescription(server);
case 'extendsCredential':
return serverToExtendedCredentialDescription(server, isKnownCredentialType);
default:
return null;
}
}
function serverToNodeDescription(server, baseDescription, isKnownCredentialType) {
if (server.authType !== 'oauth2' && server.authType !== 'extendsCredential')
return null;
const remote = pickRemote(server);
if (!remote)
return null;
const displayName = `${server.title} MCP`;
const description = structuredClone(baseDescription);
if (server.status === 'deprecated') {
description.hidden = true;
}
else {
delete description.hidden;
}
description.displayName = displayName;
description.name = (0, change_case_1.camelCase)(server.slug);
description.iconUrl = pickIconUrl(server.icons);
description.description = server.tagline;
description.defaults = { name: displayName };
description.credentials = getNodeDescriptionCredentials(server, isKnownCredentialType);
if (description.codex) {
description.codex.alias?.push(server.title, displayName);
if (server.websiteUrl) {
description.codex.resources = { primaryDocumentation: [{ url: server.websiteUrl }] };
}
}
description.properties = withRemoteDefaults(description.properties, remote.transport, remote.endpointUrl);
description.builderHint = {
...description.builderHint,
searchHint: `Agent-optimised ${server.title} integration. When wiring an ai_tool to an AI Agent for ${server.title}, use THIS node, not the native action node — this variant exposes ${server.title}'s tools in the shape AI Agents expect and ships pre-configured connection details.`,
};
return description;
}
//# sourceMappingURL=node-description-transform.js.map