mcp-server-db2i 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +45 -3
  2. package/dist/config.d.ts +29 -0
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +25 -0
  5. package/dist/config.js.map +1 -1
  6. package/dist/db/connection.d.ts +0 -13
  7. package/dist/db/connection.d.ts.map +1 -1
  8. package/dist/db/connection.js +15 -32
  9. package/dist/db/connection.js.map +1 -1
  10. package/dist/db/queries.d.ts +22 -0
  11. package/dist/db/queries.d.ts.map +1 -1
  12. package/dist/db/queries.js +42 -35
  13. package/dist/db/queries.js.map +1 -1
  14. package/dist/index.js +43 -136
  15. package/dist/index.js.map +1 -1
  16. package/dist/server.d.ts +39 -0
  17. package/dist/server.d.ts.map +1 -0
  18. package/dist/server.js +133 -0
  19. package/dist/server.js.map +1 -0
  20. package/dist/tools/metadata.d.ts +51 -194
  21. package/dist/tools/metadata.d.ts.map +1 -1
  22. package/dist/tools/metadata.js +35 -167
  23. package/dist/tools/metadata.js.map +1 -1
  24. package/dist/tools/query.d.ts +7 -21
  25. package/dist/tools/query.d.ts.map +1 -1
  26. package/dist/tools/query.js +12 -22
  27. package/dist/tools/query.js.map +1 -1
  28. package/dist/utils/logger.d.ts +48 -0
  29. package/dist/utils/logger.d.ts.map +1 -0
  30. package/dist/utils/logger.js +124 -0
  31. package/dist/utils/logger.js.map +1 -0
  32. package/dist/utils/rateLimiter.d.ts +90 -0
  33. package/dist/utils/rateLimiter.d.ts.map +1 -0
  34. package/dist/utils/rateLimiter.js +215 -0
  35. package/dist/utils/rateLimiter.js.map +1 -0
  36. package/dist/utils/security/sqlSecurityValidator.d.ts +101 -0
  37. package/dist/utils/security/sqlSecurityValidator.d.ts.map +1 -0
  38. package/dist/utils/security/sqlSecurityValidator.js +312 -0
  39. package/dist/utils/security/sqlSecurityValidator.js.map +1 -0
  40. package/package.json +17 -3
package/dist/index.js CHANGED
@@ -5,170 +5,77 @@
5
5
  * A Model Context Protocol server for querying and inspecting
6
6
  * IBM DB2 for i (DB2i) databases using the JT400 JDBC driver.
7
7
  */
8
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
8
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
- import { z } from 'zod';
11
9
  import { loadConfig } from './config.js';
12
10
  import { initializePool, testConnection } from './db/connection.js';
