@danielblomma/cortex-mcp 0.4.2 → 0.6.4

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 (61) hide show
  1. package/README.md +64 -16
  2. package/bin/cortex.mjs +32 -60
  3. package/package.json +17 -3
  4. package/scaffold/.context/ontology.cypher +47 -0
  5. package/scaffold/.githooks/post-commit +14 -0
  6. package/scaffold/.githooks/post-rewrite +23 -0
  7. package/scaffold/mcp/package-lock.json +19 -23
  8. package/scaffold/mcp/package.json +3 -1
  9. package/scaffold/mcp/src/contextEntities.ts +311 -0
  10. package/scaffold/mcp/src/defaults.ts +6 -0
  11. package/scaffold/mcp/src/embed.ts +163 -37
  12. package/scaffold/mcp/src/frontmatter.ts +39 -0
  13. package/scaffold/mcp/src/graph.ts +330 -109
  14. package/scaffold/mcp/src/graphMetrics.ts +12 -0
  15. package/scaffold/mcp/src/impactPresentation.ts +202 -0
  16. package/scaffold/mcp/src/impactRanking.ts +237 -0
  17. package/scaffold/mcp/src/impactResponse.ts +47 -0
  18. package/scaffold/mcp/src/impactResults.ts +173 -0
  19. package/scaffold/mcp/src/impactSeed.ts +33 -0
  20. package/scaffold/mcp/src/impactTraversal.ts +83 -0
  21. package/scaffold/mcp/src/jsonl.ts +34 -0
  22. package/scaffold/mcp/src/loadGraph.ts +345 -86
  23. package/scaffold/mcp/src/paths.ts +24 -2
  24. package/scaffold/mcp/src/presets.ts +137 -0
  25. package/scaffold/mcp/src/relatedResponse.ts +30 -0
  26. package/scaffold/mcp/src/relatedTraversal.ts +101 -0
  27. package/scaffold/mcp/src/rules.ts +27 -0
  28. package/scaffold/mcp/src/search.ts +191 -355
  29. package/scaffold/mcp/src/searchCore.ts +274 -0
  30. package/scaffold/mcp/src/searchResults.ts +133 -0
  31. package/scaffold/mcp/src/server.ts +95 -3
  32. package/scaffold/mcp/src/types.ts +99 -3
  33. package/scaffold/scripts/context.sh +12 -46
  34. package/scaffold/scripts/dashboard.mjs +797 -0
  35. package/scaffold/scripts/dashboard.sh +13 -0
  36. package/scaffold/scripts/ingest.mjs +2219 -59
  37. package/scaffold/scripts/install-git-hooks.sh +3 -1
  38. package/scaffold/scripts/memory-compile.mjs +232 -0
  39. package/scaffold/scripts/memory-compile.sh +20 -0
  40. package/scaffold/scripts/memory-lint.mjs +375 -0
  41. package/scaffold/scripts/memory-lint.sh +20 -0
  42. package/scaffold/scripts/parsers/config.mjs +178 -0
  43. package/scaffold/scripts/parsers/cpp.mjs +316 -0
  44. package/scaffold/scripts/parsers/dotnet/VbNetParser/Program.cs +374 -0
  45. package/scaffold/scripts/parsers/dotnet/VbNetParser/VbNetParser.csproj +13 -0
  46. package/scaffold/scripts/parsers/javascript/ast.mjs +61 -0
  47. package/scaffold/scripts/parsers/javascript/calls.mjs +53 -0
  48. package/scaffold/scripts/parsers/javascript/chunks.mjs +388 -0
  49. package/scaffold/scripts/parsers/javascript/imports.mjs +162 -0
  50. package/scaffold/scripts/parsers/javascript/patterns.mjs +82 -0
  51. package/scaffold/scripts/parsers/javascript/scope-analysis.mjs +3 -0
  52. package/scaffold/scripts/parsers/javascript/scope-builder.mjs +305 -0
  53. package/scaffold/scripts/parsers/javascript/scope-resolver.mjs +82 -0
  54. package/scaffold/scripts/parsers/javascript.mjs +27 -350
  55. package/scaffold/scripts/parsers/resources.mjs +166 -0
  56. package/scaffold/scripts/parsers/sql.mjs +137 -0
  57. package/scaffold/scripts/parsers/vbnet.mjs +143 -0
  58. package/scaffold/scripts/status.sh +15 -8
  59. package/scaffold/scripts/capture-note.sh +0 -55
  60. package/scaffold/scripts/plan-state-engine.cjs +0 -310
  61. package/scaffold/scripts/plan-state.sh +0 -71
