@grafema/mcp 0.2.1-beta → 0.2.6-beta

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 (96) hide show
  1. package/README.md +49 -25
  2. package/dist/analysis-worker.js +16 -8
  3. package/dist/analysis-worker.js.map +1 -0
  4. package/dist/analysis.d.ts.map +1 -1
  5. package/dist/analysis.js +1 -0
  6. package/dist/analysis.js.map +1 -0
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +27 -7
  9. package/dist/config.js.map +1 -0
  10. package/dist/definitions.d.ts +4 -4
  11. package/dist/definitions.d.ts.map +1 -1
  12. package/dist/definitions.js +158 -3
  13. package/dist/definitions.js.map +1 -0
  14. package/dist/handlers/analysis-handlers.d.ts +9 -0
  15. package/dist/handlers/analysis-handlers.d.ts.map +1 -0
  16. package/dist/handlers/analysis-handlers.js +73 -0
  17. package/dist/handlers/analysis-handlers.js.map +1 -0
  18. package/dist/handlers/context-handlers.d.ts +21 -0
  19. package/dist/handlers/context-handlers.d.ts.map +1 -0
  20. package/dist/handlers/context-handlers.js +330 -0
  21. package/dist/handlers/context-handlers.js.map +1 -0
  22. package/dist/handlers/coverage-handlers.d.ts +6 -0
  23. package/dist/handlers/coverage-handlers.d.ts.map +1 -0
  24. package/dist/handlers/coverage-handlers.js +42 -0
  25. package/dist/handlers/coverage-handlers.js.map +1 -0
  26. package/dist/handlers/dataflow-handlers.d.ts +8 -0
  27. package/dist/handlers/dataflow-handlers.d.ts.map +1 -0
  28. package/dist/handlers/dataflow-handlers.js +140 -0
  29. package/dist/handlers/dataflow-handlers.js.map +1 -0
  30. package/dist/handlers/documentation-handlers.d.ts +6 -0
  31. package/dist/handlers/documentation-handlers.d.ts.map +1 -0
  32. package/dist/handlers/documentation-handlers.js +79 -0
  33. package/dist/handlers/documentation-handlers.js.map +1 -0
  34. package/dist/handlers/guarantee-handlers.d.ts +21 -0
  35. package/dist/handlers/guarantee-handlers.d.ts.map +1 -0
  36. package/dist/handlers/guarantee-handlers.js +251 -0
  37. package/dist/handlers/guarantee-handlers.js.map +1 -0
  38. package/dist/handlers/guard-handlers.d.ts +14 -0
  39. package/dist/handlers/guard-handlers.d.ts.map +1 -0
  40. package/dist/handlers/guard-handlers.js +77 -0
  41. package/dist/handlers/guard-handlers.js.map +1 -0
  42. package/dist/handlers/index.d.ts +14 -0
  43. package/dist/handlers/index.d.ts.map +1 -0
  44. package/dist/handlers/index.js +14 -0
  45. package/dist/handlers/index.js.map +1 -0
  46. package/dist/handlers/issue-handlers.d.ts +6 -0
  47. package/dist/handlers/issue-handlers.d.ts.map +1 -0
  48. package/dist/handlers/issue-handlers.js +66 -0
  49. package/dist/handlers/issue-handlers.js.map +1 -0
  50. package/dist/handlers/project-handlers.d.ts +7 -0
  51. package/dist/handlers/project-handlers.d.ts.map +1 -0
  52. package/dist/handlers/project-handlers.js +153 -0
  53. package/dist/handlers/project-handlers.js.map +1 -0
  54. package/dist/handlers/query-handlers.d.ts +8 -0
  55. package/dist/handlers/query-handlers.d.ts.map +1 -0
  56. package/dist/handlers/query-handlers.js +171 -0
  57. package/dist/handlers/query-handlers.js.map +1 -0
  58. package/dist/handlers.d.ts +6 -2
  59. package/dist/handlers.d.ts.map +1 -1
  60. package/dist/handlers.js +367 -20
  61. package/dist/handlers.js.map +1 -0
  62. package/dist/prompts.d.ts +25 -0
  63. package/dist/prompts.d.ts.map +1 -0
  64. package/dist/prompts.js +33 -0
  65. package/dist/prompts.js.map +1 -0
  66. package/dist/server.js +52 -20
  67. package/dist/server.js.map +1 -0
  68. package/dist/state.js +1 -0
  69. package/dist/state.js.map +1 -0
  70. package/dist/types.d.ts +59 -1
  71. package/dist/types.d.ts.map +1 -1
  72. package/dist/types.js +1 -0
  73. package/dist/types.js.map +1 -0
  74. package/dist/utils.js +2 -1
  75. package/dist/utils.js.map +1 -0
  76. package/package.json +4 -3
  77. package/src/analysis-worker.ts +20 -9
  78. package/src/analysis.ts +2 -1
  79. package/src/config.ts +36 -4
  80. package/src/definitions.ts +162 -5
  81. package/src/handlers/analysis-handlers.ts +105 -0
  82. package/src/handlers/context-handlers.ts +410 -0
  83. package/src/handlers/coverage-handlers.ts +56 -0
  84. package/src/handlers/dataflow-handlers.ts +193 -0
  85. package/src/handlers/documentation-handlers.ts +89 -0
  86. package/src/handlers/guarantee-handlers.ts +278 -0
  87. package/src/handlers/guard-handlers.ts +100 -0
  88. package/src/handlers/index.ts +14 -0
  89. package/src/handlers/issue-handlers.ts +81 -0
  90. package/src/handlers/project-handlers.ts +200 -0
  91. package/src/handlers/query-handlers.ts +232 -0
  92. package/src/prompts.ts +56 -0
  93. package/src/server.ts +87 -21
  94. package/src/types.ts +68 -1
  95. package/src/utils.ts +2 -2
  96. package/src/handlers.ts +0 -1180
