@bluspace/mssql-mcp-server
Version:
Microsoft SQL Server MCP (Model Context Protocol) Server - AI-powered database interaction tool
127 lines (126 loc) • 5.55 kB
JavaScript
import { Command } from "commander";
import { z } from "zod";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { initDb } from "./db.js";
import { registerSchemaTools } from "./tools/schema.js";
import { registerCrudTools } from "./tools/crud.js";
import { registerQueryBuilderTools } from "./tools/query-builder.js";
import { registerStoredProcedureTools } from "./tools/stored-procedures.js";
import { registerTransactionTools } from "./tools/transactions.js";
import { registerBulkOperationTools } from "./tools/bulk-operations.js";
import { registerDdlTools } from "./tools/ddl.js";
import https from "https";
const cli = new Command();
cli
.name("mssql-mcp-server")
.description("An MCP server for interacting with Microsoft SQL Server databases")
.version("1.2.0")
.requiredOption("--user <string>", "Database user")
.requiredOption("--password <string>", "Database password")
.requiredOption("--server <string>", "SQL Server hostname or IP")
.option("--port <number>", "Database port", "1433")
.requiredOption("--database <string>", "Database name")
.option("--permissions <string>", "Allowed operations: read, write, or all", "all");
const opts = cli.parse(process.argv).opts();
// Validate permissions using Zod
const permissionsSchema = z.enum(["read", "write", "all"]);
try {
// This will throw if validation fails
const perms = permissionsSchema.parse(opts.permissions);
// Logging functions that all go to stderr to keep stdout clean for JSON-RPC
function debug(message) {
console.error(`[DEBUG] ${message}`);
}
// Replace console.log with a function that logs to stderr instead
const log = (message) => {
console.error(`[INFO] ${message}`);
};
async function main() {
debug('MCP server process started');
log("Starting SQL MCP Server...");
// Version check - helps users know if they're on an old cached version
log(`Running version 1.2.0`);
// Check for latest version (non-blocking)
https.get('https://registry.npmjs.org/@bluspace/mssql-mcp-server/latest', (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => {
try {
const latest = JSON.parse(data).version;
if (latest && latest !== '1.2.0') {
log(`\n⚠️ Update available: ${latest} (current: 1.2.0)`);
log(`To update: npx clear-npx-cache && npx @bluspace/mssql-mcp-server@latest\n`);
}
}
catch (e) {
// Silently ignore version check errors
}
});
}).on('error', () => {
// Silently ignore network errors
});
// Initialize MCP server
debug('Creating MCP server instance');
const server = new McpServer({
name: "SQL MCP Server",
version: "1.2.0"
});
try {
// Connect to DB
debug(`Attempting to connect to SQL Server at ${opts.server}:${opts.port}/${opts.database}...`);
log(`Connecting to SQL Server at ${opts.server}:${opts.port}/${opts.database}...`);
const db = await initDb({
user: opts.user,
password: opts.password,
server: opts.server,
port: Number(opts.port),
database: opts.database,
permissions: perms
});
log("Database connection successful");
// Register tools based on permissions
debug('About to register schema tools');
log("Registering schema tools...");
registerSchemaTools(server, db);
// Always register query builder (read-only tool)
log("Registering query builder tools...");
registerQueryBuilderTools(server, db);
// Register stored procedure tools (can be read-only)
log("Registering stored procedure tools...");
registerStoredProcedureTools(server, db);
if (perms === "write" || perms === "all") {
log("Registering CRUD tools...");
registerCrudTools(server, db);
log("Registering DDL tools...");
registerDdlTools(server, db);
log("Registering transaction tools...");
registerTransactionTools(server, db);
log("Registering bulk operation tools...");
registerBulkOperationTools(server, db);
}
// Start STDIO transport
debug('About to start MCP server over STDIO');
log("Starting MCP server over STDIO...");
const transport = new StdioServerTransport();
await server.connect(transport);
log("SQL MCP Server is ready");
debug('Server initialization complete');
}
catch (err) {
console.error("Failed to initialize server:", err);
process.exit(1);
}
}
main().catch(err => {
console.error("Fatal error:", err);
process.exit(1);
});
}
catch (err) {
const validationError = err;
console.error("Invalid permissions value:", validationError.message);
console.error("Please use one of: read, write, all");
process.exit(1);
}