@cano721/mysql-mcp-server 0.7.0 → 0.8.1

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 (3) hide show
  1. package/README.md +28 -10
  2. package/build/index.js +55 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -343,6 +343,11 @@ MySQL 서버에서 접근 가능한 모든 데이터베이스를 나열합니다
343
343
  - `table` (필수): 연관 테이블을 찾을 기준 테이블명
344
344
  - `database` (선택사항): 데이터베이스명
345
345
  - `depth` (선택사항): 탐색할 최대 깊이 (기본값: 3, 10 초과 시 경고)
346
+ - `include_pattern_match` (선택사항): 컬럼명 패턴 매칭 포함 여부 (기본값: false)
347
+
348
+ **검색 방법**:
349
+ 1. **FK 제약조건 기반** (기본): 실제 Foreign Key가 설정된 테이블만 조회
350
+ 2. **패턴 매칭 포함**: `user_sn`, `user_id` 같은 컬럼명 패턴으로 추가 테이블 탐색
346
351
 
347
352
  **예제**:
348
353
  ```json
@@ -357,29 +362,41 @@ MySQL 서버에서 접근 가능한 모든 데이터베이스를 나열합니다
357
362
  }
358
363
  ```
359
364
 
365
+ **패턴 매칭 포함 예제**:
366
+ ```json
367
+ {
368
+ "server_name": "mysql",
369
+ "tool_name": "get_related_tables",
370
+ "arguments": {
371
+ "database": "my_database",
372
+ "table": "user",
373
+ "depth": 2,
374
+ "include_pattern_match": true
375
+ }
376
+ }
377
+ ```
378
+
360
379
  **응답 예시**:
361
380
  ```json
362
381
  {
363
382
  "root_table": "user",
364
383
  "database": "my_database",
365
384
  "requested_depth": 2,
385
+ "search_method": "fk_constraint",
386
+ "fk_relations_count": 55,
387
+ "pattern_match_count": 0,
366
388
  "total_relations": 55,
367
- "relations": [
389
+ "fk_relations": [
368
390
  {
369
391
  "depth": 1,
370
392
  "child_table": "user_matching_information",
371
393
  "fk_column": "user_sn",
372
394
  "parent_table": "user",
373
- "constraint_name": "FK_USER_MATCHING_INFORMATION_USER_SN"
374
- },
375
- {
376
- "depth": 2,
377
- "child_table": "user_matching_profile",
378
- "fk_column": "user_matching_information_sn",
379
- "parent_table": "user_matching_information",
380
- "constraint_name": "FK_USER_MATCHING_PROFILE_USER_INFORMATION_SN"
395
+ "constraint_name": "FK_USER_MATCHING_INFORMATION_USER_SN",
396
+ "match_type": "fk_constraint"
381
397
  }
382
- ]
398
+ ],
399
+ "note": "FK 제약조건 기반으로 조회되었습니다. 패턴 매칭도 포함하려면 '패턴 매칭도 포함해줘'라고 요청해보세요."
383
400
  }
384
401
  ```
385
402
 
@@ -775,6 +792,7 @@ echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | npx @cano721/mysql-mcp-s
775
792
 
776
793
  | 버전 | 날짜 | 주요 변경 사항 |
777
794
  |------|------|---------------|
795
+ | 0.8.0 | 2025-01-09 | `get_related_tables`에 패턴 매칭 옵션 추가, depth 제한 제거 |
778
796
  | 0.7.0 | 2025-01-09 | `get_related_tables` 도구 추가 (FK 기반 연관 테이블 depth별 조회) |
779
797
  | 0.6.0 | 2025-01-09 | `analyze_table` → `analyze_query`로 변경, `@latest` 태그 문서 추가 |
780
798
  | 0.5.0 | 2025-01-09 | `explain_query`, `analyze_table` 전용 도구 추가 |
package/build/index.js CHANGED
@@ -122,7 +122,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
122
122
  },