13
- import { executeQueryTool } from './tools/query.js';
14
- import { listSchemasTool, listTablesTool, describeTableTool, listViewsTool, listIndexesTool, getTableConstraintsTool, } from './tools/metadata.js';
15
- const SERVER_NAME = 'mcp-server-db2i';
16
- const SERVER_VERSION = '1.0.0';
17
- /**
18
- * Create and configure the MCP server
19
- */
20
- function createServer() {
21
- const server = new McpServer({
22
- name: SERVER_NAME,
23
- version: SERVER_VERSION,
24
- });
25
- // Register execute_query tool
26
- server.tool('execute_query', 'Execute a read-only SQL SELECT query against the IBM DB2i database. Only SELECT statements are allowed for security. Results are limited by default to prevent large result sets.', {
27
- sql: z.string().describe('SQL SELECT query to execute'),
28
- params: z.array(z.unknown()).optional().describe('Query parameters for prepared statement'),
29
- limit: z.number().optional().default(1000).describe('Maximum number of rows to return (default: 1000)'),
30
- }, async (args) => {
31
- const result = await executeQueryTool({
32
- sql: args.sql,
33
- params: args.params,
34
- limit: args.limit ?? 1000,
35
- });
36
- return {
37
- content: [
38
- {
39
- type: 'text',
40
- text: JSON.stringify(result, null, 2),
41
- },
42
- ],
43
- };
44
- });
45
- // Register list_schemas tool
46
- server.tool('list_schemas', 'List all schemas (libraries) in the IBM DB2i database. Optionally filter by name pattern using * as wildcard.', {
47
- filter: z.string().optional().describe('Filter pattern for schema names. Use * as wildcard. Example: "QSYS*" matches schemas starting with QSYS'),
48
- }, async (args) => {
49
- const result = await listSchemasTool({ filter: args.filter });
50
- return {
51
- content: [
52
- {
53
- type: 'text',
54
- text: JSON.stringify(result, null, 2),
55
- },
56
- ],
57
- };
58
- });
59
- // Register list_tables tool
60
- server.tool('list_tables', 'List all tables in a schema (library). Uses DB2I_SCHEMA env var if schema not provided. Optionally filter by name pattern using * as wildcard.', {
61
- schema: z.string().optional().describe('Schema (library) name to list tables from. Uses DB2I_SCHEMA env var if not provided.'),
62
- filter: z.string().optional().describe('Filter pattern for table names. Use * as wildcard. Example: "CUST*" matches tables starting with CUST'),
63
- }, async (args) => {
64
- const result = await listTablesTool({ schema: args.schema, filter: args.filter });
65
- return {
66
- content: [
67
- {
68
- type: 'text',
69
- text: JSON.stringify(result, null, 2),
70
- },
71
- ],
72
- };
73
- });
74
- // Register describe_table tool
75
- server.tool('describe_table', 'Get detailed column information for a specific table including data types, lengths, nullability, defaults, and CCSID. Uses DB2I_SCHEMA env var if schema not provided.', {
76
- schema: z.string().optional().describe('Schema (library) name containing the table. Uses DB2I_SCHEMA env var if not provided.'),
77
- table: z.string().describe('Table name to describe'),
78
- }, async (args) => {
79
- const result = await describeTableTool({ schema: args.schema, table: args.table });
80
- return {
81
- content: [
82
- {
83
- type: 'text',
84
- text: JSON.stringify(result, null, 2),
85
- },
86
- ],
87
- };
88
- });
89
- // Register list_views tool
90
- server.tool('list_views', 'List all views in a schema (library). Uses DB2I_SCHEMA env var if schema not provided. Optionally filter by name pattern using * as wildcard.', {
91
- schema: z.string().optional().describe('Schema (library) name to list views from. Uses DB2I_SCHEMA env var if not provided.'),
92
- filter: z.string().optional().describe('Filter pattern for view names. Use * as wildcard.'),
93
- }, async (args) => {
94
- const result = await listViewsTool({ schema: args.schema, filter: args.filter });
95
- return {
96
- content: [
97
- {
98
- type: 'text',
99
- text: JSON.stringify(result, null, 2),
100
- },
101
- ],
102
- };
103
- });
104
- // Register list_indexes tool
105
- server.tool('list_indexes', 'List all indexes for a specific table including uniqueness and column information. Uses DB2I_SCHEMA env var if schema not provided.', {
106
- schema: z.string().optional().describe('Schema (library) name containing the table. Uses DB2I_SCHEMA env var if not provided.'),
107
- table: z.string().describe('Table name to list indexes for'),
108
- }, async (args) => {
109
- const result = await listIndexesTool({ schema: args.schema, table: args.table });
110
- return {
111
- content: [
112
- {
113
- type: 'text',
114
- text: JSON.stringify(result, null, 2),
115
- },
116
- ],
117
- };
118
- });
119
- // Register get_table_constraints tool
120
- server.tool('get_table_constraints', 'Get all constraints (primary keys, foreign keys, unique constraints) for a specific table. Uses DB2I_SCHEMA env var if schema not provided.', {
121
- schema: z.string().optional().describe('Schema (library) name containing the table. Uses DB2I_SCHEMA env var if not provided.'),
122
- table: z.string().describe('Table name to get constraints for'),
123
- }, async (args) => {
124
- const result = await getTableConstraintsTool({ schema: args.schema, table: args.table });
125
- return {
126
- content: [
127
- {
128
- type: 'text',
129
- text: JSON.stringify(result, null, 2),
130
- },
131
- ],
132
- };
133
- });
134
- return server;
135
- }
11
+ import { logger, flushLogger } from './utils/logger.js';
12
+ import { getRateLimiter } from './utils/rateLimiter.js';
13
+ import { createServer, SERVER_NAME, SERVER_VERSION } from './server.js';
136
14
  /**
137
15
  * Main entry point
138
16
  */
