Skip to main content
Glama
NakiriYuuzu

MSSQL MCP Server

by NakiriYuuzu
database.ts5.33 kB
import sql from 'mssql' import { DatabaseConfig, QueryResult, DatabaseInfo, TableInfo, ColumnInfo } from './types.js' export class MSSQLManager { private pool: sql.ConnectionPool | null = null private config: DatabaseConfig | null = null private currentDatabase: string | null = null constructor() {} /** * 建立資料庫連接 */ async connect(config: DatabaseConfig): Promise<void> { try { // 如果已有連接,先關閉 if (this.pool) { await this.disconnect() } this.config = config this.currentDatabase = config.database || null const poolConfig: sql.config = { server: config.server, port: config.port, database: config.database, user: config.user, password: config.password, options: config.options || { encrypt: true, trustServerCertificate: false, connectionTimeout: 30000, requestTimeout: 30000, } } this.pool = new sql.ConnectionPool(poolConfig) await this.pool.connect() console.log(`已連接到 MSSQL 伺服器: ${config.server}${config.database ? `, 資料庫: ${config.database}` : ''}`) } catch (error) { throw new Error(`連接資料庫失敗: ${error instanceof Error ? error.message : String(error)}`) } } /** * 斷開資料庫連接 */ async disconnect(): Promise<void> { if (this.pool) { await this.pool.close() this.pool = null console.log('已斷開資料庫連接') } } /** * 檢查是否已連接 */ isConnected(): boolean { return this.pool !== null && this.pool.connected } /** * 取得目前資料庫名稱 */ getCurrentDatabase(): string | null { return this.currentDatabase } /** * 切換到指定資料庫 */ async switchDatabase(databaseName: string): Promise<void> { if (!this.isConnected() || !this.config) { throw new Error('尚未建立資料庫連接') } try { // 建立新的連接配置 const newConfig = { ...this.config, database: databaseName } await this.connect(newConfig) this.currentDatabase = databaseName console.log(`已切換到資料庫: ${databaseName}`) } catch (error) { throw new Error(`切換資料庫失敗: ${error instanceof Error ? error.message : String(error)}`) } } /** * 執行 SQL 查詢 */ async executeQuery(query: string): Promise<QueryResult> { if (!this.isConnected() || !this.pool) { throw new Error('尚未建立資料庫連接') } try { const request = this.pool.request() const result = await request.query(query) return { recordset: result.recordset || [], recordsets: result.recordsets ? (Array.isArray(result.recordsets) ? result.recordsets.map(rs => Array.from(rs)) : [Array.from(result.recordsets as any)]) : [], rowsAffected: Array.isArray(result.rowsAffected) ? result.rowsAffected : [result.rowsAffected || 0], output: result.output || {} } } catch (error) { throw new Error(`執行查詢失敗: ${error instanceof Error ? error.message : String(error)}`) } } /** * 取得所有資料庫清單 */ async getDatabases(): Promise<DatabaseInfo[]> { const query = ` SELECT name, database_id, create_date, collation_name FROM sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb') ORDER BY name ` const result = await this.executeQuery(query) return result.recordset as DatabaseInfo[] } /** * 取得目前資料庫的所有資料表 */ async getTables(): Promise<TableInfo[]> { if (!this.currentDatabase) { throw new Error('尚未選擇資料庫') } const query = ` SELECT TABLE_NAME as table_name, TABLE_SCHEMA as table_schema, TABLE_TYPE as table_type FROM INFORMATION_SCHEMA.TABLES ORDER BY TABLE_SCHEMA, TABLE_NAME ` const result = await this.executeQuery(query) return result.recordset as TableInfo[] } /** * 取得指定資料表的欄位資訊 */ async getTableColumns(tableName: string, schemaName: string = 'dbo'): Promise<ColumnInfo[]> { if (!this.currentDatabase) { throw new Error('尚未選擇資料庫') } const query = ` SELECT COLUMN_NAME as column_name, DATA_TYPE as data_type, IS_NULLABLE as is_nullable, CHARACTER_MAXIMUM_LENGTH as character_maximum_length, NUMERIC_PRECISION as numeric_precision, NUMERIC_SCALE as numeric_scale FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '${tableName}' AND TABLE_SCHEMA = '${schemaName}' ORDER BY ORDINAL_POSITION ` const result = await this.executeQuery(query) return result.recordset as ColumnInfo[] } /** * 測試連接 */ async testConnection(): Promise<boolean> { try { await this.executeQuery('SELECT 1 as test') return true } catch { return false } } }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/NakiriYuuzu/Mssql-Mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server