130 lines
3.8 KiB
JavaScript
130 lines
3.8 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* SQL Server MCP Server - Node.js 实现
|
|
* 提供 execute_sql 工具用于执行 SQL 语句
|
|
*/
|
|
|
|
const sql = require('mssql');
|
|
const readline = require('readline');
|
|
|
|
const config = {
|
|
server: process.env.MSSQL_SERVER || '192.168.195.15',
|
|
port: parseInt(process.env.MSSQL_PORT) || 1433,
|
|
user: process.env.MSSQL_USER || 'sa',
|
|
password: process.env.MSSQL_PASSWORD || 'Dbt@com@123',
|
|
database: process.env.MSSQL_DATABASE || 'honey_box',
|
|
options: {
|
|
encrypt: false,
|
|
trustServerCertificate: true
|
|
}
|
|
};
|
|
|
|
let pool = null;
|
|
|
|
async function getPool() {
|
|
if (!pool) {
|
|
pool = await sql.connect(config);
|
|
}
|
|
return pool;
|
|
}
|
|
|
|
async function executeSQL(query) {
|
|
const p = await getPool();
|
|
const result = await p.request().query(query);
|
|
return result;
|
|
}
|
|
|
|
function sendResponse(id, result) {
|
|
const response = { jsonrpc: '2.0', id, result };
|
|
process.stdout.write(JSON.stringify(response) + '\n');
|
|
}
|
|
|
|
function sendError(id, code, message) {
|
|
const response = { jsonrpc: '2.0', id, error: { code, message } };
|
|
process.stdout.write(JSON.stringify(response) + '\n');
|
|
}
|
|
|
|
async function handleRequest(request) {
|
|
const { id, method, params } = request;
|
|
|
|
try {
|
|
switch (method) {
|
|
case 'initialize':
|
|
sendResponse(id, {
|
|
protocolVersion: '2024-11-05',
|
|
capabilities: { tools: {} },
|
|
serverInfo: { name: 'mssql-node-mcp', version: '1.0.0' }
|
|
});
|
|
break;
|
|
|
|
case 'tools/list':
|
|
sendResponse(id, {
|
|
tools: [{
|
|
name: 'execute_sql',
|
|
description: 'Execute SQL query on SQL Server database',
|
|
inputSchema: {
|
|
type: 'object',
|
|
properties: {
|
|
query: { type: 'string', description: 'SQL query to execute' }
|
|
},
|
|
required: ['query']
|
|
}
|
|
}]
|
|
});
|
|
break;
|
|
|
|
case 'tools/call':
|
|
if (params.name === 'execute_sql') {
|
|
const query = params.arguments.query;
|
|
const result = await executeSQL(query);
|
|
|
|
let content;
|
|
if (result.recordset && result.recordset.length > 0) {
|
|
content = JSON.stringify(result.recordset, null, 2);
|
|
} else if (result.rowsAffected) {
|
|
content = `Rows affected: ${result.rowsAffected.join(', ')}`;
|
|
} else {
|
|
content = 'Query executed successfully';
|
|
}
|
|
|
|
sendResponse(id, {
|
|
content: [{ type: 'text', text: content }]
|
|
});
|
|
} else {
|
|
sendError(id, -32601, `Unknown tool: ${params.name}`);
|
|
}
|
|
break;
|
|
|
|
case 'notifications/initialized':
|
|
case 'notifications/cancelled':
|
|
// 忽略通知
|
|
break;
|
|
|
|
default:
|
|
if (id !== undefined) {
|
|
sendError(id, -32601, `Method not found: ${method}`);
|
|
}
|
|
}
|
|
} catch (err) {
|
|
if (id !== undefined) {
|
|
sendError(id, -32000, err.message);
|
|
}
|
|
}
|
|
}
|
|
|
|
const rl = readline.createInterface({ input: process.stdin });
|
|
|
|
rl.on('line', async (line) => {
|
|
try {
|
|
const request = JSON.parse(line);
|
|
await handleRequest(request);
|
|
} catch (err) {
|
|
// 忽略解析错误
|
|
}
|
|
});
|
|
|
|
process.on('SIGINT', async () => {
|
|
if (pool) await pool.close();
|
|
process.exit(0);
|
|
});
|