139
17
  async function main() {
18
+ let server = null;
19
+ /**
20
+ * Gracefully shutdown the server
21
+ */
22
+ function shutdown(signal) {
23
+ logger.info(`Received ${signal}, shutting down...`);
24
+ if (server) {
25
+ server.close().then(() => {
26
+ logger.info('MCP server closed');
27
+ flushLogger();
28
+ process.exit(0);
29
+ }).catch((error) => {
30
+ logger.error({ err: error }, 'Error closing MCP server');
31
+ flushLogger();
32
+ process.exit(1);
33
+ });
34
+ }
35
+ else {
36
+ flushLogger();
37
+ process.exit(0);
38
+ }
39
+ }
140
40
  try {
41
+ logger.info('Starting MCP server...');
141
42
  // Load configuration from environment variables
142
43
  const config = loadConfig();
44
+ logger.debug({ hostname: config.hostname, port: config.port }, 'Configuration loaded');
143
45
  // Initialize database connection pool
144
46
  initializePool(config);
47
+ logger.debug('Database connection pool initialized');
145
48
  // Test the connection
146
49
  const connected = await testConnection();
147
50
  if (!connected) {
148
- console.error('Warning: Could not verify database connection. The server will start but queries may fail.');
51
+ logger.warn('Could not verify database connection. The server will start but queries may fail.');
52
+ }
53
+ else {
54
+ logger.info('Database connection verified');
149
55
  }
56
+ // Initialize rate limiter (logs its own config)
57
+ getRateLimiter();
150
58
  // Create MCP server
151
- const server = createServer();
59
+ server = createServer();
60
+ logger.debug('MCP server instance created');
152
61
  // Connect via stdio transport
153
62
  const transport = new StdioServerTransport();
154
63
  await server.connect(transport);
64
+ logger.info({ name: SERVER_NAME, version: SERVER_VERSION }, 'MCP server connected via stdio transport');
155
65
  // Handle shutdown gracefully
156
- process.on('SIGINT', () => {
157
- process.exit(0);
158
- });
159
- process.on('SIGTERM', () => {
160
- process.exit(0);
161
- });
66
+ process.on('SIGINT', () => shutdown('SIGINT'));
67
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
162
68
  }
163
69
  catch (error) {
164
- const message = error instanceof Error ? error.message : 'Unknown error';
165
- console.error(`Failed to start MCP server: ${message}`);
70
+ logger.fatal({ err: error }, 'Failed to start MCP server');
71
+ flushLogger();
166
72
  process.exit(1);
167
73
  }
168
74
  }
169
75
  // Run the server
170
76
  main().catch((error) => {
171
- console.error('Fatal error:', error);
77
+ logger.fatal({ err: error }, 'Fatal error during server startup');
78
+ flushLogger();
172
79
  process.exit(1);
173
80
  });
