409e92d6ae
Build and Push Docker Images / Build Docker Image (push) Has been cancelled
Build and Push Docker Images / Build Railway Docker Image (push) Has been cancelled
Build and Publish n8n Docker Image / test-image (push) Has been cancelled
Dependency Compatibility Check / Fresh Install Dependency Check (push) Has been cancelled
Build and Publish n8n Docker Image / build-and-push (push) Has been cancelled
Build and Publish n8n Docker Image / create-release (push) Has been cancelled
Automated Release / Detect Version Change (push) Has been cancelled
Automated Release / Generate Release Notes (push) Has been cancelled
Automated Release / Create GitHub Release (push) Has been cancelled
Automated Release / Package MCPB Bundle (push) Has been cancelled
Automated Release / Build and Verify (push) Has been cancelled
Automated Release / Publish to NPM (push) Has been cancelled
Automated Release / Build and Push Docker Images (push) Has been cancelled
Automated Release / Update Documentation (push) Has been cancelled
Automated Release / Notify Release Completion (push) Has been cancelled
Secret Scan / secretlint (push) Has been cancelled
Test Suite / test (push) Has been cancelled
Test Suite / cjs-runtime (push) Has been cancelled
Test Suite / publish-results (push) Has been cancelled
107 lines
2.6 KiB
JavaScript
Executable File
107 lines
2.6 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
/**
|
|
* HTTP-to-stdio bridge for n8n-MCP
|
|
* Connects to n8n-MCP HTTP server and bridges stdio communication
|
|
*/
|
|
|
|
const http = require('http');
|
|
const readline = require('readline');
|
|
|
|
// Use MCP_URL from environment or construct from HOST/PORT if available
|
|
const defaultHost = process.env.HOST || 'localhost';
|
|
const defaultPort = process.env.PORT || '3000';
|
|
const MCP_URL = process.env.MCP_URL || `http://${defaultHost}:${defaultPort}/mcp`;
|
|
const AUTH_TOKEN = process.env.AUTH_TOKEN || process.argv[2];
|
|
|
|
if (!AUTH_TOKEN) {
|
|
console.error('Error: AUTH_TOKEN environment variable or first argument required');
|
|
process.exit(1);
|
|
}
|
|
|
|
// Parse URL
|
|
const url = new URL(MCP_URL);
|
|
|
|
// Create readline interface for stdio
|
|
const rl = readline.createInterface({
|
|
input: process.stdin,
|
|
output: process.stdout,
|
|
terminal: false
|
|
});
|
|
|
|
// Buffer for incomplete JSON messages
|
|
let buffer = '';
|
|
|
|
// Handle incoming stdio messages
|
|
rl.on('line', async (line) => {
|
|
try {
|
|
const message = JSON.parse(line);
|
|
|
|
// Forward to HTTP server
|
|
const options = {
|
|
hostname: url.hostname,
|
|
port: url.port || 80,
|
|
path: url.pathname,
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${AUTH_TOKEN}`,
|
|
'Accept': 'application/json, text/event-stream'
|
|
}
|
|
};
|
|
|
|
const req = http.request(options, (res) => {
|
|
let responseData = '';
|
|
|
|
res.on('data', (chunk) => {
|
|
responseData += chunk;
|
|
});
|
|
|
|
res.on('end', () => {
|
|
try {
|
|
// Try to parse as JSON
|
|
const response = JSON.parse(responseData);
|
|
console.log(JSON.stringify(response));
|
|
} catch (e) {
|
|
// Handle SSE format
|
|
const lines = responseData.split('\n');
|
|
for (const line of lines) {
|
|
if (line.startsWith('data: ')) {
|
|
try {
|
|
const data = JSON.parse(line.substring(6));
|
|
console.log(JSON.stringify(data));
|
|
} catch (e) {
|
|
// Ignore parse errors
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
req.on('error', (error) => {
|
|
console.error(JSON.stringify({
|
|
jsonrpc: '2.0',
|
|
error: {
|
|
code: -32000,
|
|
message: `HTTP request failed: ${error.message}`
|
|
},
|
|
id: message.id || null
|
|
}));
|
|
});
|
|
|
|
req.write(JSON.stringify(message));
|
|
req.end();
|
|
} catch (error) {
|
|
// Not valid JSON, ignore
|
|
}
|
|
});
|
|
|
|
// Handle process termination
|
|
process.on('SIGTERM', () => {
|
|
process.exit(0);
|
|
});
|
|
|
|
process.on('SIGINT', () => {
|
|
process.exit(0);
|
|
}); |