mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-03-18 00:13:08 +00:00
This commit adds a complete integration between n8n workflow automation and the Model Context Protocol (MCP): Features: - MCP server that exposes n8n workflows as tools, resources, and prompts - Custom n8n node for connecting to MCP servers from workflows - Bidirectional bridge for data format conversion - Token-based authentication and credential management - Comprehensive error handling and logging - Full test coverage for core components Infrastructure: - TypeScript/Node.js project setup with proper build configuration - Docker support with multi-stage builds - Development and production docker-compose configurations - Installation script for n8n custom node deployment Documentation: - Detailed README with usage examples and API reference - Environment configuration templates - Troubleshooting guide 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
150 lines
3.5 KiB
TypeScript
150 lines
3.5 KiB
TypeScript
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
import { WebSocketClientTransport } from '@modelcontextprotocol/sdk/client/websocket.js';
|
|
import {
|
|
CallToolRequest,
|
|
ListToolsRequest,
|
|
ListResourcesRequest,
|
|
ReadResourceRequest,
|
|
ListPromptsRequest,
|
|
GetPromptRequest,
|
|
CallToolResultSchema,
|
|
ListToolsResultSchema,
|
|
ListResourcesResultSchema,
|
|
ReadResourceResultSchema,
|
|
ListPromptsResultSchema,
|
|
GetPromptResultSchema,
|
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
|
|
export interface MCPClientConfig {
|
|
serverUrl: string;
|
|
authToken?: string;
|
|
connectionType: 'http' | 'websocket' | 'stdio';
|
|
}
|
|
|
|
export class MCPClient {
|
|
private client: Client;
|
|
private config: MCPClientConfig;
|
|
private connected: boolean = false;
|
|
|
|
constructor(config: MCPClientConfig) {
|
|
this.config = config;
|
|
this.client = new Client(
|
|
{
|
|
name: 'n8n-mcp-client',
|
|
version: '1.0.0',
|
|
},
|
|
{
|
|
capabilities: {},
|
|
}
|
|
);
|
|
}
|
|
|
|
async connect(): Promise<void> {
|
|
if (this.connected) {
|
|
return;
|
|
}
|
|
|
|
let transport;
|
|
|
|
switch (this.config.connectionType) {
|
|
case 'websocket':
|
|
const wsUrl = this.config.serverUrl.replace(/^http/, 'ws');
|
|
transport = new WebSocketClientTransport(new URL(wsUrl));
|
|
break;
|
|
|
|
case 'stdio':
|
|
// For stdio, the serverUrl should be the command to execute
|
|
const [command, ...args] = this.config.serverUrl.split(' ');
|
|
transport = new StdioClientTransport({
|
|
command,
|
|
args,
|
|
});
|
|
break;
|
|
|
|
default:
|
|
throw new Error(`HTTP transport is not yet supported for MCP clients`);
|
|
}
|
|
|
|
await this.client.connect(transport);
|
|
this.connected = true;
|
|
}
|
|
|
|
async disconnect(): Promise<void> {
|
|
if (this.connected) {
|
|
await this.client.close();
|
|
this.connected = false;
|
|
}
|
|
}
|
|
|
|
async listTools(): Promise<any> {
|
|
await this.ensureConnected();
|
|
return await this.client.request(
|
|
{ method: 'tools/list' } as ListToolsRequest,
|
|
ListToolsResultSchema
|
|
);
|
|
}
|
|
|
|
async callTool(name: string, args: any): Promise<any> {
|
|
await this.ensureConnected();
|
|
return await this.client.request(
|
|
{
|
|
method: 'tools/call',
|
|
params: {
|
|
name,
|
|
arguments: args,
|
|
},
|
|
} as CallToolRequest,
|
|
CallToolResultSchema
|
|
);
|
|
}
|
|
|
|
async listResources(): Promise<any> {
|
|
await this.ensureConnected();
|
|
return await this.client.request(
|
|
{ method: 'resources/list' } as ListResourcesRequest,
|
|
ListResourcesResultSchema
|
|
);
|
|
}
|
|
|
|
async readResource(uri: string): Promise<any> {
|
|
await this.ensureConnected();
|
|
return await this.client.request(
|
|
{
|
|
method: 'resources/read',
|
|
params: {
|
|
uri,
|
|
},
|
|
} as ReadResourceRequest,
|
|
ReadResourceResultSchema
|
|
);
|
|
}
|
|
|
|
async listPrompts(): Promise<any> {
|
|
await this.ensureConnected();
|
|
return await this.client.request(
|
|
{ method: 'prompts/list' } as ListPromptsRequest,
|
|
ListPromptsResultSchema
|
|
);
|
|
}
|
|
|
|
async getPrompt(name: string, args?: any): Promise<any> {
|
|
await this.ensureConnected();
|
|
return await this.client.request(
|
|
{
|
|
method: 'prompts/get',
|
|
params: {
|
|
name,
|
|
arguments: args,
|
|
},
|
|
} as GetPromptRequest,
|
|
GetPromptResultSchema
|
|
);
|
|
}
|
|
|
|
private async ensureConnected(): Promise<void> {
|
|
if (!this.connected) {
|
|
await this.connect();
|
|
}
|
|
}
|
|
} |