diff --git a/packages/@n8n/nodes-langchain/nodes/mcp/McpClientTool/__test__/McpClientTool.node.test.ts b/packages/@n8n/nodes-langchain/nodes/mcp/McpClientTool/__test__/McpClientTool.node.test.ts index 8a413e5d168..63108cef58b 100644 --- a/packages/@n8n/nodes-langchain/nodes/mcp/McpClientTool/__test__/McpClientTool.node.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/mcp/McpClientTool/__test__/McpClientTool.node.test.ts @@ -292,7 +292,9 @@ describe('McpClientTool', () => { it('should successfully execute a tool', async () => { jest.spyOn(Client.prototype, 'connect').mockResolvedValue(); - jest.spyOn(Client.prototype, 'callTool').mockResolvedValue({ content: 'Sunny' }); + jest + .spyOn(Client.prototype, 'callTool') + .mockResolvedValue({ toolResult: 'Sunny', content: [] }); jest.spyOn(Client.prototype, 'listTools').mockResolvedValue({ tools: [ { @@ -326,9 +328,11 @@ describe('McpClientTool', () => { it('should handle tool errors', async () => { jest.spyOn(Client.prototype, 'connect').mockResolvedValue(); - jest - .spyOn(Client.prototype, 'callTool') - .mockResolvedValue({ isError: true, content: [{ text: 'Weather unknown at location' }] }); + jest.spyOn(Client.prototype, 'callTool').mockResolvedValue({ + isError: true, + toolResult: 'Weather unknown at location', + content: [{ text: 'Weather unknown at location' }], + }); jest.spyOn(Client.prototype, 'listTools').mockResolvedValue({ tools: [ { diff --git a/packages/@n8n/nodes-langchain/nodes/mcp/shared/utils.ts b/packages/@n8n/nodes-langchain/nodes/mcp/shared/utils.ts index 40134dcdc9f..dc60019b415 100644 --- a/packages/@n8n/nodes-langchain/nodes/mcp/shared/utils.ts +++ b/packages/@n8n/nodes-langchain/nodes/mcp/shared/utils.ts @@ -114,7 +114,7 @@ export async function connectMcpClient({ return createResultError({ type: 'invalid_url', error: endpoint.error }); } - const client = new Client({ name, version: version.toString() }, { capabilities: { tools: {} } }); + const client = new Client({ name, version: version.toString() }, { capabilities: {} }); if (serverTransport === 'httpStreamable') { try { diff --git a/packages/@n8n/nodes-langchain/package.json b/packages/@n8n/nodes-langchain/package.json index da12d9a8d45..1c17987d915 100644 --- a/packages/@n8n/nodes-langchain/package.json +++ b/packages/@n8n/nodes-langchain/package.json @@ -203,7 +203,7 @@ "@langchain/redis": "1.0.1", "@langchain/textsplitters": "1.0.1", "@langchain/weaviate": "1.0.1", - "@modelcontextprotocol/sdk": "1.20.0", + "@modelcontextprotocol/sdk": "1.24.0", "@mozilla/readability": "0.6.0", "@n8n/client-oauth2": "workspace:*", "@n8n/config": "workspace:*", diff --git a/packages/cli/src/modules/mcp/__tests__/execute-workflow.tool.test.ts b/packages/cli/src/modules/mcp/__tests__/execute-workflow.tool.test.ts index 7c6ac46bd32..f9a5fa21772 100644 --- a/packages/cli/src/modules/mcp/__tests__/execute-workflow.tool.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/execute-workflow.tool.test.ts @@ -738,7 +738,7 @@ describe('execute-workflow MCP tool', () => { ); // Call through the tool handler to test telemetry - await tool.handler({ workflowId: 'error-tracking' }, {} as any); + await tool.handler({ workflowId: 'error-tracking', inputs: undefined }, {} as any); expect(telemetry.track).toHaveBeenCalledWith( 'User called mcp tool', diff --git a/packages/cli/src/modules/mcp/__tests__/mcp-oauth-service.test.ts b/packages/cli/src/modules/mcp/__tests__/mcp-oauth-service.test.ts index 9a2b77127cf..05eca7a3b47 100644 --- a/packages/cli/src/modules/mcp/__tests__/mcp-oauth-service.test.ts +++ b/packages/cli/src/modules/mcp/__tests__/mcp-oauth-service.test.ts @@ -68,6 +68,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: SUPPORTED_SCOPES.join(' '), + logo_uri: undefined, + tos_uri: undefined, }); }); @@ -111,6 +113,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read write', + logo_uri: undefined, + tos_uri: undefined, }; oauthClientRepository.insert.mockResolvedValue({} as any); @@ -140,6 +144,8 @@ describe('McpOAuthService', () => { client_secret_expires_at: 1234567890, response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; oauthClientRepository.insert.mockResolvedValue({} as any); @@ -166,6 +172,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; const error = new Error('Database error'); @@ -192,6 +200,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read write', + logo_uri: undefined, + tos_uri: undefined, }; const params = { @@ -222,6 +232,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; const params = { @@ -250,6 +262,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; const params = { @@ -291,6 +305,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; authorizationCodeService.getCodeChallenge.mockResolvedValue('challenge-123'); @@ -315,6 +331,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; const authRecord = { @@ -365,6 +383,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; const authRecord = { @@ -398,6 +418,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; const newTokens = { @@ -447,6 +469,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; tokenService.revokeAccessToken.mockResolvedValue(true); @@ -469,6 +493,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; tokenService.revokeRefreshToken.mockResolvedValue(true); @@ -491,6 +517,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; tokenService.revokeAccessToken.mockResolvedValue(true); @@ -512,6 +540,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; tokenService.revokeAccessToken.mockResolvedValue(false); @@ -534,6 +564,8 @@ describe('McpOAuthService', () => { token_endpoint_auth_method: 'none', response_types: ['code'], scope: 'read', + logo_uri: undefined, + tos_uri: undefined, }; tokenService.revokeAccessToken.mockResolvedValue(false); diff --git a/packages/cli/src/modules/mcp/mcp-oauth-service.ts b/packages/cli/src/modules/mcp/mcp-oauth-service.ts index e84127eb8f9..13c76e58e10 100644 --- a/packages/cli/src/modules/mcp/mcp-oauth-service.ts +++ b/packages/cli/src/modules/mcp/mcp-oauth-service.ts @@ -57,6 +57,8 @@ export class McpOAuthService implements OAuthServerProvider { }), response_types: ['code'], scope: SUPPORTED_SCOPES.join(' '), + logo_uri: undefined, + tos_uri: undefined, }; }, registerClient: async ( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2779171a65a..2b78bafa3bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -378,7 +378,7 @@ importers: version: 1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)) '@langchain/langgraph': specifier: 1.0.2 - version: 1.0.2(@langchain/core@1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(zod-to-json-schema@3.24.6(zod@3.25.67))(zod@3.25.67) + version: 1.0.2(@langchain/core@1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(zod-to-json-schema@3.25.0(zod@3.25.67))(zod@3.25.67) '@langchain/openai': specifier: 'catalog:' version: 1.1.3(@langchain/core@1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -1078,7 +1078,7 @@ importers: version: 5.3.0(encoding@0.1.13) '@google/genai': specifier: 1.19.0 - version: 1.19.0(@modelcontextprotocol/sdk@1.20.0)(bufferutil@4.0.9)(utf-8-validate@5.0.10) + version: 1.19.0(@modelcontextprotocol/sdk@1.24.0(zod@3.25.67))(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@google/generative-ai': specifier: 0.21.0 version: 0.21.0 @@ -1099,7 +1099,7 @@ importers: version: 1.0.1(@langchain/core@1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13) '@langchain/community': specifier: 'catalog:' - version: 1.0.5(e0c14078fc79d0957987f04ba80f836a) + version: 1.0.5(98d49f2e32edc045c97e45bba7d1d36c) '@langchain/core': specifier: 'catalog:' version: 1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)) @@ -1140,8 +1140,8 @@ importers: specifier: 1.0.1 version: 1.0.1(@langchain/core@1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13) '@modelcontextprotocol/sdk': - specifier: 1.20.0 - version: 1.20.0 + specifier: 1.24.0 + version: 1.24.0(zod@3.25.67) '@mozilla/readability': specifier: 0.6.0 version: 0.6.0 @@ -6248,9 +6248,15 @@ packages: '@mistralai/mistralai@1.10.0': resolution: {integrity: sha512-tdIgWs4Le8vpvPiUEWne6tK0qbVc+jMenujnvTqOjogrJUsCSQhus0tHTU1avDDh5//Rq2dFgP9mWRAdIEoBqg==} - '@modelcontextprotocol/sdk@1.20.0': - resolution: {integrity: sha512-kOQ4+fHuT4KbR2iq2IjeV32HiihueuOf1vJkq18z08CLZ1UQrTc8BXJpVfxZkq45+inLLD+D4xx4nBjUelJa4Q==} + '@modelcontextprotocol/sdk@1.24.0': + resolution: {integrity: sha512-D8h5KXY2vHFW8zTuxn2vuZGN0HGrQ5No6LkHwlEA9trVgNdPL3TF1dSqKA7Dny6BbBYKSW/rOBDXdC8KJAjUCg==} engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + zod: 3.25.67 + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true '@mongodb-js/saslprep@1.1.9': resolution: {integrity: sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==} @@ -13261,6 +13267,9 @@ packages: jose@6.0.11: resolution: {integrity: sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg==} + jose@6.1.2: + resolution: {integrity: sha512-MpcPtHLE5EmztuFIqB0vzHAWJPpmN1E6L4oo+kze56LIs3MyXIj9ZHMDxqOvkP38gBR7K1v3jqd4WU2+nrfONQ==} + joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -18414,6 +18423,11 @@ packages: peerDependencies: zod: 3.25.67 + zod-to-json-schema@3.25.0: + resolution: {integrity: sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==} + peerDependencies: + zod: 3.25.67 + zod@3.25.67: resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} @@ -21076,13 +21090,13 @@ snapshots: transitivePeerDependencies: - encoding - '@browserbasehq/stagehand@1.9.0(@playwright/test@1.56.0)(bufferutil@4.0.9)(deepmerge@4.3.1)(dotenv@16.6.1)(encoding@0.1.13)(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(utf-8-validate@5.0.10)(zod@3.25.67)': + '@browserbasehq/stagehand@1.9.0(@playwright/test@1.56.0)(bufferutil@4.0.9)(deepmerge@4.3.1)(dotenv@17.2.3)(encoding@0.1.13)(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(utf-8-validate@5.0.10)(zod@3.25.67)': dependencies: '@anthropic-ai/sdk': 0.27.3(encoding@0.1.13) '@browserbasehq/sdk': 2.6.0(encoding@0.1.13) '@playwright/test': 1.56.0 deepmerge: 4.3.1 - dotenv: 16.6.1 + dotenv: 17.2.3 openai: 6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67) sharp: 0.33.5 ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) @@ -21655,12 +21669,12 @@ snapshots: - encoding - supports-color - '@google/genai@1.19.0(@modelcontextprotocol/sdk@1.20.0)(bufferutil@4.0.9)(utf-8-validate@5.0.10)': + '@google/genai@1.19.0(@modelcontextprotocol/sdk@1.24.0(zod@3.25.67))(bufferutil@4.0.9)(utf-8-validate@5.0.10)': dependencies: google-auth-library: 9.15.1 ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) optionalDependencies: - '@modelcontextprotocol/sdk': 1.20.0 + '@modelcontextprotocol/sdk': 1.24.0(zod@3.25.67) transitivePeerDependencies: - bufferutil - supports-color @@ -22303,9 +22317,9 @@ snapshots: - aws-crt - encoding - '@langchain/community@1.0.5(e0c14078fc79d0957987f04ba80f836a)': + '@langchain/community@1.0.5(98d49f2e32edc045c97e45bba7d1d36c)': dependencies: - '@browserbasehq/stagehand': 1.9.0(@playwright/test@1.56.0)(bufferutil@4.0.9)(deepmerge@4.3.1)(dotenv@16.6.1)(encoding@0.1.13)(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(utf-8-validate@5.0.10)(zod@3.25.67) + '@browserbasehq/stagehand': 1.9.0(@playwright/test@1.56.0)(bufferutil@4.0.9)(deepmerge@4.3.1)(dotenv@17.2.3)(encoding@0.1.13)(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(utf-8-validate@5.0.10)(zod@3.25.67) '@ibm-cloud/watsonx-ai': 1.1.2 '@langchain/classic': 1.0.5(@langchain/core@1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(cheerio@1.0.0)(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@langchain/core': 1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)) @@ -22434,7 +22448,7 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - '@langchain/langgraph@1.0.2(@langchain/core@1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(zod-to-json-schema@3.24.6(zod@3.25.67))(zod@3.25.67)': + '@langchain/langgraph@1.0.2(@langchain/core@1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(zod-to-json-schema@3.25.0(zod@3.25.67))(zod@3.25.67)': dependencies: '@langchain/core': 1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)) '@langchain/langgraph-checkpoint': 1.0.0(@langchain/core@1.1.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.9.1(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))) @@ -22442,7 +22456,7 @@ snapshots: uuid: 10.0.0 zod: 3.25.67 optionalDependencies: - zod-to-json-schema: 3.24.6(zod@3.25.67) + zod-to-json-schema: 3.25.0(zod@3.25.67) transitivePeerDependencies: - react - react-dom @@ -22616,9 +22630,10 @@ snapshots: zod: 3.25.67 zod-to-json-schema: 3.24.6(zod@3.25.67) - '@modelcontextprotocol/sdk@1.20.0': + '@modelcontextprotocol/sdk@1.24.0(zod@3.25.67)': dependencies: - ajv: 6.12.6 + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) content-type: 1.0.5 cors: 2.8.5 cross-spawn: 7.0.6 @@ -22626,10 +22641,11 @@ snapshots: eventsource-parser: 3.0.1 express: 5.1.0 express-rate-limit: 7.5.0(express@5.1.0) + jose: 6.1.2 pkce-challenge: 5.0.0(patch_hash=651e785d0b7bbf5be9210e1e895c39a16dc3ce8a5a3843b4819565fb6e175b90) raw-body: 3.0.0 zod: 3.25.67 - zod-to-json-schema: 3.24.6(zod@3.25.67) + zod-to-json-schema: 3.25.0(zod@3.25.67) transitivePeerDependencies: - supports-color @@ -31406,6 +31422,8 @@ snapshots: jose@6.0.11: {} + jose@6.1.2: {} + joycon@3.1.1: {} js-base64@3.7.2(patch_hash=bb02fdf69495c7b0768791b60ab6e1a002053b8decd19a174f5755691e5c9500): {} @@ -37483,6 +37501,10 @@ snapshots: dependencies: zod: 3.25.67 + zod-to-json-schema@3.25.0(zod@3.25.67): + dependencies: + zod: 3.25.67 + zod@3.25.67: {} zod@4.1.12: {}