@shrkcrft/mcp-server 0.1.0-alpha.2 → 0.1.0-alpha.20

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 (189) hide show
  1. package/dist/index.d.ts +4 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +4 -0
  4. package/dist/server/columnar-format.d.ts +34 -0
  5. package/dist/server/columnar-format.d.ts.map +1 -0
  6. package/dist/server/columnar-format.js +95 -0
  7. package/dist/server/create-mcp-server.d.ts +3 -0
  8. package/dist/server/create-mcp-server.d.ts.map +1 -1
  9. package/dist/server/create-mcp-server.js +24 -9
  10. package/dist/server/fit-array-to-budget.d.ts +24 -0
  11. package/dist/server/fit-array-to-budget.d.ts.map +1 -0
  12. package/dist/server/fit-array-to-budget.js +60 -0
  13. package/dist/server/serialize-tool-data.d.ts +15 -0
  14. package/dist/server/serialize-tool-data.d.ts.map +1 -0
  15. package/dist/server/serialize-tool-data.js +22 -0
  16. package/dist/server/tool-definition.d.ts +15 -0
  17. package/dist/server/tool-definition.d.ts.map +1 -1
  18. package/dist/server/tool-input-validators.d.ts.map +1 -1
  19. package/dist/server/tool-input-validators.js +43 -0
  20. package/dist/tools/agent-brief.tool.d.ts.map +1 -1
  21. package/dist/tools/agent-brief.tool.js +20 -0
  22. package/dist/tools/align-cache.tool.d.ts +11 -0
  23. package/dist/tools/align-cache.tool.d.ts.map +1 -0
  24. package/dist/tools/align-cache.tool.js +76 -0
  25. package/dist/tools/all-tools.d.ts.map +1 -1
  26. package/dist/tools/all-tools.js +72 -7
  27. package/dist/tools/architecture-map.tool.d.ts.map +1 -1
  28. package/dist/tools/architecture-map.tool.js +4 -2
  29. package/dist/tools/code-find-usages.tool.d.ts +16 -0
  30. package/dist/tools/code-find-usages.tool.d.ts.map +1 -0
  31. package/dist/tools/code-find-usages.tool.js +180 -0
  32. package/dist/tools/command-catalog.tool.d.ts.map +1 -1
  33. package/dist/tools/command-catalog.tool.js +11 -7
  34. package/dist/tools/compress-context.tool.d.ts +8 -0
  35. package/dist/tools/compress-context.tool.d.ts.map +1 -0
  36. package/dist/tools/compress-context.tool.js +81 -0
  37. package/dist/tools/dashboard-summary.tool.d.ts.map +1 -1
  38. package/dist/tools/dashboard-summary.tool.js +2 -4
  39. package/dist/tools/delegate-task.tool.d.ts +3 -0
  40. package/dist/tools/delegate-task.tool.d.ts.map +1 -0
  41. package/dist/tools/delegate-task.tool.js +94 -0
  42. package/dist/tools/deps-audit.tool.d.ts +10 -0
  43. package/dist/tools/deps-audit.tool.d.ts.map +1 -0
  44. package/dist/tools/deps-audit.tool.js +251 -0
  45. package/dist/tools/diff-check.tool.d.ts +15 -0
  46. package/dist/tools/diff-check.tool.d.ts.map +1 -0
  47. package/dist/tools/diff-check.tool.js +157 -0
  48. package/dist/tools/file-advice.tool.d.ts +22 -0
  49. package/dist/tools/file-advice.tool.d.ts.map +1 -0
  50. package/dist/tools/file-advice.tool.js +88 -0
  51. package/dist/tools/get-api-surface-diff.tool.d.ts +3 -0
  52. package/dist/tools/get-api-surface-diff.tool.d.ts.map +1 -0
  53. package/dist/tools/get-api-surface-diff.tool.js +60 -0
  54. package/dist/tools/get-arch-violations.tool.d.ts +3 -0
  55. package/dist/tools/get-arch-violations.tool.d.ts.map +1 -0
  56. package/dist/tools/get-arch-violations.tool.js +30 -0
  57. package/dist/tools/get-code-intelligence-state.tool.d.ts +11 -0
  58. package/dist/tools/get-code-intelligence-state.tool.d.ts.map +1 -0
  59. package/dist/tools/get-code-intelligence-state.tool.js +60 -0
  60. package/dist/tools/get-context-pack.tool.d.ts +3 -0
  61. package/dist/tools/get-context-pack.tool.d.ts.map +1 -0
  62. package/dist/tools/get-context-pack.tool.js +40 -0
  63. package/dist/tools/get-framework-entities.tool.d.ts +3 -0
  64. package/dist/tools/get-framework-entities.tool.d.ts.map +1 -0
  65. package/dist/tools/get-framework-entities.tool.js +68 -0
  66. package/dist/tools/get-graph-callers.tool.d.ts +3 -0
  67. package/dist/tools/get-graph-callers.tool.d.ts.map +1 -0
  68. package/dist/tools/get-graph-callers.tool.js +94 -0
  69. package/dist/tools/get-graph-context.tool.d.ts +3 -0
  70. package/dist/tools/get-graph-context.tool.d.ts.map +1 -0
  71. package/dist/tools/get-graph-context.tool.js +125 -0
  72. package/dist/tools/get-graph-cycles.tool.d.ts +10 -0
  73. package/dist/tools/get-graph-cycles.tool.d.ts.map +1 -0
  74. package/dist/tools/get-graph-cycles.tool.js +58 -0
  75. package/dist/tools/get-graph-deps.tool.d.ts +12 -0
  76. package/dist/tools/get-graph-deps.tool.d.ts.map +1 -0
  77. package/dist/tools/get-graph-deps.tool.js +80 -0
  78. package/dist/tools/get-graph-hubs.tool.d.ts +3 -0
  79. package/dist/tools/get-graph-hubs.tool.d.ts.map +1 -0
  80. package/dist/tools/get-graph-hubs.tool.js +61 -0
  81. package/dist/tools/get-graph-impact-analysis.tool.d.ts +3 -0
  82. package/dist/tools/get-graph-impact-analysis.tool.d.ts.map +1 -0
  83. package/dist/tools/get-graph-impact-analysis.tool.js +44 -0
  84. package/dist/tools/get-graph-impact.tool.d.ts +3 -0
  85. package/dist/tools/get-graph-impact.tool.d.ts.map +1 -0
  86. package/dist/tools/get-graph-impact.tool.js +150 -0
  87. package/dist/tools/get-graph-path.tool.d.ts +3 -0
  88. package/dist/tools/get-graph-path.tool.d.ts.map +1 -0
  89. package/dist/tools/get-graph-path.tool.js +144 -0
  90. package/dist/tools/get-graph-search.tool.d.ts +3 -0
  91. package/dist/tools/get-graph-search.tool.d.ts.map +1 -0
  92. package/dist/tools/get-graph-search.tool.js +95 -0
  93. package/dist/tools/get-graph-status.tool.d.ts +11 -0
  94. package/dist/tools/get-graph-status.tool.d.ts.map +1 -0
  95. package/dist/tools/get-graph-status.tool.js +55 -0
  96. package/dist/tools/get-graph-unresolved.tool.d.ts +11 -0
  97. package/dist/tools/get-graph-unresolved.tool.d.ts.map +1 -0
  98. package/dist/tools/get-graph-unresolved.tool.js +85 -0
  99. package/dist/tools/get-impact-baseline.tool.d.ts +9 -0
  100. package/dist/tools/get-impact-baseline.tool.d.ts.map +1 -0
  101. package/dist/tools/get-impact-baseline.tool.js +65 -0
  102. package/dist/tools/get-intent-benchmark-run.tool.d.ts +12 -0
  103. package/dist/tools/get-intent-benchmark-run.tool.d.ts.map +1 -0
  104. package/dist/tools/get-intent-benchmark-run.tool.js +55 -0
  105. package/dist/tools/get-knowledge-graph.tool.d.ts +7 -0
  106. package/dist/tools/get-knowledge-graph.tool.d.ts.map +1 -1
  107. package/dist/tools/get-knowledge-graph.tool.js +62 -3
  108. package/dist/tools/get-migrations.tool.d.ts +3 -0
  109. package/dist/tools/get-migrations.tool.d.ts.map +1 -0
  110. package/dist/tools/get-migrations.tool.js +70 -0
  111. package/dist/tools/get-pattern-registry.tool.d.ts +8 -0
  112. package/dist/tools/get-pattern-registry.tool.d.ts.map +1 -0
  113. package/dist/tools/get-pattern-registry.tool.js +40 -0
  114. package/dist/tools/get-quality-gate.tool.d.ts +3 -0
  115. package/dist/tools/get-quality-gate.tool.d.ts.map +1 -0
  116. package/dist/tools/get-quality-gate.tool.js +27 -0
  117. package/dist/tools/get-relevant-context.tool.d.ts.map +1 -1
  118. package/dist/tools/get-relevant-context.tool.js +30 -6
  119. package/dist/tools/get-rules-for-file.tool.d.ts +3 -0
  120. package/dist/tools/get-rules-for-file.tool.d.ts.map +1 -0
  121. package/dist/tools/get-rules-for-file.tool.js +54 -0
  122. package/dist/tools/get-structural-rewrite-plan.tool.d.ts +3 -0
  123. package/dist/tools/get-structural-rewrite-plan.tool.d.ts.map +1 -0
  124. package/dist/tools/get-structural-rewrite-plan.tool.js +46 -0
  125. package/dist/tools/get-structural-search.tool.d.ts +3 -0
  126. package/dist/tools/get-structural-search.tool.d.ts.map +1 -0
  127. package/dist/tools/get-structural-search.tool.js +35 -0
  128. package/dist/tools/get-task-packet.tool.d.ts.map +1 -1
  129. package/dist/tools/get-task-packet.tool.js +26 -22
  130. package/dist/tools/graph-staleness.d.ts +34 -0
  131. package/dist/tools/graph-staleness.d.ts.map +1 -0
  132. package/dist/tools/graph-staleness.js +36 -0
  133. package/dist/tools/list-boundary-rules.tool.d.ts.map +1 -1
  134. package/dist/tools/list-boundary-rules.tool.js +20 -16
  135. package/dist/tools/list-knowledge.tool.d.ts.map +1 -1
  136. package/dist/tools/list-knowledge.tool.js +14 -13
  137. package/dist/tools/list-packs.tool.d.ts.map +1 -1
  138. package/dist/tools/list-packs.tool.js +19 -15
  139. package/dist/tools/list-path-conventions.tool.d.ts.map +1 -1
  140. package/dist/tools/list-path-conventions.tool.js +19 -15
  141. package/dist/tools/list-pipelines.tool.d.ts.map +1 -1
  142. package/dist/tools/list-pipelines.tool.js +18 -14
  143. package/dist/tools/list-presets.tool.d.ts.map +1 -1
  144. package/dist/tools/list-presets.tool.js +25 -21
  145. package/dist/tools/list-rules.tool.d.ts.map +1 -1
  146. package/dist/tools/list-rules.tool.js +18 -14
  147. package/dist/tools/list-templates.tool.d.ts.map +1 -1
  148. package/dist/tools/list-templates.tool.js +18 -14
  149. package/dist/tools/plan-quality-review.tool.d.ts +21 -0
  150. package/dist/tools/plan-quality-review.tool.d.ts.map +1 -0
  151. package/dist/tools/plan-quality-review.tool.js +294 -0
  152. package/dist/tools/primary-tools.d.ts +24 -0
  153. package/dist/tools/primary-tools.d.ts.map +1 -0
  154. package/dist/tools/primary-tools.js +86 -0
  155. package/dist/tools/r19-extras.tool.js +1 -1
  156. package/dist/tools/r32-profiles.tool.d.ts +0 -3
  157. package/dist/tools/r32-profiles.tool.d.ts.map +1 -1
  158. package/dist/tools/r32-profiles.tool.js +3 -54
  159. package/dist/tools/retrieve-original.tool.d.ts +9 -0
  160. package/dist/tools/retrieve-original.tool.d.ts.map +1 -0
  161. package/dist/tools/retrieve-original.tool.js +47 -0
  162. package/dist/tools/runtime-reports.tool.d.ts.map +1 -1
  163. package/dist/tools/runtime-reports.tool.js +1 -3
  164. package/dist/tools/safety-audit.tool.d.ts.map +1 -1
  165. package/dist/tools/safety-audit.tool.js +1 -4
  166. package/dist/tools/search-knowledge.tool.d.ts.map +1 -1
  167. package/dist/tools/search-knowledge.tool.js +17 -13
  168. package/dist/tools/search.tool.d.ts.map +1 -1
  169. package/dist/tools/search.tool.js +11 -8
  170. package/dist/tools/smart-context-bundle.tool.d.ts +17 -0
  171. package/dist/tools/smart-context-bundle.tool.d.ts.map +1 -0
  172. package/dist/tools/smart-context-bundle.tool.js +110 -0
  173. package/dist/tools/smart-context-feed.tool.d.ts +17 -0
  174. package/dist/tools/smart-context-feed.tool.d.ts.map +1 -0
  175. package/dist/tools/smart-context-feed.tool.js +138 -0
  176. package/dist/tools/start-here.tool.js +2 -2
  177. package/package.json +28 -16
  178. package/dist/tools/r22-extras.tool.d.ts +0 -4
  179. package/dist/tools/r22-extras.tool.d.ts.map +0 -1
  180. package/dist/tools/r22-extras.tool.js +0 -42
  181. package/dist/tools/r26-ingest.tool.d.ts +0 -10
  182. package/dist/tools/r26-ingest.tool.d.ts.map +0 -1
  183. package/dist/tools/r26-ingest.tool.js +0 -174
  184. package/dist/tools/r28-plugin-lifecycle.tool.d.ts +0 -4
  185. package/dist/tools/r28-plugin-lifecycle.tool.d.ts.map +0 -1
  186. package/dist/tools/r28-plugin-lifecycle.tool.js +0 -94
  187. package/dist/tools/r34-search-unified.tool.d.ts +0 -3
  188. package/dist/tools/r34-search-unified.tool.d.ts.map +0 -1
  189. package/dist/tools/r34-search-unified.tool.js +0 -38
