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.
- package/README.md +45 -3
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +25 -0
- package/dist/config.js.map +1 -1
- package/dist/db/connection.d.ts +0 -13
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +15 -32
- package/dist/db/connection.js.map +1 -1
- package/dist/db/queries.d.ts +22 -0
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +42 -35
- package/dist/db/queries.js.map +1 -1
- package/dist/index.js +43 -136
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +39 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +133 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/metadata.d.ts +51 -194
- package/dist/tools/metadata.d.ts.map +1 -1
- package/dist/tools/metadata.js +35 -167
- package/dist/tools/metadata.js.map +1 -1
- package/dist/tools/query.d.ts +7 -21
- package/dist/tools/query.d.ts.map +1 -1
- package/dist/tools/query.js +12 -22
- package/dist/tools/query.js.map +1 -1
- package/dist/utils/logger.d.ts +48 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +124 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/rateLimiter.d.ts +90 -0
- package/dist/utils/rateLimiter.d.ts.map +1 -0
- package/dist/utils/rateLimiter.js +215 -0
- package/dist/utils/rateLimiter.js.map +1 -0
- package/dist/utils/security/sqlSecurityValidator.d.ts +101 -0
- package/dist/utils/security/sqlSecurityValidator.d.ts.map +1 -0
- package/dist/utils/security/sqlSecurityValidator.js +312 -0
- package/dist/utils/security/sqlSecurityValidator.js.map +1 -0
- package/package.json +17 -3
package/README.md
CHANGED
|
@@ -20,9 +20,11 @@ A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server for IB
|
|
|
20
20
|
| `list_tables` | List tables in a schema (with optional filter) |
|
|
21
21
|
| `describe_table` | Get detailed column information |
|
|
22
22
|
| `list_views` | List views in a schema (with optional filter) |
|
|
23
|
-
| `list_indexes` | List indexes for a table |
|
|
23
|
+
| `list_indexes` | List SQL indexes for a table |
|
|
24
24
|
| `get_table_constraints` | Get primary keys, foreign keys, unique constraints |
|
|
25
25
|
|
|
26
|
+
> **Note:** `list_indexes` and `get_table_constraints` query the `QSYS2` SQL catalog views and only return SQL-defined objects. Legacy DDS Logical Files and Physical File constraints are not included. This is standard DB2 for i behavior.
|
|
27
|
+
|
|
26
28
|
### Filter Syntax
|
|
27
29
|
|
|
28
30
|
The list tools support pattern matching:
|
|
@@ -70,11 +72,22 @@ DB2I_HOSTNAME=your-ibm-i-host.com
|
|
|
70
72
|
DB2I_USERNAME=your-username
|
|
71
73
|
DB2I_PASSWORD=your-password
|
|
72
74
|
|
|
73
|
-
# Optional
|
|
75
|
+
# Optional - Database
|
|
74
76
|
DB2I_PORT=446 # Default: 446
|
|
75
77
|
DB2I_DATABASE=*LOCAL # Default: *LOCAL
|
|
76
78
|
DB2I_SCHEMA=your-default-schema # Default schema for all tools (can be overridden per-call)
|
|
77
79
|
DB2I_JDBC_OPTIONS=naming=system;date format=iso
|
|
80
|
+
|
|
81
|
+
# Optional - Logging
|
|
82
|
+
LOG_LEVEL=info # debug, info, warn, error, fatal (default: info)
|
|
83
|
+
NODE_ENV=production # production = JSON logs, development = pretty logs
|
|
84
|
+
LOG_PRETTY=true # Override: force pretty (true) or JSON (false) logs
|
|
85
|
+
LOG_COLORS=true # Override: force colors on/off (auto-detected by default)
|
|
86
|
+
|
|
87
|
+
# Optional - Rate Limiting
|
|
88
|
+
RATE_LIMIT_WINDOW_MS=900000 # Time window in ms (default: 900000 = 15 minutes)
|
|
89
|
+
RATE_LIMIT_MAX_REQUESTS=100 # Max requests per window (default: 100)
|
|
90
|
+
RATE_LIMIT_ENABLED=true # Set to 'false' to disable (default: true)
|
|
78
91
|
```
|
|
79
92
|
|
|
80
93
|
### Environment Variables
|
|
@@ -88,6 +101,13 @@ DB2I_JDBC_OPTIONS=naming=system;date format=iso
|
|
|
88
101
|
| `DB2I_DATABASE` | No | `*LOCAL` | Database name |
|
|
89
102
|
| `DB2I_SCHEMA` | No | - | Default schema/library for tools. If set, you don't need to specify schema in each tool call. |
|
|
90
103
|
| `DB2I_JDBC_OPTIONS` | No | - | Additional JDBC options (semicolon-separated) |
|
|
104
|
+
| `LOG_LEVEL` | No | `info` | Log level: `debug`, `info`, `warn`, `error`, `fatal` |
|
|
105
|
+
| `NODE_ENV` | No | - | Set to `production` for JSON logs, otherwise pretty-printed |
|
|
106
|
+
| `LOG_PRETTY` | No | - | Override log format: `true` = pretty, `false` = JSON |
|
|
107
|
+
| `LOG_COLORS` | No | auto | Override colors: `true`/`false` (auto-detects TTY by default) |
|
|
108
|
+
| `RATE_LIMIT_WINDOW_MS` | No | `900000` | Rate limit time window in milliseconds (15 min) |
|
|
109
|
+
| `RATE_LIMIT_MAX_REQUESTS` | No | `100` | Maximum requests allowed per window |
|
|
110
|
+
| `RATE_LIMIT_ENABLED` | No | `true` | Set to `false` or `0` to disable rate limiting |
|
|
91
111
|
|
|
92
112
|
### JDBC Options
|
|
93
113
|
|
|
@@ -223,20 +243,41 @@ npm run build
|
|
|
223
243
|
|
|
224
244
|
# Run production build
|
|
225
245
|
npm start
|
|
246
|
+
|
|
247
|
+
# Run tests
|
|
248
|
+
npm test
|
|
249
|
+
|
|
250
|
+
# Run tests in watch mode
|
|
251
|
+
npm run test:watch
|
|
252
|
+
|
|
253
|
+
# Lint code
|
|
254
|
+
npm run lint
|
|
255
|
+
|
|
256
|
+
# Lint and fix
|
|
257
|
+
npm run lint:fix
|
|
258
|
+
|
|
259
|
+
# Type check
|
|
260
|
+
npm run typecheck
|
|
226
261
|
```
|
|
227
262
|
|
|
228
263
|
## Security
|
|
229
264
|
|
|
230
265
|
- **Read-only access**: Only SELECT statements are permitted
|
|
231
266
|
- **No credentials in code**: All sensitive data via environment variables
|
|
232
|
-
- **Query validation**:
|
|
267
|
+
- **Query validation**: AST-based SQL parsing plus regex validation blocks dangerous operations
|
|
233
268
|
- **Result limiting**: Default limit of 1000 rows prevents large result sets
|
|
269
|
+
- **Rate limiting**: Configurable request throttling to prevent abuse (100 req/15 min default)
|
|
270
|
+
- **Structured logging**: Automatic redaction of sensitive fields like passwords
|
|
234
271
|
|
|
235
272
|
## Compatibility
|
|
236
273
|
|
|
237
274
|
- IBM i V7R3 and later (V7R5 recommended)
|
|
238
275
|
- Works with any IBM i system accessible via JDBC over TCP/IP
|
|
239
276
|
|
|
277
|
+
## Related Projects
|
|
278
|
+
|
|
279
|
+
- **[IBM ibmi-mcp-server](https://github.com/IBM/ibmi-mcp-server)** - IBM's official MCP server for IBM i systems. Offers YAML-based SQL tool definitions, AI agent frameworks, and production deployment options. Requires [Mapepire](https://mapepire-ibmi.github.io/) to be installed on your IBM i system, but if you can manage that prerequisite, it's worth checking out for more advanced use cases.
|
|
280
|
+
|
|
240
281
|
## Contributing
|
|
241
282
|
|
|
242
283
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
@@ -250,3 +291,4 @@ MIT License - see [LICENSE](LICENSE) for details.
|
|
|
250
291
|
- [node-jt400](https://www.npmjs.com/package/node-jt400) - JT400 JDBC driver wrapper for Node.js
|
|
251
292
|
- [Model Context Protocol](https://modelcontextprotocol.io/) - The protocol specification
|
|
252
293
|
- [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk) - Official TypeScript SDK
|
|
294
|
+
- [IBM ibmi-mcp-server](https://github.com/IBM/ibmi-mcp-server) - SQL security validation patterns inspired by their approach to AST-based query validation
|
package/dist/config.d.ts
CHANGED
|
@@ -11,6 +11,15 @@ export interface DB2iConfig {
|
|
|
11
11
|
schema: string;
|
|
12
12
|
jdbcOptions: Record<string, string>;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Valid log levels for the application
|
|
16
|
+
*/
|
|
17
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
|
18
|
+
/**
|
|
19
|
+
* Get the configured log level from environment
|
|
20
|
+
* Defaults to 'info' if not set or invalid
|
|
21
|
+
*/
|
|
22
|
+
export declare function getLogLevel(): LogLevel;
|
|
14
23
|
/**
|
|
15
24
|
* Load configuration from environment variables
|
|
16
25
|
*/
|
|
@@ -28,4 +37,24 @@ export declare function buildConnectionConfig(config: DB2iConfig): {
|
|
|
28
37
|
* Get the default schema from config
|
|
29
38
|
*/
|
|
30
39
|
export declare function getDefaultSchema(config: DB2iConfig): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Rate limit configuration interface
|
|
42
|
+
*/
|
|
43
|
+
export interface RateLimitConfig {
|
|
44
|
+
/** Time window in milliseconds (default: 900000 = 15 minutes) */
|
|
45
|
+
windowMs: number;
|
|
46
|
+
/** Maximum requests allowed per window (default: 100) */
|
|
47
|
+
maxRequests: number;
|
|
48
|
+
/** Whether rate limiting is enabled (default: true) */
|
|
49
|
+
enabled: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Default rate limit configuration values
|
|
53
|
+
*
|
|
54
|
+
* Environment variables:
|
|
55
|
+
* - RATE_LIMIT_WINDOW_MS: Time window in milliseconds (default: 900000)
|
|
56
|
+
* - RATE_LIMIT_MAX_REQUESTS: Max requests per window (default: 100)
|
|
57
|
+
* - RATE_LIMIT_ENABLED: Set to 'false' or '0' to disable (default: true)
|
|
58
|
+
*/
|
|
59
|
+
export declare const DEFAULT_RATE_LIMIT: RateLimitConfig;
|
|
31
60
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AA6BD;;GAEG;AACH,wBAAgB,UAAU,IAAI,UAAU,CAwBvC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB,CA4BA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAEvE"}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAErE;;;GAGG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAStC;AA6BD;;GAEG;AACH,wBAAgB,UAAU,IAAI,UAAU,CAwBvC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB,CA4BA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAEvE;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAIhC,CAAC"}
|
package/dist/config.js
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
* Configuration module for IBM DB2i MCP Server
|
|
3
3
|
* Handles environment variables and JDBC connection options
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* Get the configured log level from environment
|
|
7
|
+
* Defaults to 'info' if not set or invalid
|
|
8
|
+
*/
|
|
9
|
+
export function getLogLevel() {
|
|
10
|
+
const level = process.env.LOG_LEVEL?.toLowerCase();
|
|
11
|
+
const validLevels = ['debug', 'info', 'warn', 'error', 'fatal'];
|
|
12
|
+
if (level && validLevels.includes(level)) {
|
|
13
|
+
return level;
|
|
14
|
+
}
|
|
15
|
+
return 'info';
|
|
16
|
+
}
|
|
5
17
|
/**
|
|
6
18
|
* Parse JDBC options from a semicolon-separated string
|
|
7
19
|
* Format: "key1=value1;key2=value2"
|
|
@@ -80,4 +92,17 @@ export function buildConnectionConfig(config) {
|
|
|
80
92
|
export function getDefaultSchema(config) {
|
|
81
93
|
return config.schema || undefined;
|
|
82
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Default rate limit configuration values
|
|
97
|
+
*
|
|
98
|
+
* Environment variables:
|
|
99
|
+
* - RATE_LIMIT_WINDOW_MS: Time window in milliseconds (default: 900000)
|
|
100
|
+
* - RATE_LIMIT_MAX_REQUESTS: Max requests per window (default: 100)
|
|
101
|
+
* - RATE_LIMIT_ENABLED: Set to 'false' or '0' to disable (default: true)
|
|
102
|
+
*/
|
|
103
|
+
export const DEFAULT_RATE_LIMIT = {
|
|
104
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
105
|
+
maxRequests: 100,
|
|
106
|
+
enabled: true,
|
|
107
|
+
};
|
|
83
108
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/db/connection.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JDBC Connection Manager for IBM DB2i using node-jt400
|
|
3
3
|
*/
|
|
4
|
-
import { pool } from 'node-jt400';
|
|
5
4
|
import type { DB2iConfig } from '../config.js';
|
|
6
5
|
export interface QueryResult {
|
|
7
6
|
rows: Record<string, unknown>[];
|
|
@@ -19,24 +18,12 @@ export interface QueryResult {
|
|
|
19
18
|
* Initialize the connection pool
|
|
20
19
|
*/
|
|
21
20
|
export declare function initializePool(config: DB2iConfig): void;
|
|
22
|
-
/**
|
|
23
|
-
* Get the connection pool instance
|
|
24
|
-
*/
|
|
25
|
-
export declare function getPool(): ReturnType<typeof pool>;
|
|
26
21
|
/**
|
|
27
22
|
* Execute a query and return results
|
|
28
23
|
*/
|
|
29
24
|
export declare function executeQuery(sql: string, params?: unknown[]): Promise<QueryResult>;
|
|
30
|
-
/**
|
|
31
|
-
* Execute a query with metadata about columns
|
|
32
|
-
*/
|
|
33
|
-
export declare function executeQueryWithMetadata(sql: string, params?: unknown[]): Promise<QueryResult>;
|
|
34
25
|
/**
|
|
35
26
|
* Test the database connection
|
|
36
27
|
*/
|
|
37
28
|
export declare function testConnection(): Promise<boolean>;
|
|
38
|
-
/**
|
|
39
|
-
* Close the connection pool
|
|
40
|
-
*/
|
|
41
|
-
export declare function closePool(): Promise<void>;
|
|
42
29
|
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM/C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE;QACT,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,KAAK,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,SAAS,EAAE,MAAM,CAAC;YAClB,KAAK,EAAE,MAAM,CAAC;SACf,CAAC,CAAC;KACJ,CAAC;CACH;AAID;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAKvD;AA4BD;;GAEG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,OAAO,EAAO,GACrB,OAAO,CAAC,WAAW,CAAC,CAgBtB;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAUvD"}
|
package/dist/db/connection.js
CHANGED
|
@@ -3,18 +3,22 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { pool } from 'node-jt400';
|
|
5
5
|
import { buildConnectionConfig } from '../config.js';
|
|
6
|
+
import { createChildLogger } from '../utils/logger.js';
|
|
7
|
+
const log = createChildLogger({ component: 'database' });
|
|
6
8
|
let connectionPool = null;
|
|
7
9
|
/**
|
|
8
10
|
* Initialize the connection pool
|
|
9
11
|
*/
|
|
10
12
|
export function initializePool(config) {
|
|
13
|
+
log.debug({ hostname: config.hostname, port: config.port }, 'Initializing connection pool');
|
|
11
14
|
const connectionConfig = buildConnectionConfig(config);
|
|
12
15
|
connectionPool = pool(connectionConfig);
|
|
16
|
+
log.info({ hostname: config.hostname }, 'Connection pool created');
|
|
13
17
|
}
|
|
14
18
|
/**
|
|
15
|
-
* Get the connection pool instance
|
|
19
|
+
* Get the connection pool instance (internal use only)
|
|
16
20
|
*/
|
|
17
|
-
|
|
21
|
+
function getPool() {
|
|
18
22
|
if (!connectionPool) {
|
|
19
23
|
throw new Error('Connection pool not initialized. Call initializePool first.');
|
|
20
24
|
}
|
|
@@ -45,31 +49,16 @@ function toParams(params) {
|
|
|
45
49
|
export async function executeQuery(sql, params = []) {
|
|
46
50
|
const db = getPool();
|
|
47
51
|
try {
|
|
52
|
+
log.debug({ sql: sql.substring(0, 200), paramCount: params.length }, 'Executing query');
|
|
48
53
|
const typedParams = toParams(params);
|
|
49
54
|
const results = await db.query(sql, typedParams);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
const message = error instanceof Error ? error.message : 'Unknown database error';
|
|
56
|
-
throw new Error(`Database query failed: ${message}`);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Execute a query with metadata about columns
|
|
61
|
-
*/
|
|
62
|
-
export async function executeQueryWithMetadata(sql, params = []) {
|
|
63
|
-
const db = getPool();
|
|
64
|
-
try {
|
|
65
|
-
const typedParams = toParams(params);
|
|
66
|
-
const results = await db.query(sql, typedParams);
|
|
67
|
-
return {
|
|
68
|
-
rows: results,
|
|
69
|
-
};
|
|
55
|
+
const rows = results;
|
|
56
|
+
log.debug({ rowCount: rows.length }, 'Query completed');
|
|
57
|
+
return { rows };
|
|
70
58
|
}
|
|
71
59
|
catch (error) {
|
|
72
60
|
const message = error instanceof Error ? error.message : 'Unknown database error';
|
|
61
|
+
log.debug({ err: error, sql: sql.substring(0, 200) }, 'Database query failed');
|
|
73
62
|
throw new Error(`Database query failed: ${message}`);
|
|
74
63
|
}
|
|
75
64
|
}
|
|
@@ -78,20 +67,14 @@ export async function executeQueryWithMetadata(sql, params = []) {
|
|
|
78
67
|
*/
|
|
79
68
|
export async function testConnection() {
|
|
80
69
|
try {
|
|
70
|
+
log.debug('Testing database connection');
|
|
81
71
|
await executeQuery('SELECT 1 FROM SYSIBM.SYSDUMMY1');
|
|
72
|
+
log.debug('Connection test successful');
|
|
82
73
|
return true;
|
|
83
74
|
}
|
|
84
|
-
catch {
|
|
75
|
+
catch (error) {
|
|
76
|
+
log.warn({ err: error }, 'Connection test failed');
|
|
85
77
|
return false;
|
|
86
78
|
}
|
|
87
79
|
}
|
|
88
|
-
/**
|
|
89
|
-
* Close the connection pool
|
|
90
|
-
*/
|
|
91
|
-
export async function closePool() {
|
|
92
|
-
if (connectionPool) {
|
|
93
|
-
// node-jt400 pool doesn't have explicit close, but we can clear the reference
|
|
94
|
-
connectionPool = null;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
80
|
//# sourceMappingURL=connection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGlC,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":"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"}
|
package/dist/db/queries.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Query helpers for IBM DB2i metadata and data access
|
|
3
3
|
*/
|
|
4
|
+
import { SqlSecurityValidator, validateQuery as validateSqlQuery, type SecurityValidationResult, type SecurityConfig } from '../utils/security/sqlSecurityValidator.js';
|
|
5
|
+
export { SqlSecurityValidator, validateSqlQuery, type SecurityValidationResult, type SecurityConfig };
|
|
4
6
|
/**
|
|
5
7
|
* Convert a filter pattern to SQL LIKE pattern
|
|
6
8
|
* Supports:
|
|
@@ -12,8 +14,22 @@
|
|
|
12
14
|
export declare function filterToLikePattern(filter: string | undefined): string;
|
|
13
15
|
/**
|
|
14
16
|
* Validate that a query is read-only (SELECT only)
|
|
17
|
+
*
|
|
18
|
+
* Uses the enhanced SqlSecurityValidator with AST parsing and regex fallback
|
|
19
|
+
* for comprehensive security validation.
|
|
20
|
+
*
|
|
21
|
+
* @param sql - SQL query to validate
|
|
22
|
+
* @returns true if the query is safe to execute, false otherwise
|
|
15
23
|
*/
|
|
16
24
|
export declare function isReadOnlyQuery(sql: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Validate a query and return detailed results including any violations
|
|
27
|
+
*
|
|
28
|
+
* @param sql - SQL query to validate
|
|
29
|
+
* @param config - Optional security configuration
|
|
30
|
+
* @returns Detailed validation result with violations
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateQuery(sql: string, config?: SecurityConfig): SecurityValidationResult;
|
|
17
33
|
/**
|
|
18
34
|
* List all schemas/libraries
|
|
19
35
|
*/
|
|
@@ -46,6 +62,9 @@ export declare function describeTable(schema: string, table: string): Promise<Ar
|
|
|
46
62
|
}>>;
|
|
47
63
|
/**
|
|
48
64
|
* List views in a schema
|
|
65
|
+
*
|
|
66
|
+
* Note: This only returns SQL-defined views (CREATE VIEW).
|
|
67
|
+
* For legacy DDS logical files, query QSYS.QADBFDEP.
|
|
49
68
|
*/
|
|
50
69
|
export declare function listViews(schema: string, filter?: string): Promise<Array<{
|
|
51
70
|
view_name: string;
|
|
@@ -53,6 +72,9 @@ export declare function listViews(schema: string, filter?: string): Promise<Arra
|
|
|
53
72
|
}>>;
|
|
54
73
|
/**
|
|
55
74
|
* List indexes for a table
|
|
75
|
+
*
|
|
76
|
+
* Note: This only returns SQL-defined indexes (CREATE INDEX).
|
|
77
|
+
* For legacy DDS logical files, query QSYS.QADBFDEP and QSYS.QADBKFLD.
|
|
56
78
|
*/
|
|
57
79
|
export declare function listIndexes(schema: string, table: string): Promise<Array<{
|
|
58
80
|
index_name: string;
|
package/dist/db/queries.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/db/queries.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/db/queries.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,oBAAoB,EACpB,aAAa,IAAI,gBAAgB,EACjC,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACpB,MAAM,2CAA2C,CAAC;AAGnD,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,KAAK,wBAAwB,EAAE,KAAK,cAAc,EAAE,CAAC;AAEtG;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAiBtE;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGlD;AAEH;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,wBAAwB,CAE5F;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAAC,CAkBtH;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,KAAK,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAAC,CAqBvF;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,KAAK,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC,CAAC,CAiCF;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAAC,CAoBjE;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,KAAK,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC,CA4BF;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,KAAK,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC,CAAC,CAAC,CAqCF"}
|
package/dist/db/queries.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* Query helpers for IBM DB2i metadata and data access
|
|
3
3
|
*/
|
|
4
4
|
import { executeQuery } from './connection.js';
|
|
5
|
+
import { SqlSecurityValidator, validateQuery as validateSqlQuery, } from '../utils/security/sqlSecurityValidator.js';
|
|
6
|
+
// Re-export for backwards compatibility and convenience
|
|
7
|
+
export { SqlSecurityValidator, validateSqlQuery };
|
|
5
8
|
/**
|
|
6
9
|
* Convert a filter pattern to SQL LIKE pattern
|
|
7
10
|
* Supports:
|
|
@@ -27,35 +30,26 @@ export function filterToLikePattern(filter) {
|
|
|
27
30
|
}
|
|
28
31
|
/**
|
|
29
32
|
* Validate that a query is read-only (SELECT only)
|
|
33
|
+
*
|
|
34
|
+
* Uses the enhanced SqlSecurityValidator with AST parsing and regex fallback
|
|
35
|
+
* for comprehensive security validation.
|
|
36
|
+
*
|
|
37
|
+
* @param sql - SQL query to validate
|
|
38
|
+
* @returns true if the query is safe to execute, false otherwise
|
|
30
39
|
*/
|
|
31
40
|
export function isReadOnlyQuery(sql) {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
'ALTER',
|
|
45
|
-
'TRUNCATE',
|
|
46
|
-
'GRANT',
|
|
47
|
-
'REVOKE',
|
|
48
|
-
'CALL',
|
|
49
|
-
'EXECUTE',
|
|
50
|
-
];
|
|
51
|
-
for (const keyword of dangerousKeywords) {
|
|
52
|
-
// Check if keyword appears as a statement (not inside a string or comment)
|
|
53
|
-
const regex = new RegExp(`\\b${keyword}\\b`, 'i');
|
|
54
|
-
if (regex.test(trimmed)) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return true;
|
|
41
|
+
const result = SqlSecurityValidator.validateQuery(sql);
|
|
42
|
+
return result.isValid;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Validate a query and return detailed results including any violations
|
|
46
|
+
*
|
|
47
|
+
* @param sql - SQL query to validate
|
|
48
|
+
* @param config - Optional security configuration
|
|
49
|
+
* @returns Detailed validation result with violations
|
|
50
|
+
*/
|
|
51
|
+
export function validateQuery(sql, config) {
|
|
52
|
+
return SqlSecurityValidator.validateQuery(sql, config);
|
|
59
53
|
}
|
|
60
54
|
/**
|
|
61
55
|
* List all schemas/libraries
|
|
@@ -135,6 +129,9 @@ export async function describeTable(schema, table) {
|
|
|
135
129
|
}
|
|
136
130
|
/**
|
|
137
131
|
* List views in a schema
|
|
132
|
+
*
|
|
133
|
+
* Note: This only returns SQL-defined views (CREATE VIEW).
|
|
134
|
+
* For legacy DDS logical files, query QSYS.QADBFDEP.
|
|
138
135
|
*/
|
|
139
136
|
export async function listViews(schema, filter) {
|
|
140
137
|
const pattern = filterToLikePattern(filter);
|
|
@@ -156,18 +153,28 @@ export async function listViews(schema, filter) {
|
|
|
156
153
|
}
|
|
157
154
|
/**
|
|
158
155
|
* List indexes for a table
|
|
156
|
+
*
|
|
157
|
+
* Note: This only returns SQL-defined indexes (CREATE INDEX).
|
|
158
|
+
* For legacy DDS logical files, query QSYS.QADBFDEP and QSYS.QADBKFLD.
|
|
159
159
|
*/
|
|
160
160
|
export async function listIndexes(schema, table) {
|
|
161
161
|
const sql = `
|
|
162
162
|
SELECT
|
|
163
|
-
INDEX_NAME,
|
|
164
|
-
INDEX_SCHEMA,
|
|
165
|
-
IS_UNIQUE,
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
163
|
+
I.INDEX_NAME,
|
|
164
|
+
I.INDEX_SCHEMA,
|
|
165
|
+
I.IS_UNIQUE,
|
|
166
|
+
COALESCE(
|
|
167
|
+
LISTAGG(K.COLUMN_NAME, ', ') WITHIN GROUP (ORDER BY K.ORDINAL_POSITION),
|
|
168
|
+
''
|
|
169
|
+
) AS COLUMN_NAMES
|
|
170
|
+
FROM QSYS2.SYSINDEXES I
|
|
171
|
+
LEFT JOIN QSYS2.SYSKEYS K
|
|
172
|
+
ON I.INDEX_SCHEMA = K.INDEX_SCHEMA
|
|
173
|
+
AND I.INDEX_NAME = K.INDEX_NAME
|
|
174
|
+
WHERE I.TABLE_SCHEMA = ?
|
|
175
|
+
AND I.TABLE_NAME = ?
|
|
176
|
+
GROUP BY I.INDEX_NAME, I.INDEX_SCHEMA, I.IS_UNIQUE
|
|
177
|
+
ORDER BY I.INDEX_NAME
|
|
171
178
|
`;
|
|
172
179
|
const result = await executeQuery(sql, [schema.toUpperCase(), table.toUpperCase()]);
|
|
173
180
|
return result.rows.map(row => ({
|
package/dist/db/queries.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/db/queries.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/db/queries.ts"],"names":[],"mappings":"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"}
|