@kage-core/kage-graph-mcp 1.0.0 → 1.1.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.
- package/README.md +304 -0
- package/dist/cli.js +783 -0
- package/dist/daemon.js +282 -0
- package/dist/index.js +677 -21
- package/dist/kernel.js +4493 -0
- package/dist/registry/index.js +373 -0
- package/package.json +26 -8
- package/viewer/app.js +1727 -0
- package/viewer/index.html +161 -0
- package/viewer/styles.css +628 -0
- package/index.ts +0 -254
- package/tsconfig.json +0 -14
package/dist/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.listTools = listTools;
|
|
5
|
+
exports.callTool = callTool;
|
|
4
6
|
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
5
7
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
8
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
9
|
+
const kernel_js_1 = require("./kernel.js");
|
|
7
10
|
const BASE_URL = "https://raw.githubusercontent.com/kage-core/kage-graph/master";
|
|
8
11
|
async function fetchText(url) {
|
|
9
12
|
const res = await fetch(url);
|
|
@@ -15,12 +18,18 @@ async function fetchJSON(url) {
|
|
|
15
18
|
const text = await fetchText(url);
|
|
16
19
|
return JSON.parse(text);
|
|
17
20
|
}
|
|
21
|
+
function domainNodeCount(domain) {
|
|
22
|
+
return (0, kernel_js_1.catalogDomainNodeCount)(domain);
|
|
23
|
+
}
|
|
24
|
+
function domainTopTags(domain) {
|
|
25
|
+
return domain.top_tags ?? [];
|
|
26
|
+
}
|
|
18
27
|
function scoreMatch(query, node) {
|
|
19
|
-
const terms = query.toLowerCase().split(/\s+/);
|
|
28
|
+
const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
20
29
|
let score = 0;
|
|
21
30
|
const title = node.title.toLowerCase();
|
|
22
31
|
const summary = (node.summary || "").toLowerCase();
|
|
23
|
-
const tags = node.tags.map((t) => t.toLowerCase());
|
|
32
|
+
const tags = (node.tags ?? []).map((t) => t.toLowerCase());
|
|
24
33
|
for (const term of terms) {
|
|
25
34
|
if (title.includes(term))
|
|
26
35
|
score += 3;
|
|
@@ -32,14 +41,22 @@ function scoreMatch(query, node) {
|
|
|
32
41
|
return score;
|
|
33
42
|
}
|
|
34
43
|
function scoreDomainMatch(query, domain) {
|
|
35
|
-
const terms = query.toLowerCase().split(/\s+/);
|
|
44
|
+
const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
45
|
+
const tags = domainTopTags(domain);
|
|
36
46
|
return terms.reduce((sum, term) => {
|
|
37
|
-
return sum +
|
|
47
|
+
return sum + tags.filter((t) => t.includes(term)).length;
|
|
38
48
|
}, 0);
|
|
39
49
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
50
|
+
function arrayArg(value) {
|
|
51
|
+
if (Array.isArray(value))
|
|
52
|
+
return value.map(String);
|
|
53
|
+
if (typeof value === "string")
|
|
54
|
+
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
const server = new index_js_1.Server({ name: "kage-graph", version: "1.1.0" }, { capabilities: { tools: {} } });
|
|
58
|
+
function listTools() {
|
|
59
|
+
return [
|
|
43
60
|
{
|
|
44
61
|
name: "kage_search",
|
|
45
62
|
description: "Search the kage community knowledge graph for gotchas, patterns, configs, and architectural decisions across auth, database, payments, deployment, frontend, testing, and more. Returns node summaries ranked by relevance.",
|
|
@@ -84,16 +101,381 @@ server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
|
84
101
|
properties: {},
|
|
85
102
|
},
|
|
86
103
|
},
|
|
87
|
-
|
|
104
|
+
{
|
|
105
|
+
name: "kage_recall",
|
|
106
|
+
description: "Recall repo-local Kage memory from .agent_memory packets. Returns an agent-ready context block plus ranked packet summaries.",
|
|
107
|
+
inputSchema: {
|
|
108
|
+
type: "object",
|
|
109
|
+
properties: {
|
|
110
|
+
query: { type: "string" },
|
|
111
|
+
project_dir: { type: "string" },
|
|
112
|
+
limit: { type: "number" },
|
|
113
|
+
explain: { type: "boolean" },
|
|
114
|
+
json: { type: "boolean" },
|
|
115
|
+
},
|
|
116
|
+
required: ["query", "project_dir"],
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "kage_graph",
|
|
121
|
+
description: "Query the repo-local Kage knowledge graph. Returns typed, evidence-backed graph facts from entities, edges, and episodes.",
|
|
122
|
+
inputSchema: {
|
|
123
|
+
type: "object",
|
|
124
|
+
properties: {
|
|
125
|
+
project_dir: { type: "string" },
|
|
126
|
+
query: { type: "string" },
|
|
127
|
+
limit: { type: "number" },
|
|
128
|
+
},
|
|
129
|
+
required: ["project_dir", "query"],
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "kage_code_graph",
|
|
134
|
+
description: "Query the source-derived codebase graph: files, symbols, imports, calls, routes, tests, package scripts. This is generated from code, not learned memory.",
|
|
135
|
+
inputSchema: {
|
|
136
|
+
type: "object",
|
|
137
|
+
properties: {
|
|
138
|
+
project_dir: { type: "string" },
|
|
139
|
+
query: { type: "string" },
|
|
140
|
+
limit: { type: "number" },
|
|
141
|
+
json: { type: "boolean" },
|
|
142
|
+
},
|
|
143
|
+
required: ["project_dir"],
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "kage_metrics",
|
|
148
|
+
description: "Return concise Kage adoption and quality metrics: code graph counts, language/parser coverage, memory graph evidence coverage, pending/approved packets, validation state, and readiness score.",
|
|
149
|
+
inputSchema: {
|
|
150
|
+
type: "object",
|
|
151
|
+
properties: {
|
|
152
|
+
project_dir: { type: "string" },
|
|
153
|
+
},
|
|
154
|
+
required: ["project_dir"],
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "kage_quality",
|
|
159
|
+
description: "Return memory quality metrics: useful memory ratio, duplicate burden, stale/wrong feedback, evidence coverage, path grounding, and review queue size.",
|
|
160
|
+
inputSchema: {
|
|
161
|
+
type: "object",
|
|
162
|
+
properties: {
|
|
163
|
+
project_dir: { type: "string" },
|
|
164
|
+
},
|
|
165
|
+
required: ["project_dir"],
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "kage_benchmark",
|
|
170
|
+
description: "Return Kage proof metrics: runbook, bug-fix, decision and code-flow coverage, recall hit rate, estimated rediscovery avoided, tokens saved, and time-to-first-use.",
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: "object",
|
|
173
|
+
properties: {
|
|
174
|
+
project_dir: { type: "string" },
|
|
175
|
+
},
|
|
176
|
+
required: ["project_dir"],
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "kage_setup_agent",
|
|
181
|
+
description: "Generate MCP/setup instructions for Codex, Claude Code, Cursor, Windsurf, Gemini CLI, OpenCode, Cline, Goose, Roo Code, Kilo Code, Claude Desktop, Aider, or generic MCP.",
|
|
182
|
+
inputSchema: {
|
|
183
|
+
type: "object",
|
|
184
|
+
properties: {
|
|
185
|
+
agent: { type: "string", enum: kernel_js_1.SETUP_AGENTS },
|
|
186
|
+
project_dir: { type: "string" },
|
|
187
|
+
write: { type: "boolean" },
|
|
188
|
+
},
|
|
189
|
+
required: ["agent", "project_dir"],
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: "kage_verify_agent",
|
|
194
|
+
description: "Verify that Kage is truly active for the current agent: config, repo policy, indexes, recall, code graph, and this live MCP tool reachability.",
|
|
195
|
+
inputSchema: {
|
|
196
|
+
type: "object",
|
|
197
|
+
properties: {
|
|
198
|
+
agent: { type: "string", enum: kernel_js_1.SETUP_AGENTS },
|
|
199
|
+
project_dir: { type: "string" },
|
|
200
|
+
},
|
|
201
|
+
required: ["agent", "project_dir"],
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: "kage_graph_visual",
|
|
206
|
+
description: "Export the repo-local Kage knowledge graph as Mermaid flowchart text for visual inspection.",
|
|
207
|
+
inputSchema: {
|
|
208
|
+
type: "object",
|
|
209
|
+
properties: {
|
|
210
|
+
project_dir: { type: "string" },
|
|
211
|
+
limit: { type: "number" },
|
|
212
|
+
},
|
|
213
|
+
required: ["project_dir"],
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: "kage_branch_overlay",
|
|
218
|
+
description: "Build and return branch overlay metadata: branch, head, merge-base, changed files, and pending packet IDs.",
|
|
219
|
+
inputSchema: {
|
|
220
|
+
type: "object",
|
|
221
|
+
properties: {
|
|
222
|
+
project_dir: { type: "string" },
|
|
223
|
+
},
|
|
224
|
+
required: ["project_dir"],
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: "kage_learn",
|
|
229
|
+
description: "Capture an actual reusable learning from the current session as repo-local memory. Prefer this over diff proposal when the agent knows what was learned.",
|
|
230
|
+
inputSchema: {
|
|
231
|
+
type: "object",
|
|
232
|
+
properties: {
|
|
233
|
+
project_dir: { type: "string" },
|
|
234
|
+
learning: { type: "string" },
|
|
235
|
+
title: { type: "string" },
|
|
236
|
+
type: { type: "string" },
|
|
237
|
+
evidence: { type: "string" },
|
|
238
|
+
verified_by: { type: "string" },
|
|
239
|
+
tags: { type: "array", items: { type: "string" } },
|
|
240
|
+
paths: { type: "array", items: { type: "string" } },
|
|
241
|
+
stack: { type: "array", items: { type: "string" } },
|
|
242
|
+
},
|
|
243
|
+
required: ["project_dir", "learning"],
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: "kage_capture",
|
|
248
|
+
description: "Create a repo-local Kage memory packet immediately. Org/global promotion still requires explicit human review.",
|
|
249
|
+
inputSchema: {
|
|
250
|
+
type: "object",
|
|
251
|
+
properties: {
|
|
252
|
+
project_dir: { type: "string" },
|
|
253
|
+
title: { type: "string" },
|
|
254
|
+
summary: { type: "string" },
|
|
255
|
+
body: { type: "string" },
|
|
256
|
+
type: { type: "string" },
|
|
257
|
+
tags: { type: "array", items: { type: "string" } },
|
|
258
|
+
paths: { type: "array", items: { type: "string" } },
|
|
259
|
+
stack: { type: "array", items: { type: "string" } },
|
|
260
|
+
},
|
|
261
|
+
required: ["project_dir", "title", "body"],
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: "kage_observe",
|
|
266
|
+
description: "Store an automatic local observation event from an agent session. Observations are privacy-scanned, deduplicated, and never published automatically.",
|
|
267
|
+
inputSchema: {
|
|
268
|
+
type: "object",
|
|
269
|
+
properties: {
|
|
270
|
+
project_dir: { type: "string" },
|
|
271
|
+
type: { type: "string", enum: ["session_start", "user_prompt", "tool_use", "tool_result", "file_change", "command_result", "test_result", "session_end"] },
|
|
272
|
+
session_id: { type: "string" },
|
|
273
|
+
agent: { type: "string" },
|
|
274
|
+
tool: { type: "string" },
|
|
275
|
+
path: { type: "string" },
|
|
276
|
+
command: { type: "string" },
|
|
277
|
+
exit_code: { type: "number" },
|
|
278
|
+
text: { type: "string" },
|
|
279
|
+
summary: { type: "string" },
|
|
280
|
+
timestamp: { type: "string" },
|
|
281
|
+
metadata: { type: "object" },
|
|
282
|
+
},
|
|
283
|
+
required: ["project_dir", "type"],
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
name: "kage_distill",
|
|
288
|
+
description: "Distill stored observations for one session into repo-local memory candidates. Org/global promotion still requires explicit human review.",
|
|
289
|
+
inputSchema: {
|
|
290
|
+
type: "object",
|
|
291
|
+
properties: {
|
|
292
|
+
project_dir: { type: "string" },
|
|
293
|
+
session_id: { type: "string" },
|
|
294
|
+
},
|
|
295
|
+
required: ["project_dir", "session_id"],
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
name: "kage_feedback",
|
|
300
|
+
description: "Record usefulness feedback on an approved repo-local memory packet: helpful, wrong, or stale.",
|
|
301
|
+
inputSchema: {
|
|
302
|
+
type: "object",
|
|
303
|
+
properties: {
|
|
304
|
+
project_dir: { type: "string" },
|
|
305
|
+
packet_id: { type: "string" },
|
|
306
|
+
kind: { type: "string", enum: ["helpful", "wrong", "stale"] },
|
|
307
|
+
},
|
|
308
|
+
required: ["project_dir", "packet_id", "kind"],
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
name: "kage_install_policy",
|
|
313
|
+
description: "Install or update the repo AGENTS.md policy that tells coding agents to use Kage automatically.",
|
|
314
|
+
inputSchema: {
|
|
315
|
+
type: "object",
|
|
316
|
+
properties: {
|
|
317
|
+
project_dir: { type: "string" },
|
|
318
|
+
},
|
|
319
|
+
required: ["project_dir"],
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
name: "kage_validate",
|
|
324
|
+
description: "Validate repo-local Kage memory packets, pending packets, generated indexes, and sensitive-content checks.",
|
|
325
|
+
inputSchema: {
|
|
326
|
+
type: "object",
|
|
327
|
+
properties: {
|
|
328
|
+
project_dir: { type: "string" },
|
|
329
|
+
},
|
|
330
|
+
required: ["project_dir"],
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
name: "kage_registry_recommend",
|
|
335
|
+
description: "Recommend documentation packs, skills, and optional MCPs for this repo based on its package metadata. Recommendations never install anything automatically.",
|
|
336
|
+
inputSchema: {
|
|
337
|
+
type: "object",
|
|
338
|
+
properties: {
|
|
339
|
+
project_dir: { type: "string" },
|
|
340
|
+
},
|
|
341
|
+
required: ["project_dir"],
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
name: "kage_marketplace",
|
|
346
|
+
description: "Build a local marketplace manifest for recommended docs, skills, and MCP packs. This never installs anything automatically.",
|
|
347
|
+
inputSchema: {
|
|
348
|
+
type: "object",
|
|
349
|
+
properties: {
|
|
350
|
+
project_dir: { type: "string" },
|
|
351
|
+
},
|
|
352
|
+
required: ["project_dir"],
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
name: "kage_org_status",
|
|
357
|
+
description: "Inspect the local org-memory inbox, approved packets, rejected packets, audit count, and registry path.",
|
|
358
|
+
inputSchema: {
|
|
359
|
+
type: "object",
|
|
360
|
+
properties: {
|
|
361
|
+
project_dir: { type: "string" },
|
|
362
|
+
org: { type: "string" },
|
|
363
|
+
},
|
|
364
|
+
required: ["project_dir", "org"],
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
name: "kage_org_upload_candidate",
|
|
369
|
+
description: "Upload an approved repo packet into the local org review inbox. This creates a candidate only; it does not approve org memory.",
|
|
370
|
+
inputSchema: {
|
|
371
|
+
type: "object",
|
|
372
|
+
properties: {
|
|
373
|
+
project_dir: { type: "string" },
|
|
374
|
+
org: { type: "string" },
|
|
375
|
+
packet_id: { type: "string" },
|
|
376
|
+
},
|
|
377
|
+
required: ["project_dir", "org", "packet_id"],
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
name: "kage_org_recall",
|
|
382
|
+
description: "Recall approved local org memory. Repo-local recall should still take priority when results conflict.",
|
|
383
|
+
inputSchema: {
|
|
384
|
+
type: "object",
|
|
385
|
+
properties: {
|
|
386
|
+
project_dir: { type: "string" },
|
|
387
|
+
org: { type: "string" },
|
|
388
|
+
query: { type: "string" },
|
|
389
|
+
limit: { type: "number" },
|
|
390
|
+
json: { type: "boolean" },
|
|
391
|
+
},
|
|
392
|
+
required: ["project_dir", "org", "query"],
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
name: "kage_layered_recall",
|
|
397
|
+
description: "Recall with Kage's priority order: branch > repo local > org > global. Org/global are included only when explicitly requested.",
|
|
398
|
+
inputSchema: {
|
|
399
|
+
type: "object",
|
|
400
|
+
properties: {
|
|
401
|
+
project_dir: { type: "string" },
|
|
402
|
+
query: { type: "string" },
|
|
403
|
+
org: { type: "string" },
|
|
404
|
+
include_global: { type: "boolean" },
|
|
405
|
+
json: { type: "boolean" },
|
|
406
|
+
},
|
|
407
|
+
required: ["project_dir", "query"],
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
name: "kage_global_build",
|
|
412
|
+
description: "Build a local static global/CDN bundle from human-promoted public candidates and the marketplace manifest. This does not upload anywhere.",
|
|
413
|
+
inputSchema: {
|
|
414
|
+
type: "object",
|
|
415
|
+
properties: {
|
|
416
|
+
project_dir: { type: "string" },
|
|
417
|
+
org: { type: "string" },
|
|
418
|
+
},
|
|
419
|
+
required: ["project_dir"],
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
name: "kage_promote_public_candidate",
|
|
424
|
+
description: "Create a sanitized local public-review candidate from an approved repo memory packet. This does not publish to the global graph.",
|
|
425
|
+
inputSchema: {
|
|
426
|
+
type: "object",
|
|
427
|
+
properties: {
|
|
428
|
+
project_dir: { type: "string" },
|
|
429
|
+
packet_id: { type: "string" },
|
|
430
|
+
},
|
|
431
|
+
required: ["project_dir", "packet_id"],
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
name: "kage_export_public_bundle",
|
|
436
|
+
description: "Export local public-review candidates as a static public bundle catalog. This still does not publish anywhere.",
|
|
437
|
+
inputSchema: {
|
|
438
|
+
type: "object",
|
|
439
|
+
properties: {
|
|
440
|
+
project_dir: { type: "string" },
|
|
441
|
+
},
|
|
442
|
+
required: ["project_dir"],
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
name: "kage_review_artifact",
|
|
447
|
+
description: "Create a Markdown review artifact summarizing pending memory packets for PR or human review.",
|
|
448
|
+
inputSchema: {
|
|
449
|
+
type: "object",
|
|
450
|
+
properties: {
|
|
451
|
+
project_dir: { type: "string" },
|
|
452
|
+
},
|
|
453
|
+
required: ["project_dir"],
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
name: "kage_propose_from_diff",
|
|
458
|
+
description: "Create or update a branch review summary and repo-local change-memory packet from local git status and diff metadata. Org/global promotion still requires explicit human review.",
|
|
459
|
+
inputSchema: {
|
|
460
|
+
type: "object",
|
|
461
|
+
properties: {
|
|
462
|
+
project_dir: { type: "string" },
|
|
463
|
+
},
|
|
464
|
+
required: ["project_dir"],
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
];
|
|
468
|
+
}
|
|
469
|
+
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
470
|
+
tools: listTools(),
|
|
88
471
|
}));
|
|
89
|
-
|
|
90
|
-
const { name, arguments: args } = request.params;
|
|
472
|
+
async function callTool(name, args) {
|
|
91
473
|
if (name === "kage_list_domains") {
|
|
92
474
|
const catalog = await fetchJSON(`${BASE_URL}/catalog.json`);
|
|
93
475
|
const lines = Object.entries(catalog.domains)
|
|
94
|
-
.filter(([, d]) => d
|
|
95
|
-
.sort(([, a], [, b]) => b
|
|
96
|
-
.map(([domain, d]) => `**${domain}** — ${d
|
|
476
|
+
.filter(([, d]) => domainNodeCount(d) > 0)
|
|
477
|
+
.sort(([, a], [, b]) => domainNodeCount(b) - domainNodeCount(a))
|
|
478
|
+
.map(([domain, d]) => `**${domain}** — ${domainNodeCount(d)} nodes | tags: ${domainTopTags(d).slice(0, 5).join(", ")}`);
|
|
97
479
|
return {
|
|
98
480
|
content: [
|
|
99
481
|
{
|
|
@@ -107,32 +489,28 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
107
489
|
const query = String(args?.query ?? "");
|
|
108
490
|
const domainFilter = args?.domain ? String(args.domain) : null;
|
|
109
491
|
const catalog = await fetchJSON(`${BASE_URL}/catalog.json`);
|
|
110
|
-
// Pick domains to search
|
|
111
492
|
let domainsToSearch;
|
|
112
493
|
if (domainFilter) {
|
|
113
494
|
domainsToSearch = [domainFilter];
|
|
114
495
|
}
|
|
115
496
|
else {
|
|
116
497
|
domainsToSearch = Object.entries(catalog.domains)
|
|
117
|
-
.filter(([, d]) => d
|
|
498
|
+
.filter(([, d]) => domainNodeCount(d) > 0)
|
|
118
499
|
.map(([name, d]) => ({ name, score: scoreDomainMatch(query, d) }))
|
|
119
500
|
.sort((a, b) => b.score - a.score)
|
|
120
501
|
.slice(0, 3)
|
|
121
502
|
.filter((d) => d.score > 0)
|
|
122
503
|
.map((d) => d.name);
|
|
123
|
-
// Fall back to all non-empty domains if no tag match
|
|
124
504
|
if (domainsToSearch.length === 0) {
|
|
125
505
|
domainsToSearch = Object.entries(catalog.domains)
|
|
126
|
-
.filter(([, d]) => d
|
|
506
|
+
.filter(([, d]) => domainNodeCount(d) > 0)
|
|
127
507
|
.map(([name]) => name);
|
|
128
508
|
}
|
|
129
509
|
}
|
|
130
|
-
// Fetch indexes in parallel
|
|
131
510
|
const indexResults = await Promise.allSettled(domainsToSearch.map(async (domain) => {
|
|
132
511
|
const index = await fetchJSON(`${BASE_URL}/domains/${domain}/index.json`);
|
|
133
512
|
return { domain, nodes: index.nodes };
|
|
134
513
|
}));
|
|
135
|
-
// Score and rank all nodes
|
|
136
514
|
const scored = [];
|
|
137
515
|
for (const result of indexResults) {
|
|
138
516
|
if (result.status === "fulfilled") {
|
|
@@ -161,7 +539,7 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
161
539
|
return [
|
|
162
540
|
`### [${i + 1}] ${n.title}`,
|
|
163
541
|
`**Domain:** ${r.domain} | **Type:** ${n.type} | **Score:** ${n.score} | **Updated:** ${n.updated}`,
|
|
164
|
-
`**Tags:** ${n.tags.join(", ")}`,
|
|
542
|
+
`**Tags:** ${(n.tags ?? []).join(", ")}`,
|
|
165
543
|
n.summary ? `**Summary:** ${n.summary}` : "",
|
|
166
544
|
`**Fetch:** domain="${r.domain}" node_id="${n.id}"`,
|
|
167
545
|
]
|
|
@@ -185,10 +563,288 @@ server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
|
185
563
|
content: [{ type: "text", text: content }],
|
|
186
564
|
};
|
|
187
565
|
}
|
|
566
|
+
if (name === "kage_recall") {
|
|
567
|
+
const result = (0, kernel_js_1.recall)(String(args?.project_dir ?? ""), String(args?.query ?? ""), Number(args?.limit ?? 5), Boolean(args?.explain));
|
|
568
|
+
return {
|
|
569
|
+
content: [{ type: "text", text: args?.json || args?.explain ? JSON.stringify(result, null, 2) : result.context_block }],
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
if (name === "kage_graph") {
|
|
573
|
+
const result = (0, kernel_js_1.queryGraph)(String(args?.project_dir ?? ""), String(args?.query ?? ""), Number(args?.limit ?? 10));
|
|
574
|
+
return {
|
|
575
|
+
content: [{ type: "text", text: result.context_block }],
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
if (name === "kage_code_graph") {
|
|
579
|
+
const projectDir = String(args?.project_dir ?? "");
|
|
580
|
+
const query = typeof args?.query === "string" ? args.query : "";
|
|
581
|
+
if (query) {
|
|
582
|
+
const result = (0, kernel_js_1.queryCodeGraph)(projectDir, query, Number(args?.limit ?? 10));
|
|
583
|
+
return {
|
|
584
|
+
content: [{ type: "text", text: args?.json ? JSON.stringify(result, null, 2) : result.context_block }],
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
const result = (0, kernel_js_1.buildCodeGraph)(projectDir);
|
|
588
|
+
return {
|
|
589
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
if (name === "kage_metrics") {
|
|
593
|
+
const result = (0, kernel_js_1.kageMetrics)(String(args?.project_dir ?? ""));
|
|
594
|
+
return {
|
|
595
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
if (name === "kage_quality") {
|
|
599
|
+
const result = (0, kernel_js_1.qualityReport)(String(args?.project_dir ?? ""));
|
|
600
|
+
return {
|
|
601
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
if (name === "kage_benchmark") {
|
|
605
|
+
const result = (0, kernel_js_1.benchmarkProject)(String(args?.project_dir ?? ""));
|
|
606
|
+
return {
|
|
607
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
if (name === "kage_setup_agent") {
|
|
611
|
+
const result = (0, kernel_js_1.setupAgent)(String(args?.agent ?? ""), String(args?.project_dir ?? ""), { write: Boolean(args?.write) });
|
|
612
|
+
return {
|
|
613
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
if (name === "kage_verify_agent") {
|
|
617
|
+
const result = (0, kernel_js_1.verifyAgentActivation)(String(args?.agent ?? ""), String(args?.project_dir ?? ""), { mcpToolReachable: true });
|
|
618
|
+
return {
|
|
619
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
if (name === "kage_graph_visual") {
|
|
623
|
+
const result = (0, kernel_js_1.graphMermaid)(String(args?.project_dir ?? ""), Number(args?.limit ?? 40));
|
|
624
|
+
return {
|
|
625
|
+
content: [{ type: "text", text: `\`\`\`mermaid\n${result.mermaid}\n\`\`\`` }],
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
if (name === "kage_branch_overlay") {
|
|
629
|
+
const result = (0, kernel_js_1.buildBranchOverlay)(String(args?.project_dir ?? ""));
|
|
630
|
+
return {
|
|
631
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
if (name === "kage_learn") {
|
|
635
|
+
const result = (0, kernel_js_1.learn)({
|
|
636
|
+
projectDir: String(args?.project_dir ?? ""),
|
|
637
|
+
learning: String(args?.learning ?? ""),
|
|
638
|
+
title: args?.title ? String(args.title) : undefined,
|
|
639
|
+
type: args?.type ? String(args.type) : undefined,
|
|
640
|
+
evidence: args?.evidence ? String(args.evidence) : undefined,
|
|
641
|
+
verifiedBy: args?.verified_by ? String(args.verified_by) : undefined,
|
|
642
|
+
tags: arrayArg(args?.tags),
|
|
643
|
+
paths: arrayArg(args?.paths),
|
|
644
|
+
stack: arrayArg(args?.stack),
|
|
645
|
+
});
|
|
646
|
+
return {
|
|
647
|
+
content: [
|
|
648
|
+
{
|
|
649
|
+
type: "text",
|
|
650
|
+
text: result.ok
|
|
651
|
+
? `Captured session learning: ${result.path}\nRepo-local memory is written immediately. Org/global promotion still requires explicit review.`
|
|
652
|
+
: `Learning capture blocked:\n${result.errors.map((error) => `- ${error}`).join("\n")}`,
|
|
653
|
+
},
|
|
654
|
+
],
|
|
655
|
+
isError: !result.ok,
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
if (name === "kage_capture") {
|
|
659
|
+
const result = (0, kernel_js_1.capture)({
|
|
660
|
+
projectDir: String(args?.project_dir ?? ""),
|
|
661
|
+
title: String(args?.title ?? ""),
|
|
662
|
+
summary: args?.summary ? String(args.summary) : undefined,
|
|
663
|
+
body: String(args?.body ?? ""),
|
|
664
|
+
type: args?.type ? String(args.type) : undefined,
|
|
665
|
+
tags: arrayArg(args?.tags),
|
|
666
|
+
paths: arrayArg(args?.paths),
|
|
667
|
+
stack: arrayArg(args?.stack),
|
|
668
|
+
});
|
|
669
|
+
return {
|
|
670
|
+
content: [
|
|
671
|
+
{
|
|
672
|
+
type: "text",
|
|
673
|
+
text: result.ok
|
|
674
|
+
? `Captured repo-local packet: ${result.path}\nOrg/global promotion still requires explicit review.`
|
|
675
|
+
: `Capture blocked:\n${result.errors.map((error) => `- ${error}`).join("\n")}`,
|
|
676
|
+
},
|
|
677
|
+
],
|
|
678
|
+
isError: !result.ok,
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
if (name === "kage_observe") {
|
|
682
|
+
const projectDir = String(args?.project_dir ?? "");
|
|
683
|
+
const event = { ...args };
|
|
684
|
+
delete event.project_dir;
|
|
685
|
+
const result = (0, kernel_js_1.observe)(projectDir, event);
|
|
686
|
+
return {
|
|
687
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
688
|
+
isError: !result.ok,
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
if (name === "kage_distill") {
|
|
692
|
+
const result = (0, kernel_js_1.distillSession)(String(args?.project_dir ?? ""), String(args?.session_id ?? "default"));
|
|
693
|
+
return {
|
|
694
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
695
|
+
isError: !result.ok,
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
if (name === "kage_feedback") {
|
|
699
|
+
const result = (0, kernel_js_1.recordFeedback)(String(args?.project_dir ?? ""), String(args?.packet_id ?? ""), String(args?.kind ?? ""));
|
|
700
|
+
return {
|
|
701
|
+
content: [
|
|
702
|
+
{
|
|
703
|
+
type: "text",
|
|
704
|
+
text: result.ok
|
|
705
|
+
? `Recorded ${args?.kind} feedback for ${args?.packet_id}`
|
|
706
|
+
: `Feedback failed:\n${result.errors.map((error) => `- ${error}`).join("\n")}`,
|
|
707
|
+
},
|
|
708
|
+
],
|
|
709
|
+
isError: !result.ok,
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
if (name === "kage_install_policy") {
|
|
713
|
+
const result = (0, kernel_js_1.installAgentPolicy)(String(args?.project_dir ?? ""));
|
|
714
|
+
return {
|
|
715
|
+
content: [
|
|
716
|
+
{
|
|
717
|
+
type: "text",
|
|
718
|
+
text: `${result.created ? "Created" : result.updated ? "Updated" : "Already current"} agent policy: ${result.path}`,
|
|
719
|
+
},
|
|
720
|
+
],
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
if (name === "kage_validate") {
|
|
724
|
+
const result = (0, kernel_js_1.validateProject)(String(args?.project_dir ?? ""));
|
|
725
|
+
const text = [
|
|
726
|
+
result.ok ? "Validation passed." : "Validation failed.",
|
|
727
|
+
result.errors.length ? `\nErrors:\n${result.errors.map((error) => `- ${error}`).join("\n")}` : "",
|
|
728
|
+
result.warnings.length ? `\nWarnings:\n${result.warnings.map((warning) => `- ${warning}`).join("\n")}` : "",
|
|
729
|
+
].join("");
|
|
730
|
+
return {
|
|
731
|
+
content: [{ type: "text", text }],
|
|
732
|
+
isError: !result.ok,
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
if (name === "kage_registry_recommend") {
|
|
736
|
+
const result = (0, kernel_js_1.registryRecommendations)(String(args?.project_dir ?? ""));
|
|
737
|
+
return {
|
|
738
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
if (name === "kage_marketplace") {
|
|
742
|
+
const result = (0, kernel_js_1.buildMarketplace)(String(args?.project_dir ?? ""));
|
|
743
|
+
return {
|
|
744
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
745
|
+
isError: !result.ok,
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
if (name === "kage_org_status") {
|
|
749
|
+
const result = (0, kernel_js_1.orgStatus)(String(args?.project_dir ?? ""), String(args?.org ?? "local"));
|
|
750
|
+
return {
|
|
751
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
if (name === "kage_org_upload_candidate") {
|
|
755
|
+
const result = (0, kernel_js_1.orgUploadPacket)(String(args?.project_dir ?? ""), String(args?.org ?? "local"), String(args?.packet_id ?? ""));
|
|
756
|
+
return {
|
|
757
|
+
content: [
|
|
758
|
+
{
|
|
759
|
+
type: "text",
|
|
760
|
+
text: result.ok
|
|
761
|
+
? `Created org review candidate: ${result.path}\nApprove explicitly with: kage org review --approve`
|
|
762
|
+
: `Org upload blocked:\n${result.errors.map((error) => `- ${error}`).join("\n")}`,
|
|
763
|
+
},
|
|
764
|
+
],
|
|
765
|
+
isError: !result.ok,
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
if (name === "kage_org_recall") {
|
|
769
|
+
const result = (0, kernel_js_1.orgRecall)(String(args?.project_dir ?? ""), String(args?.org ?? "local"), String(args?.query ?? ""), Number(args?.limit ?? 5));
|
|
770
|
+
return {
|
|
771
|
+
content: [{ type: "text", text: args?.json ? JSON.stringify(result, null, 2) : result.context_block }],
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
if (name === "kage_layered_recall") {
|
|
775
|
+
const result = (0, kernel_js_1.layeredRecall)(String(args?.project_dir ?? ""), String(args?.query ?? ""), {
|
|
776
|
+
org: args?.org ? String(args.org) : undefined,
|
|
777
|
+
includeGlobal: Boolean(args?.include_global),
|
|
778
|
+
});
|
|
779
|
+
return {
|
|
780
|
+
content: [{ type: "text", text: args?.json ? JSON.stringify(result, null, 2) : result.context_block }],
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
if (name === "kage_global_build") {
|
|
784
|
+
const result = (0, kernel_js_1.buildGlobalCdnBundle)(String(args?.project_dir ?? ""), String(args?.org ?? "local"));
|
|
785
|
+
return {
|
|
786
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
787
|
+
isError: !result.ok,
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
if (name === "kage_promote_public_candidate") {
|
|
791
|
+
const result = (0, kernel_js_1.createPublicCandidate)(String(args?.project_dir ?? ""), String(args?.packet_id ?? ""));
|
|
792
|
+
return {
|
|
793
|
+
content: [
|
|
794
|
+
{
|
|
795
|
+
type: "text",
|
|
796
|
+
text: result.ok
|
|
797
|
+
? `Created local public-review candidate: ${result.path}\nThis does not publish until a human submits it.`
|
|
798
|
+
: `Promotion blocked:\n${result.errors.map((error) => `- ${error}`).join("\n")}`,
|
|
799
|
+
},
|
|
800
|
+
],
|
|
801
|
+
isError: !result.ok,
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
if (name === "kage_export_public_bundle") {
|
|
805
|
+
const result = (0, kernel_js_1.exportPublicBundle)(String(args?.project_dir ?? ""));
|
|
806
|
+
return {
|
|
807
|
+
content: [
|
|
808
|
+
{
|
|
809
|
+
type: "text",
|
|
810
|
+
text: result.ok
|
|
811
|
+
? `Exported public bundle: ${result.path}\nPackets: ${result.packetCount}`
|
|
812
|
+
: `Public bundle blocked:\n${result.errors.map((error) => `- ${error}`).join("\n")}`,
|
|
813
|
+
},
|
|
814
|
+
],
|
|
815
|
+
isError: !result.ok,
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
if (name === "kage_review_artifact") {
|
|
819
|
+
const result = (0, kernel_js_1.createReviewArtifact)(String(args?.project_dir ?? ""));
|
|
820
|
+
return {
|
|
821
|
+
content: [{ type: "text", text: `Wrote review artifact: ${result.path}\nPending packets: ${result.pending}` }],
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
if (name === "kage_propose_from_diff") {
|
|
825
|
+
const result = (0, kernel_js_1.proposeFromDiff)(String(args?.project_dir ?? ""));
|
|
826
|
+
return {
|
|
827
|
+
content: [
|
|
828
|
+
{
|
|
829
|
+
type: "text",
|
|
830
|
+
text: result.ok
|
|
831
|
+
? `Wrote branch review summary: ${result.path}\nCaptured repo-local change memory: ${result.packetPath ?? "(none)"}\nChanged files: ${result.changedFiles.join(", ")}`
|
|
832
|
+
: `Proposal blocked:\n${result.errors.map((error) => `- ${error}`).join("\n")}`,
|
|
833
|
+
},
|
|
834
|
+
],
|
|
835
|
+
isError: !result.ok,
|
|
836
|
+
};
|
|
837
|
+
}
|
|
188
838
|
throw new Error(`Unknown tool: ${name}`);
|
|
839
|
+
}
|
|
840
|
+
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
841
|
+
const { name, arguments: args } = request.params;
|
|
842
|
+
return callTool(name, args);
|
|
189
843
|
});
|
|
190
844
|
async function main() {
|
|
191
845
|
const transport = new stdio_js_1.StdioServerTransport();
|
|
192
846
|
await server.connect(transport);
|
|
193
847
|
}
|
|
194
|
-
|
|
848
|
+
if (require.main === module) {
|
|
849
|
+
main().catch(console.error);
|
|
850
|
+
}
|