@@ -0,0 +1,60 @@
1
+ import { buildCodeIntelligenceChecks, DoctorSeverity, } from '@shrkcrft/inspector';
2
+ import { FORMAT_INPUT_PROPERTY, formatObjectArrays } from "../server/columnar-format.js";
3
+ /**
4
+ * Read-only MCP mirror of `shrk code-intel`. Returns the same 14
5
+ * code-intelligence doctor findings in one shot — agents can pull
6
+ * the entire state without iterating `shrk doctor`'s full check list.
7
+ *
8
+ * Stable output schema (`sharkcraft.code-intelligence-state/v1`) so
9
+ * downstream renderers (dashboard, CI bots) can rely on the shape.
10
+ */
11
+ export const getCodeIntelligenceStateTool = {
12
+ name: 'get_code_intelligence_state',
13
+ description: 'Return all code-intelligence doctor findings (graph, rule-graph, api-surface, quality-gate, migrations, architecture, impact, framework, structural-search, context-planner) in one payload. Read-only.',
14
+ cliCommand: 'code-intel',
15
+ inputSchema: {
16
+ type: 'object',
17
+ properties: {
18
+ only: { type: 'array', items: { type: 'string' } },
19
+ checkId: { type: 'string' },
20
+ ...FORMAT_INPUT_PROPERTY,
21
+ },
22
+ additionalProperties: false,
23
+ },
24
+ handler(input, ctx) {
25
+ const args = input;
26
+ let checks = buildCodeIntelligenceChecks(ctx.inspection.projectRoot);
27
+ if (args.checkId) {
28
+ checks = checks.filter((c) => c.id === args.checkId);
29
+ }
30
+ if (args.only && args.only.length > 0) {
31
+ const allowed = new Set(args.only.map((s) => s.toLowerCase()));
32
+ checks = checks.filter((c) => allowed.has(c.severity));
33
+ }
34
+ const summary = summarize(checks);
35
+ const data = {
36
+ schema: 'sharkcraft.code-intelligence-state/v1',
37
+ totalChecks: checks.length,
38
+ summary,
39
+ checks,
40
+ };
41
+ return { data: formatObjectArrays(data, input) };
42
+ },
43
+ };
44
+ function summarize(checks) {
45
+ let ok = 0;
46
+ let info = 0;
47
+ let warnings = 0;
48
+ let errors = 0;
49
+ for (const c of checks) {
50
+ if (c.severity === DoctorSeverity.Ok)
51
+ ok += 1;
52
+ else if (c.severity === DoctorSeverity.Info)
53
+ info += 1;
54
+ else if (c.severity === DoctorSeverity.Warning)
55
+ warnings += 1;
56
+ else if (c.severity === DoctorSeverity.Error)
57
+ errors += 1;
58
+ }
59
+ return { ok, info, warnings, errors };
60
+ }
@@ -0,0 +1,3 @@
1
+ import type { IToolDefinition } from '../server/tool-definition.js';
2
+ export declare const getContextPackTool: IToolDefinition;
3
+ //# sourceMappingURL=get-context-pack.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-context-pack.tool.d.ts","sourceRoot":"","sources":["../../src/tools/get-context-pack.tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAUpE,eAAO,MAAM,kBAAkB,EAAE,eAoChC,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { planContext } from '@shrkcrft/context-planner';
2
+ export const getContextPackTool = {
3
+ name: 'get_context_pack',
4
+ description: 'Produce a deterministic, token-budgeted context pack (`sharkcraft.context-pack/v1`) for an AI coding agent: ranked relevant files, applicable rules, paths, templates, likely tests, surfaced risks, do-not-touch zones. Read-only.',
5
+ cliCommand: 'plan-context',
6
+ inputSchema: {
7
+ type: 'object',
8
+ properties: {
9
+ task: { type: 'string' },
10
+ budgetTokens: { type: 'number' },
11
+ hintedFiles: { type: 'array', items: { type: 'string' } },
12
+ hintedPackages: { type: 'array', items: { type: 'string' } },
13
+ maxFiles: { type: 'number' },
14
+ },
15
+ required: ['task'],
16
+ additionalProperties: false,
17
+ },
18
+ handler(input, ctx) {
19
+ const args = input;
20
+ const task = (args.task ?? '').trim();
21
+ if (!task) {
22
+ return {
23
+ isError: true,
24
+ error: { code: 'invalid-input', message: 'task is required' },
25
+ };
26
+ }
27
+ const pack = planContext({
28
+ projectRoot: ctx.inspection.projectRoot,
29
+ task,
30
+ budgetTokens: clamp(args.budgetTokens ?? 8000, 500, 64000),
31
+ maxFiles: clamp(args.maxFiles ?? 30, 1, 200),
32
+ ...(args.hintedFiles ? { hintedFiles: args.hintedFiles } : {}),
33
+ ...(args.hintedPackages ? { hintedPackages: args.hintedPackages } : {}),
34
+ });
35
+ return { data: pack };
36
+ },
37
+ };
38
+ function clamp(n, lo, hi) {
39
+ return Math.max(lo, Math.min(hi, n));
40
+ }
@@ -0,0 +1,3 @@
1
+ import type { IToolDefinition } from '../server/tool-definition.js';
2
+ export declare const getFrameworkEntitiesTool: IToolDefinition;
3
+ //# sourceMappingURL=get-framework-entities.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-framework-entities.tool.d.ts","sourceRoot":"","sources":["../../src/tools/get-framework-entities.tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAYpE,eAAO,MAAM,wBAAwB,EAAE,eA+DtC,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { FrameworkQueryApi } from '@shrkcrft/framework-scanners';
2
+ const NEXT = 'shrk framework index';
3
+ export const getFrameworkEntitiesTool = {
4
+ name: 'get_framework_entities',
5
+ description: 'Read-only: list framework entities discovered by the extractors (NestJS controllers/modules/providers/routes, React components/hook usages). Filters: framework, subtype, file. Pass `routes: true` for the NestJS route table.',
6
+ cliCommand: 'framework list',
7
+ inputSchema: {
8
+ type: 'object',
9
+ properties: {
10
+ framework: { type: 'string' },
11
+ subtype: { type: 'string' },
12
+ file: { type: 'string' },
13
+ limit: { type: 'number' },
14
+ routes: { type: 'boolean' },
15
+ },
16
+ additionalProperties: false,
17
+ },
18
+ handler(input, ctx) {
19
+ const args = input;
20
+ const missing = FrameworkQueryApi.missingDescription(ctx.inspection.projectRoot);
21
+ if (missing) {
22
+ return {
23
+ isError: true,
24
+ error: { code: 'framework-missing', message: missing, details: { nextCommand: NEXT } },
25
+ };
26
+ }
27
+ const api = FrameworkQueryApi.fromStore(ctx.inspection.projectRoot);
28
+ if (args.routes) {
29
+ const routes = api.routes();
30
+ return {
31
+ data: {
32
+ schema: 'sharkcraft.framework-routes/v1',
33
+ total: routes.length,
34
+ routes,
35
+ },
36
+ };
37
+ }
38
+ const limit = clamp(args.limit ?? 100, 1, 2000);
39
+ const entities = api.list({
40
+ ...(args.framework ? { framework: args.framework } : {}),
41
+ ...(args.subtype ? { subtype: args.subtype } : {}),
42
+ ...(args.file ? { file: args.file } : {}),
43
+ limit,
44
+ });
45
+ return {
46
+ data: {
47
+ schema: 'sharkcraft.framework-list/v1',
48
+ filters: {
49
+ framework: args.framework ?? null,
50
+ subtype: args.subtype ?? null,
51
+ file: args.file ?? null,
52
+ },
53
+ total: entities.length,
54
+ entities: entities.map((n) => ({
55
+ id: n.id,
56
+ label: n.label,
57
+ path: n.path,
58
+ framework: n.data?.['framework'] ?? null,
59
+ subtype: n.data?.['subtype'] ?? null,
60
+ data: n.data,
61
+ })),
62
+ },
63
+ };
64
+ },
65
+ };
66
+ function clamp(n, lo, hi) {
67
+ return Math.max(lo, Math.min(hi, n));
68
+ }
@@ -0,0 +1,3 @@
1
+ import type { IToolDefinition } from '../server/tool-definition.js';
2
+ export declare const getGraphCallersTool: IToolDefinition;
3
+ //# sourceMappingURL=get-graph-callers.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-graph-callers.tool.d.ts","sourceRoot":"","sources":["../../src/tools/get-graph-callers.tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAWpE,eAAO,MAAM,mBAAmB,EAAE,eAsEjC,CAAC"}
@@ -0,0 +1,94 @@
1
+ import { GraphQueryApi, GraphStore, loadGraphApiCached } from '@shrkcrft/graph';
2
+ import { FORMAT_INPUT_PROPERTY, formatObjectArrays } from "../server/columnar-format.js";
3
+ import { callGraphLanguageNote, graphResultStaleness } from "./graph-staleness.js";
4
+ const NEXT = 'shrk graph index';
5
+ export const getGraphCallersTool = {
6
+ name: 'get_graph_callers',
7
+ description: 'Find who calls/references a symbol (use this instead of grep before changing a function/type). Returns each caller as path:line of the first call site. Mode "call" → calls-symbol edges; mode "reference" → both references-symbol and calls-symbol. Read-only; needs `shrk graph index`.',
8
+ cliCommand: 'graph callers',
9
+ inputSchema: {
10
+ type: 'object',
11
+ properties: {
12
+ symbol: { type: 'string' },
13
+ mode: { type: 'string', enum: ['call', 'reference'] },
14
+ ...FORMAT_INPUT_PROPERTY,
15
+ },
16
+ required: ['symbol'],
17
+ additionalProperties: false,
18
+ },
19
+ handler(input, ctx) {
20
+ const args = input;
21
+ const target = (args.symbol ?? '').trim();
22
+ if (!target) {
23
+ return {
24
+ isError: true,
25
+ error: { code: 'invalid-input', message: 'symbol is required' },
26
+ };
27
+ }
28
+ const mode = args.mode ?? 'call';
29
+ const store = new GraphStore(ctx.inspection.projectRoot);
30
+ if (!store.exists()) {
31
+ return {
32
+ isError: true,
33
+ error: {
34
+ code: 'graph-missing',
35
+ message: `Code-intelligence index is missing. Run '${NEXT}'.`,
36
+ details: { nextCommand: NEXT },
37
+ },
38
+ };
39
+ }
40
+ const api = loadGraphApiCached(ctx.inspection.projectRoot) ?? GraphQueryApi.fromStore(ctx.inspection.projectRoot);
41
+ const sym = resolveSymbol(api, target);
42
+ if (!sym) {
43
+ return {
44
+ isError: true,
45
+ error: {
46
+ code: 'not-found',
47
+ message: `No symbol matched "${target}".`,
48
+ details: { target },
49
+ },
50
+ };
51
+ }
52
+ const cwd = ctx.inspection.projectRoot;
53
+ const sites = mode === 'reference' ? api.referenceSitesOf(sym.id) : api.callerSitesOf(sym.id);
54
+ // Targeted staleness over the result files: drop callers whose file was
55
+ // deleted on disk, flag those whose content changed since indexing — so a
56
+ // stale index never silently serves a wrong/dead caller. Read-only.
57
+ const fresh = graphResultStaleness(api, cwd, [sym.path, ...sites.map((s) => s.node.path)]);
58
+ const live = sites.filter((s) => !s.node.path || !fresh.deletedSet.has(s.node.path));
59
+ const note = callGraphLanguageNote(api, sym);
60
+ const data = {
61
+ schema: 'sharkcraft.graph-callers/v1',
62
+ symbol: summarise(sym),
63
+ mode,
64
+ total: live.length,
65
+ callers: live.slice(0, 200).map((s) => ({
66
+ ...summarise(s.node),
67
+ ...(s.line ? { line: s.line } : {}),
68
+ })),
69
+ ...(note ? { note } : {}),
70
+ ...(fresh.field ?? {}),
71
+ };
72
+ return { data: formatObjectArrays(data, input) };
73
+ },
74
+ };
75
+ function resolveSymbol(api, target) {
76
+ if (target.startsWith('symbol:'))
77
+ return api.neighbours(target)?.node;
78
+ const syms = api.findSymbol(target, { exact: true, limit: 5 });
79
+ if (syms.length === 0)
80
+ return undefined;
81
+ if (syms.length === 1)
82
+ return syms[0];
83
+ const exported = syms.find((s) => (s.data?.['isExported'] ?? false) === true);
84
+ return exported ?? syms[0];
85
+ }
86
+ function summarise(n) {
87
+ return {
88
+ id: n.id,
89
+ kind: n.kind,
90
+ label: n.label,
91
+ ...(n.path ? { path: n.path } : {}),
92
+ ...(n.line ? { line: n.line } : {}),
93
+ };
94
+ }
@@ -0,0 +1,3 @@
1
+ import type { IToolDefinition } from '../server/tool-definition.js';
2
+ export declare const getGraphContextTool: IToolDefinition;
3
+ //# sourceMappingURL=get-graph-context.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-graph-context.tool.d.ts","sourceRoot":"","sources":["../../src/tools/get-graph-context.tool.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAUpE,eAAO,MAAM,mBAAmB,EAAE,eAsGjC,CAAC"}
@@ -0,0 +1,125 @@
1
+ import { GraphQueryApi, GraphStore, NodeKind, loadGraphApiCached, } from '@shrkcrft/graph';
2
+ import { FORMAT_INPUT_PROPERTY, formatObjectArrays } from "../server/columnar-format.js";
3
+ import { dropDeleted, graphResultStaleness } from "./graph-staleness.js";
4
+ const NEXT = 'shrk graph index';
5
+ export const getGraphContextTool = {
6
+ name: 'get_graph_context',
7
+ description: 'Return graph context for a file or symbol: declared symbols, files this imports, files that import it. Read-only.',
8
+ cliCommand: 'graph context',
9
+ inputSchema: {
10
+ type: 'object',
11
+ properties: { target: { type: 'string' }, ...FORMAT_INPUT_PROPERTY },
12
+ required: ['target'],
13
+ additionalProperties: false,
14
+ },
15
+ handler(input, ctx) {
16
+ const args = input;
17
+ const target = (args.target ?? '').trim();
18
+ if (!target) {
19
+ return {
20
+ isError: true,
21
+ error: { code: 'invalid-input', message: 'target is required' },
22
+ };
23
+ }
24
+ const store = new GraphStore(ctx.inspection.projectRoot);
25
+ if (!store.exists()) {
26
+ return {
27
+ isError: true,
28
+ error: {
29
+ code: 'graph-missing',
30
+ message: `Code-intelligence index is missing. Run '${NEXT}'.`,
31
+ details: { nextCommand: NEXT },
32
+ },
33
+ };
34
+ }
35
+ const api = loadGraphApiCached(ctx.inspection.projectRoot) ?? GraphQueryApi.fromStore(ctx.inspection.projectRoot);
36
+ const anchor = resolveAnchor(api, target);
37
+ if (!anchor) {
38
+ return {
39
+ isError: true,
40
+ error: {
41
+ code: 'not-found',
42
+ message: `No graph node matched "${target}".`,
43
+ details: { target },
44
+ },
45
+ };
46
+ }
47
+ // A SYMBOL has no imports-file edges (those are file→file), so its import
48
+ // context is the DECLARING FILE's imports — compute neighbours on that file
49
+ // (mirrors the CLI; otherwise importsFrom/importedBy are wrongly empty).
50
+ const declaringFile = anchor.kind === NodeKind.Symbol
51
+ ? api.declaringFileOf(anchor.id) ?? (anchor.path ? api.findFile(anchor.path) : undefined)
52
+ : undefined;
53
+ const subjectId = anchor.kind === NodeKind.File ? anchor.id : declaringFile?.id ?? anchor.id;
54
+ const neighbours = api.neighbours(subjectId);
55
+ const symbols = anchor.kind === NodeKind.File ? api.symbolsIn(anchor.id) : [];
56
+ // Who uses this symbol — references + calls (the CLI provides these; the MCP
57
+ // previously omitted them, returning a confidently-wrong "nothing uses this").
58
+ const referencedBy = anchor.kind === NodeKind.Symbol ? api.referencesOf(anchor.id) : [];
59
+ const calledBy = anchor.kind === NodeKind.Symbol ? api.callersOf(anchor.id) : [];
60
+ // Typed subtype/supertype edges (extends / implements) — the precise
61
+ // "who implements this interface" answer for a symbol anchor.
62
+ const subtypes = anchor.kind === NodeKind.Symbol ? api.subtypesOf(anchor.id) : [];
63
+ const supertypes = anchor.kind === NodeKind.Symbol ? api.supertypesOf(anchor.id) : [];
64
+ const importsFrom = neighbours.out
65
+ .filter((o) => o.edge.kind === 'imports-file')
66
+ .slice(0, 50)
67
+ .map((o) => 'resolved' in o.target
68
+ ? { id: o.target.id, resolved: false }
69
+ : { ...summarise(o.target), resolved: true });
70
+ const importedBy = neighbours.in
71
+ .filter((i) => i.edge.kind === 'imports-file')
72
+ .slice(0, 50)
73
+ .map((i) => 'resolved' in i.source
74
+ ? { id: i.source.id, resolved: false }
75
+ : { ...summarise(i.source), resolved: true });
76
+ const referencedByRows = referencedBy.slice(0, 50).map(summarise);
77
+ const calledByRows = calledBy.slice(0, 50).map(summarise);
78
+ // Drop imports/refs to/from files deleted on disk; flag the rest if changed.
79
+ const fresh = graphResultStaleness(api, ctx.inspection.projectRoot, [
80
+ anchor.path,
81
+ ...importsFrom.map((x) => ('path' in x ? x.path : undefined)),
82
+ ...importedBy.map((x) => ('path' in x ? x.path : undefined)),
83
+ ...referencedByRows.map((x) => x.path),
84
+ ...calledByRows.map((x) => x.path),
85
+ ]);
86
+ const data = {
87
+ schema: 'sharkcraft.graph-context/v1',
88
+ anchor: summarise(anchor),
89
+ ...(declaringFile ? { declaredIn: summarise(declaringFile) } : {}),
90
+ importsFrom: dropDeleted(importsFrom, fresh.deletedSet),
91
+ importedBy: dropDeleted(importedBy, fresh.deletedSet),
92
+ symbols: symbols.slice(0, 50).map(summarise),
93
+ ...(referencedByRows.length > 0 ? { referencedBy: dropDeleted(referencedByRows, fresh.deletedSet) } : {}),
94
+ ...(calledByRows.length > 0 ? { calledBy: dropDeleted(calledByRows, fresh.deletedSet) } : {}),
95
+ ...(subtypes.length > 0 ? { subtypes: subtypes.slice(0, 50).map(summarise) } : {}),
96
+ ...(supertypes.length > 0 ? { supertypes: supertypes.slice(0, 50).map(summarise) } : {}),
97
+ ...(fresh.field ?? {}),
98
+ };
99
+ return { data: formatObjectArrays(data, input) };
100
+ },
101
+ };
102
+ function resolveAnchor(api, target) {
103
+ const direct = api.neighbours(target);
104
+ if (direct)
105
+ return direct.node;
106
+ if (target.startsWith('file:') || target.startsWith('symbol:') || target.startsWith('package:')) {
107
+ return undefined;
108
+ }
109
+ const f = api.findFile(target);
110
+ if (f)
111
+ return f;
112
+ const syms = api.findSymbol(target, { exact: true, limit: 1 });
113
+ if (syms.length > 0)
114
+ return syms[0];
115
+ return undefined;
116
+ }
117
+ function summarise(n) {
118
+ return {
119
+ id: n.id,
120
+ kind: n.kind,
121
+ label: n.label,
122
+ ...(n.path ? { path: n.path } : {}),
123
+ ...(n.line ? { line: n.line } : {}),
124
+ };
125
+ }
@@ -0,0 +1,10 @@
1
+ import type { IToolDefinition } from '../server/tool-definition.js';
2
+ /**
3
+ * Read-only MCP mirror of `shrk graph cycles`. Returns the full SCC
4
+ * list (sorted by size desc) so agents can answer "show me every
5
+ * import cycle in this repo" in a single tool call. Mirrors the safety
6
+ * contract: read-only, structured error with nextCommand when state
7
+ * is missing.
8
+ */
9
+ export declare const getGraphCyclesTool: IToolDefinition;
10
+ //# sourceMappingURL=get-graph-cycles.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-graph-cycles.tool.d.ts","sourceRoot":"","sources":["../../src/tools/get-graph-cycles.tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAYpE;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAmDhC,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { GraphQueryApi, GraphStore, loadGraphApiCached } from '@shrkcrft/graph';
2
+ import { FORMAT_INPUT_PROPERTY, formatObjectArrays } from "../server/columnar-format.js";
3
+ const NEXT = 'shrk graph index';
4
+ /**
5
+ * Read-only MCP mirror of `shrk graph cycles`. Returns the full SCC
6
+ * list (sorted by size desc) so agents can answer "show me every
7
+ * import cycle in this repo" in a single tool call. Mirrors the safety
8
+ * contract: read-only, structured error with nextCommand when state
9
+ * is missing.
10
+ */
11
+ export const getGraphCyclesTool = {
12
+ name: 'get_graph_cycles',
13
+ description: 'Return every import cycle in the code graph (strongly-connected components of size ≥ 2 over `imports-file` edges). Sorted by size desc. Read-only.',
14
+ cliCommand: 'graph cycles',
15
+ inputSchema: {
16
+ type: 'object',
17
+ properties: {
18
+ limit: { type: 'number' },
19
+ minSize: { type: 'number' },
20
+ ...FORMAT_INPUT_PROPERTY,
21
+ },
22
+ additionalProperties: false,
23
+ },
24
+ handler(input, ctx) {
25
+ const args = input;
26
+ const rawLimit = typeof args.limit === 'number' && Number.isFinite(args.limit) && args.limit > 0
27
+ ? args.limit
28
+ : 50;
29
+ const minSize = typeof args.minSize === 'number' && Number.isFinite(args.minSize) && args.minSize >= 2
30
+ ? args.minSize
31
+ : 2;
32
+ const store = new GraphStore(ctx.inspection.projectRoot);
33
+ if (!store.exists()) {
34
+ return {
35
+ isError: true,
36
+ error: {
37
+ code: 'graph-missing',
38
+ message: `Code-intelligence index is missing. Run '${NEXT}'.`,
39
+ details: { nextCommand: NEXT },
40
+ },
41
+ };
42
+ }
43
+ const api = loadGraphApiCached(ctx.inspection.projectRoot) ?? GraphQueryApi.fromStore(ctx.inspection.projectRoot);
44
+ const all = api.cycles();
45
+ const filtered = all.filter((c) => c.size >= minSize);
46
+ const limited = filtered.slice(0, rawLimit);
47
+ const data = {
48
+ schema: 'sharkcraft.graph-cycles/v1',
49
+ total: filtered.length,
50
+ truncated: filtered.length > rawLimit,
51
+ cycles: limited.map((c) => ({
52
+ size: c.size,
53
+ paths: c.paths ?? c.nodeIds.map((id) => id.replace(/^file:/, '')),
54
+ })),
55
+ };
56
+ return { data: formatObjectArrays(data, input) };
57
+ },
58
+ };
@@ -0,0 +1,12 @@
1
+ import type { IToolDefinition } from '../server/tool-definition.js';
2
+ /**
3
+ * Read-only MCP mirror of `shrk graph deps`. Returns the workspace
4
+ * package's outbound (`depends on`) and inbound (`depended on by`)
5
+ * `package-depends-on` edges from the persisted code graph.
6
+ *
7
+ * Mirrors the safety contract: structured `graph-missing` error when
8
+ * the index isn't built; `not-found` when no `package:<name>` node
9
+ * exists.
10
+ */
11
+ export declare const getGraphDepsTool: IToolDefinition;
12
+ //# sourceMappingURL=get-graph-deps.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-graph-deps.tool.d.ts","sourceRoot":"","sources":["../../src/tools/get-graph-deps.tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AASpE;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAmE9B,CAAC"}
@@ -0,0 +1,80 @@
1
+ import { EdgeKind, GraphQueryApi, GraphStore, loadGraphApiCached } from '@shrkcrft/graph';
2
+ const NEXT = 'shrk graph index';
3
+ /**
4
+ * Read-only MCP mirror of `shrk graph deps`. Returns the workspace
5
+ * package's outbound (`depends on`) and inbound (`depended on by`)
6
+ * `package-depends-on` edges from the persisted code graph.
7
+ *
8
+ * Mirrors the safety contract: structured `graph-missing` error when
9
+ * the index isn't built; `not-found` when no `package:<name>` node
10
+ * exists.
11
+ */
12
+ export const getGraphDepsTool = {
13
+ name: 'get_graph_deps',
14
+ description: 'Return inbound + outbound `package-depends-on` edges for a workspace package. Read-only.',
15
+ cliCommand: 'graph deps',
16
+ inputSchema: {
17
+ type: 'object',
18
+ properties: {
19
+ package: { type: 'string' },
20
+ },
21
+ required: ['package'],
22
+ additionalProperties: false,
23
+ },
24
+ handler(input, ctx) {
25
+ const args = input;
26
+ const target = (args.package ?? '').trim();
27
+ if (!target) {
28
+ return {
29
+ isError: true,
30
+ error: { code: 'invalid-input', message: 'package is required' },
31
+ };
32
+ }
33
+ const store = new GraphStore(ctx.inspection.projectRoot);
34
+ if (!store.exists()) {
35
+ return {
36
+ isError: true,
37
+ error: {
38
+ code: 'graph-missing',
39
+ message: `Code-intelligence index is missing. Run '${NEXT}'.`,
40
+ details: { nextCommand: NEXT },
41
+ },
42
+ };
43
+ }
44
+ const api = loadGraphApiCached(ctx.inspection.projectRoot) ?? GraphQueryApi.fromStore(ctx.inspection.projectRoot);
45
+ const pkgId = `package:${target}`;
46
+ const pkgNode = api.neighbours(pkgId)?.node;
47
+ if (!pkgNode) {
48
+ return {
49
+ isError: true,
50
+ error: {
51
+ code: 'not-found',
52
+ message: `No workspace package node "${target}" in the graph.`,
53
+ details: { target },
54
+ },
55
+ };
56
+ }
57
+ const dependsOn = api
58
+ .packageDeps(target)
59
+ .map((n) => n.id.replace(/^package:/, ''))
60
+ .sort();
61
+ const dependedOnBy = [];
62
+ for (const p of api.allPackages()) {
63
+ const name = p.id.replace(/^package:/, '');
64
+ if (name === target)
65
+ continue;
66
+ if (api.packageDeps(name).some((n) => n.id === pkgId))
67
+ dependedOnBy.push(name);
68
+ }
69
+ dependedOnBy.sort();
70
+ void EdgeKind;
71
+ return {
72
+ data: {
73
+ schema: 'sharkcraft.graph-deps/v1',
74
+ package: target,
75
+ dependsOn,
76
+ dependedOnBy,
77
+ },
78
+ };
79
+ },
80
+ };
@@ -0,0 +1,3 @@
1
+ import type { IToolDefinition } from '../server/tool-definition.js';
2
+ export declare const getGraphHubsTool: IToolDefinition;
3
+ //# sourceMappingURL=get-graph-hubs.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-graph-hubs.tool.d.ts","sourceRoot":"","sources":["../../src/tools/get-graph-hubs.tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAWpE,eAAO,MAAM,gBAAgB,EAAE,eA4C9B,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { GraphQueryApi, GraphStore, loadGraphApiCached } from '@shrkcrft/graph';
2
+ import { FORMAT_INPUT_PROPERTY, formatObjectArrays } from "../server/columnar-format.js";
3
+ const NEXT = 'shrk graph index';
4
+ export const getGraphHubsTool = {
5
+ name: 'get_graph_hubs',
6
+ description: 'The most-depended-on code: symbols ranked by how many DISTINCT files reference them, files by how many import them. The "load-bearing code" to change most carefully (biggest blast radius) and understand first when onboarding — the companion to get_graph_impact. Pass `path` (e.g. "packages/foo") to scope to one subsystem. Read-only; needs `shrk graph index`.',
7
+ cliCommand: 'graph hubs',
8
+ inputSchema: {
9
+ type: 'object',
10
+ properties: {
11
+ limit: { type: 'number' },
12
+ path: { type: 'string' },
13
+ ...FORMAT_INPUT_PROPERTY,
14
+ },
15
+ additionalProperties: false,
16
+ },
17
+ handler(input, ctx) {
18
+ const args = input;
19
+ const limit = clampLimit(args.limit);
20
+ const projectRoot = ctx.inspection.projectRoot;
21
+ const store = new GraphStore(projectRoot);
22
+ if (!store.exists()) {
23
+ return {
24
+ isError: true,
25
+ error: {
26
+ code: 'graph-missing',
27
+ message: `Code-intelligence index is missing. Run '${NEXT}'.`,
28
+ details: { nextCommand: NEXT },
29
+ },
30
+ };
31
+ }
32
+ const api = loadGraphApiCached(projectRoot) ?? GraphQueryApi.fromStore(projectRoot);
33
+ const pathScope = typeof args.path === 'string' && args.path.trim().length > 0 ? args.path.trim() : undefined;
34
+ const hubs = api.topHubs(limit, pathScope);
35
+ const row = (h) => ({
36
+ ...summarise(h.node),
37
+ inDegree: h.inDegree,
38
+ });
39
+ const data = {
40
+ schema: 'sharkcraft.graph-hubs/v1',
41
+ ...(pathScope ? { path: pathScope } : {}),
42
+ symbols: hubs.symbols.map(row),
43
+ files: hubs.files.map(row),
44
+ };
45
+ return { data: formatObjectArrays(data, input) };
46
+ },
47
+ };
48
+ function clampLimit(raw) {
49
+ if (typeof raw !== 'number' || !Number.isFinite(raw))
50
+ return 15;
51
+ return Math.max(1, Math.min(100, Math.floor(raw)));
52
+ }
53
+ function summarise(n) {
54
+ return {
55
+ id: n.id,
56
+ kind: n.kind,
57
+ label: n.label,
58
+ ...(n.path ? { path: n.path } : {}),
59
+ ...(n.line ? { line: n.line } : {}),
60
+ };
61
+ }