@cequenceai/mcp-cli
Version:
Cequence MCP CLI - Command-line tool for setting up Cequence MCP servers with AI clients
435 lines (434 loc) ⢠21 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const commander_1 = require("commander");
const chalk_1 = __importDefault(require("chalk"));
const ora_1 = __importDefault(require("ora"));
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const cursor_1 = require("./clients/cursor");
const claude_1 = require("./clients/claude");
const windsurf_1 = require("./clients/windsurf");
const claudecode_1 = require("./clients/claudecode");
const vscode_1 = require("./clients/vscode");
const validation_1 = require("./utils/validation");
// Read version from package.json
const packageJsonPath = path.join(__dirname, '..', 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
const program = new commander_1.Command();
program
.name('cequence-mcp')
.description('Cequence MCP CLI - Command-line tool for setting up Cequence MCP servers with AI clients')
.version(packageJson.version);
program
.command('cursor')
.description('Setup Cequence MCP server with Cursor IDE')
.requiredOption('-u, --url <url>', 'Cequence MCP server URL')
.option('-n, --name <name>', 'MCP server name')
.option('-k, --api-key <key>', 'API key for authentication (if required)')
.option('--no-refresh', 'Disable automatic token refresh (requires manual login when token expires)')
.action(async (options) => {
const spinner = (0, ora_1.default)('Setting up Cequence MCP server with Cursor IDE...').start();
try {
// Validate URL
if (!(0, validation_1.validateMcpUrl)(options.url)) {
spinner.fail('Invalid Cequence MCP server URL');
process.exit(1);
}
await (0, cursor_1.setupCursor)({
url: options.url,
name: options.name || 'Cequence MCP Gateway',
apiKey: options.apiKey,
noRefresh: options.noRefresh
});
spinner.succeed(chalk_1.default.green('ā
Cequence MCP server successfully configured for Cursor IDE!'));
console.log(chalk_1.default.cyan('\nš Next steps:'));
console.log(' 1. Restart Cursor IDE');
console.log(' 2. Open the command palette (Cmd/Ctrl + Shift + P)');
console.log(' 3. Look for MCP-related commands');
console.log(' 4. Your Cequence-secured APIs are now available as MCP tools');
}
catch (error) {
spinner.fail('Failed to setup Cequence MCP server');
console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : String(error));
process.exit(1);
}
});
program
.command('claude')
.description('Setup Cequence MCP server with Claude AI')
.requiredOption('-u, --url <url>', 'Cequence MCP server URL')
.option('-n, --name <name>', 'MCP server name')
.option('-k, --api-key <key>', 'API key for authentication (if required)')
.option('--no-refresh', 'Disable automatic token refresh (requires manual login when token expires)')
.action(async (options) => {
const spinner = (0, ora_1.default)('Setting up Cequence MCP server with Claude AI...').start();
try {
// Validate URL
if (!(0, validation_1.validateMcpUrl)(options.url)) {
spinner.fail('Invalid Cequence MCP server URL');
process.exit(1);
}
await (0, claude_1.setupClaude)({
url: options.url,
name: options.name || 'Cequence MCP Gateway',
apiKey: options.apiKey,
noRefresh: options.noRefresh
});
spinner.succeed(chalk_1.default.green('ā
Cequence MCP server successfully configured for Claude AI!'));
console.log(chalk_1.default.cyan('\nš Next steps:'));
console.log(' 1. Restart Claude AI application');
console.log(' 2. The Cequence MCP server should be available in your conversation');
console.log(' 3. Start using your secured APIs through Claude\'s interface');
}
catch (error) {
spinner.fail('Failed to setup Cequence MCP server');
console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : String(error));
process.exit(1);
}
});
program
.command('windsurf')
.description('Setup Cequence MCP server with Windsurf IDE')
.requiredOption('-u, --url <url>', 'Cequence MCP server URL')
.option('-n, --name <name>', 'MCP server name')
.option('-k, --api-key <key>', 'API key for authentication (if required)')
.option('--no-refresh', 'Disable automatic token refresh (requires manual login when token expires)')
.action(async (options) => {
const spinner = (0, ora_1.default)('Setting up Cequence MCP server with Windsurf IDE...').start();
try {
// Validate URL
if (!(0, validation_1.validateMcpUrl)(options.url)) {
spinner.fail('Invalid Cequence MCP server URL');
process.exit(1);
}
const result = await (0, windsurf_1.setupWindsurf)({
url: options.url,
name: options.name || 'Cequence MCP Gateway',
apiKey: options.apiKey,
noRefresh: options.noRefresh
});
if (!result.success) {
spinner.fail('Failed to setup Cequence MCP server');
console.error(chalk_1.default.red('Error:'), result.message);
process.exit(1);
}
spinner.succeed(chalk_1.default.green('ā
Cequence MCP server successfully configured for Windsurf IDE!'));
console.log(chalk_1.default.cyan(`\nš Configuration written to: ${result.configPath}`));
console.log(chalk_1.default.cyan('\nš Next steps:'));
console.log(' 1. Restart Windsurf IDE');
console.log(' 2. Open the command palette (Cmd/Ctrl + Shift + P)');
console.log(' 3. Look for MCP-related commands');
console.log(' 4. Your Cequence-secured APIs are now available as MCP tools');
}
catch (error) {
spinner.fail('Failed to setup Cequence MCP server');
console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : String(error));
process.exit(1);
}
});
program
.command('claudecode')
.description('Setup Cequence MCP server with Claude Code')
.requiredOption('-u, --url <url>', 'Cequence MCP server URL')
.option('-n, --name <name>', 'MCP server name')
.option('-t, --transport <transport>', 'Transport type (http or sse)', 'http')
.option('-k, --api-key <key>', 'API key for authentication (if required)')
.action(async (options) => {
const spinner = (0, ora_1.default)('Setting up Cequence MCP server with Claude Code...').start();
try {
// Validate URL
if (!(0, validation_1.validateMcpUrl)(options.url)) {
spinner.fail('Invalid Cequence MCP server URL');
process.exit(1);
}
// Validate transport
const transport = options.transport?.toLowerCase();
if (transport !== 'http' && transport !== 'sse') {
spinner.fail('Invalid transport type. Use "http" or "sse"');
process.exit(1);
}
const result = await (0, claudecode_1.setupClaudeCode)({
url: options.url,
name: options.name || 'Cequence MCP Gateway',
apiKey: options.apiKey
}, transport);
if (!result.success) {
spinner.fail('Failed to setup Cequence MCP server');
console.error(chalk_1.default.red('Error:'), result.message);
process.exit(1);
}
spinner.succeed(chalk_1.default.green('ā
Cequence MCP server successfully configured for Claude Code!'));
console.log(chalk_1.default.cyan('\nš Next steps:'));
console.log(' 1. Claude Code will automatically detect the new MCP server');
console.log(' 2. You can verify with: claude mcp list');
console.log(' 3. Start using your secured APIs through Claude Code');
}
catch (error) {
spinner.fail('Failed to setup Cequence MCP server');
console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : String(error));
process.exit(1);
}
});
program
.command('vscode')
.description('Setup Cequence MCP server with VS Code')
.requiredOption('-u, --url <url>', 'Cequence MCP server URL')
.option('-n, --name <name>', 'MCP server name')
.option('-g, --global', 'Configure globally for all workspaces (default: workspace-specific)')
.option('-w, --workspace <path>', 'Workspace path for project-specific config')
.option('-k, --api-key <key>', 'API key for authentication (if required)')
.action(async (options) => {
const configType = options.global ? 'global' : 'workspace';
const spinner = (0, ora_1.default)(`Setting up Cequence MCP server with VS Code (${configType})...`).start();
try {
// Validate URL
if (!(0, validation_1.validateMcpUrl)(options.url)) {
spinner.fail('Invalid Cequence MCP server URL');
process.exit(1);
}
const result = await (0, vscode_1.setupVSCode)({
url: options.url,
name: options.name || 'Cequence MCP Gateway',
apiKey: options.apiKey
}, options.global || false, options.workspace);
if (!result.success) {
spinner.fail('Failed to setup Cequence MCP server');
console.error(chalk_1.default.red('Error:'), result.message);
process.exit(1);
}
spinner.succeed(chalk_1.default.green('ā
Cequence MCP server successfully configured for VS Code!'));
console.log(chalk_1.default.cyan(`\nš Configuration written to: ${result.configPath}`));
console.log(chalk_1.default.cyan('\nš Next steps:'));
console.log(' 1. Reload VS Code (Cmd/Ctrl + Shift + P ā "Developer: Reload Window")');
console.log(' 2. Ensure GitHub Copilot is installed and activated');
console.log(' 3. The MCP server should appear in your Copilot tools');
console.log(' 4. Your Cequence-secured APIs are now available as MCP tools');
}
catch (error) {
spinner.fail('Failed to setup Cequence MCP server');
console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : String(error));
process.exit(1);
}
});
program
.command('serve')
.description('Start MCP bridge server (internal use by Claude AI)')
.requiredOption('-u, --url <url>', 'HTTP MCP server URL to bridge')
.option('-n, --name <name>', 'MCP server name')
.option('-k, --api-key <key>', 'API key for authentication (if required)')
.action(async (options) => {
// This command creates a stdio-based MCP server that bridges to HTTP
const http = require('http');
const https = require('https');
const { URL } = require('url');
try {
const serverUrl = new URL(options.url);
const client = serverUrl.protocol === 'https:' ? https : http;
// Set up stdio for MCP protocol
process.stdin.setEncoding('utf8');
process.stdin.resume();
let buffer = '';
process.stdin.on('data', async (chunk) => {
buffer += chunk;
// Process complete JSON-RPC messages (each ends with newline)
let newlineIndex;
while ((newlineIndex = buffer.indexOf('\n')) >= 0) {
const line = buffer.slice(0, newlineIndex).trim();
buffer = buffer.slice(newlineIndex + 1);
if (line) {
try {
const request = JSON.parse(line);
// Validate JSON-RPC request structure
if (!request.jsonrpc || !request.method) {
const errorResponse = {
jsonrpc: '2.0',
id: request.id || null,
error: {
code: -32600,
message: 'Invalid Request: Missing jsonrpc or method'
}
};
process.stdout.write(JSON.stringify(errorResponse) + '\n');
continue;
}
// Forward request to HTTP MCP server
const postData = JSON.stringify(request);
const headers = {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData),
'Accept': 'application/json, text/event-stream'
};
// Add API key header if provided
if (options.apiKey) {
headers['Authorization'] = `Bearer ${options.apiKey}`;
}
const requestOptions = {
hostname: serverUrl.hostname,
port: serverUrl.port,
path: serverUrl.pathname,
method: 'POST',
headers,
timeout: 30000 // 30 second timeout
};
const httpReq = client.request(requestOptions, (httpRes) => {
let responseData = '';
httpRes.on('data', (chunk) => {
responseData += chunk;
});
httpRes.on('end', () => {
try {
if (responseData.trim()) {
const response = JSON.parse(responseData);
// Ensure response has proper JSON-RPC structure
if (!response.jsonrpc) {
response.jsonrpc = '2.0';
}
if (response.id === undefined) {
response.id = request.id;
}
process.stdout.write(JSON.stringify(response) + '\n');
}
else {
// Empty response - send error
const errorResponse = {
jsonrpc: '2.0',
id: request.id || null,
error: {
code: -32603,
message: 'Empty response from HTTP server'
}
};
process.stdout.write(JSON.stringify(errorResponse) + '\n');
}
}
catch (parseError) {
// Invalid JSON response
const errorResponse = {
jsonrpc: '2.0',
id: request.id || null,
error: {
code: -32603,
message: `Invalid JSON response from HTTP server: ${parseError?.message || 'Unknown error'}`
}
};
process.stdout.write(JSON.stringify(errorResponse) + '\n');
}
});
});
httpReq.on('timeout', () => {
httpReq.destroy();
const errorResponse = {
jsonrpc: '2.0',
id: request.id || null,
error: {
code: -32603,
message: 'Request timeout'
}
};
process.stdout.write(JSON.stringify(errorResponse) + '\n');
});
httpReq.on('error', (error) => {
const errorResponse = {
jsonrpc: '2.0',
id: request.id || null,
error: {
code: -32603,
message: `HTTP request error: ${error?.message || 'Unknown error'}`
}
};
process.stdout.write(JSON.stringify(errorResponse) + '\n');
});
httpReq.write(postData);
httpReq.end();
}
catch (parseError) {
// Invalid JSON input
const errorResponse = {
jsonrpc: '2.0',
id: null,
error: {
code: -32700,
message: `Parse error: ${parseError?.message || 'Unknown error'}`
}
};
process.stdout.write(JSON.stringify(errorResponse) + '\n');
}
}
}
});
process.stdin.on('end', () => {
process.exit(0);
});
process.stdin.on('error', (error) => {
console.error('Stdin error:', error);
process.exit(1);
});
}
catch (error) {
console.error('Bridge server error:', error);
process.exit(1);
}
});
program
.command('list')
.description('List configured Cequence MCP servers')
.action(async () => {
console.log(chalk_1.default.blue('š Configured Cequence MCP Servers:'));
// TODO: Implement listing functionality
console.log(chalk_1.default.yellow(' Feature coming soon...'));
});
// Handle unknown commands
program.on('command:*', () => {
console.error(chalk_1.default.red('Invalid command:'), program.args.join(' '));
console.log(chalk_1.default.cyan('Available commands:'));
console.log(' cursor - Setup Cequence MCP server with Cursor IDE');
console.log(' claude - Setup Cequence MCP server with Claude Desktop');
console.log(' claudecode - Setup Cequence MCP server with Claude Code');
console.log(' vscode - Setup Cequence MCP server with VS Code');
console.log(' windsurf - Setup Cequence MCP server with Windsurf IDE');
console.log(' serve - Start MCP bridge server (internal use)');
console.log(' list - List configured Cequence MCP servers');
process.exit(1);
});
// Show help when no command is provided
if (!process.argv.slice(2).length) {
program.outputHelp();
}
program.parse(process.argv);