@@ -6,9 +6,11 @@ import { DEFAULT_LIMIT, MAX_LIMIT } from './utils.js';
6
6
 
7
7
  interface SchemaProperty {
8
8
  type: string;
9
- description: string;
9
+ description?: string;
10
10
  enum?: string[];
11
- items?: { type: string };
11
+ items?: SchemaProperty;
12
+ properties?: Record<string, SchemaProperty>;
13
+ required?: string[];
12
14
  }
13
15
 
14
16
  export interface ToolDefinition {
@@ -33,7 +35,7 @@ Available predicates:
33
35
 
34
36
  NODE TYPES:
35
37
  - MODULE, FUNCTION, METHOD, CLASS, VARIABLE, PARAMETER
36
- - CALL, METHOD_CALL, CALL_SITE
38
+ - CALL, PROPERTY_ACCESS, METHOD_CALL, CALL_SITE
37
39
  - http:route, http:request, db:query, socketio:emit, socketio:on
38
40
 
39
41
  EDGE TYPES:
@@ -101,7 +103,7 @@ Returns call sites with file locations and whether they're resolved.`,
101
103
  properties: {
102
104
  type: {
103
105
  type: 'string',
104
- description: 'Node type (e.g., FUNCTION, CLASS, MODULE)',
106
+ description: 'Node type (e.g., FUNCTION, CLASS, MODULE, PROPERTY_ACCESS)',
105
107
  },
106
108
  name: {
107
109
  type: 'string',
@@ -390,7 +392,7 @@ Examples:
390
392
  properties: {
391
393
  topic: {
392
394
  type: 'string',
393
- description: 'Topic: queries, types, guarantees, or overview',
395
+ description: 'Topic: queries, types, guarantees, onboarding, or overview',
394
396
  },
395
397
  },
396
398
  },
@@ -505,4 +507,159 @@ Max transitive depth is 5 to prevent explosion.`,
505
507
  required: ['name'],
506
508
  },
507
509
  },
510
+ {
511
+ name: 'get_context',
512
+ description: `Get deep context for a graph node: source code + full graph neighborhood.
513
+
514
+ Shows ALL incoming and outgoing edges grouped by type, with source code
515
+ at each connected node's location. Works for ANY node type.
516
+
517
+ Use this after find_nodes or query_graph to deep-dive into a specific node.
518
+
519
+ Output includes:
520
+ - Node info (type, name, semantic ID, location)
521
+ - Source code at the node's location
522
+ - All outgoing edges (what this node connects to)
523
+ - All incoming edges (what connects to this node)
524
+ - Code context at each connected node's location
525
+
526
+ Primary edges (CALLS, ASSIGNED_FROM, DEPENDS_ON, etc.) include code context.
527
+ Structural edges (CONTAINS, HAS_SCOPE, etc.) are shown in compact form.`,
528
+ inputSchema: {
529
+ type: 'object',
530
+ properties: {
531
+ semanticId: {
532
+ type: 'string',
533
+ description: 'Exact semantic ID of the node (from find_nodes or query_graph)',
534
+ },
535
+ contextLines: {
536
+ type: 'number',
537
+ description: 'Lines of code context around each reference (default: 3)',
538
+ },
539
+ edgeType: {
540
+ type: 'string',
541
+ description: 'Filter by edge type (comma-separated, e.g., "CALLS,ASSIGNED_FROM")',
542
+ },
543
+ },
544
+ required: ['semanticId'],
545
+ },
546
+ },
547
+ {
548
+ name: 'get_file_overview',
549
+ description: `Get a structured overview of all entities in a file with their relationships.
550
+
551
+ Shows imports, exports, classes, functions, and variables with key edges
552
+ (CALLS, EXTENDS, ASSIGNED_FROM). Use this for file-level understanding
553
+ before diving into specific nodes with get_context.
554
+
555
+ Output includes:
556
+ - Imports: module sources and imported names
557
+ - Exports: named and default exports
558
+ - Classes: with methods and their call targets
559
+ - Functions: with call targets
560
+ - Variables: with assignment sources
561
+
562
+ This is the recommended first step when exploring a file.
563
+ After using this, use get_context with specific node IDs for details.`,
564
+ inputSchema: {
565
+ type: 'object',
566
+ properties: {
567
+ file: {
568
+ type: 'string',
569
+ description: 'File path (relative to project root or absolute)',
570
+ },
571
+ include_edges: {
572
+ type: 'boolean',
573
+ description:
574
+ 'Include relationship edges like CALLS, EXTENDS (default: true). Set false for faster results.',
575
+ },
576
+ },
577
+ required: ['file'],
578
+ },
579
+ },
580
+ {
581
+ name: 'read_project_structure',
582
+ description: `Get the directory structure of the project.
583
+ Returns a tree of files and directories, useful for understanding
584
+ project layout during onboarding.
585
+
586
+ Excludes: node_modules, .git, dist, build, .grafema, coverage, .next, .nuxt
587
+
588
+ Use this tool when studying a new project to identify services,
589
+ packages, and entry points.`,
590
+ inputSchema: {
591
+ type: 'object',
592
+ properties: {
593
+ path: {
594
+ type: 'string',
595
+ description: 'Subdirectory to scan (relative to project root). Default: project root.',
596
+ },
597
+ depth: {
598
+ type: 'number',
599
+ description: 'Maximum directory depth (default: 3, max: 5)',
600
+ },
601
+ include_files: {
602
+ type: 'boolean',
603
+ description: 'Include files in output, not just directories (default: true)',
604
+ },
605
+ },
606
+ },
607
+ },
608
+ {
609
+ name: 'write_config',
610
+ description: `Write or update the Grafema configuration file (.grafema/config.yaml).
611
+ Validates all inputs before writing. Creates .grafema/ directory if needed.
612
+
613
+ Use this tool after studying the project to save the discovered configuration.
614
+ Only include fields you want to override — defaults are used for omitted fields.`,
615
+ inputSchema: {
616
+ type: 'object',
617
+ properties: {
618
+ services: {
619
+ type: 'array',
620
+ items: {
621
+ type: 'object',
622
+ properties: {
623
+ name: { type: 'string', description: 'Service name (e.g., "backend")' },
624
+ path: { type: 'string', description: 'Path relative to project root (e.g., "apps/backend")' },
625
+ entryPoint: { type: 'string', description: 'Entry point file relative to service path (e.g., "src/index.ts")' },
626
+ },
627
+ required: ['name', 'path'],
628
+ },
629
+ description: 'Service definitions (leave empty to use auto-discovery)',
630
+ },
631
+ plugins: {
632
+ type: 'object',
633
+ properties: {
634
+ indexing: { type: 'array', items: { type: 'string' }, description: 'Indexing plugins' },
635
+ analysis: { type: 'array', items: { type: 'string' }, description: 'Analysis plugins' },
636
+ enrichment: { type: 'array', items: { type: 'string' }, description: 'Enrichment plugins' },
637
+ validation: { type: 'array', items: { type: 'string' }, description: 'Validation plugins' },
638
+ },
639
+ description: 'Plugin configuration (omit to use defaults)',
640
+ },
641
+ include: {
642
+ type: 'array',
643
+ items: { type: 'string' },
644
+ description: 'Glob patterns for files to include (e.g., ["src/**/*.ts"])',
645
+ },
646
+ exclude: {
647
+ type: 'array',
648
+ items: { type: 'string' },
649
+ description: 'Glob patterns for files to exclude (e.g., ["**/*.test.ts"])',
650
+ },
651
+ workspace: {
652
+ type: 'object',
653
+ properties: {
654
+ roots: {
655
+ type: 'array',
656
+ items: { type: 'string' },
657
+ description: 'Root directories for multi-root workspace',
658
+ },
659
+ },
660
+ description: 'Multi-root workspace config (only for workspaces)',
661
+ },
662
+ },
663
+ },
664
+ },
508
665
  ];
@@ -0,0 +1,105 @@
1
+ /**
2
+ * MCP Analysis Handlers
3
+ */
4
+
5
+ import { ensureAnalyzed } from '../analysis.js';
6
+ import { getAnalysisStatus, getOrCreateBackend, isAnalysisRunning } from '../state.js';
7
+ import {
8
+ textResult,
9
+ errorResult,
10
+ } from '../utils.js';
11
+ import type {
12
+ ToolResult,
13
+ AnalyzeProjectArgs,
14
+ GetSchemaArgs,
15
+ } from '../types.js';
16
+
17
+ // === ANALYSIS HANDLERS ===
18
+
19
+ export async function handleAnalyzeProject(args: AnalyzeProjectArgs): Promise<ToolResult> {
20
+ const { service, force } = args;
21
+
22
+ // Early check: return error for force=true if analysis is already running
23
+ // This provides immediate feedback instead of waiting or causing corruption
24
+ if (force && isAnalysisRunning()) {
25
+ return errorResult(
26
+ 'Cannot force re-analysis: analysis is already in progress. ' +
27
+ 'Use get_analysis_status to check current status, or wait for completion.'
28
+ );
29
+ }
30
+
31
+ // Note: setIsAnalyzed(false) is now handled inside ensureAnalyzed() within the lock
32
+ // to prevent race conditions where multiple calls could both clear the database
33
+
34
+ try {
35
+ await ensureAnalyzed(service || null, force || false);
36
+ const status = getAnalysisStatus();
37
+
38
+ return textResult(
39
+ `Analysis complete!\n` +
40
+ `- Services discovered: ${status.servicesDiscovered}\n` +
41
+ `- Services analyzed: ${status.servicesAnalyzed}\n` +
42
+ `- Total time: ${status.timings.total || 'N/A'}s`
43
+ );
44
+ } catch (error) {
45
+ const message = error instanceof Error ? error.message : String(error);
46
+ return errorResult(message);
47
+ }
48
+ }
49
+
50
+ export async function handleGetAnalysisStatus(): Promise<ToolResult> {
51
+ const status = getAnalysisStatus();
52
+
53
+ return textResult(
54
+ `Analysis Status:\n` +
55
+ `- Running: ${status.running}\n` +
56
+ `- Phase: ${status.phase || 'N/A'}\n` +
57
+ `- Message: ${status.message || 'N/A'}\n` +
58
+ `- Services discovered: ${status.servicesDiscovered}\n` +
59
+ `- Services analyzed: ${status.servicesAnalyzed}\n` +
60
+ (status.error ? `- Error: ${status.error}\n` : '')
61
+ );
62
+ }
63
+
64
+ export async function handleGetStats(): Promise<ToolResult> {
65
+ const db = await getOrCreateBackend();
66
+
67
+ const nodeCount = await db.nodeCount();
68
+ const edgeCount = await db.edgeCount();
69
+ const nodesByType = await db.countNodesByType();
70
+ const edgesByType = await db.countEdgesByType();
71
+
72
+ return textResult(
73
+ `Graph Statistics:\n\n` +
74
+ `Total nodes: ${nodeCount.toLocaleString()}\n` +
75
+ `Total edges: ${edgeCount.toLocaleString()}\n\n` +
76
+ `Nodes by type:\n${JSON.stringify(nodesByType, null, 2)}\n\n` +
77
+ `Edges by type:\n${JSON.stringify(edgesByType, null, 2)}`
78
+ );
79
+ }
80
+
81
+ export async function handleGetSchema(args: GetSchemaArgs): Promise<ToolResult> {
82
+ const db = await getOrCreateBackend();
83
+ const { type = 'all' } = args;
84
+
85
+ const nodesByType = await db.countNodesByType();
86
+ const edgesByType = await db.countEdgesByType();
87
+
88
+ let output = '';
89
+
90
+ if (type === 'nodes' || type === 'all') {
91
+ output += `Node Types (${Object.keys(nodesByType).length}):\n`;
92
+ for (const [t, count] of Object.entries(nodesByType)) {
93
+ output += ` - ${t}: ${count}\n`;
94
+ }
95
+ }
96
+
97
+ if (type === 'edges' || type === 'all') {
98
+ output += `\nEdge Types (${Object.keys(edgesByType).length}):\n`;
99
+ for (const [t, count] of Object.entries(edgesByType)) {
100
+ output += ` - ${t}: ${count}\n`;
101
+ }
102
+ }
103
+
104
+ return textResult(output);
105
+ }