@@ -0,0 +1,137 @@
1
+ import type { ImpactParams, RelatedParams, SearchParams } from "./types.js";
2
+
3
+ export type ResponsePreset = "full" | "compact" | "minimal";
4
+
5
+ type ImpactPresetOptions = {
6
+ includeScores: boolean;
7
+ includeReasons: boolean;
8
+ verbosePaths: boolean;
9
+ maxPathHopsShown: number;
10
+ };
11
+
12
+ type SearchPresetOptions = {
13
+ includeScores: boolean;
14
+ includeMatchedRules: boolean;
15
+ includeContent: boolean;
16
+ };
17
+
18
+ type RelatedPresetOptions = {
19
+ includeEdges: boolean;
20
+ includeEntityMetadata: boolean;
21
+ };
22
+
23
+ function resolvePresetOptions<TDefaults extends Record<string, boolean | number | string>>(
24
+ responsePreset: ResponsePreset | undefined,
25
+ presetDefaultsByMode: Record<ResponsePreset, TDefaults>,
26
+ explicitOverrides: Partial<TDefaults>
27
+ ): TDefaults & { responsePreset: ResponsePreset } {
28
+ const resolvedPreset = responsePreset ?? "full";
29
+ const presetDefaults = presetDefaultsByMode[resolvedPreset];
30
+
31
+ return {
32
+ responsePreset: resolvedPreset,
33
+ ...presetDefaults,
34
+ ...Object.fromEntries(
35
+ Object.entries(explicitOverrides).filter(([, value]) => value !== undefined)
36
+ )
37
+ } as TDefaults & { responsePreset: ResponsePreset };
38
+ }
39
+
40
+ export function resolveImpactResponsePreset(parsed: ImpactParams): {
41
+ responsePreset: ResponsePreset;
42
+ includeScores: boolean;
43
+ includeReasons: boolean;
44
+ verbosePaths: boolean;
45
+ maxPathHopsShown: number;
46
+ } {
47
+ return resolvePresetOptions<ImpactPresetOptions>(
48
+ parsed.response_preset,
49
+ {
50
+ full: {
51
+ includeScores: true,
52
+ includeReasons: true,
53
+ verbosePaths: true,
54
+ maxPathHopsShown: 2
55
+ },
56
+ compact: {
57
+ includeScores: false,
58
+ includeReasons: true,
59
+ verbosePaths: false,
60
+ maxPathHopsShown: 2
61
+ },
62
+ minimal: {
63
+ includeScores: false,
64
+ includeReasons: false,
65
+ verbosePaths: false,
66
+ maxPathHopsShown: 1
67
+ }
68
+ },
69
+ {
70
+ includeScores: parsed.include_scores,
71
+ includeReasons: parsed.include_reasons,
72
+ verbosePaths: parsed.verbose_paths,
73
+ maxPathHopsShown: parsed.max_path_hops_shown
74
+ }
75
+ );
76
+ }
77
+
78
+ export function resolveSearchResponsePreset(parsed: SearchParams): {
79
+ responsePreset: ResponsePreset;
80
+ includeScores: boolean;
81
+ includeMatchedRules: boolean;
82
+ includeContent: boolean;
83
+ } {
84
+ return resolvePresetOptions<SearchPresetOptions>(
85
+ parsed.response_preset,
86
+ {
87
+ full: {
88
+ includeScores: true,
89
+ includeMatchedRules: true,
90
+ includeContent: false
91
+ },
92
+ compact: {
93
+ includeScores: false,
94
+ includeMatchedRules: true,
95
+ includeContent: false
96
+ },
97
+ minimal: {
98
+ includeScores: false,
99
+ includeMatchedRules: false,
100
+ includeContent: false
101
+ }
102
+ },
103
+ {
104
+ includeScores: parsed.include_scores,
105
+ includeMatchedRules: parsed.include_matched_rules,
106
+ includeContent: parsed.include_content
107
+ }
108
+ );
109
+ }
110
+
111
+ export function resolveRelatedResponsePreset(parsed: RelatedParams): {
112
+ responsePreset: ResponsePreset;
113
+ includeEdges: boolean;
114
+ includeEntityMetadata: boolean;
115
+ } {
116
+ return resolvePresetOptions<RelatedPresetOptions>(
117
+ parsed.response_preset,
118
+ {
119
+ full: {
120
+ includeEdges: true,
121
+ includeEntityMetadata: true
122
+ },
123
+ compact: {
124
+ includeEdges: false,
125
+ includeEntityMetadata: true
126
+ },
127
+ minimal: {
128
+ includeEdges: false,
129
+ includeEntityMetadata: false
130
+ }
131
+ },
132
+ {
133
+ includeEdges: parsed.include_edges,
134
+ includeEntityMetadata: parsed.include_entity_metadata
135
+ }
136
+ );
137
+ }
@@ -0,0 +1,30 @@
1
+ import type { RelatedParams, ToolPayload } from "./types.js";
2
+
3
+ export function buildRelatedResponseMeta(params: {
4
+ parsed: RelatedParams;
5
+ responsePreset: "full" | "compact" | "minimal";
6
+ includeEdges: boolean;
7
+ includeEntityMetadata: boolean;
8
+ contextSource: string;
9
+ }): ToolPayload {
10
+ return {
11
+ entity_id: params.parsed.entity_id,
12
+ depth: params.parsed.depth,
13
+ response_preset: params.responsePreset,
14
+ include_edges: params.includeEdges,
15
+ include_entity_metadata: params.includeEntityMetadata,
16
+ context_source: params.contextSource
17
+ };
18
+ }
19
+
20
+ export function buildEmptyRelatedResponse(params: {
21
+ meta: ToolPayload;
22
+ warning: string;
23
+ }): ToolPayload {
24
+ return {
25
+ ...params.meta,
26
+ related: [],
27
+ edges: [],
28
+ warning: params.warning
29
+ };
30
+ }
@@ -0,0 +1,101 @@
1
+ import type { JsonObject, RelationRecord } from "./types.js";
2
+
3
+ export function traverseRelatedGraph(params: {
4
+ entityId: string;
5
+ relations: RelationRecord[];
6
+ depth: number;
7
+ catalog: Map<string, JsonObject>;
8
+ includeEntityMetadata: boolean;
9
+ }): {
10
+ related: JsonObject[];
11
+ traversedEdges: JsonObject[];
12
+ } {
13
+ const outgoing = new Map<string, RelationRecord[]>();
14
+ const incoming = new Map<string, RelationRecord[]>();
15
+
16
+ for (const relation of params.relations) {
17
+ const outList = outgoing.get(relation.from) ?? [];
18
+ outList.push(relation);
19
+ outgoing.set(relation.from, outList);
20
+
21
+ const inList = incoming.get(relation.to) ?? [];
22
+ inList.push(relation);
23
+ incoming.set(relation.to, inList);
24
+ }
25
+
26
+ const seen = new Set<string>([params.entityId]);
27
+ const queue: Array<{ id: string; hop: number }> = [{ id: params.entityId, hop: 0 }];
28
+ const related: JsonObject[] = [];
29
+ const traversedEdges: JsonObject[] = [];
30
+ const traversedEdgeKeys = new Set<string>();
31
+
32
+ while (queue.length > 0) {
33
+ const current = queue.shift() as { id: string; hop: number };
34
+ if (current.hop >= params.depth) {
35
+ continue;
36
+ }
37
+
38
+ const neighbors = [
39
+ ...(outgoing.get(current.id) ?? []).map((edge) => ({
40
+ edge,
41
+ next: edge.to,
42
+ direction: "outgoing"
43
+ })),
44
+ ...(incoming.get(current.id) ?? []).map((edge) => ({
45
+ edge,
46
+ next: edge.from,
47
+ direction: "incoming"
48
+ }))
49
+ ];
50
+
51
+ for (const neighbor of neighbors) {
52
+ const target = neighbor.next;
53
+ if (!seen.has(target)) {
54
+ seen.add(target);
55
+ queue.push({ id: target, hop: current.hop + 1 });
56
+
57
+ const entity = params.catalog.get(target) ?? {
58
+ id: target,
59
+ type: "Unknown",
60
+ label: target,
61
+ status: "unknown",
62
+ source_of_truth: false
63
+ };
64
+
65
+ related.push(
66
+ params.includeEntityMetadata
67
+ ? {
68
+ ...entity,
69
+ hops: current.hop + 1,
70
+ via_relation: neighbor.edge.relation,
71
+ direction: neighbor.direction
72
+ }
73
+ : {
74
+ id: entity.id,
75
+ type: entity.type,
76
+ label: entity.label,
77
+ hops: current.hop + 1,
78
+ via_relation: neighbor.edge.relation,
79
+ direction: neighbor.direction
80
+ }
81
+ );
82
+ }
83
+
84
+ const edgeKey = `${neighbor.edge.from}|${neighbor.edge.relation}|${neighbor.edge.to}|${neighbor.edge.note}`;
85
+ if (!traversedEdgeKeys.has(edgeKey)) {
86
+ traversedEdgeKeys.add(edgeKey);
87
+ traversedEdges.push({
88
+ from: neighbor.edge.from,
89
+ to: neighbor.edge.to,
90
+ relation: neighbor.edge.relation,
91
+ note: neighbor.edge.note
92
+ });
93
+ }
94
+ }
95
+ }
96
+
97
+ return {
98
+ related,
99
+ traversedEdges
100
+ };
101
+ }
@@ -0,0 +1,27 @@
1
+ import { loadContextData } from "./graph.js";
2
+ import type { RulesParams, ToolPayload } from "./types.js";
3
+
4
+ export async function runContextRules(parsed: RulesParams): Promise<ToolPayload> {
5
+ const data = await loadContextData();
6
+
7
+ const rules = data.rules
8
+ .filter((rule) => parsed.include_inactive || rule.status === "active")
9
+ .filter((rule) => !parsed.scope || rule.scope === parsed.scope || rule.scope === "global")
10
+ .sort((a, b) => b.priority - a.priority)
11
+ .map((rule) => ({
12
+ id: rule.id,
13
+ title: rule.title,
14
+ description: rule.body,
15
+ priority: rule.priority,
16
+ scope: rule.scope,
17
+ status: rule.status
18
+ }));
19
+
20
+ return {
21
+ scope: parsed.scope ?? "global",
22
+ count: rules.length,
23
+ context_source: data.source,
24
+ warning: data.warning,
25
+ rules
26
+ };
27
+ }