# mssql-mcp-server 設定 for windows pat1
來源: https://github.com/c0h1b4/mssql-mcp-server
這個原本應該是給 linux 環境使用
windows 環境無法直接執行,所以有以下的修改
<div style='color:red;'>
※ 提醒需要先安裝
<a href='https://nodejs.org/zh-tw/download'> Node.js </a>
才能執行下面的操作<br/>
</div>
## 修改程式
### src/index.ts
:::spoiler 原本
```js
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import type { CallToolRequest, ListToolsRequest } from '@modelcontextprotocol/sdk/types.js';
import {
CallToolRequestSchema,
ErrorCode,
ListToolsRequestSchema,
McpError,
} from '@modelcontextprotocol/sdk/types.js';
import sql from 'mssql';
interface QueryArgs {
connectionString?: string;
host?: string;
port?: number;
database?: string;
username?: string;
password?: string;
query: string;
encrypt?: boolean;
trustServerCertificate?: boolean;
}
const isValidQueryArgs = (args: unknown): args is QueryArgs => {
const candidate = args as Record<string, unknown>;
if (typeof candidate !== 'object' || candidate === null) {
return false;
}
// Query is required
if (typeof candidate.query !== 'string') {
return false;
}
// Either connectionString OR (host + username + password) must be provided
if (candidate.connectionString !== undefined) {
if (typeof candidate.connectionString !== 'string') {
return false;
}
} else {
if (typeof candidate.host !== 'string') {
return false;
}
if (typeof candidate.username !== 'string') {
return false;
}
if (typeof candidate.password !== 'string') {
return false;
}
}
// Optional parameters
if (candidate.port !== undefined && typeof candidate.port !== 'number') {
return false;
}
if (candidate.database !== undefined && typeof candidate.database !== 'string') {
return false;
}
if (candidate.encrypt !== undefined && typeof candidate.encrypt !== 'boolean') {
return false;
}
if (
candidate.trustServerCertificate !== undefined &&
typeof candidate.trustServerCertificate !== 'boolean'
) {
return false;
}
return true;
};
export class MssqlServer {
private server: Server;
private pools: Map<string, sql.ConnectionPool>;
constructor() {
this.server = new Server(
{
name: 'mssql-server',
version: '0.1.0',
},
{
capabilities: {
tools: {},
},
}
);
this.pools = new Map();
this.setupToolHandlers();
// Error handling
this.server.onerror = (error): void => console.error('[MCP Error]', error);
process.on('SIGINT', () => {
void this.cleanup();
process.exit(0);
});
}
private async cleanup(): Promise<void> {
const closePromises = Array.from(this.pools.values()).map((pool) => pool.close());
await Promise.all(closePromises);
this.pools.clear();
await this.server.close();
}
private getConnectionConfig(args: QueryArgs): sql.config {
if (args.connectionString) {
return {
server: args.connectionString, // Using server instead of connectionString as per mssql types
};
}
if (!args.host) {
throw new McpError(
ErrorCode.InvalidRequest,
'Host is required when not using connection string'
);
}
return {
server: args.host,
port: args.port || 1433,
database: args.database || 'master',
user: args.username,
password: args.password,
options: {
encrypt: args.encrypt ?? false,
trustServerCertificate: args.trustServerCertificate ?? true,
},
};
}
private async getPool(config: sql.config): Promise<sql.ConnectionPool> {
const key = JSON.stringify(config);
let pool = this.pools.get(key);
if (!pool) {
pool = new sql.ConnectionPool(config);
await pool.connect();
this.pools.set(key, pool);
}
return pool;
}
async handleQuery(args: QueryArgs): Promise<{ content: Array<{ type: string; text: string }> }> {
try {
const config = this.getConnectionConfig(args);
const pool = await this.getPool(config);
const result = await pool.request().query(args.query);
return {
content: [
{
type: 'text',
text: JSON.stringify(result.recordset, null, 2),
},
],
};
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new McpError(ErrorCode.InternalError, `Database error: ${message}`);
}
}
private setupToolHandlers(): void {
this.server.setRequestHandler(ListToolsRequestSchema, (_request: ListToolsRequest) =>
Promise.resolve({
tools: [
{
name: 'query',
description: 'Execute a SQL query on a MSSQL database',
inputSchema: {
type: 'object',
properties: {
connectionString: {
type: 'string',
description: 'Full connection string (alternative to individual parameters)',
},
host: {
type: 'string',
description: 'Database server hostname',
},
port: {
type: 'number',
description: 'Database server port (default: 1433)',
},
database: {
type: 'string',
description: 'Database name (default: master)',
},
username: {
type: 'string',
description: 'Database username',
},
password: {
type: 'string',
description: 'Database password',
},
query: {
type: 'string',
description: 'SQL query to execute',
},
encrypt: {
type: 'boolean',
description: 'Enable encryption (default: false)',
},
trustServerCertificate: {
type: 'boolean',
description: 'Trust server certificate (default: true)',
},
},
required: ['query'],
oneOf: [
{ required: ['connectionString'] },
{ required: ['host', 'username', 'password'] },
],
},
},
],
})
);
this.server.setRequestHandler(
CallToolRequestSchema,
async (
request: CallToolRequest
): Promise<{ content: Array<{ type: string; text: string }> }> => {
const params = request.params as { name: string; arguments: unknown };
if (params.name !== 'query') {
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${params.name}`);
}
if (!isValidQueryArgs(params.arguments)) {
throw new McpError(ErrorCode.InvalidRequest, 'Invalid query arguments');
}
return this.handleQuery(params.arguments);
}
);
}
async run(): Promise<void> {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('MSSQL MCP server running on stdio');
}
}
// Only start the server if this file is being run directly
if (import.meta.url === `file://${process.argv[1]}`) {
const server = new MssqlServer();
void server.run().catch(console.error);
}
}
```
:::
:::spoiler 修改
```js
#!/usr/bin/env node
import dotenv from 'dotenv';
dotenv.config();
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import type { CallToolRequest, ListToolsRequest } from '@modelcontextprotocol/sdk/types.js';
import {
CallToolRequestSchema,
ErrorCode,
ListToolsRequestSchema,
McpError,
} from '@modelcontextprotocol/sdk/types.js';
import sql from 'mssql';
interface QueryArgs {
connectionString?: string;
host?: string;
port?: number;
database?: string;
username?: string;
password?: string;
query: string;
encrypt?: boolean;
trustServerCertificate?: boolean;
}
const isValidQueryArgs = (args: unknown): args is QueryArgs => {
const candidate = args as Record<string, unknown>;
if (typeof candidate !== 'object' || candidate === null) {
return false;
}
// Query is required
if (typeof candidate.query !== 'string') {
return false;
}
// Optional parameters
if (candidate.port !== undefined && typeof candidate.port !== 'number') {
return false;
}
if (candidate.database !== undefined && typeof candidate.database !== 'string') {
return false;
}
if (candidate.encrypt !== undefined && typeof candidate.encrypt !== 'boolean') {
return false;
}
if (
candidate.trustServerCertificate !== undefined &&
typeof candidate.trustServerCertificate !== 'boolean'
) {
return false;
}
return true;
};
export class MssqlServer {
private server: Server;
private pools: Map<string, sql.ConnectionPool>;
constructor() {
this.server = new Server(
{
name: 'mssql-server',
version: '0.1.0',
},
{
capabilities: {
tools: {},
},
}
);
this.pools = new Map();
this.setupToolHandlers();
// Error handling
this.server.onerror = (error): void => console.error('[MCP Error]', error);
process.on('SIGINT', () => {
void this.cleanup();
process.exit(0);
});
}
private async cleanup(): Promise<void> {
const closePromises = Array.from(this.pools.values()).map((pool) => pool.close());
await Promise.all(closePromises);
this.pools.clear();
await this.server.close();
}
private getConnectionConfig(args: QueryArgs): sql.config {
const host = args.host ?? process.env.MSSQL_HOST;
const port = args.port ?? parseInt(process.env.MSSQL_PORT || "1433");
const database = args.database ?? process.env.MSSQL_DATABASE;
const user = args.username ?? process.env.MSSQL_USER;
const password = args.password ?? process.env.MSSQL_PASSWORD;
const encrypt = args.encrypt !== undefined
? args.encrypt
: process.env.MSSQL_ENCRYPT === "true";
const trustServerCert = args.trustServerCertificate !== undefined
? args.trustServerCertificate
: process.env.MSSQL_TRUST_SERVER_CERTIFICATE === "true";
if (!host || !user || !password) {
throw new McpError(ErrorCode.InvalidRequest, "Missing connection info: host/user/password");
}
return {
server: host,
port,
database,
user,
password,
options: {
encrypt,
trustServerCertificate: trustServerCert,
},
};
}
private async getPool(config: sql.config): Promise<sql.ConnectionPool> {
const key = JSON.stringify(config);
let pool = this.pools.get(key);
if (!pool) {
pool = new sql.ConnectionPool(config);
await pool.connect();
this.pools.set(key, pool);
}
return pool;
}
async handleQuery(args: QueryArgs): Promise<{ content: Array<{ type: string; text: string }> }> {
try {
const config = this.getConnectionConfig(args);
const pool = await this.getPool(config);
const result = await pool.request().query(args.query);
return {
content: [
{
type: 'text',
text: JSON.stringify(result.recordset, null, 2),
},
],
};
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new McpError(ErrorCode.InternalError, `Database error: ${message}`);
}
}
private setupToolHandlers(): void {
this.server.setRequestHandler(ListToolsRequestSchema, (_request: ListToolsRequest) =>
Promise.resolve({
tools: [
{
name: 'query',
description: 'Execute a SQL query on a MSSQL database',
inputSchema: {
type: 'object',
properties: {
connectionString: {
type: 'string',
description: 'Full connection string (alternative to individual parameters)',
},
host: {
type: 'string',
description: 'Database server hostname',
},
port: {
type: 'number',
description: 'Database server port (default: 1433)',
},
database: {
type: 'string',
description: 'Database name (default: master)',
},
username: {
type: 'string',
description: 'Database username',
},
password: {
type: 'string',
description: 'Database password',
},
query: {
type: 'string',
description: 'SQL query to execute',
},
encrypt: {
type: 'boolean',
description: 'Enable encryption (default: false)',
},
trustServerCertificate: {
type: 'boolean',
description: 'Trust server certificate (default: true)',
},
},
required: ['query']
},
},
],
})
);
this.server.setRequestHandler(
CallToolRequestSchema,
async (
request: CallToolRequest
): Promise<{ content: Array<{ type: string; text: string }> }> => {
const params = request.params as { name: string; arguments: unknown };
if (params.name !== 'query') {
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${params.name}`);
}
if (!isValidQueryArgs(params.arguments)) {
throw new McpError(ErrorCode.InvalidRequest, 'Invalid query arguments');
}
return this.handleQuery(params.arguments);
}
);
}
async run(): Promise<void> {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('MSSQL MCP server running on stdio');
}
}
const server = new MssqlServer();
void server.run().catch(console.error);
```
:::
### package.json
原本↓
```json
"scripts": {
"build": "tsc && chmod +x build/index.js",
"start": "node build/index.js",
"dev": "tsx watch src/index.ts",
"lint": "eslint . --ext .ts",
"format": "prettier --write \"src/**/*.ts\"",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^0.1.0",
"mssql": "^10.0.1"
}
```
修改↓
```json
"scripts": {
"build": "tsc", // 拿掉 && chmod +x build/index.js
"start": "node build/index.js",
"dev": "tsx watch src/index.ts",
"lint": "eslint . --ext .ts",
"format": "prettier --write \"src/**/*.ts\"",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.10.1", // 抓最新的
"mssql": "^10.0.1"
}
```
``` @modelcontextprotocol/sdk ``` 版本號從這裡查: https://www.npmjs.com/package/@modelcontextprotocol/sdk
### tsconfig.json
原本↓
```json
"exclude": ["node_modules", "build"]
```
修改↓ (build 的時候過濾掉測試檔)
```json
"exclude": ["node_modules", "build", "src/index.test.ts","src/__tests__/server.test.ts"]
```
## 安裝
開啟 mssql-mcp-server 資料夾
在上方路徑的地方輸入 cmd



輸入指令
``` cmd
npm install && npm install dotenv --save && npm run build
```
看到這個畫面代表執行成功

確認一下 mssql-mcp-server/build/src/index.js 有沒有出現

測試一下能不能執行 ``` node build/src/index.js ```
看到這個畫面代表前面的設定已完成,然後按 crtl+c 結束這個指令

[mssql-mcp-server 設定 for windows part2 (設定到 claude desktop)](https://hackmd.io/@maddie-wang/BkL_EMHkle)