123
123
  {
124
124
  name: "get_related_tables",
125
- description: "Get all tables related to a specific table through foreign keys (parent and child relationships with depth)",
125
+ description: "Find all related/connected/associated tables linked to a specific table through foreign keys. Discovers table relationships and dependencies with depth traversal. Use this when asked to find related tables, connected tables, associated tables, or table relationships.",
126
126
  inputSchema: {
127
127
  type: "object",
128
128
  properties: {
@@ -137,6 +137,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
137
137
  depth: {
138
138
  type: "number",
139
139
  description: "Maximum depth to traverse relationships (default: 3, warning if > 10)"
140
+ },
141
+ include_pattern_match: {
142
+ type: "boolean",
143
+ description: "Include tables found by column name pattern matching (e.g., user_sn, user_id). Default: false"
140
144
  }
141
145
  },
142
146
  required: ["table"]
@@ -295,6 +299,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
295
299
  const table = request.params.arguments?.table;
296
300
  const database = request.params.arguments?.database;
297
301
  const requestedDepth = request.params.arguments?.depth || 3;
302
+ const includePatternMatch = request.params.arguments?.include_pattern_match || false;
298
303
  if (!table) {
299
304
  throw new McpError(ErrorCode.InvalidParams, "Table name is required");
300
305
  }
@@ -340,7 +345,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
340
345
  child_table: row.child_table,
341
346
  fk_column: row.fk_column,
342
347
  parent_table: row.parent_table,
343
- constraint_name: row.constraint_name
348
+ constraint_name: row.constraint_name,
349
+ match_type: 'fk_constraint'
344
350
  });
345
351
  if (!visited.has(row.child_table)) {
346
352
  visited.add(row.child_table);
@@ -371,7 +377,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
371
377
  child_table: row.child_table,
372
378
  fk_column: row.fk_column,
373
379
  parent_table: row.parent_table,
374
- constraint_name: row.constraint_name
380
+ constraint_name: row.constraint_name,
381
+ match_type: 'fk_constraint'
375
382
  });
376
383
  }
377
384
  if (!visited.has(row.parent_table)) {
@@ -386,12 +393,55 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
386
393
  return a.depth - b.depth;
387
394
  return a.child_table.localeCompare(b.child_table);
388
395
  });
396
+ // Pattern matching for tables without FK constraints
397
+ let patternMatchResults = [];
398
+ if (includePatternMatch) {
399
+ console.error('[Tool] Including pattern match results');
400
+ // Common patterns: table_sn, table_id, table_code, sn_table, id_table
401
+ const patterns = [
402
+ `${table}_sn`, `${table}_id`, `${table}_code`,
403
+ `sn_${table}`, `id_${table}`,
404
+ `${table}sn`, `${table}id`
405
+ ];
406
+ const patternQuery = `
407
+ SELECT DISTINCT
408
+ c.TABLE_NAME as related_table,
409
+ c.COLUMN_NAME as matching_column
410
+ FROM information_schema.COLUMNS c
411
+ WHERE c.TABLE_SCHEMA = ?
412
+ AND c.TABLE_NAME != ?
413
+ AND (${patterns.map(() => 'LOWER(c.COLUMN_NAME) = LOWER(?)').join(' OR ')})
414
+ `;
415
+ const { rows: patternRows } = await executeQuery(pool, patternQuery, [dbName, table, ...patterns]);
416
+ // Filter out tables already found via FK
417
+ const fkTables = new Set(results.map(r => r.child_table));
418
+ fkTables.add(table);
419
+ for (const row of patternRows) {
420
+ if (!fkTables.has(row.related_table)) {
421
+ patternMatchResults.push({
422
+ depth: 1,
423
+ child_table: row.related_table,
424
+ fk_column: row.matching_column,
425
+ parent_table: table,
426
+ constraint_name: '(pattern match)',
427
+ match_type: 'pattern_match'
428
+ });
429
+ }
430
+ }
431
+ }
389
432
  const response = {
390
433
  root_table: table,
391
434
  database: dbName,
392
435
  requested_depth: requestedDepth,
393
- total_relations: results.length,
394
- relations: results
436
+ search_method: includePatternMatch ? 'fk_constraint + pattern_match' : 'fk_constraint',
437
+ fk_relations_count: results.length,
438
+ pattern_match_count: patternMatchResults.length,
439
+ total_relations: results.length + patternMatchResults.length,
440
+ fk_relations: results,
441
+ pattern_match_relations: includePatternMatch ? patternMatchResults : undefined,
442
+ note: includePatternMatch
443
+ ? "FK 제약조건 + 컬럼명 패턴 매칭 결과입니다."
444
+ : "FK 제약조건 기반으로 조회되었습니다. 패턴 매칭도 포함하려면 '패턴 매칭도 포함해줘'라고 요청해보세요."
395
445
  };
396
446
  if (warning) {
397
447
  response.warning = warning;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cano721/mysql-mcp-server",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "An MCP server that provides read-only access to MySQL databases.",
5
5
  "type": "module",
6
6
  "bin": {