import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import chalk from 'chalk';
import { spawn } from 'child_process';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Create MCP client
const client = new Client();
// Function to start the MCP server
async function startMcpServer() {
// Get the absolute path to the server executable
const serverPath = path.resolve(__dirname, '../../git-analytics-mcp-server/dist/index.js');
console.log(chalk.blue('\n[Client] Server path:', serverPath));
if (!serverPath) {
throw new Error('Server path is undefined');
}
const config = {
command: 'node',
args: [serverPath],
env: {
GIT_ANALYTICS_DEFAULT_PATH: process.cwd(),
GIT_ANALYTICS_DEBUG: 'true' // Enable debug mode to see more information
}
};
console.log(chalk.blue('[Client] Starting server with config:', JSON.stringify(config, null, 2)));
const serverProcess = spawn(config.command, config.args, {
env: { ...process.env, ...config.env }
});
// Handle server output
serverProcess.stdout.on('data', (data) => {
console.log(chalk.blue('[Server Output]', data.toString()));
});
serverProcess.stderr.on('data', (data) => {
console.error(chalk.red('[Server Error]', data.toString()));
});
// Create transport
console.log(chalk.blue('[Client] Creating stdio transport...'));
const transport = new StdioClientTransport(serverProcess);
transport.on('message', (msg) => {
console.log('[Server] Incoming message:', msg);
});
console.log(chalk.blue('[Client] Connecting to server...'));
await client.connect(transport);
console.log(chalk.green('[Client] Connected to server successfully'));
return { client, serverProcess };
}
// Function to list available tools
async function listTools(client) {
try {
console.log(chalk.blue('\n[Client] Requesting available tools...'));
const response = await client.listTools();
console.log(chalk.green('[Client] Available Tools:'));
response.tools.forEach(tool => {
console.log(chalk.yellow(`\n[Client] ${tool.name}:`));
console.log(` Description: ${tool.description}`);
console.log(' Parameters:');
Object.entries(tool.inputSchema.properties).forEach(([name, prop]) => {
console.log(` - ${name}: ${prop.description}`);
});
});
} catch (error) {
console.error(chalk.red('[Client] Error listing tools:', error.message));
}
}
// Function to call a tool
async function callTool(client, toolName, args = {}) {
try {
console.log(chalk.blue(`\n[Client] Calling tool: ${toolName}`));
console.log(chalk.yellow('[Client] Arguments:', JSON.stringify(args, null, 2)));
const response = await client.callTool(toolName, args);
if (response.content) {
console.log(chalk.green('[Client] Received response:'));
response.content.forEach(content => {
if (content.type === 'text') {
console.log(content.text);
}
});
}
} catch (error) {
console.error(chalk.red(`[Client] Error calling ${toolName}:`, error.message));
}
}
// Main function
async function main() {
try {
console.log(chalk.blue('\n[Client] Starting MCP client...'));
const { client, serverProcess } = await startMcpServer();
// List available tools
await listTools(client);
// Example: Get repository overview
await callTool(client, 'get_repository_overview', {
path: process.cwd()
});
// Example: Get author stats
await callTool(client, 'get_author_stats', {
path: process.cwd()
});
// Cleanup
console.log(chalk.blue('\n[Client] Cleaning up...'));
serverProcess.kill();
console.log(chalk.green('[Client] Done'));
} catch (error) {
console.error(chalk.red('[Client] Error:', error.message));
process.exit(1);
}
}
main();