174
81
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * MCP Server Factory
3
+ *
4
+ * Creates and configures the MCP server with all tools registered.
5
+ * Extracted from index.ts for testability.
6
+ */
7
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
+ export declare const SERVER_NAME: string;
9
+ export declare const SERVER_VERSION: string;
10
+ /**
11
+ * Standard tool result type
12
+ */
13
+ export interface ToolResult {
14
+ success: boolean;
15
+ error?: string;
16
+ [key: string]: unknown;
17
+ }
18
+ /**
19
+ * MCP tool response type
20
+ */
21
+ export type McpToolResponse = {
22
+ content: Array<{
23
+ type: 'text';
24
+ text: string;
25
+ }>;
26
+ isError?: true;
27
+ };
28
+ /**
29
+ * Creates a tool handler wrapper that applies rate limiting and standardizes responses.
30
+ * Eliminates boilerplate code across all tool registrations.
31
+ */
32
+ export declare function withToolHandler<TArgs, TResult extends ToolResult>(handler: (args: TArgs) => Promise<TResult>, errorMessage: string): (args: TArgs) => Promise<McpToolResponse>;
33
+ /**
34
+ * Create and configure the MCP server with all tools registered.
35
+ *
36
+ * @returns Configured McpServer instance ready to connect to a transport
37
+ */
38
+ export declare function createServer(): McpServer;
39
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAkBpE,eAAO,MAAM,WAAW,QAAmB,CAAC;AAC5C,eAAO,MAAM,cAAc,QAAsB,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,SAAS,UAAU,EAC/D,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,EAC1C,YAAY,EAAE,MAAM,GACnB,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,eAAe,CAAC,CA4B3C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,SAAS,CAyIxC"}
package/dist/server.js ADDED
@@ -0,0 +1,133 @@
1
+ /**
2
+ * MCP Server Factory
3
+ *
4
+ * Creates and configures the MCP server with all tools registered.
5
+ * Extracted from index.ts for testability.
6
+ */
7
+ import { createRequire } from 'module';
8
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
+ import { z } from 'zod';
10
+ import { executeQueryTool } from './tools/query.js';
11
+ import { listSchemasTool, listTablesTool, describeTableTool, listViewsTool, listIndexesTool, getTableConstraintsTool, } from './tools/metadata.js';
12
+ import { getRateLimiter } from './utils/rateLimiter.js';
13
+ // Read version from package.json to keep it in sync with npm releases
14
+ const require = createRequire(import.meta.url);
15
+ const packageJson = require('../package.json');
16
+ export const SERVER_NAME = packageJson.name;
17
+ export const SERVER_VERSION = packageJson.version;
18
+ /**
19
+ * Creates a tool handler wrapper that applies rate limiting and standardizes responses.
20
+ * Eliminates boilerplate code across all tool registrations.
21
+ */
22
+ export function withToolHandler(handler, errorMessage) {
23
+ return async (args) => {
24
+ // Check rate limit
25
+ const rateLimiter = getRateLimiter();
26
+ const rateResult = rateLimiter.checkLimit();
27
+ if (!rateResult.allowed) {
28
+ const error = rateLimiter.formatError(rateResult);
29
+ return {
30
+ content: [{ type: 'text', text: JSON.stringify(error, null, 2) }],
31
+ isError: true,
32
+ };
33
+ }
34
+ // Execute the tool
35
+ const result = await handler(args);
36
+ if (!result.success) {
37
+ return {
38
+ content: [{ type: 'text', text: result.error ?? errorMessage }],
39
+ isError: true,
40
+ };
41
+ }
42
+ return {
43
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
44
+ };
45
+ };
46
+ }
47
+ /**
48
+ * Create and configure the MCP server with all tools registered.
49
+ *
50
+ * @returns Configured McpServer instance ready to connect to a transport
51
+ */
52
+ export function createServer() {
53
+ const server = new McpServer({
54
+ name: SERVER_NAME,
55
+ version: SERVER_VERSION,
56
+ });
57
+ // Register execute_query tool
58
+ server.registerTool('execute_query', {
59
+ title: 'Execute SQL Query',
60
+ description: 'Execute a read-only SQL SELECT query against the IBM DB2i database. Only SELECT statements are allowed for security. Results are limited by default to prevent large result sets.',
61
+ annotations: { readOnlyHint: true },
62
+ inputSchema: {
63
+ sql: z.string().describe('SQL SELECT query to execute'),
64
+ params: z.array(z.unknown()).optional().describe('Query parameters for prepared statement'),
65
+ limit: z.number().optional().default(1000).describe('Maximum number of rows to return (default: 1000)'),
66
+ },
67
+ }, withToolHandler((args) => executeQueryTool({
68
+ sql: args.sql,
69
+ params: args.params,
70
+ limit: args.limit ?? 1000,
71
+ }), 'Query failed'));
72
+ // Register list_schemas tool
73
+ server.registerTool('list_schemas', {
74
+ title: 'List Schemas',
75
+ description: 'List all schemas (libraries) in the IBM DB2i database. Optionally filter by name pattern using * as wildcard.',
76
+ annotations: { readOnlyHint: true },
77
+ inputSchema: {
78
+ filter: z.string().optional().describe('Filter pattern for schema names. Use * as wildcard. Example: "QSYS*" matches schemas starting with QSYS'),
79
+ },
80
+ }, withToolHandler((args) => listSchemasTool({ filter: args.filter }), 'Failed to list schemas'));
81
+ // Register list_tables tool
82
+ server.registerTool('list_tables', {
83
+ title: 'List Tables',
84
+ description: 'List all tables in a schema (library). Uses DB2I_SCHEMA env var if schema not provided. Optionally filter by name pattern using * as wildcard.',
85
+ annotations: { readOnlyHint: true },
86
+ inputSchema: {
87
+ schema: z.string().optional().describe('Schema (library) name to list tables from. Uses DB2I_SCHEMA env var if not provided.'),
88
+ filter: z.string().optional().describe('Filter pattern for table names. Use * as wildcard. Example: "CUST*" matches tables starting with CUST'),
89
+ },
90
+ }, withToolHandler((args) => listTablesTool({ schema: args.schema, filter: args.filter }), 'Failed to list tables'));
91
+ // Register describe_table tool
92
+ server.registerTool('describe_table', {
93
+ title: 'Describe Table',
94
+ description: 'Get detailed column information for a specific table including data types, lengths, nullability, defaults, and CCSID. Uses DB2I_SCHEMA env var if schema not provided.',
95
+ annotations: { readOnlyHint: true },
96
+ inputSchema: {
97
+ schema: z.string().optional().describe('Schema (library) name containing the table. Uses DB2I_SCHEMA env var if not provided.'),
98
+ table: z.string().describe('Table name to describe'),
99
+ },
100
+ }, withToolHandler((args) => describeTableTool({ schema: args.schema, table: args.table }), 'Failed to describe table'));
101
+ // Register list_views tool
102
+ server.registerTool('list_views', {
103
+ title: 'List Views',
104
+ description: 'List all views in a schema (library). Uses DB2I_SCHEMA env var if schema not provided. Optionally filter by name pattern using * as wildcard.',
105
+ annotations: { readOnlyHint: true },
106
+ inputSchema: {
107
+ schema: z.string().optional().describe('Schema (library) name to list views from. Uses DB2I_SCHEMA env var if not provided.'),
108
+ filter: z.string().optional().describe('Filter pattern for view names. Use * as wildcard.'),
109
+ },
110
+ }, withToolHandler((args) => listViewsTool({ schema: args.schema, filter: args.filter }), 'Failed to list views'));
111
+ // Register list_indexes tool
112
+ server.registerTool('list_indexes', {
113
+ title: 'List Indexes',
114
+ description: 'List all indexes for a specific table including uniqueness and column information. Uses DB2I_SCHEMA env var if schema not provided.',
115
+ annotations: { readOnlyHint: true },
116
+ inputSchema: {
117
+ schema: z.string().optional().describe('Schema (library) name containing the table. Uses DB2I_SCHEMA env var if not provided.'),
118
+ table: z.string().describe('Table name to list indexes for'),
119
+ },
120
+ }, withToolHandler((args) => listIndexesTool({ schema: args.schema, table: args.table }), 'Failed to list indexes'));
121
+ // Register get_table_constraints tool
122
+ server.registerTool('get_table_constraints', {
123
+ title: 'Get Table Constraints',
124
+ description: 'Get all constraints (primary keys, foreign keys, unique constraints) for a specific table. Uses DB2I_SCHEMA env var if schema not provided.',
125
+ annotations: { readOnlyHint: true },
126
+ inputSchema: {
127
+ schema: z.string().optional().describe('Schema (library) name containing the table. Uses DB2I_SCHEMA env var if not provided.'),
128
+ table: z.string().describe('Table name to get constraints for'),
129
+ },
130
+ }, withToolHandler((args) => getTableConstraintsTool({ schema: args.schema, table: args.table }), 'Failed to get constraints'));
131
+ return server;
132
+ }
133
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}