UNPKG

@n8n/n8n-nodes-langchain

Version:

![Banner image](https://user-images.githubusercontent.com/10284570/173569848-c624317f-42b1-45a6-ab09-f0ea3c247648.png)

228 lines 8.14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getAllTools = getAllTools; exports.mapToNodeOperationError = mapToNodeOperationError; exports.connectMcpClient = connectMcpClient; exports.getAuthHeaders = getAuthHeaders; exports.tryRefreshOAuth2Token = tryRefreshOAuth2Token; exports.isStructuredContent = isStructuredContent; const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js"); const sse_js_1 = require("@modelcontextprotocol/sdk/client/sse.js"); const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/client/streamableHttp.js"); const n8n_workflow_1 = require("n8n-workflow"); const ai_utilities_1 = require("@n8n/ai-utilities"); async function getAllTools(client, cursor) { const { tools, nextCursor } = await client.listTools({ cursor }); if (nextCursor) { return tools.concat(await getAllTools(client, nextCursor)); } return tools; } function safeCreateUrl(url, baseUrl) { try { return (0, n8n_workflow_1.createResultOk)(new URL(url, baseUrl)); } catch (error) { return (0, n8n_workflow_1.createResultError)(error); } } function normalizeAndValidateUrl(input) { const withProtocol = !/^https?:\/\//i.test(input) ? `https://${input}` : input; const parsedUrl = safeCreateUrl(withProtocol); if (!parsedUrl.ok) { return (0, n8n_workflow_1.createResultError)(parsedUrl.error); } return parsedUrl; } function errorHasCode(error, code) { return (!!error && typeof error === 'object' && (('code' in error && Number(error.code) === code) || ('message' in error && typeof error.message === 'string' && error.message.includes(code.toString())))); } function isUnauthorizedError(error) { return errorHasCode(error, 401); } function isForbiddenError(error) { return errorHasCode(error, 403); } function mapToNodeOperationError(node, error) { switch (error.type) { case 'invalid_url': return new n8n_workflow_1.NodeOperationError(node, error.error, { message: 'Could not connect to your MCP server. The provided URL is invalid.', }); case 'auth': return new n8n_workflow_1.NodeOperationError(node, error.error, { message: 'Could not connect to your MCP server. Authentication failed.', description: error.error.message, }); case 'connection': default: return new n8n_workflow_1.NodeOperationError(node, error.error, { message: 'Could not connect to your MCP server', description: error.error.message, }); } } async function connectMcpClient({ headers, serverTransport, endpointUrl, name, version, onUnauthorized, }) { const endpoint = normalizeAndValidateUrl(endpointUrl); if (!endpoint.ok) { return (0, n8n_workflow_1.createResultError)({ type: 'invalid_url', error: endpoint.error }); } const authFetch = createAuthFetch(headers, onUnauthorized); const client = new index_js_1.Client({ name, version: version.toString() }, { capabilities: {} }); if (serverTransport === 'httpStreamable') { try { const transport = new streamableHttp_js_1.StreamableHTTPClientTransport(endpoint.result, { fetch: authFetch, }); await client.connect(transport); return (0, n8n_workflow_1.createResultOk)(client); } catch (error) { if (isUnauthorizedError(error) || isForbiddenError(error)) { return (0, n8n_workflow_1.createResultError)({ type: 'auth', error: error }); } else { return (0, n8n_workflow_1.createResultError)({ type: 'connection', error: error }); } } } try { const sseTransport = new sse_js_1.SSEClientTransport(endpoint.result, { eventSourceInit: { fetch: async (url, init) => await authFetch(url, { ...init, headers: { ...headersToRecord(init?.headers), Accept: 'text/event-stream', }, }), }, fetch: authFetch, }); await client.connect(sseTransport); return (0, n8n_workflow_1.createResultOk)(client); } catch (error) { if (isUnauthorizedError(error) || isForbiddenError(error)) { return (0, n8n_workflow_1.createResultError)({ type: 'auth', error: error }); } else { return (0, n8n_workflow_1.createResultError)({ type: 'connection', error: error }); } } } function headersToRecord(headers) { if (!headers) return {}; if (headers instanceof Headers) return Object.fromEntries(headers.entries()); if (Array.isArray(headers)) return Object.fromEntries(headers); return headers; } function createAuthFetch(initialHeaders, onUnauthorized) { let headers = initialHeaders; return async (input, init) => { const response = await (0, ai_utilities_1.proxyFetch)(input, { ...init, headers: { ...headersToRecord(init?.headers), ...headers, }, }); if (response.status !== 401 || !onUnauthorized) { return response; } const refreshedHeaders = await onUnauthorized(headers); if (!refreshedHeaders) { return response; } headers = refreshedHeaders; return await (0, ai_utilities_1.proxyFetch)(input, { ...init, headers: { ...headersToRecord(init?.headers), ...headers, }, }); }; } async function getAuthHeaders(ctx, authentication) { switch (authentication) { case 'headerAuth': { const header = await ctx .getCredentials('httpHeaderAuth') .catch(() => null); if (!header) return {}; return { headers: { [header.name]: header.value } }; } case 'bearerAuth': { const result = await ctx .getCredentials('httpBearerAuth') .catch(() => null); if (!result) return {}; return { headers: { Authorization: `Bearer ${result.token}` } }; } case 'mcpOAuth2Api': { const result = await ctx .getCredentials('mcpOAuth2Api') .catch(() => null); if (!result) return {}; return { headers: { Authorization: `Bearer ${result.oauthTokenData.access_token}` } }; } case 'multipleHeadersAuth': { const result = await ctx .getCredentials('httpMultipleHeadersAuth') .catch(() => null); if (!result) return {}; return { headers: result.headers.values.reduce((acc, cur) => { acc[cur.name] = cur.value; return acc; }, {}), }; } case 'none': default: { return {}; } } } async function tryRefreshOAuth2Token(ctx, authentication, headers) { if (authentication !== 'mcpOAuth2Api') { return null; } let access_token = null; try { const result = (await ctx.helpers.refreshOAuth2Token.call(ctx, 'mcpOAuth2Api')); access_token = result?.access_token; } catch (error) { return null; } if (!access_token) { return null; } if (!headers) { return { Authorization: `Bearer ${access_token}`, }; } return { ...headers, Authorization: `Bearer ${access_token}`, }; } function isStructuredContent(value) { return (value !== undefined && value !== null && typeof value === 'object' && !Array.isArray(value)); } //# sourceMappingURL=utils.js.map