@vheins/local-memory-mcp 0.18.12 → 0.19.0
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.id.md +9 -1
- package/README.md +32 -17
- package/dist/{chunk-UWAZ66N5.js → chunk-AKFMCVQ4.js} +1202 -981
- package/dist/dashboard/public/assets/{index-wAYh22Zy.css → index-CtKekPIh.css} +1 -1
- package/dist/dashboard/public/assets/index-DsmurBbn.js +150 -0
- package/dist/dashboard/public/index.html +2 -2
- package/dist/dashboard/server.js +251 -172
- package/dist/mcp/server.js +3322 -2119
- package/dist/prompts/create-task.md +10 -2
- package/dist/prompts/documentation-sync.md +1 -1
- package/dist/prompts/learning-retrospective.md +1 -1
- package/dist/prompts/memory-agent-core.md +8 -2
- package/dist/prompts/project-briefing.md +2 -2
- package/dist/prompts/review-and-audit.md +2 -2
- package/dist/prompts/review-and-post-issue.md +3 -3
- package/dist/prompts/scrum-master.md +1 -1
- package/dist/prompts/sentinel-issue-resolver.md +1 -1
- package/dist/prompts/server/instructions.md +10 -2
- package/dist/prompts/session-planner.md +1 -1
- package/dist/prompts/task-memory-executor.md +2 -2
- package/dist/prompts/tool-usage-guidelines.md +9 -2
- package/package.json +5 -1
- package/dist/dashboard/public/assets/index-BA3gfiDm.js +0 -149
|
@@ -1,131 +1,5 @@
|
|
|
1
|
-
// src/mcp/capabilities.ts
|
|
2
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3
|
-
import path2 from "path";
|
|
4
|
-
|
|
5
|
-
// src/mcp/prompts/loader.ts
|
|
6
|
-
import fs from "fs";
|
|
7
|
-
import path from "path";
|
|
8
|
-
import { fileURLToPath } from "url";
|
|
9
|
-
import matter from "gray-matter";
|
|
10
|
-
var __filename = fileURLToPath(import.meta.url);
|
|
11
|
-
var __dirname = path.dirname(__filename);
|
|
12
|
-
function findPromptDir() {
|
|
13
|
-
const candidates = [
|
|
14
|
-
// Production if chunked into dist/
|
|
15
|
-
"./prompts",
|
|
16
|
-
// Production if inlined into dist/mcp/
|
|
17
|
-
"../prompts",
|
|
18
|
-
// Dev: /src/mcp/prompts/definitions (next to loader.ts)
|
|
19
|
-
"./definitions"
|
|
20
|
-
].map((relPath) => path.resolve(__dirname, relPath));
|
|
21
|
-
for (const dir of candidates) {
|
|
22
|
-
if (fs.existsSync(dir)) {
|
|
23
|
-
const files = fs.readdirSync(dir);
|
|
24
|
-
if (files.some((f) => f.endsWith(".md"))) {
|
|
25
|
-
return dir;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return path.resolve(__dirname, "./definitions");
|
|
30
|
-
}
|
|
31
|
-
var PROMPT_DIR = findPromptDir();
|
|
32
|
-
function listPromptFiles() {
|
|
33
|
-
if (!fs.existsSync(PROMPT_DIR)) return [];
|
|
34
|
-
return fs.readdirSync(PROMPT_DIR).filter((file) => file.endsWith(".md")).map((file) => file.replace(/\.md$/, "")).sort();
|
|
35
|
-
}
|
|
36
|
-
function loadPromptFromMarkdown(name) {
|
|
37
|
-
const filePath = path.join(PROMPT_DIR, `${name}.md`);
|
|
38
|
-
if (!fs.existsSync(filePath)) {
|
|
39
|
-
throw new Error(`Prompt file not found: ${filePath}`);
|
|
40
|
-
}
|
|
41
|
-
const fileContent = fs.readFileSync(filePath, "utf-8");
|
|
42
|
-
const { data, content } = matter(fileContent);
|
|
43
|
-
return {
|
|
44
|
-
name: data.name || name,
|
|
45
|
-
description: data.description || "",
|
|
46
|
-
arguments: data.arguments || [],
|
|
47
|
-
agent: data.agent,
|
|
48
|
-
content: content.trim()
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
function findServerInstructionsDir() {
|
|
52
|
-
const candidates = [
|
|
53
|
-
// Production if chunked into dist/
|
|
54
|
-
"./prompts/server",
|
|
55
|
-
// Production if inlined into dist/mcp/
|
|
56
|
-
"../prompts/server",
|
|
57
|
-
// Dev: /src/mcp/prompts/server (next to loader.ts)
|
|
58
|
-
"./server"
|
|
59
|
-
].map((relPath) => path.resolve(__dirname, relPath));
|
|
60
|
-
for (const dir of candidates) {
|
|
61
|
-
if (fs.existsSync(dir)) {
|
|
62
|
-
const filePath = path.join(dir, "instructions.md");
|
|
63
|
-
if (fs.existsSync(filePath)) {
|
|
64
|
-
return dir;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return path.resolve(__dirname, "./server");
|
|
69
|
-
}
|
|
70
|
-
var SERVER_DIR = findServerInstructionsDir();
|
|
71
|
-
function loadServerInstructions() {
|
|
72
|
-
const filePath = path.join(SERVER_DIR, "instructions.md");
|
|
73
|
-
if (!fs.existsSync(filePath)) {
|
|
74
|
-
throw new Error(`Server instructions file not found: ${filePath}`);
|
|
75
|
-
}
|
|
76
|
-
const fileContent = fs.readFileSync(filePath, "utf-8");
|
|
77
|
-
const { content } = matter(fileContent);
|
|
78
|
-
return content.trim();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// src/mcp/capabilities.ts
|
|
82
|
-
var __dirname2 = path2.dirname(fileURLToPath2(import.meta.url));
|
|
83
|
-
var pkgVersion = "0.1.0";
|
|
84
|
-
if ("0.18.12") {
|
|
85
|
-
pkgVersion = "0.18.12";
|
|
86
|
-
} else {
|
|
87
|
-
let searchDir = __dirname2;
|
|
88
|
-
for (let i = 0; i < 5; i++) {
|
|
89
|
-
const candidate = path2.join(searchDir, "package.json");
|
|
90
|
-
try {
|
|
91
|
-
if (fs.existsSync(candidate)) {
|
|
92
|
-
const pkg = JSON.parse(fs.readFileSync(candidate, "utf8"));
|
|
93
|
-
if (pkg.name === "@vheins/local-memory-mcp" && pkg.version) {
|
|
94
|
-
pkgVersion = pkg.version;
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
} catch {
|
|
99
|
-
}
|
|
100
|
-
searchDir = path2.dirname(searchDir);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
var MCP_PROTOCOL_VERSION = "2025-03-26";
|
|
104
|
-
var SERVER_INSTRUCTIONS = loadServerInstructions();
|
|
105
|
-
var CAPABILITIES = {
|
|
106
|
-
serverInfo: {
|
|
107
|
-
name: "local-memory-mcp",
|
|
108
|
-
version: pkgVersion,
|
|
109
|
-
instructions: SERVER_INSTRUCTIONS
|
|
110
|
-
},
|
|
111
|
-
capabilities: {
|
|
112
|
-
completions: {},
|
|
113
|
-
logging: {},
|
|
114
|
-
resources: {
|
|
115
|
-
subscribe: true,
|
|
116
|
-
listChanged: true
|
|
117
|
-
},
|
|
118
|
-
tools: {
|
|
119
|
-
listChanged: false
|
|
120
|
-
},
|
|
121
|
-
prompts: {
|
|
122
|
-
listChanged: true
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
|
|
127
1
|
// src/mcp/utils/logger.ts
|
|
128
|
-
import
|
|
2
|
+
import fs from "fs";
|
|
129
3
|
var LEVELS = {
|
|
130
4
|
debug: 0,
|
|
131
5
|
info: 1,
|
|
@@ -225,31 +99,17 @@ var logger = {
|
|
|
225
99
|
log("emergency", message, context);
|
|
226
100
|
}
|
|
227
101
|
};
|
|
228
|
-
function setLogLevel(level) {
|
|
229
|
-
const raw = level.toLowerCase();
|
|
230
|
-
const normalized = LEVEL_ALIASES[raw] || raw;
|
|
231
|
-
if (!(normalized in LEVELS)) {
|
|
232
|
-
const error = new Error(`Invalid log level: ${level}`);
|
|
233
|
-
error.code = -32602;
|
|
234
|
-
throw error;
|
|
235
|
-
}
|
|
236
|
-
currentLevel = normalized;
|
|
237
|
-
return currentLevel;
|
|
238
|
-
}
|
|
239
|
-
function getLogLevel() {
|
|
240
|
-
return currentLevel;
|
|
241
|
-
}
|
|
242
102
|
function addLogSink(sink) {
|
|
243
103
|
sinks.add(sink);
|
|
244
104
|
return () => sinks.delete(sink);
|
|
245
105
|
}
|
|
246
106
|
var LOG_LEVEL_VALUES = Object.keys(LEVELS);
|
|
247
107
|
function createFileSink(logDir, maxFiles = 5) {
|
|
248
|
-
|
|
249
|
-
const existing =
|
|
108
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
109
|
+
const existing = fs.readdirSync(logDir).filter((f) => f.startsWith("mcp-") && f.endsWith(".log")).sort();
|
|
250
110
|
while (existing.length >= maxFiles) {
|
|
251
111
|
try {
|
|
252
|
-
|
|
112
|
+
fs.unlinkSync(`${logDir}/${existing.shift()}`);
|
|
253
113
|
} catch {
|
|
254
114
|
}
|
|
255
115
|
}
|
|
@@ -259,7 +119,7 @@ function createFileSink(logDir, maxFiles = 5) {
|
|
|
259
119
|
const line = `${(/* @__PURE__ */ new Date()).toISOString()} [${payload.level.toUpperCase()}] [pid:${process.pid}] ${JSON.stringify(payload.data)}
|
|
260
120
|
`;
|
|
261
121
|
try {
|
|
262
|
-
|
|
122
|
+
fs.appendFileSync(logFile, line);
|
|
263
123
|
} catch {
|
|
264
124
|
}
|
|
265
125
|
};
|
|
@@ -267,8 +127,8 @@ function createFileSink(logDir, maxFiles = 5) {
|
|
|
267
127
|
|
|
268
128
|
// src/mcp/storage/sqlite.ts
|
|
269
129
|
import Database from "better-sqlite3";
|
|
270
|
-
import
|
|
271
|
-
import
|
|
130
|
+
import path2 from "path";
|
|
131
|
+
import fs3 from "fs";
|
|
272
132
|
import os from "os";
|
|
273
133
|
|
|
274
134
|
// src/mcp/storage/migrations.ts
|
|
@@ -504,6 +364,50 @@ var MigrationManager = class {
|
|
|
504
364
|
CREATE INDEX IF NOT EXISTS idx_claims_task_id ON claims(task_id);
|
|
505
365
|
CREATE INDEX IF NOT EXISTS idx_claims_agent ON claims(agent);
|
|
506
366
|
CREATE INDEX IF NOT EXISTS idx_claims_claimed_at ON claims(claimed_at);
|
|
367
|
+
|
|
368
|
+
CREATE TABLE IF NOT EXISTS entities (
|
|
369
|
+
name TEXT PRIMARY KEY,
|
|
370
|
+
type TEXT NOT NULL DEFAULT 'unknown',
|
|
371
|
+
description TEXT,
|
|
372
|
+
repo TEXT NOT NULL DEFAULT '',
|
|
373
|
+
owner TEXT NOT NULL DEFAULT '',
|
|
374
|
+
created_at TEXT NOT NULL,
|
|
375
|
+
updated_at TEXT NOT NULL
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
CREATE INDEX IF NOT EXISTS idx_entities_type ON entities(type);
|
|
379
|
+
CREATE INDEX IF NOT EXISTS idx_entities_repo ON entities(repo);
|
|
380
|
+
|
|
381
|
+
CREATE TABLE IF NOT EXISTS relations (
|
|
382
|
+
from_entity TEXT NOT NULL,
|
|
383
|
+
to_entity TEXT NOT NULL,
|
|
384
|
+
relation_type TEXT NOT NULL,
|
|
385
|
+
repo TEXT NOT NULL DEFAULT '',
|
|
386
|
+
owner TEXT NOT NULL DEFAULT '',
|
|
387
|
+
created_at TEXT NOT NULL,
|
|
388
|
+
PRIMARY KEY (from_entity, to_entity, relation_type),
|
|
389
|
+
FOREIGN KEY (from_entity) REFERENCES entities(name) ON DELETE CASCADE,
|
|
390
|
+
FOREIGN KEY (to_entity) REFERENCES entities(name) ON DELETE CASCADE
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
CREATE INDEX IF NOT EXISTS idx_relations_from ON relations(from_entity);
|
|
394
|
+
CREATE INDEX IF NOT EXISTS idx_relations_to ON relations(to_entity);
|
|
395
|
+
CREATE INDEX IF NOT EXISTS idx_relations_type ON relations(relation_type);
|
|
396
|
+
CREATE INDEX IF NOT EXISTS idx_relations_repo ON relations(repo);
|
|
397
|
+
|
|
398
|
+
CREATE TABLE IF NOT EXISTS observations (
|
|
399
|
+
id TEXT PRIMARY KEY,
|
|
400
|
+
entity_name TEXT NOT NULL,
|
|
401
|
+
observation TEXT NOT NULL,
|
|
402
|
+
repo TEXT NOT NULL DEFAULT '',
|
|
403
|
+
owner TEXT NOT NULL DEFAULT '',
|
|
404
|
+
created_at TEXT NOT NULL,
|
|
405
|
+
FOREIGN KEY (entity_name) REFERENCES entities(name) ON DELETE CASCADE
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
CREATE INDEX IF NOT EXISTS idx_observations_entity ON observations(entity_name);
|
|
409
|
+
CREATE INDEX IF NOT EXISTS idx_observations_repo ON observations(repo);
|
|
410
|
+
CREATE INDEX IF NOT EXISTS idx_observations_created_at ON observations(created_at);
|
|
507
411
|
`);
|
|
508
412
|
const columnsToAdd = [
|
|
509
413
|
{ name: "title", table: "memories", definition: "ALTER TABLE memories ADD COLUMN title TEXT" },
|
|
@@ -672,7 +576,7 @@ var MigrationManager = class {
|
|
|
672
576
|
HAVING cnt > 1
|
|
673
577
|
`);
|
|
674
578
|
if (dupRows.length > 0) {
|
|
675
|
-
|
|
579
|
+
logger.info(`Found ${dupRows.length} duplicate task_code(s). Deduplicating by suffix...`);
|
|
676
580
|
for (const dup of dupRows) {
|
|
677
581
|
const rows = this.all(
|
|
678
582
|
`SELECT id, task_code, created_at FROM tasks
|
|
@@ -686,7 +590,7 @@ var MigrationManager = class {
|
|
|
686
590
|
const newCode = `${dup.task_code}-${i + 1}`;
|
|
687
591
|
this.run("UPDATE tasks SET task_code = ? WHERE id = ?", newCode, rows[i].id);
|
|
688
592
|
}
|
|
689
|
-
|
|
593
|
+
logger.info(` Deduplicated ${dup.task_code}: kept 1 (${rows[0].id}), renamed ${rows.length - 1} rows`);
|
|
690
594
|
}
|
|
691
595
|
}
|
|
692
596
|
this.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_tasks_code_owner_repo ON tasks(owner, repo, task_code);`);
|
|
@@ -1323,7 +1227,7 @@ var MemoryEntity = class extends BaseEntity {
|
|
|
1323
1227
|
let sql = "SELECT * FROM memories WHERE code = ?";
|
|
1324
1228
|
const params = [code];
|
|
1325
1229
|
if (owner && repo) {
|
|
1326
|
-
sql += " AND owner = ? AND repo = ?";
|
|
1230
|
+
sql += " AND ((owner = ? AND repo = ?) OR is_global = 1)";
|
|
1327
1231
|
params.push(owner, repo);
|
|
1328
1232
|
}
|
|
1329
1233
|
const row = this.get(sql, params);
|
|
@@ -1523,9 +1427,11 @@ var MemoryEntity = class extends BaseEntity {
|
|
|
1523
1427
|
incrementHitCounts(ids) {
|
|
1524
1428
|
if (!ids || ids.length === 0) return;
|
|
1525
1429
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1430
|
+
const placeholders = ids.map(() => "?").join(",");
|
|
1431
|
+
this.run(`UPDATE memories SET hit_count = hit_count + 1, last_used_at = ? WHERE id IN (${placeholders})`, [
|
|
1432
|
+
now,
|
|
1433
|
+
...ids
|
|
1434
|
+
]);
|
|
1529
1435
|
}
|
|
1530
1436
|
incrementRecallCount(id) {
|
|
1531
1437
|
this.run("UPDATE memories SET recall_count = recall_count + 1, last_used_at = ? WHERE id = ?", [
|
|
@@ -1570,9 +1476,20 @@ var MemoryEntity = class extends BaseEntity {
|
|
|
1570
1476
|
search,
|
|
1571
1477
|
offset = 0,
|
|
1572
1478
|
limit = 50,
|
|
1573
|
-
sortBy = "created_at",
|
|
1574
1479
|
sortOrder = "DESC"
|
|
1575
1480
|
} = options;
|
|
1481
|
+
let sortBy = options.sortBy ?? "created_at";
|
|
1482
|
+
const ALLOWED_SORT_COLUMNS = /* @__PURE__ */ new Set([
|
|
1483
|
+
"created_at",
|
|
1484
|
+
"updated_at",
|
|
1485
|
+
"importance",
|
|
1486
|
+
"hit_count",
|
|
1487
|
+
"title",
|
|
1488
|
+
"recall_rate"
|
|
1489
|
+
]);
|
|
1490
|
+
if (!ALLOWED_SORT_COLUMNS.has(sortBy)) {
|
|
1491
|
+
sortBy = "created_at";
|
|
1492
|
+
}
|
|
1576
1493
|
const where = ["1=1"];
|
|
1577
1494
|
const params = [];
|
|
1578
1495
|
if (owner) {
|
|
@@ -1616,7 +1533,7 @@ var MemoryEntity = class extends BaseEntity {
|
|
|
1616
1533
|
...this.rowToMemoryEntry(row),
|
|
1617
1534
|
recall_rate: row.recall_rate || 0
|
|
1618
1535
|
}));
|
|
1619
|
-
return { items,
|
|
1536
|
+
return { items, total, limit, offset };
|
|
1620
1537
|
}
|
|
1621
1538
|
};
|
|
1622
1539
|
|
|
@@ -2479,34 +2396,45 @@ var SystemEntity = class extends BaseEntity {
|
|
|
2479
2396
|
const pendingHandoffsByRepo = Object.fromEntries(pendingHandoffRows.map((row) => [row.repo, row.count]));
|
|
2480
2397
|
const unassignedHandoffsByRepo = Object.fromEntries(unassignedHandoffRows.map((row) => [row.repo, row.count]));
|
|
2481
2398
|
const staleClaimsByRepo = Object.fromEntries(staleClaimRows.map((row) => [row.repo, row.count]));
|
|
2482
|
-
const
|
|
2399
|
+
const ownerWhere = owner ? " WHERE owner = ?" : "";
|
|
2400
|
+
const memoryCountRows = this.all(
|
|
2401
|
+
`SELECT repo, COUNT(*) as count FROM memories${ownerWhere} GROUP BY repo`,
|
|
2402
|
+
ownerParams
|
|
2403
|
+
);
|
|
2404
|
+
const memoryCountByRepo = Object.fromEntries(memoryCountRows.map((r) => [r.repo, r.count]));
|
|
2405
|
+
const taskAggRows = this.all(
|
|
2406
|
+
`SELECT repo, status, COUNT(*) as count FROM tasks${ownerWhere} GROUP BY repo, status`,
|
|
2407
|
+
ownerParams
|
|
2408
|
+
);
|
|
2409
|
+
const taskCountsByRepo = {};
|
|
2410
|
+
for (const row of taskAggRows) {
|
|
2411
|
+
if (!taskCountsByRepo[row.repo]) {
|
|
2412
|
+
taskCountsByRepo[row.repo] = { total: 0, byStatus: {} };
|
|
2413
|
+
}
|
|
2414
|
+
taskCountsByRepo[row.repo].total += row.count;
|
|
2415
|
+
taskCountsByRepo[row.repo].byStatus[row.status] = row.count;
|
|
2416
|
+
}
|
|
2417
|
+
const lastActivityRows = this.all(
|
|
2418
|
+
`SELECT repo, MAX(updated_at) as last FROM (
|
|
2419
|
+
SELECT repo, updated_at FROM memories${ownerWhere}
|
|
2420
|
+
UNION ALL
|
|
2421
|
+
SELECT repo, updated_at FROM tasks${ownerWhere}
|
|
2422
|
+
) GROUP BY repo`,
|
|
2423
|
+
owner ? [owner, owner] : []
|
|
2424
|
+
);
|
|
2425
|
+
const lastActivityByRepo = Object.fromEntries(lastActivityRows.map((r) => [r.repo, r.last]));
|
|
2483
2426
|
return repos.map((repo) => {
|
|
2484
|
-
const
|
|
2485
|
-
|
|
2486
|
-
owner ? [repo, owner] : [repo]
|
|
2487
|
-
);
|
|
2488
|
-
const lastActivityRow = this.get(
|
|
2489
|
-
`SELECT MAX(created_at) as last FROM (SELECT created_at FROM memories WHERE repo = ?${repoOwnerFilter} UNION ALL SELECT created_at FROM tasks WHERE repo = ?${repoOwnerFilter} UNION ALL SELECT created_at FROM action_log WHERE repo = ?${repoOwnerFilter})`,
|
|
2490
|
-
owner ? [repo, owner, repo, owner, repo, owner] : [repo, repo, repo]
|
|
2491
|
-
);
|
|
2492
|
-
const taskStatusRows = this.all(
|
|
2493
|
-
`SELECT status, COUNT(*) as count FROM tasks WHERE repo = ?${repoOwnerFilter} GROUP BY status`,
|
|
2494
|
-
owner ? [repo, owner] : [repo]
|
|
2495
|
-
);
|
|
2496
|
-
const taskStatusMap = {};
|
|
2497
|
-
taskStatusRows.forEach((r) => {
|
|
2498
|
-
taskStatusMap[r.status] = r.count;
|
|
2499
|
-
});
|
|
2500
|
-
const taskCount = taskStatusRows.reduce((sum, r) => sum + r.count, 0);
|
|
2427
|
+
const memCount = memoryCountByRepo[repo] ?? 0;
|
|
2428
|
+
const taskInfo = taskCountsByRepo[repo] ?? { total: 0, byStatus: {} };
|
|
2501
2429
|
return {
|
|
2502
2430
|
repo,
|
|
2503
|
-
memoryCount:
|
|
2504
|
-
taskCount,
|
|
2505
|
-
inProgressCount:
|
|
2506
|
-
pendingCount:
|
|
2507
|
-
blockedCount:
|
|
2508
|
-
backlogCount:
|
|
2509
|
-
lastActivity:
|
|
2431
|
+
memoryCount: memCount,
|
|
2432
|
+
taskCount: taskInfo.total,
|
|
2433
|
+
inProgressCount: taskInfo.byStatus["in_progress"] ?? 0,
|
|
2434
|
+
pendingCount: taskInfo.byStatus["pending"] ?? 0,
|
|
2435
|
+
blockedCount: taskInfo.byStatus["blocked"] ?? 0,
|
|
2436
|
+
backlogCount: taskInfo.byStatus["backlog"] ?? 0,
|
|
2437
|
+
lastActivity: lastActivityByRepo[repo] ?? null,
|
|
2510
2438
|
activeClaims: activeClaimsByRepo[repo] ?? 0,
|
|
2511
2439
|
pendingHandoffs: pendingHandoffsByRepo[repo] ?? 0,
|
|
2512
2440
|
unassignedHandoffs: unassignedHandoffsByRepo[repo] ?? 0,
|
|
@@ -2766,7 +2694,7 @@ var StandardEntity = class extends BaseEntity {
|
|
|
2766
2694
|
let sql = "SELECT * FROM coding_standards WHERE code = ?";
|
|
2767
2695
|
const params = [code];
|
|
2768
2696
|
if (owner && repo) {
|
|
2769
|
-
sql += " AND owner = ? AND repo = ?";
|
|
2697
|
+
sql += " AND ((owner = ? AND repo = ?) OR is_global = 1)";
|
|
2770
2698
|
params.push(owner, repo);
|
|
2771
2699
|
}
|
|
2772
2700
|
const row = this.get(sql, params);
|
|
@@ -3175,8 +3103,8 @@ var HandoffEntity = class extends BaseEntity {
|
|
|
3175
3103
|
|
|
3176
3104
|
// src/mcp/storage/write-lock.ts
|
|
3177
3105
|
import lockfile from "proper-lockfile";
|
|
3178
|
-
import
|
|
3179
|
-
import
|
|
3106
|
+
import path from "path";
|
|
3107
|
+
import fs2 from "fs";
|
|
3180
3108
|
var LOCK_STALE_MS = 3e4;
|
|
3181
3109
|
var LOCK_RETRY_DELAY_MS = 200;
|
|
3182
3110
|
var LOCK_RETRY_COUNT = 250;
|
|
@@ -3185,9 +3113,9 @@ var WriteLock = class {
|
|
|
3185
3113
|
locked = false;
|
|
3186
3114
|
constructor(dbPath) {
|
|
3187
3115
|
this.lockTarget = dbPath;
|
|
3188
|
-
if (!
|
|
3189
|
-
|
|
3190
|
-
|
|
3116
|
+
if (!fs2.existsSync(dbPath)) {
|
|
3117
|
+
fs2.mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
3118
|
+
fs2.writeFileSync(dbPath, "");
|
|
3191
3119
|
}
|
|
3192
3120
|
}
|
|
3193
3121
|
/**
|
|
@@ -3239,13 +3167,13 @@ var WriteLock = class {
|
|
|
3239
3167
|
// src/mcp/storage/sqlite.ts
|
|
3240
3168
|
function resolveDbPath() {
|
|
3241
3169
|
if (process.env.MEMORY_DB_PATH) return process.env.MEMORY_DB_PATH;
|
|
3242
|
-
const standardConfigDir = process.platform === "win32" ?
|
|
3243
|
-
const standardPath =
|
|
3244
|
-
if (
|
|
3245
|
-
const legacyPath =
|
|
3246
|
-
if (
|
|
3247
|
-
const localCwdFile =
|
|
3248
|
-
if (
|
|
3170
|
+
const standardConfigDir = process.platform === "win32" ? path2.join(os.homedir(), ".local-memory-mcp") : process.platform === "darwin" ? path2.join(os.homedir(), "Library", "Application Support", "local-memory-mcp") : path2.join(os.homedir(), ".config", "local-memory-mcp");
|
|
3171
|
+
const standardPath = path2.join(standardConfigDir, "memory.db");
|
|
3172
|
+
if (fs3.existsSync(standardPath)) return standardPath;
|
|
3173
|
+
const legacyPath = path2.join(os.homedir(), ".config", "local-memory-mcp", "memory.db");
|
|
3174
|
+
if (fs3.existsSync(legacyPath)) return legacyPath;
|
|
3175
|
+
const localCwdFile = path2.join(process.cwd(), "storage", "memory.db");
|
|
3176
|
+
if (fs3.existsSync(localCwdFile)) return localCwdFile;
|
|
3249
3177
|
return standardPath;
|
|
3250
3178
|
}
|
|
3251
3179
|
var DB_PATH = resolveDbPath();
|
|
@@ -3268,9 +3196,9 @@ var SQLiteStore = class _SQLiteStore {
|
|
|
3268
3196
|
const finalPath = dbPath ?? DB_PATH;
|
|
3269
3197
|
this.dbPathInstance = finalPath;
|
|
3270
3198
|
if (finalPath !== ":memory:") {
|
|
3271
|
-
const dbDir =
|
|
3272
|
-
if (!
|
|
3273
|
-
|
|
3199
|
+
const dbDir = path2.dirname(finalPath);
|
|
3200
|
+
if (!fs3.existsSync(dbDir)) {
|
|
3201
|
+
fs3.mkdirSync(dbDir, { recursive: true });
|
|
3274
3202
|
}
|
|
3275
3203
|
}
|
|
3276
3204
|
this.db = new Database(finalPath);
|
|
@@ -3329,12 +3257,12 @@ var SQLiteStore = class _SQLiteStore {
|
|
|
3329
3257
|
*/
|
|
3330
3258
|
_attemptRecovery(dbPath) {
|
|
3331
3259
|
const backupPath = dbPath + ".backup";
|
|
3332
|
-
if (
|
|
3260
|
+
if (fs3.existsSync(backupPath)) {
|
|
3333
3261
|
logger.warn("[SQLiteStore] Attempting recovery from backup", { backupPath });
|
|
3334
3262
|
try {
|
|
3335
3263
|
const corruptPath = `${dbPath}.corrupt_${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").slice(0, 15)}`;
|
|
3336
|
-
|
|
3337
|
-
|
|
3264
|
+
fs3.copyFileSync(dbPath, corruptPath);
|
|
3265
|
+
fs3.copyFileSync(backupPath, dbPath);
|
|
3338
3266
|
logger.warn("[SQLiteStore] Recovery successful. Corrupt file saved to", { corruptPath });
|
|
3339
3267
|
} catch (err) {
|
|
3340
3268
|
logger.error("[SQLiteStore] Recovery failed", { error: String(err) });
|
|
@@ -3352,7 +3280,7 @@ var SQLiteStore = class _SQLiteStore {
|
|
|
3352
3280
|
try {
|
|
3353
3281
|
this.db.pragma("wal_checkpoint(PASSIVE)");
|
|
3354
3282
|
const backupPath = this.dbPathInstance + ".backup";
|
|
3355
|
-
|
|
3283
|
+
fs3.copyFileSync(this.dbPathInstance, backupPath);
|
|
3356
3284
|
} catch (err) {
|
|
3357
3285
|
logger.warn("[SQLiteStore] Backup failed", { error: String(err) });
|
|
3358
3286
|
}
|
|
@@ -3475,8 +3403,8 @@ var RealVectorStore = class {
|
|
|
3475
3403
|
};
|
|
3476
3404
|
|
|
3477
3405
|
// src/mcp/session.ts
|
|
3478
|
-
import
|
|
3479
|
-
import { fileURLToPath
|
|
3406
|
+
import path3 from "path";
|
|
3407
|
+
import { fileURLToPath } from "url";
|
|
3480
3408
|
function createSessionContext() {
|
|
3481
3409
|
return {
|
|
3482
3410
|
roots: [],
|
|
@@ -3488,60 +3416,13 @@ function createSessionContext() {
|
|
|
3488
3416
|
supportsElicitationUrl: false
|
|
3489
3417
|
};
|
|
3490
3418
|
}
|
|
3491
|
-
function updateSessionFromInitialize(session, params) {
|
|
3492
|
-
const capabilities = params?.capabilities || {};
|
|
3493
|
-
session.clientInfo = params?.clientInfo;
|
|
3494
|
-
session.clientCapabilities = capabilities;
|
|
3495
|
-
session.supportsRoots = Boolean(capabilities.roots);
|
|
3496
|
-
session.supportsSampling = Boolean(capabilities.sampling);
|
|
3497
|
-
const sampling = capabilities.sampling;
|
|
3498
|
-
session.supportsSamplingTools = Boolean(sampling?.tools);
|
|
3499
|
-
session.supportsElicitation = Boolean(capabilities.elicitation);
|
|
3500
|
-
session.supportsElicitationForm = supportsElicitationMode(capabilities.elicitation, "form");
|
|
3501
|
-
session.supportsElicitationUrl = supportsElicitationMode(capabilities.elicitation, "url");
|
|
3502
|
-
}
|
|
3503
|
-
function supportsElicitationMode(capability, mode) {
|
|
3504
|
-
if (!capability || typeof capability !== "object") {
|
|
3505
|
-
return false;
|
|
3506
|
-
}
|
|
3507
|
-
const cap = capability;
|
|
3508
|
-
if (mode === "form") {
|
|
3509
|
-
return Object.keys(cap).length === 0 || typeof cap.form === "object";
|
|
3510
|
-
}
|
|
3511
|
-
return typeof cap.url === "object";
|
|
3512
|
-
}
|
|
3513
|
-
function updateSessionRoots(session, roots) {
|
|
3514
|
-
const normalized = normalizeRoots(roots);
|
|
3515
|
-
const previous = JSON.stringify(session.roots);
|
|
3516
|
-
const next = JSON.stringify(normalized);
|
|
3517
|
-
session.roots = normalized;
|
|
3518
|
-
return previous !== next;
|
|
3519
|
-
}
|
|
3520
|
-
function normalizeRoots(roots) {
|
|
3521
|
-
if (!Array.isArray(roots)) return [];
|
|
3522
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3523
|
-
const normalized = [];
|
|
3524
|
-
for (const root of roots) {
|
|
3525
|
-
if (!root || typeof root !== "object") continue;
|
|
3526
|
-
const r = root;
|
|
3527
|
-
const uri = typeof r.uri === "string" ? r.uri : void 0;
|
|
3528
|
-
const name = typeof r.name === "string" ? r.name : void 0;
|
|
3529
|
-
if (!uri || seen.has(uri)) continue;
|
|
3530
|
-
seen.add(uri);
|
|
3531
|
-
normalized.push({ uri, name });
|
|
3532
|
-
}
|
|
3533
|
-
return normalized;
|
|
3534
|
-
}
|
|
3535
|
-
function extractRootsFromResult(result) {
|
|
3536
|
-
return normalizeRoots(result?.roots);
|
|
3537
|
-
}
|
|
3538
3419
|
function getFilesystemRoots(session) {
|
|
3539
3420
|
if (!session) return [];
|
|
3540
3421
|
const resolved = [];
|
|
3541
3422
|
for (const root of session.roots) {
|
|
3542
3423
|
if (!root.uri.startsWith("file://")) continue;
|
|
3543
3424
|
try {
|
|
3544
|
-
resolved.push(
|
|
3425
|
+
resolved.push(path3.resolve(fileURLToPath(root.uri)));
|
|
3545
3426
|
} catch {
|
|
3546
3427
|
}
|
|
3547
3428
|
}
|
|
@@ -3550,19 +3431,19 @@ function getFilesystemRoots(session) {
|
|
|
3550
3431
|
function isPathWithinRoots(targetPath, session) {
|
|
3551
3432
|
const roots = getFilesystemRoots(session);
|
|
3552
3433
|
if (roots.length === 0) return true;
|
|
3553
|
-
const normalizedTarget =
|
|
3434
|
+
const normalizedTarget = path3.resolve(targetPath);
|
|
3554
3435
|
return roots.some((rootPath) => {
|
|
3555
|
-
const relative =
|
|
3556
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
3436
|
+
const relative = path3.relative(rootPath, normalizedTarget);
|
|
3437
|
+
return relative === "" || !relative.startsWith("..") && !path3.isAbsolute(relative);
|
|
3557
3438
|
});
|
|
3558
3439
|
}
|
|
3559
3440
|
function findContainingRoot(targetPath, session) {
|
|
3560
3441
|
const roots = getFilesystemRoots(session);
|
|
3561
3442
|
if (roots.length === 0) return null;
|
|
3562
|
-
const normalizedTarget =
|
|
3443
|
+
const normalizedTarget = path3.resolve(targetPath);
|
|
3563
3444
|
for (const rootPath of roots) {
|
|
3564
|
-
const relative =
|
|
3565
|
-
if (relative === "" || !relative.startsWith("..") && !
|
|
3445
|
+
const relative = path3.relative(rootPath, normalizedTarget);
|
|
3446
|
+
if (relative === "" || !relative.startsWith("..") && !path3.isAbsolute(relative)) {
|
|
3566
3447
|
return rootPath;
|
|
3567
3448
|
}
|
|
3568
3449
|
}
|
|
@@ -3571,14 +3452,14 @@ function findContainingRoot(targetPath, session) {
|
|
|
3571
3452
|
function inferRepoFromSession(session) {
|
|
3572
3453
|
const roots = getFilesystemRoots(session);
|
|
3573
3454
|
if (roots.length === 1) {
|
|
3574
|
-
return
|
|
3455
|
+
return path3.basename(roots[0]);
|
|
3575
3456
|
}
|
|
3576
3457
|
return void 0;
|
|
3577
3458
|
}
|
|
3578
3459
|
function inferOwnerFromSession(session) {
|
|
3579
3460
|
const roots = getFilesystemRoots(session);
|
|
3580
3461
|
if (roots.length === 1) {
|
|
3581
|
-
const parts = roots[0].split(
|
|
3462
|
+
const parts = roots[0].split(path3.sep).filter(Boolean);
|
|
3582
3463
|
if (parts.length >= 2) {
|
|
3583
3464
|
return parts[parts.length - 2];
|
|
3584
3465
|
}
|
|
@@ -3586,8 +3467,84 @@ function inferOwnerFromSession(session) {
|
|
|
3586
3467
|
return void 0;
|
|
3587
3468
|
}
|
|
3588
3469
|
|
|
3589
|
-
// src/mcp/
|
|
3590
|
-
|
|
3470
|
+
// src/mcp/prompts/loader.ts
|
|
3471
|
+
import fs4 from "fs";
|
|
3472
|
+
import path4 from "path";
|
|
3473
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3474
|
+
import matter from "gray-matter";
|
|
3475
|
+
var __filename = fileURLToPath2(import.meta.url);
|
|
3476
|
+
var __dirname = path4.dirname(__filename);
|
|
3477
|
+
function findPromptDir() {
|
|
3478
|
+
const candidates = [
|
|
3479
|
+
// Production if chunked into dist/
|
|
3480
|
+
"./prompts",
|
|
3481
|
+
// Production if inlined into dist/mcp/
|
|
3482
|
+
"../prompts",
|
|
3483
|
+
// Dev: /src/mcp/prompts/definitions (next to loader.ts)
|
|
3484
|
+
"./definitions"
|
|
3485
|
+
].map((relPath) => path4.resolve(__dirname, relPath));
|
|
3486
|
+
for (const dir of candidates) {
|
|
3487
|
+
if (fs4.existsSync(dir)) {
|
|
3488
|
+
const files = fs4.readdirSync(dir);
|
|
3489
|
+
if (files.some((f) => f.endsWith(".md"))) {
|
|
3490
|
+
return dir;
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3494
|
+
return path4.resolve(__dirname, "./definitions");
|
|
3495
|
+
}
|
|
3496
|
+
var PROMPT_DIR = findPromptDir();
|
|
3497
|
+
function listPromptFiles() {
|
|
3498
|
+
if (!fs4.existsSync(PROMPT_DIR)) return [];
|
|
3499
|
+
return fs4.readdirSync(PROMPT_DIR).filter((file) => file.endsWith(".md")).map((file) => file.replace(/\.md$/, "")).sort();
|
|
3500
|
+
}
|
|
3501
|
+
function loadPromptFromMarkdown(name) {
|
|
3502
|
+
const filePath = path4.join(PROMPT_DIR, `${name}.md`);
|
|
3503
|
+
if (!fs4.existsSync(filePath)) {
|
|
3504
|
+
throw new Error(`Prompt file not found: ${filePath}`);
|
|
3505
|
+
}
|
|
3506
|
+
const fileContent = fs4.readFileSync(filePath, "utf-8");
|
|
3507
|
+
const { data, content } = matter(fileContent);
|
|
3508
|
+
return {
|
|
3509
|
+
name: data.name || name,
|
|
3510
|
+
description: data.description || "",
|
|
3511
|
+
arguments: data.arguments || [],
|
|
3512
|
+
agent: data.agent,
|
|
3513
|
+
content: content.trim()
|
|
3514
|
+
};
|
|
3515
|
+
}
|
|
3516
|
+
function findServerInstructionsDir() {
|
|
3517
|
+
const candidates = [
|
|
3518
|
+
// Production if chunked into dist/
|
|
3519
|
+
"./prompts/server",
|
|
3520
|
+
// Production if inlined into dist/mcp/
|
|
3521
|
+
"../prompts/server",
|
|
3522
|
+
// Dev: /src/mcp/prompts/server (next to loader.ts)
|
|
3523
|
+
"./server"
|
|
3524
|
+
].map((relPath) => path4.resolve(__dirname, relPath));
|
|
3525
|
+
for (const dir of candidates) {
|
|
3526
|
+
if (fs4.existsSync(dir)) {
|
|
3527
|
+
const filePath = path4.join(dir, "instructions.md");
|
|
3528
|
+
if (fs4.existsSync(filePath)) {
|
|
3529
|
+
return dir;
|
|
3530
|
+
}
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
return path4.resolve(__dirname, "./server");
|
|
3534
|
+
}
|
|
3535
|
+
var SERVER_DIR = findServerInstructionsDir();
|
|
3536
|
+
function loadServerInstructions() {
|
|
3537
|
+
const filePath = path4.join(SERVER_DIR, "instructions.md");
|
|
3538
|
+
if (!fs4.existsSync(filePath)) {
|
|
3539
|
+
throw new Error(`Server instructions file not found: ${filePath}`);
|
|
3540
|
+
}
|
|
3541
|
+
const fileContent = fs4.readFileSync(filePath, "utf-8");
|
|
3542
|
+
const { content } = matter(fileContent);
|
|
3543
|
+
return content.trim();
|
|
3544
|
+
}
|
|
3545
|
+
|
|
3546
|
+
// src/mcp/tools/definitions/memory.ts
|
|
3547
|
+
var MEMORY_TOOL_DEFINITIONS = [
|
|
3591
3548
|
{
|
|
3592
3549
|
name: "memory-synthesize",
|
|
3593
3550
|
title: "Memory Synthesize",
|
|
@@ -3640,60 +3597,6 @@ var TOOL_DEFINITIONS = [
|
|
|
3640
3597
|
required: ["repo", "objective", "answer", "iterations", "toolCalls"]
|
|
3641
3598
|
}
|
|
3642
3599
|
},
|
|
3643
|
-
{
|
|
3644
|
-
name: "task-create-interactive",
|
|
3645
|
-
title: "Interactive Task Create",
|
|
3646
|
-
description: "Create a task with MCP elicitation fallback for any missing required fields. Best when an agent knows a task is needed but still needs user confirmation for repo, title, or phase.",
|
|
3647
|
-
annotations: {
|
|
3648
|
-
readOnlyHint: false,
|
|
3649
|
-
idempotentHint: false,
|
|
3650
|
-
destructiveHint: false,
|
|
3651
|
-
openWorldHint: false
|
|
3652
|
-
},
|
|
3653
|
-
inputSchema: {
|
|
3654
|
-
type: "object",
|
|
3655
|
-
properties: {
|
|
3656
|
-
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
3657
|
-
repo: {
|
|
3658
|
-
type: "string",
|
|
3659
|
-
description: "Repository name. Optional when it can be inferred from MCP roots or elicited from the user."
|
|
3660
|
-
},
|
|
3661
|
-
task_code: { type: "string" },
|
|
3662
|
-
phase: { type: "string" },
|
|
3663
|
-
title: { type: "string", minLength: 3, maxLength: 100 },
|
|
3664
|
-
description: {
|
|
3665
|
-
type: "string",
|
|
3666
|
-
minLength: 1,
|
|
3667
|
-
description: "Detailed description. MUST follow format: 1. Context & Analysis, 2. Step & Implementation, 3. Acceptance & Verification"
|
|
3668
|
-
},
|
|
3669
|
-
status: { type: "string", enum: ["backlog", "pending"], default: "backlog" },
|
|
3670
|
-
priority: {
|
|
3671
|
-
type: "number",
|
|
3672
|
-
minimum: 1,
|
|
3673
|
-
maximum: 5,
|
|
3674
|
-
default: 3,
|
|
3675
|
-
description: "Task priority where 1=Low, 2=Normal, 3=Medium, 4=High, 5=Critical."
|
|
3676
|
-
},
|
|
3677
|
-
agent: { type: "string" },
|
|
3678
|
-
role: { type: "string" },
|
|
3679
|
-
doc_path: { type: "string" },
|
|
3680
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
3681
|
-
},
|
|
3682
|
-
required: ["owner"]
|
|
3683
|
-
},
|
|
3684
|
-
outputSchema: {
|
|
3685
|
-
type: "object",
|
|
3686
|
-
properties: {
|
|
3687
|
-
repo: { type: "string" },
|
|
3688
|
-
task_code: { type: "string" },
|
|
3689
|
-
phase: { type: "string" },
|
|
3690
|
-
title: { type: "string" },
|
|
3691
|
-
status: { type: "string" },
|
|
3692
|
-
priority: { type: "number" }
|
|
3693
|
-
},
|
|
3694
|
-
required: ["repo", "task_code", "phase", "title", "status", "priority"]
|
|
3695
|
-
}
|
|
3696
|
-
},
|
|
3697
3600
|
{
|
|
3698
3601
|
name: "memory-detail",
|
|
3699
3602
|
title: "Memory Detail",
|
|
@@ -3723,100 +3626,15 @@ var TOOL_DEFINITIONS = [
|
|
|
3723
3626
|
}
|
|
3724
3627
|
},
|
|
3725
3628
|
{
|
|
3726
|
-
name: "
|
|
3727
|
-
title: "
|
|
3728
|
-
description: "
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
properties: {
|
|
3736
|
-
id: { type: "string", format: "uuid", description: "Coding standard ID." },
|
|
3737
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON details." }
|
|
3738
|
-
}
|
|
3739
|
-
},
|
|
3740
|
-
{
|
|
3741
|
-
title: "By code",
|
|
3742
|
-
required: ["code", "owner", "repo"],
|
|
3743
|
-
properties: {
|
|
3744
|
-
code: { type: "string", description: "Short standard code (e.g. 'A3KPQ2')." },
|
|
3745
|
-
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)." },
|
|
3746
|
-
repo: { type: "string", description: "Repository/project name." },
|
|
3747
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON details." }
|
|
3748
|
-
}
|
|
3749
|
-
}
|
|
3750
|
-
]
|
|
3751
|
-
}
|
|
3752
|
-
},
|
|
3753
|
-
{
|
|
3754
|
-
name: "task-detail",
|
|
3755
|
-
title: "Task Detail",
|
|
3756
|
-
description: "Fetch full details of a specific task by ID or task code. Use this when you have a task ID or code and need to read the full description and comments.",
|
|
3757
|
-
inputSchema: {
|
|
3758
|
-
type: "object",
|
|
3759
|
-
oneOf: [
|
|
3760
|
-
{
|
|
3761
|
-
title: "By ID",
|
|
3762
|
-
required: ["owner", "repo", "id"],
|
|
3763
|
-
properties: {
|
|
3764
|
-
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
3765
|
-
repo: { type: "string", description: "Repository name" },
|
|
3766
|
-
id: { type: "string", format: "uuid", description: "Task ID" },
|
|
3767
|
-
structured: {
|
|
3768
|
-
type: "boolean",
|
|
3769
|
-
default: false,
|
|
3770
|
-
description: "If true, returns structured JSON without the text content details."
|
|
3771
|
-
}
|
|
3772
|
-
}
|
|
3773
|
-
},
|
|
3774
|
-
{
|
|
3775
|
-
title: "By task_code",
|
|
3776
|
-
required: ["owner", "repo", "task_code"],
|
|
3777
|
-
properties: {
|
|
3778
|
-
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
3779
|
-
repo: { type: "string", description: "Repository name" },
|
|
3780
|
-
task_code: { type: "string", description: "Task code (e.g. TASK-001)" },
|
|
3781
|
-
structured: {
|
|
3782
|
-
type: "boolean",
|
|
3783
|
-
default: false,
|
|
3784
|
-
description: "If true, returns structured JSON without the text content details."
|
|
3785
|
-
}
|
|
3786
|
-
}
|
|
3787
|
-
},
|
|
3788
|
-
{
|
|
3789
|
-
title: "By task_codes",
|
|
3790
|
-
required: ["owner", "repo", "task_codes"],
|
|
3791
|
-
properties: {
|
|
3792
|
-
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
3793
|
-
repo: { type: "string", description: "Repository name" },
|
|
3794
|
-
task_codes: {
|
|
3795
|
-
type: "array",
|
|
3796
|
-
items: { type: "string" },
|
|
3797
|
-
minItems: 1,
|
|
3798
|
-
description: "Array of task codes (e.g. TASK-001)"
|
|
3799
|
-
},
|
|
3800
|
-
structured: {
|
|
3801
|
-
type: "boolean",
|
|
3802
|
-
default: false,
|
|
3803
|
-
description: "If true, returns structured JSON without the text content details."
|
|
3804
|
-
}
|
|
3805
|
-
}
|
|
3806
|
-
}
|
|
3807
|
-
]
|
|
3808
|
-
}
|
|
3809
|
-
},
|
|
3810
|
-
{
|
|
3811
|
-
name: "memory-store",
|
|
3812
|
-
title: "Memory Store",
|
|
3813
|
-
description: "Store a new durable knowledge entry. Do not store coordination state here: task claims, file claims, agent registration, and handoffs belong to task-claim, task-update, and handoff-* tools. Keep 'title' concise and human-readable; put auxiliary context into 'metadata'.",
|
|
3814
|
-
annotations: {
|
|
3815
|
-
readOnlyHint: false,
|
|
3816
|
-
idempotentHint: false,
|
|
3817
|
-
destructiveHint: false,
|
|
3818
|
-
openWorldHint: false
|
|
3819
|
-
},
|
|
3629
|
+
name: "memory-store",
|
|
3630
|
+
title: "Memory Store",
|
|
3631
|
+
description: "Store a new durable knowledge entry. Do not store coordination state here: task claims, file claims, agent registration, and handoffs belong to task-claim, task-update, and handoff-* tools. Keep 'title' concise and human-readable; put auxiliary context into 'metadata'.",
|
|
3632
|
+
annotations: {
|
|
3633
|
+
readOnlyHint: false,
|
|
3634
|
+
idempotentHint: false,
|
|
3635
|
+
destructiveHint: false,
|
|
3636
|
+
openWorldHint: false
|
|
3637
|
+
},
|
|
3820
3638
|
inputSchema: {
|
|
3821
3639
|
type: "object",
|
|
3822
3640
|
oneOf: [
|
|
@@ -4278,85 +4096,6 @@ var TOOL_DEFINITIONS = [
|
|
|
4278
4096
|
required: ["success"]
|
|
4279
4097
|
}
|
|
4280
4098
|
},
|
|
4281
|
-
{
|
|
4282
|
-
name: "standard-delete",
|
|
4283
|
-
title: "Standard Delete",
|
|
4284
|
-
description: "Delete one or more coding standards. Supports single 'id' or bulk 'ids'.",
|
|
4285
|
-
annotations: {
|
|
4286
|
-
readOnlyHint: false,
|
|
4287
|
-
idempotentHint: false,
|
|
4288
|
-
destructiveHint: true,
|
|
4289
|
-
openWorldHint: false
|
|
4290
|
-
},
|
|
4291
|
-
inputSchema: {
|
|
4292
|
-
type: "object",
|
|
4293
|
-
oneOf: [
|
|
4294
|
-
{
|
|
4295
|
-
title: "By single ID",
|
|
4296
|
-
required: ["owner", "repo", "id"],
|
|
4297
|
-
properties: {
|
|
4298
|
-
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4299
|
-
repo: { type: "string", description: "Repository name." },
|
|
4300
|
-
id: { type: "string", format: "uuid", description: "Coding standard ID to delete." },
|
|
4301
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4302
|
-
}
|
|
4303
|
-
},
|
|
4304
|
-
{
|
|
4305
|
-
title: "By bulk IDs",
|
|
4306
|
-
required: ["owner", "repo", "ids"],
|
|
4307
|
-
properties: {
|
|
4308
|
-
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4309
|
-
repo: { type: "string", description: "Repository name." },
|
|
4310
|
-
ids: {
|
|
4311
|
-
type: "array",
|
|
4312
|
-
items: { type: "string", format: "uuid" },
|
|
4313
|
-
minItems: 1,
|
|
4314
|
-
description: "Array of coding standard IDs to delete"
|
|
4315
|
-
},
|
|
4316
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4317
|
-
}
|
|
4318
|
-
},
|
|
4319
|
-
{
|
|
4320
|
-
title: "By single code",
|
|
4321
|
-
required: ["owner", "repo", "code"],
|
|
4322
|
-
properties: {
|
|
4323
|
-
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4324
|
-
repo: { type: "string", description: "Repository name." },
|
|
4325
|
-
code: { type: "string", maxLength: 20, description: "Short standard code." },
|
|
4326
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4327
|
-
}
|
|
4328
|
-
},
|
|
4329
|
-
{
|
|
4330
|
-
title: "By bulk codes",
|
|
4331
|
-
required: ["owner", "repo", "codes"],
|
|
4332
|
-
properties: {
|
|
4333
|
-
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4334
|
-
repo: { type: "string", description: "Repository name." },
|
|
4335
|
-
codes: {
|
|
4336
|
-
type: "array",
|
|
4337
|
-
items: { type: "string", maxLength: 20 },
|
|
4338
|
-
minItems: 1,
|
|
4339
|
-
description: "Array of standard codes to delete"
|
|
4340
|
-
},
|
|
4341
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4342
|
-
}
|
|
4343
|
-
}
|
|
4344
|
-
]
|
|
4345
|
-
},
|
|
4346
|
-
outputSchema: {
|
|
4347
|
-
type: "object",
|
|
4348
|
-
properties: {
|
|
4349
|
-
success: { type: "boolean" },
|
|
4350
|
-
id: { type: "string" },
|
|
4351
|
-
code: { type: "string" },
|
|
4352
|
-
ids: { type: "array", items: { type: "string" } },
|
|
4353
|
-
codes: { type: "array", items: { type: "string" } },
|
|
4354
|
-
repo: { type: "string" },
|
|
4355
|
-
deletedCount: { type: "number" }
|
|
4356
|
-
},
|
|
4357
|
-
required: ["success"]
|
|
4358
|
-
}
|
|
4359
|
-
},
|
|
4360
4099
|
{
|
|
4361
4100
|
name: "memory-recap",
|
|
4362
4101
|
title: "Memory Recap",
|
|
@@ -4430,39 +4169,38 @@ var TOOL_DEFINITIONS = [
|
|
|
4430
4169
|
},
|
|
4431
4170
|
required: ["schema", "repo", "count", "total", "offset", "limit", "stats", "top"]
|
|
4432
4171
|
}
|
|
4433
|
-
}
|
|
4172
|
+
}
|
|
4173
|
+
];
|
|
4174
|
+
|
|
4175
|
+
// src/mcp/tools/definitions/task.ts
|
|
4176
|
+
var TASK_TOOL_DEFINITIONS = [
|
|
4434
4177
|
{
|
|
4435
|
-
name: "task-create",
|
|
4436
|
-
title: "Task Create",
|
|
4437
|
-
description: "
|
|
4178
|
+
name: "task-create-interactive",
|
|
4179
|
+
title: "Interactive Task Create",
|
|
4180
|
+
description: "Create a task with MCP elicitation fallback for any missing required fields. Best when an agent knows a task is needed but still needs user confirmation for repo, title, or phase.",
|
|
4438
4181
|
annotations: {
|
|
4439
4182
|
readOnlyHint: false,
|
|
4440
4183
|
idempotentHint: false,
|
|
4184
|
+
destructiveHint: false,
|
|
4441
4185
|
openWorldHint: false
|
|
4442
4186
|
},
|
|
4443
4187
|
inputSchema: {
|
|
4444
4188
|
type: "object",
|
|
4445
4189
|
properties: {
|
|
4446
4190
|
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4447
|
-
repo: {
|
|
4448
|
-
task_code: { type: "string", description: "Unique task code (e.g. TASK-001) (Required for single task)" },
|
|
4449
|
-
phase: { type: "string", description: "Project phase (Required for single task)" },
|
|
4450
|
-
title: {
|
|
4191
|
+
repo: {
|
|
4451
4192
|
type: "string",
|
|
4452
|
-
|
|
4453
|
-
maxLength: 100,
|
|
4454
|
-
description: "Task objective (Required for single task)"
|
|
4193
|
+
description: "Repository name. Optional when it can be inferred from MCP roots or elicited from the user."
|
|
4455
4194
|
},
|
|
4195
|
+
task_code: { type: "string" },
|
|
4196
|
+
phase: { type: "string" },
|
|
4197
|
+
title: { type: "string", minLength: 3, maxLength: 100 },
|
|
4456
4198
|
description: {
|
|
4457
4199
|
type: "string",
|
|
4200
|
+
minLength: 1,
|
|
4458
4201
|
description: "Detailed description. MUST follow format: 1. Context & Analysis, 2. Step & Implementation, 3. Acceptance & Verification"
|
|
4459
4202
|
},
|
|
4460
|
-
status: {
|
|
4461
|
-
type: "string",
|
|
4462
|
-
enum: ["backlog", "pending"],
|
|
4463
|
-
default: "backlog",
|
|
4464
|
-
description: "New tasks MUST start in 'backlog' if there are already 10 pending tasks. Otherwise can start in 'pending'."
|
|
4465
|
-
},
|
|
4203
|
+
status: { type: "string", enum: ["backlog", "pending"], default: "backlog" },
|
|
4466
4204
|
priority: {
|
|
4467
4205
|
type: "number",
|
|
4468
4206
|
minimum: 1,
|
|
@@ -4470,22 +4208,138 @@ var TOOL_DEFINITIONS = [
|
|
|
4470
4208
|
default: 3,
|
|
4471
4209
|
description: "Task priority where 1=Low, 2=Normal, 3=Medium, 4=High, 5=Critical."
|
|
4472
4210
|
},
|
|
4473
|
-
agent: { type: "string"
|
|
4474
|
-
role: { type: "string"
|
|
4475
|
-
doc_path: { type: "string"
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4211
|
+
agent: { type: "string" },
|
|
4212
|
+
role: { type: "string" },
|
|
4213
|
+
doc_path: { type: "string" },
|
|
4214
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4215
|
+
},
|
|
4216
|
+
required: ["owner"]
|
|
4217
|
+
},
|
|
4218
|
+
outputSchema: {
|
|
4219
|
+
type: "object",
|
|
4220
|
+
properties: {
|
|
4221
|
+
repo: { type: "string" },
|
|
4222
|
+
task_code: { type: "string" },
|
|
4223
|
+
phase: { type: "string" },
|
|
4224
|
+
title: { type: "string" },
|
|
4225
|
+
status: { type: "string" },
|
|
4226
|
+
priority: { type: "number" }
|
|
4227
|
+
},
|
|
4228
|
+
required: ["repo", "task_code", "phase", "title", "status", "priority"]
|
|
4229
|
+
}
|
|
4230
|
+
},
|
|
4231
|
+
{
|
|
4232
|
+
name: "task-detail",
|
|
4233
|
+
title: "Task Detail",
|
|
4234
|
+
description: "Fetch full details of a specific task by ID or task code. Use this when you have a task ID or code and need to read the full description and comments.",
|
|
4235
|
+
inputSchema: {
|
|
4236
|
+
type: "object",
|
|
4237
|
+
oneOf: [
|
|
4238
|
+
{
|
|
4239
|
+
title: "By ID",
|
|
4240
|
+
required: ["owner", "repo", "id"],
|
|
4241
|
+
properties: {
|
|
4242
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4243
|
+
repo: { type: "string", description: "Repository name" },
|
|
4244
|
+
id: { type: "string", format: "uuid", description: "Task ID" },
|
|
4245
|
+
structured: {
|
|
4246
|
+
type: "boolean",
|
|
4247
|
+
default: false,
|
|
4248
|
+
description: "If true, returns structured JSON without the text content details."
|
|
4249
|
+
}
|
|
4250
|
+
}
|
|
4485
4251
|
},
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4252
|
+
{
|
|
4253
|
+
title: "By task_code",
|
|
4254
|
+
required: ["owner", "repo", "task_code"],
|
|
4255
|
+
properties: {
|
|
4256
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4257
|
+
repo: { type: "string", description: "Repository name" },
|
|
4258
|
+
task_code: { type: "string", description: "Task code (e.g. TASK-001)" },
|
|
4259
|
+
structured: {
|
|
4260
|
+
type: "boolean",
|
|
4261
|
+
default: false,
|
|
4262
|
+
description: "If true, returns structured JSON without the text content details."
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
4265
|
+
},
|
|
4266
|
+
{
|
|
4267
|
+
title: "By task_codes",
|
|
4268
|
+
required: ["owner", "repo", "task_codes"],
|
|
4269
|
+
properties: {
|
|
4270
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4271
|
+
repo: { type: "string", description: "Repository name" },
|
|
4272
|
+
task_codes: {
|
|
4273
|
+
type: "array",
|
|
4274
|
+
items: { type: "string" },
|
|
4275
|
+
minItems: 1,
|
|
4276
|
+
description: "Array of task codes (e.g. TASK-001)"
|
|
4277
|
+
},
|
|
4278
|
+
structured: {
|
|
4279
|
+
type: "boolean",
|
|
4280
|
+
default: false,
|
|
4281
|
+
description: "If true, returns structured JSON without the text content details."
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
]
|
|
4286
|
+
}
|
|
4287
|
+
},
|
|
4288
|
+
{
|
|
4289
|
+
name: "task-create",
|
|
4290
|
+
title: "Task Create",
|
|
4291
|
+
description: "Register one or more new tasks in a repository. task_code must be unique within the repository. Supports single task object or an array of tasks for bulk creation.",
|
|
4292
|
+
annotations: {
|
|
4293
|
+
readOnlyHint: false,
|
|
4294
|
+
idempotentHint: false,
|
|
4295
|
+
openWorldHint: false
|
|
4296
|
+
},
|
|
4297
|
+
inputSchema: {
|
|
4298
|
+
type: "object",
|
|
4299
|
+
properties: {
|
|
4300
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
4301
|
+
repo: { type: "string", description: "Repository/project name" },
|
|
4302
|
+
task_code: { type: "string", description: "Unique task code (e.g. TASK-001) (Required for single task)" },
|
|
4303
|
+
phase: { type: "string", description: "Project phase (Required for single task)" },
|
|
4304
|
+
title: {
|
|
4305
|
+
type: "string",
|
|
4306
|
+
minLength: 3,
|
|
4307
|
+
maxLength: 100,
|
|
4308
|
+
description: "Task objective (Required for single task)"
|
|
4309
|
+
},
|
|
4310
|
+
description: {
|
|
4311
|
+
type: "string",
|
|
4312
|
+
description: "Detailed description. MUST follow format: 1. Context & Analysis, 2. Step & Implementation, 3. Acceptance & Verification"
|
|
4313
|
+
},
|
|
4314
|
+
status: {
|
|
4315
|
+
type: "string",
|
|
4316
|
+
enum: ["backlog", "pending"],
|
|
4317
|
+
default: "backlog",
|
|
4318
|
+
description: "New tasks MUST start in 'backlog' if there are already 10 pending tasks. Otherwise can start in 'pending'."
|
|
4319
|
+
},
|
|
4320
|
+
priority: {
|
|
4321
|
+
type: "number",
|
|
4322
|
+
minimum: 1,
|
|
4323
|
+
maximum: 5,
|
|
4324
|
+
default: 3,
|
|
4325
|
+
description: "Task priority where 1=Low, 2=Normal, 3=Medium, 4=High, 5=Critical."
|
|
4326
|
+
},
|
|
4327
|
+
agent: { type: "string", description: "Agent assigned to this task" },
|
|
4328
|
+
role: { type: "string", description: "Role of the assigned agent" },
|
|
4329
|
+
doc_path: { type: "string", description: "Path to related documentation file" },
|
|
4330
|
+
tags: { type: "array", items: { type: "string" }, description: "Tags for categorization" },
|
|
4331
|
+
metadata: { type: "object", description: "Structured metadata for additional context" },
|
|
4332
|
+
parent_id: {
|
|
4333
|
+
type: "string",
|
|
4334
|
+
description: "Optional parent task ID (UUID) or parent task code (e.g. TASK-001). Resolved to UUID before storing."
|
|
4335
|
+
},
|
|
4336
|
+
depends_on: {
|
|
4337
|
+
type: "string",
|
|
4338
|
+
description: "Optional task ID (UUID) or task code (e.g. TASK-001). Resolved to UUID before storing."
|
|
4339
|
+
},
|
|
4340
|
+
est_tokens: { type: "number", minimum: 0, description: "Estimated tokens budget for this task" },
|
|
4341
|
+
tasks: {
|
|
4342
|
+
type: "array",
|
|
4489
4343
|
items: {
|
|
4490
4344
|
type: "object",
|
|
4491
4345
|
properties: {
|
|
@@ -5047,7 +4901,11 @@ var TOOL_DEFINITIONS = [
|
|
|
5047
4901
|
},
|
|
5048
4902
|
required: ["schema", "query", "count", "total", "offset", "limit", "results"]
|
|
5049
4903
|
}
|
|
5050
|
-
}
|
|
4904
|
+
}
|
|
4905
|
+
];
|
|
4906
|
+
|
|
4907
|
+
// src/mcp/tools/definitions/handoff.ts
|
|
4908
|
+
var HANDOFF_TOOL_DEFINITIONS = [
|
|
5051
4909
|
{
|
|
5052
4910
|
name: "handoff-create",
|
|
5053
4911
|
title: "Handoff Create",
|
|
@@ -5303,6 +5161,117 @@ var TOOL_DEFINITIONS = [
|
|
|
5303
5161
|
},
|
|
5304
5162
|
required: ["success", "repo", "task_id"]
|
|
5305
5163
|
}
|
|
5164
|
+
}
|
|
5165
|
+
];
|
|
5166
|
+
|
|
5167
|
+
// src/mcp/tools/definitions/standard.ts
|
|
5168
|
+
var STANDARD_TOOL_DEFINITIONS = [
|
|
5169
|
+
{
|
|
5170
|
+
name: "standard-detail",
|
|
5171
|
+
title: "Standard Detail",
|
|
5172
|
+
description: "Fetch full details of a specific coding standard by ID or short code. Use after standard-search when a result is relevant and full guidance is needed.",
|
|
5173
|
+
inputSchema: {
|
|
5174
|
+
type: "object",
|
|
5175
|
+
oneOf: [
|
|
5176
|
+
{
|
|
5177
|
+
title: "By ID",
|
|
5178
|
+
required: ["id"],
|
|
5179
|
+
properties: {
|
|
5180
|
+
id: { type: "string", format: "uuid", description: "Coding standard ID." },
|
|
5181
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON details." }
|
|
5182
|
+
}
|
|
5183
|
+
},
|
|
5184
|
+
{
|
|
5185
|
+
title: "By code",
|
|
5186
|
+
required: ["code", "owner", "repo"],
|
|
5187
|
+
properties: {
|
|
5188
|
+
code: { type: "string", description: "Short standard code (e.g. 'A3KPQ2')." },
|
|
5189
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)." },
|
|
5190
|
+
repo: { type: "string", description: "Repository/project name." },
|
|
5191
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON details." }
|
|
5192
|
+
}
|
|
5193
|
+
}
|
|
5194
|
+
]
|
|
5195
|
+
}
|
|
5196
|
+
},
|
|
5197
|
+
{
|
|
5198
|
+
name: "standard-delete",
|
|
5199
|
+
title: "Standard Delete",
|
|
5200
|
+
description: "Delete one or more coding standards. Supports single 'id' or bulk 'ids'.",
|
|
5201
|
+
annotations: {
|
|
5202
|
+
readOnlyHint: false,
|
|
5203
|
+
idempotentHint: false,
|
|
5204
|
+
destructiveHint: true,
|
|
5205
|
+
openWorldHint: false
|
|
5206
|
+
},
|
|
5207
|
+
inputSchema: {
|
|
5208
|
+
type: "object",
|
|
5209
|
+
oneOf: [
|
|
5210
|
+
{
|
|
5211
|
+
title: "By single ID",
|
|
5212
|
+
required: ["owner", "repo", "id"],
|
|
5213
|
+
properties: {
|
|
5214
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
5215
|
+
repo: { type: "string", description: "Repository name." },
|
|
5216
|
+
id: { type: "string", format: "uuid", description: "Coding standard ID to delete." },
|
|
5217
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
5218
|
+
}
|
|
5219
|
+
},
|
|
5220
|
+
{
|
|
5221
|
+
title: "By bulk IDs",
|
|
5222
|
+
required: ["owner", "repo", "ids"],
|
|
5223
|
+
properties: {
|
|
5224
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
5225
|
+
repo: { type: "string", description: "Repository name." },
|
|
5226
|
+
ids: {
|
|
5227
|
+
type: "array",
|
|
5228
|
+
items: { type: "string", format: "uuid" },
|
|
5229
|
+
minItems: 1,
|
|
5230
|
+
description: "Array of coding standard IDs to delete"
|
|
5231
|
+
},
|
|
5232
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
5233
|
+
}
|
|
5234
|
+
},
|
|
5235
|
+
{
|
|
5236
|
+
title: "By single code",
|
|
5237
|
+
required: ["owner", "repo", "code"],
|
|
5238
|
+
properties: {
|
|
5239
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
5240
|
+
repo: { type: "string", description: "Repository name." },
|
|
5241
|
+
code: { type: "string", maxLength: 20, description: "Short standard code." },
|
|
5242
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
5243
|
+
}
|
|
5244
|
+
},
|
|
5245
|
+
{
|
|
5246
|
+
title: "By bulk codes",
|
|
5247
|
+
required: ["owner", "repo", "codes"],
|
|
5248
|
+
properties: {
|
|
5249
|
+
owner: { type: "string", description: "Organization/namespace (e.g., GitHub org or username)" },
|
|
5250
|
+
repo: { type: "string", description: "Repository name." },
|
|
5251
|
+
codes: {
|
|
5252
|
+
type: "array",
|
|
5253
|
+
items: { type: "string", maxLength: 20 },
|
|
5254
|
+
minItems: 1,
|
|
5255
|
+
description: "Array of standard codes to delete"
|
|
5256
|
+
},
|
|
5257
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
5258
|
+
}
|
|
5259
|
+
}
|
|
5260
|
+
]
|
|
5261
|
+
},
|
|
5262
|
+
outputSchema: {
|
|
5263
|
+
type: "object",
|
|
5264
|
+
properties: {
|
|
5265
|
+
success: { type: "boolean" },
|
|
5266
|
+
id: { type: "string" },
|
|
5267
|
+
code: { type: "string" },
|
|
5268
|
+
ids: { type: "array", items: { type: "string" } },
|
|
5269
|
+
codes: { type: "array", items: { type: "string" } },
|
|
5270
|
+
repo: { type: "string" },
|
|
5271
|
+
deletedCount: { type: "number" }
|
|
5272
|
+
},
|
|
5273
|
+
required: ["success"]
|
|
5274
|
+
}
|
|
5306
5275
|
},
|
|
5307
5276
|
{
|
|
5308
5277
|
name: "standard-store",
|
|
@@ -5483,82 +5452,652 @@ var TOOL_DEFINITIONS = [
|
|
|
5483
5452
|
structured: { type: "boolean", default: false }
|
|
5484
5453
|
}
|
|
5485
5454
|
}
|
|
5486
|
-
]
|
|
5455
|
+
]
|
|
5456
|
+
},
|
|
5457
|
+
outputSchema: {
|
|
5458
|
+
type: "object",
|
|
5459
|
+
properties: {
|
|
5460
|
+
success: { type: "boolean" },
|
|
5461
|
+
id: { type: "string" },
|
|
5462
|
+
updatedFields: { type: "array", items: { type: "string" } }
|
|
5463
|
+
},
|
|
5464
|
+
required: ["success", "id", "updatedFields"]
|
|
5465
|
+
}
|
|
5466
|
+
},
|
|
5467
|
+
{
|
|
5468
|
+
name: "standard-search",
|
|
5469
|
+
title: "Standard Search",
|
|
5470
|
+
description: "MANDATORY PRE-IMPLEMENTATION CHECK: Call before any code edit, test edit, refactor, migration, or implementation decision to find applicable coding standards. Returns a compact pointer table; use `standard-detail` for relevant results. If no relevant standards are returned, continue and state that no applicable standards were found.",
|
|
5471
|
+
annotations: {
|
|
5472
|
+
readOnlyHint: true,
|
|
5473
|
+
idempotentHint: true,
|
|
5474
|
+
openWorldHint: false
|
|
5475
|
+
},
|
|
5476
|
+
inputSchema: {
|
|
5477
|
+
type: "object",
|
|
5478
|
+
properties: {
|
|
5479
|
+
query: { type: "string", description: "Search query (optional, searches title/content)" },
|
|
5480
|
+
stack: {
|
|
5481
|
+
type: "array",
|
|
5482
|
+
items: { type: "string" },
|
|
5483
|
+
description: "Technology stack to filter by (e.g., ['react', 'nextjs'])"
|
|
5484
|
+
},
|
|
5485
|
+
tags: {
|
|
5486
|
+
type: "array",
|
|
5487
|
+
items: { type: "string" },
|
|
5488
|
+
description: "Tag filter"
|
|
5489
|
+
},
|
|
5490
|
+
language: { type: "string", description: "Programming language filter" },
|
|
5491
|
+
context: { type: "string", description: "Context/category filter" },
|
|
5492
|
+
version: { type: "string", description: "Version filter" },
|
|
5493
|
+
repo: { type: "string", description: "Repository filter (optional)" },
|
|
5494
|
+
is_global: { type: "boolean", description: "Filter by global/repo-specific" },
|
|
5495
|
+
limit: { type: "number", minimum: 1, maximum: 100, default: 20 },
|
|
5496
|
+
offset: { type: "number", minimum: 0, default: 0 },
|
|
5497
|
+
structured: { type: "boolean", default: false }
|
|
5498
|
+
},
|
|
5499
|
+
required: []
|
|
5500
|
+
},
|
|
5501
|
+
outputSchema: {
|
|
5502
|
+
type: "object",
|
|
5503
|
+
properties: {
|
|
5504
|
+
schema: { type: "string", enum: ["standard-search"] },
|
|
5505
|
+
query: { type: "string" },
|
|
5506
|
+
count: { type: "number", description: "Number of rows returned" },
|
|
5507
|
+
total: { type: "number", description: "Total number of matches before pagination" },
|
|
5508
|
+
offset: { type: "number" },
|
|
5509
|
+
limit: { type: "number" },
|
|
5510
|
+
results: {
|
|
5511
|
+
type: "object",
|
|
5512
|
+
properties: {
|
|
5513
|
+
columns: {
|
|
5514
|
+
type: "array",
|
|
5515
|
+
items: { type: "string" }
|
|
5516
|
+
},
|
|
5517
|
+
rows: {
|
|
5518
|
+
type: "array",
|
|
5519
|
+
items: { type: "array" },
|
|
5520
|
+
description: "Each row includes standard id and pointer metadata. Fetch full content via standard-detail."
|
|
5521
|
+
}
|
|
5522
|
+
},
|
|
5523
|
+
required: ["columns", "rows"]
|
|
5524
|
+
}
|
|
5525
|
+
},
|
|
5526
|
+
required: ["schema", "query", "count", "total", "offset", "limit", "results"]
|
|
5527
|
+
}
|
|
5528
|
+
}
|
|
5529
|
+
];
|
|
5530
|
+
|
|
5531
|
+
// src/mcp/tools/definitions/agent.ts
|
|
5532
|
+
var AGENT_TOOL_DEFINITIONS = [
|
|
5533
|
+
{
|
|
5534
|
+
name: "agent-context",
|
|
5535
|
+
title: "Agent Context Recall",
|
|
5536
|
+
description: "Returns relevant context for the current agent session. Auto-detects active repo, searches relevant memories, lists active tasks, and surfaces recent decisions formatted as a single context block ready for injection into agent prompts.",
|
|
5537
|
+
annotations: {
|
|
5538
|
+
readOnlyHint: true,
|
|
5539
|
+
idempotentHint: true,
|
|
5540
|
+
openWorldHint: false
|
|
5541
|
+
},
|
|
5542
|
+
inputSchema: {
|
|
5543
|
+
type: "object",
|
|
5544
|
+
properties: {
|
|
5545
|
+
owner: {
|
|
5546
|
+
type: "string",
|
|
5547
|
+
description: "Organization/namespace (e.g., GitHub org or username). Auto-detected from session when omitted."
|
|
5548
|
+
},
|
|
5549
|
+
repo: {
|
|
5550
|
+
type: "string",
|
|
5551
|
+
description: "Repository/project name. Auto-detected from session when omitted."
|
|
5552
|
+
},
|
|
5553
|
+
objective: {
|
|
5554
|
+
type: "string",
|
|
5555
|
+
description: "Current agent objective to search relevant memories around."
|
|
5556
|
+
},
|
|
5557
|
+
type_filter: {
|
|
5558
|
+
type: "string",
|
|
5559
|
+
description: "Memory type to filter by (e.g., 'decision', 'code_fact', 'pattern', 'mistake'). Default: all."
|
|
5560
|
+
},
|
|
5561
|
+
limit: {
|
|
5562
|
+
type: "number",
|
|
5563
|
+
minimum: 1,
|
|
5564
|
+
maximum: 100,
|
|
5565
|
+
default: 5,
|
|
5566
|
+
description: "Maximum number of memories to return."
|
|
5567
|
+
},
|
|
5568
|
+
structured: {
|
|
5569
|
+
type: "boolean",
|
|
5570
|
+
default: false,
|
|
5571
|
+
description: "If true, returns structured JSON results."
|
|
5572
|
+
}
|
|
5573
|
+
}
|
|
5574
|
+
},
|
|
5575
|
+
outputSchema: {
|
|
5576
|
+
type: "object",
|
|
5577
|
+
properties: {
|
|
5578
|
+
schema: { type: "string", enum: ["agent-context"] },
|
|
5579
|
+
repo: { type: "string" },
|
|
5580
|
+
objective: { type: "string" },
|
|
5581
|
+
memories: {
|
|
5582
|
+
type: "array",
|
|
5583
|
+
items: {
|
|
5584
|
+
type: "object",
|
|
5585
|
+
properties: {
|
|
5586
|
+
id: { type: "string" },
|
|
5587
|
+
code: { type: "string" },
|
|
5588
|
+
title: { type: "string" },
|
|
5589
|
+
type: { type: "string" },
|
|
5590
|
+
importance: { type: "number" }
|
|
5591
|
+
}
|
|
5592
|
+
}
|
|
5593
|
+
},
|
|
5594
|
+
decisions: {
|
|
5595
|
+
type: "array",
|
|
5596
|
+
items: {
|
|
5597
|
+
type: "object",
|
|
5598
|
+
properties: {
|
|
5599
|
+
id: { type: "string" },
|
|
5600
|
+
code: { type: "string" },
|
|
5601
|
+
title: { type: "string" },
|
|
5602
|
+
importance: { type: "number" }
|
|
5603
|
+
}
|
|
5604
|
+
}
|
|
5605
|
+
},
|
|
5606
|
+
tasks: {
|
|
5607
|
+
type: "array",
|
|
5608
|
+
items: {
|
|
5609
|
+
type: "object",
|
|
5610
|
+
properties: {
|
|
5611
|
+
task_code: { type: "string" },
|
|
5612
|
+
title: { type: "string" },
|
|
5613
|
+
status: { type: "string" },
|
|
5614
|
+
priority: { type: "number" }
|
|
5615
|
+
}
|
|
5616
|
+
}
|
|
5617
|
+
}
|
|
5618
|
+
},
|
|
5619
|
+
required: ["schema", "repo", "memories", "decisions", "tasks"]
|
|
5620
|
+
}
|
|
5621
|
+
},
|
|
5622
|
+
{
|
|
5623
|
+
name: "decision-log",
|
|
5624
|
+
title: "Decision Logger",
|
|
5625
|
+
description: "Logs a structured decision as a memory entry. Accepts a summary of what was decided, the context/situation, the rationale, and optional alternatives considered. Internally reuses the memory-store handler with type='decision' and importance=4. Owner and repo are auto-inferred from session when omitted.",
|
|
5626
|
+
annotations: {
|
|
5627
|
+
readOnlyHint: false,
|
|
5628
|
+
idempotentHint: false,
|
|
5629
|
+
openWorldHint: false
|
|
5630
|
+
},
|
|
5631
|
+
inputSchema: {
|
|
5632
|
+
type: "object",
|
|
5633
|
+
properties: {
|
|
5634
|
+
summary: {
|
|
5635
|
+
type: "string",
|
|
5636
|
+
description: "What was decided (used as the memory title). Max 255 characters."
|
|
5637
|
+
},
|
|
5638
|
+
context: {
|
|
5639
|
+
type: "string",
|
|
5640
|
+
description: "The situation or context surrounding the decision. Min 10 characters."
|
|
5641
|
+
},
|
|
5642
|
+
rationale: {
|
|
5643
|
+
type: "string",
|
|
5644
|
+
description: "Why this decision was made. Min 10 characters."
|
|
5645
|
+
},
|
|
5646
|
+
alternatives: {
|
|
5647
|
+
type: "array",
|
|
5648
|
+
items: { type: "string" },
|
|
5649
|
+
description: "Alternatives that were considered (optional)."
|
|
5650
|
+
},
|
|
5651
|
+
tags: {
|
|
5652
|
+
type: "array",
|
|
5653
|
+
items: { type: "string" },
|
|
5654
|
+
description: "Additional tags to apply (auto-includes 'decision')."
|
|
5655
|
+
},
|
|
5656
|
+
owner: {
|
|
5657
|
+
type: "string",
|
|
5658
|
+
description: "Organization/namespace. Auto-detected from session when omitted."
|
|
5659
|
+
},
|
|
5660
|
+
repo: {
|
|
5661
|
+
type: "string",
|
|
5662
|
+
description: "Repository/project name. Auto-detected from session when omitted."
|
|
5663
|
+
},
|
|
5664
|
+
structured: {
|
|
5665
|
+
type: "boolean",
|
|
5666
|
+
default: false,
|
|
5667
|
+
description: "If true, returns structured JSON results."
|
|
5668
|
+
}
|
|
5669
|
+
},
|
|
5670
|
+
required: ["summary", "context", "rationale"]
|
|
5671
|
+
},
|
|
5672
|
+
outputSchema: {
|
|
5673
|
+
type: "object",
|
|
5674
|
+
properties: {
|
|
5675
|
+
success: { type: "boolean" },
|
|
5676
|
+
id: { type: "string" },
|
|
5677
|
+
code: { type: "string" },
|
|
5678
|
+
repo: { type: "string" },
|
|
5679
|
+
type: { type: "string", enum: ["decision"] },
|
|
5680
|
+
title: { type: "string" }
|
|
5681
|
+
}
|
|
5682
|
+
}
|
|
5683
|
+
},
|
|
5684
|
+
{
|
|
5685
|
+
name: "session-summarize",
|
|
5686
|
+
title: "Session Summarizer",
|
|
5687
|
+
description: "Persists a session summary as a task_archive memory entry. Accepts a session summary, optional key decisions made, optional next steps, and optional tags. Internally reuses the memory-store handler with type='task_archive' and importance=3. Owner and repo are auto-inferred from session when omitted.",
|
|
5688
|
+
annotations: {
|
|
5689
|
+
readOnlyHint: false,
|
|
5690
|
+
idempotentHint: false,
|
|
5691
|
+
openWorldHint: false
|
|
5692
|
+
},
|
|
5693
|
+
inputSchema: {
|
|
5694
|
+
type: "object",
|
|
5695
|
+
properties: {
|
|
5696
|
+
summary: {
|
|
5697
|
+
type: "string",
|
|
5698
|
+
description: "Session summary text. Min 10 characters."
|
|
5699
|
+
},
|
|
5700
|
+
key_decisions: {
|
|
5701
|
+
type: "array",
|
|
5702
|
+
items: { type: "string" },
|
|
5703
|
+
description: "Key decisions made during this session (optional)."
|
|
5704
|
+
},
|
|
5705
|
+
next_steps: {
|
|
5706
|
+
type: "array",
|
|
5707
|
+
items: { type: "string" },
|
|
5708
|
+
description: "Next steps or follow-up actions (optional)."
|
|
5709
|
+
},
|
|
5710
|
+
tags: {
|
|
5711
|
+
type: "array",
|
|
5712
|
+
items: { type: "string" },
|
|
5713
|
+
description: "Additional tags to apply (auto-includes 'session-summary')."
|
|
5714
|
+
},
|
|
5715
|
+
owner: {
|
|
5716
|
+
type: "string",
|
|
5717
|
+
description: "Organization/namespace. Auto-detected from session when omitted."
|
|
5718
|
+
},
|
|
5719
|
+
repo: {
|
|
5720
|
+
type: "string",
|
|
5721
|
+
description: "Repository/project name. Auto-detected from session when omitted."
|
|
5722
|
+
},
|
|
5723
|
+
structured: {
|
|
5724
|
+
type: "boolean",
|
|
5725
|
+
default: false,
|
|
5726
|
+
description: "If true, returns structured JSON results."
|
|
5727
|
+
}
|
|
5728
|
+
},
|
|
5729
|
+
required: ["summary"]
|
|
5730
|
+
},
|
|
5731
|
+
outputSchema: {
|
|
5732
|
+
type: "object",
|
|
5733
|
+
properties: {
|
|
5734
|
+
success: { type: "boolean" },
|
|
5735
|
+
id: { type: "string" },
|
|
5736
|
+
code: { type: "string" },
|
|
5737
|
+
repo: { type: "string" },
|
|
5738
|
+
type: { type: "string", enum: ["task_archive"] },
|
|
5739
|
+
title: { type: "string" }
|
|
5740
|
+
}
|
|
5741
|
+
}
|
|
5742
|
+
},
|
|
5743
|
+
// ── Upstream compatibility aliases ──────────────────────────────────────
|
|
5744
|
+
{
|
|
5745
|
+
name: "remember_fact",
|
|
5746
|
+
title: "Remember Fact (Upstream)",
|
|
5747
|
+
description: "Upstream-compatible alias for memory-store. Stores a single fact as a memory entry. Accepts the same arguments as memory-store. Owner and repo are auto-inferred from session when omitted.",
|
|
5748
|
+
annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: false },
|
|
5749
|
+
inputSchema: {
|
|
5750
|
+
type: "object",
|
|
5751
|
+
properties: {
|
|
5752
|
+
owner: { type: "string", description: "Auto-detected from session." },
|
|
5753
|
+
repo: { type: "string", description: "Auto-detected from session." },
|
|
5754
|
+
title: { type: "string", description: "Title for the fact/memory." },
|
|
5755
|
+
content: { type: "string", description: "The fact content to store." },
|
|
5756
|
+
type: { type: "string", default: "code_fact" },
|
|
5757
|
+
importance: { type: "number", default: 3 },
|
|
5758
|
+
tags: { type: "array", items: { type: "string" } }
|
|
5759
|
+
},
|
|
5760
|
+
required: ["content"]
|
|
5761
|
+
},
|
|
5762
|
+
outputSchema: {
|
|
5763
|
+
type: "object",
|
|
5764
|
+
properties: { success: { type: "boolean" }, id: { type: "string" }, code: { type: "string" } }
|
|
5765
|
+
}
|
|
5766
|
+
},
|
|
5767
|
+
{
|
|
5768
|
+
name: "remember_facts",
|
|
5769
|
+
title: "Remember Facts (Upstream Bulk)",
|
|
5770
|
+
description: "Upstream-compatible alias for bulk memory-store. Stores multiple facts at once.",
|
|
5771
|
+
annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: false },
|
|
5772
|
+
inputSchema: {
|
|
5773
|
+
type: "object",
|
|
5774
|
+
properties: {
|
|
5775
|
+
owner: { type: "string" },
|
|
5776
|
+
repo: { type: "string" },
|
|
5777
|
+
facts: { type: "array", items: { type: "object" }, description: "Array of fact objects." }
|
|
5778
|
+
},
|
|
5779
|
+
required: ["facts"]
|
|
5780
|
+
},
|
|
5781
|
+
outputSchema: { type: "object", properties: { success: { type: "boolean" }, count: { type: "number" } } }
|
|
5782
|
+
},
|
|
5783
|
+
{
|
|
5784
|
+
name: "recall",
|
|
5785
|
+
title: "Recall (Upstream)",
|
|
5786
|
+
description: "Upstream-compatible alias for memory-search. Searches stored memories by query.",
|
|
5787
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
5788
|
+
inputSchema: {
|
|
5789
|
+
type: "object",
|
|
5790
|
+
properties: {
|
|
5791
|
+
owner: { type: "string" },
|
|
5792
|
+
repo: { type: "string" },
|
|
5793
|
+
query: { type: "string", description: "Search query." },
|
|
5794
|
+
type: { type: "string", description: "Filter by memory type." },
|
|
5795
|
+
limit: { type: "number", default: 10 }
|
|
5796
|
+
},
|
|
5797
|
+
required: ["query"]
|
|
5798
|
+
},
|
|
5799
|
+
outputSchema: { type: "object", properties: { memories: { type: "array", items: { type: "object" } } } }
|
|
5800
|
+
},
|
|
5801
|
+
{
|
|
5802
|
+
name: "forget",
|
|
5803
|
+
title: "Forget (Upstream)",
|
|
5804
|
+
description: "Upstream-compatible alias for memory-delete. Deletes a stored memory by id or code.",
|
|
5805
|
+
annotations: { readOnlyHint: false, idempotentHint: false, destructiveHint: true, openWorldHint: true },
|
|
5806
|
+
inputSchema: {
|
|
5807
|
+
type: "object",
|
|
5808
|
+
properties: {
|
|
5809
|
+
owner: { type: "string" },
|
|
5810
|
+
repo: { type: "string" },
|
|
5811
|
+
id: { type: "string", description: "Memory ID to delete." },
|
|
5812
|
+
code: { type: "string", description: "Memory code to delete." }
|
|
5813
|
+
},
|
|
5814
|
+
required: []
|
|
5815
|
+
},
|
|
5816
|
+
outputSchema: { type: "object", properties: { success: { type: "boolean" } } }
|
|
5817
|
+
}
|
|
5818
|
+
];
|
|
5819
|
+
|
|
5820
|
+
// src/mcp/tools/definitions/knowledge-graph.ts
|
|
5821
|
+
var KG_TOOL_DEFINITIONS = [
|
|
5822
|
+
{
|
|
5823
|
+
name: "create_entity",
|
|
5824
|
+
title: "KG Create Entity",
|
|
5825
|
+
description: "Creates a new knowledge graph entity. Entities represent nodes in the knowledge graph (e.g., concepts, people, systems). Name must be unique per repo. Owner and repo are auto-inferred from session when omitted.",
|
|
5826
|
+
annotations: {
|
|
5827
|
+
readOnlyHint: false,
|
|
5828
|
+
idempotentHint: false,
|
|
5829
|
+
destructiveHint: false,
|
|
5830
|
+
openWorldHint: false
|
|
5831
|
+
},
|
|
5832
|
+
inputSchema: {
|
|
5833
|
+
type: "object",
|
|
5834
|
+
properties: {
|
|
5835
|
+
name: {
|
|
5836
|
+
type: "string",
|
|
5837
|
+
description: "Unique entity name (acts as primary key per repo)."
|
|
5838
|
+
},
|
|
5839
|
+
type: {
|
|
5840
|
+
type: "string",
|
|
5841
|
+
default: "unknown",
|
|
5842
|
+
description: "Entity type for categorization (e.g., 'person', 'system', 'concept')."
|
|
5843
|
+
},
|
|
5844
|
+
description: {
|
|
5845
|
+
type: "string",
|
|
5846
|
+
description: "Optional description of the entity."
|
|
5847
|
+
},
|
|
5848
|
+
owner: {
|
|
5849
|
+
type: "string",
|
|
5850
|
+
description: "Organization/namespace. Auto-detected from session when omitted."
|
|
5851
|
+
},
|
|
5852
|
+
repo: {
|
|
5853
|
+
type: "string",
|
|
5854
|
+
description: "Repository/project name. Auto-detected from session when omitted."
|
|
5855
|
+
},
|
|
5856
|
+
structured: {
|
|
5857
|
+
type: "boolean",
|
|
5858
|
+
default: false,
|
|
5859
|
+
description: "If true, returns structured JSON results."
|
|
5860
|
+
}
|
|
5861
|
+
},
|
|
5862
|
+
required: ["name"]
|
|
5863
|
+
},
|
|
5864
|
+
outputSchema: {
|
|
5865
|
+
type: "object",
|
|
5866
|
+
properties: {
|
|
5867
|
+
success: { type: "boolean" },
|
|
5868
|
+
entity: {
|
|
5869
|
+
type: "object",
|
|
5870
|
+
properties: {
|
|
5871
|
+
name: { type: "string" },
|
|
5872
|
+
type: { type: "string" },
|
|
5873
|
+
description: { type: "string" },
|
|
5874
|
+
repo: { type: "string" },
|
|
5875
|
+
owner: { type: "string" }
|
|
5876
|
+
}
|
|
5877
|
+
}
|
|
5878
|
+
}
|
|
5879
|
+
}
|
|
5880
|
+
},
|
|
5881
|
+
{
|
|
5882
|
+
name: "delete_entity",
|
|
5883
|
+
title: "KG Delete Entity",
|
|
5884
|
+
description: "Deletes a knowledge graph entity by name. All related relations and observations are automatically removed via CASCADE. Owner and repo are auto-inferred from session when omitted.",
|
|
5885
|
+
annotations: {
|
|
5886
|
+
readOnlyHint: false,
|
|
5887
|
+
idempotentHint: false,
|
|
5888
|
+
destructiveHint: true,
|
|
5889
|
+
openWorldHint: false
|
|
5890
|
+
},
|
|
5891
|
+
inputSchema: {
|
|
5892
|
+
type: "object",
|
|
5893
|
+
properties: {
|
|
5894
|
+
name: {
|
|
5895
|
+
type: "string",
|
|
5896
|
+
description: "Name of the entity to delete."
|
|
5897
|
+
},
|
|
5898
|
+
owner: {
|
|
5899
|
+
type: "string",
|
|
5900
|
+
description: "Organization/namespace. Auto-detected from session when omitted."
|
|
5901
|
+
},
|
|
5902
|
+
repo: {
|
|
5903
|
+
type: "string",
|
|
5904
|
+
description: "Repository/project name. Auto-detected from session when omitted."
|
|
5905
|
+
},
|
|
5906
|
+
structured: {
|
|
5907
|
+
type: "boolean",
|
|
5908
|
+
default: false,
|
|
5909
|
+
description: "If true, returns structured JSON results."
|
|
5910
|
+
}
|
|
5911
|
+
},
|
|
5912
|
+
required: ["name"]
|
|
5913
|
+
},
|
|
5914
|
+
outputSchema: {
|
|
5915
|
+
type: "object",
|
|
5916
|
+
properties: {
|
|
5917
|
+
success: { type: "boolean" },
|
|
5918
|
+
deletedCount: { type: "number" }
|
|
5919
|
+
}
|
|
5920
|
+
}
|
|
5921
|
+
},
|
|
5922
|
+
{
|
|
5923
|
+
name: "create_relation",
|
|
5924
|
+
title: "KG Create Relation",
|
|
5925
|
+
description: "Creates a directed relation between two existing knowledge graph entities. Both from_entity and to_entity must already exist. The composite key (from_entity, to_entity, relation_type) must be unique. Owner and repo are auto-inferred from session when omitted.",
|
|
5926
|
+
annotations: {
|
|
5927
|
+
readOnlyHint: false,
|
|
5928
|
+
idempotentHint: false,
|
|
5929
|
+
destructiveHint: false,
|
|
5930
|
+
openWorldHint: false
|
|
5931
|
+
},
|
|
5932
|
+
inputSchema: {
|
|
5933
|
+
type: "object",
|
|
5934
|
+
properties: {
|
|
5935
|
+
from_entity: {
|
|
5936
|
+
type: "string",
|
|
5937
|
+
description: "Source entity name (must exist)."
|
|
5938
|
+
},
|
|
5939
|
+
to_entity: {
|
|
5940
|
+
type: "string",
|
|
5941
|
+
description: "Target entity name (must exist)."
|
|
5942
|
+
},
|
|
5943
|
+
relation_type: {
|
|
5944
|
+
type: "string",
|
|
5945
|
+
description: "Type of relation (e.g., 'depends_on', 'implements', 'part_of')."
|
|
5946
|
+
},
|
|
5947
|
+
owner: {
|
|
5948
|
+
type: "string",
|
|
5949
|
+
description: "Organization/namespace. Auto-detected from session when omitted."
|
|
5950
|
+
},
|
|
5951
|
+
repo: {
|
|
5952
|
+
type: "string",
|
|
5953
|
+
description: "Repository/project name. Auto-detected from session when omitted."
|
|
5954
|
+
},
|
|
5955
|
+
structured: {
|
|
5956
|
+
type: "boolean",
|
|
5957
|
+
default: false,
|
|
5958
|
+
description: "If true, returns structured JSON results."
|
|
5959
|
+
}
|
|
5960
|
+
},
|
|
5961
|
+
required: ["from_entity", "to_entity", "relation_type"]
|
|
5962
|
+
},
|
|
5963
|
+
outputSchema: {
|
|
5964
|
+
type: "object",
|
|
5965
|
+
properties: {
|
|
5966
|
+
success: { type: "boolean" },
|
|
5967
|
+
relation: {
|
|
5968
|
+
type: "object",
|
|
5969
|
+
properties: {
|
|
5970
|
+
from_entity: { type: "string" },
|
|
5971
|
+
to_entity: { type: "string" },
|
|
5972
|
+
relation_type: { type: "string" }
|
|
5973
|
+
}
|
|
5974
|
+
}
|
|
5975
|
+
}
|
|
5976
|
+
}
|
|
5977
|
+
},
|
|
5978
|
+
{
|
|
5979
|
+
name: "delete_relation",
|
|
5980
|
+
title: "KG Delete Relation",
|
|
5981
|
+
description: "Deletes a relation by its composite key (from_entity, to_entity, relation_type). Owner and repo are auto-inferred from session when omitted.",
|
|
5982
|
+
annotations: {
|
|
5983
|
+
readOnlyHint: false,
|
|
5984
|
+
idempotentHint: false,
|
|
5985
|
+
destructiveHint: true,
|
|
5986
|
+
openWorldHint: false
|
|
5987
|
+
},
|
|
5988
|
+
inputSchema: {
|
|
5989
|
+
type: "object",
|
|
5990
|
+
properties: {
|
|
5991
|
+
from_entity: {
|
|
5992
|
+
type: "string",
|
|
5993
|
+
description: "Source entity name."
|
|
5994
|
+
},
|
|
5995
|
+
to_entity: {
|
|
5996
|
+
type: "string",
|
|
5997
|
+
description: "Target entity name."
|
|
5998
|
+
},
|
|
5999
|
+
relation_type: {
|
|
6000
|
+
type: "string",
|
|
6001
|
+
description: "Relation type."
|
|
6002
|
+
},
|
|
6003
|
+
owner: {
|
|
6004
|
+
type: "string",
|
|
6005
|
+
description: "Organization/namespace. Auto-detected from session when omitted."
|
|
6006
|
+
},
|
|
6007
|
+
repo: {
|
|
6008
|
+
type: "string",
|
|
6009
|
+
description: "Repository/project name. Auto-detected from session when omitted."
|
|
6010
|
+
},
|
|
6011
|
+
structured: {
|
|
6012
|
+
type: "boolean",
|
|
6013
|
+
default: false,
|
|
6014
|
+
description: "If true, returns structured JSON results."
|
|
6015
|
+
}
|
|
6016
|
+
},
|
|
6017
|
+
required: ["from_entity", "to_entity", "relation_type"]
|
|
5487
6018
|
},
|
|
5488
6019
|
outputSchema: {
|
|
5489
6020
|
type: "object",
|
|
5490
6021
|
properties: {
|
|
5491
6022
|
success: { type: "boolean" },
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
},
|
|
5495
|
-
required: ["success", "id", "updatedFields"]
|
|
6023
|
+
deletedCount: { type: "number" }
|
|
6024
|
+
}
|
|
5496
6025
|
}
|
|
5497
6026
|
},
|
|
5498
6027
|
{
|
|
5499
|
-
name: "
|
|
5500
|
-
title: "
|
|
5501
|
-
description: "
|
|
6028
|
+
name: "delete_observation",
|
|
6029
|
+
title: "KG Delete Observation",
|
|
6030
|
+
description: "Deletes an observation by its ID. Observation IDs are UUIDs returned when observations are created. Owner and repo are auto-inferred from session when omitted.",
|
|
5502
6031
|
annotations: {
|
|
5503
|
-
readOnlyHint:
|
|
5504
|
-
idempotentHint:
|
|
6032
|
+
readOnlyHint: false,
|
|
6033
|
+
idempotentHint: false,
|
|
6034
|
+
destructiveHint: true,
|
|
5505
6035
|
openWorldHint: false
|
|
5506
6036
|
},
|
|
5507
6037
|
inputSchema: {
|
|
5508
6038
|
type: "object",
|
|
5509
6039
|
properties: {
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
items: { type: "string" },
|
|
5514
|
-
description: "Technology stack to filter by (e.g., ['react', 'nextjs'])"
|
|
6040
|
+
id: {
|
|
6041
|
+
type: "string",
|
|
6042
|
+
description: "UUID of the observation to delete."
|
|
5515
6043
|
},
|
|
5516
|
-
|
|
5517
|
-
type: "
|
|
5518
|
-
|
|
5519
|
-
description: "Tag filter"
|
|
6044
|
+
owner: {
|
|
6045
|
+
type: "string",
|
|
6046
|
+
description: "Organization/namespace. Auto-detected from session when omitted."
|
|
5520
6047
|
},
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
6048
|
+
repo: {
|
|
6049
|
+
type: "string",
|
|
6050
|
+
description: "Repository/project name. Auto-detected from session when omitted."
|
|
6051
|
+
},
|
|
6052
|
+
structured: {
|
|
6053
|
+
type: "boolean",
|
|
6054
|
+
default: false,
|
|
6055
|
+
description: "If true, returns structured JSON results."
|
|
6056
|
+
}
|
|
5529
6057
|
},
|
|
5530
|
-
required: []
|
|
6058
|
+
required: ["id"]
|
|
5531
6059
|
},
|
|
5532
6060
|
outputSchema: {
|
|
5533
6061
|
type: "object",
|
|
5534
6062
|
properties: {
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
total: { type: "number", description: "Total number of matches before pagination" },
|
|
5539
|
-
offset: { type: "number" },
|
|
5540
|
-
limit: { type: "number" },
|
|
5541
|
-
results: {
|
|
5542
|
-
type: "object",
|
|
5543
|
-
properties: {
|
|
5544
|
-
columns: {
|
|
5545
|
-
type: "array",
|
|
5546
|
-
items: { type: "string" }
|
|
5547
|
-
},
|
|
5548
|
-
rows: {
|
|
5549
|
-
type: "array",
|
|
5550
|
-
items: { type: "array" },
|
|
5551
|
-
description: "Each row includes standard id and pointer metadata. Fetch full content via standard-detail."
|
|
5552
|
-
}
|
|
5553
|
-
},
|
|
5554
|
-
required: ["columns", "rows"]
|
|
5555
|
-
}
|
|
5556
|
-
},
|
|
5557
|
-
required: ["schema", "query", "count", "total", "offset", "limit", "results"]
|
|
6063
|
+
success: { type: "boolean" },
|
|
6064
|
+
deletedCount: { type: "number" }
|
|
6065
|
+
}
|
|
5558
6066
|
}
|
|
5559
6067
|
}
|
|
5560
6068
|
];
|
|
5561
6069
|
|
|
6070
|
+
// src/mcp/tools/definitions/index.ts
|
|
6071
|
+
var TOOL_DEFINITIONS = [
|
|
6072
|
+
...MEMORY_TOOL_DEFINITIONS,
|
|
6073
|
+
...TASK_TOOL_DEFINITIONS,
|
|
6074
|
+
...HANDOFF_TOOL_DEFINITIONS,
|
|
6075
|
+
...STANDARD_TOOL_DEFINITIONS,
|
|
6076
|
+
...AGENT_TOOL_DEFINITIONS,
|
|
6077
|
+
...KG_TOOL_DEFINITIONS
|
|
6078
|
+
];
|
|
6079
|
+
|
|
6080
|
+
// src/mcp/utils/completion.ts
|
|
6081
|
+
var MAX_COMPLETION_VALUES = 100;
|
|
6082
|
+
function rankCompletionValues(candidates, input) {
|
|
6083
|
+
const unique = [...new Set(candidates.filter(Boolean))];
|
|
6084
|
+
const needle = input.trim().toLowerCase();
|
|
6085
|
+
if (!needle) {
|
|
6086
|
+
return unique.slice(0, MAX_COMPLETION_VALUES);
|
|
6087
|
+
}
|
|
6088
|
+
return unique.map((value) => ({ value, score: scoreCompletionValue(value, needle) })).filter((entry) => entry.score > 0).sort((a, b) => b.score - a.score || a.value.localeCompare(b.value)).map((entry) => entry.value);
|
|
6089
|
+
}
|
|
6090
|
+
function scoreCompletionValue(value, needle) {
|
|
6091
|
+
const haystack = value.toLowerCase();
|
|
6092
|
+
if (haystack === needle) return 100;
|
|
6093
|
+
if (haystack.startsWith(needle)) return 75;
|
|
6094
|
+
if (haystack.includes(needle)) return 50;
|
|
6095
|
+
const compactNeedle = needle.replace(/[\s_-]+/g, "");
|
|
6096
|
+
const compactHaystack = haystack.replace(/[\s_-]+/g, "");
|
|
6097
|
+
if (compactNeedle && compactHaystack.includes(compactNeedle)) return 25;
|
|
6098
|
+
return 0;
|
|
6099
|
+
}
|
|
6100
|
+
|
|
5562
6101
|
// src/mcp/utils/pagination.ts
|
|
5563
6102
|
function encodeCursor(offset) {
|
|
5564
6103
|
return Buffer.from(String(offset), "utf8").toString("base64");
|
|
@@ -5591,27 +6130,6 @@ function invalidPaginationParams(message) {
|
|
|
5591
6130
|
return error;
|
|
5592
6131
|
}
|
|
5593
6132
|
|
|
5594
|
-
// src/mcp/utils/completion.ts
|
|
5595
|
-
var MAX_COMPLETION_VALUES = 100;
|
|
5596
|
-
function rankCompletionValues(candidates, input) {
|
|
5597
|
-
const unique = [...new Set(candidates.filter(Boolean))];
|
|
5598
|
-
const needle = input.trim().toLowerCase();
|
|
5599
|
-
if (!needle) {
|
|
5600
|
-
return unique.slice(0, MAX_COMPLETION_VALUES);
|
|
5601
|
-
}
|
|
5602
|
-
return unique.map((value) => ({ value, score: scoreCompletionValue(value, needle) })).filter((entry) => entry.score > 0).sort((a, b) => b.score - a.score || a.value.localeCompare(b.value)).map((entry) => entry.value);
|
|
5603
|
-
}
|
|
5604
|
-
function scoreCompletionValue(value, needle) {
|
|
5605
|
-
const haystack = value.toLowerCase();
|
|
5606
|
-
if (haystack === needle) return 100;
|
|
5607
|
-
if (haystack.startsWith(needle)) return 75;
|
|
5608
|
-
if (haystack.includes(needle)) return 50;
|
|
5609
|
-
const compactNeedle = needle.replace(/[\s_-]+/g, "");
|
|
5610
|
-
const compactHaystack = haystack.replace(/[\s_-]+/g, "");
|
|
5611
|
-
if (compactNeedle && compactHaystack.includes(compactNeedle)) return 25;
|
|
5612
|
-
return 0;
|
|
5613
|
-
}
|
|
5614
|
-
|
|
5615
6133
|
// src/mcp/resources/index.ts
|
|
5616
6134
|
var DEFAULT_PAGE_SIZE = 25;
|
|
5617
6135
|
var MAX_PAGE_SIZE = 100;
|
|
@@ -5645,87 +6163,6 @@ function listResources(session, params) {
|
|
|
5645
6163
|
];
|
|
5646
6164
|
return paginateEntries("resources", resources, params);
|
|
5647
6165
|
}
|
|
5648
|
-
function listResourceTemplates(params) {
|
|
5649
|
-
const templates = [
|
|
5650
|
-
// ── Memory ──────────────────────────────────────────────────────────────
|
|
5651
|
-
{
|
|
5652
|
-
uriTemplate: "repository://{name}/memories",
|
|
5653
|
-
name: "Repository Memories",
|
|
5654
|
-
title: "Repository Memories",
|
|
5655
|
-
description: "All active memory entries for a specific repository",
|
|
5656
|
-
mimeType: "application/json",
|
|
5657
|
-
annotations: { audience: ["assistant"], priority: 0.85 }
|
|
5658
|
-
},
|
|
5659
|
-
{
|
|
5660
|
-
uriTemplate: "repository://{name}/memories?search={search}&type={type}&tag={tag}",
|
|
5661
|
-
name: "Filtered Repository Memories",
|
|
5662
|
-
title: "Filtered Repository Memories",
|
|
5663
|
-
description: "Filter or search memories within a repository by keyword, type, or tag",
|
|
5664
|
-
mimeType: "application/json",
|
|
5665
|
-
annotations: { audience: ["assistant"], priority: 0.8 }
|
|
5666
|
-
},
|
|
5667
|
-
{
|
|
5668
|
-
uriTemplate: "memory://{id}",
|
|
5669
|
-
name: "Memory Detail",
|
|
5670
|
-
title: "Memory Detail",
|
|
5671
|
-
description: "Full content and statistics for a specific memory UUID",
|
|
5672
|
-
mimeType: "application/json",
|
|
5673
|
-
annotations: { audience: ["assistant"], priority: 0.75 }
|
|
5674
|
-
},
|
|
5675
|
-
// ── Tasks ────────────────────────────────────────────────────────────────
|
|
5676
|
-
{
|
|
5677
|
-
uriTemplate: "repository://{name}/tasks",
|
|
5678
|
-
name: "Repository Tasks",
|
|
5679
|
-
title: "Repository Tasks",
|
|
5680
|
-
description: "All active tasks for a specific repository",
|
|
5681
|
-
mimeType: "application/json",
|
|
5682
|
-
annotations: { audience: ["assistant"], priority: 0.9 }
|
|
5683
|
-
},
|
|
5684
|
-
{
|
|
5685
|
-
uriTemplate: "repository://{name}/tasks?status={status}&priority={priority}",
|
|
5686
|
-
name: "Filtered Repository Tasks",
|
|
5687
|
-
title: "Filtered Repository Tasks",
|
|
5688
|
-
description: "Filter tasks within a repository by status or priority level",
|
|
5689
|
-
mimeType: "application/json",
|
|
5690
|
-
annotations: { audience: ["assistant"], priority: 0.85 }
|
|
5691
|
-
},
|
|
5692
|
-
{
|
|
5693
|
-
uriTemplate: "task://{id}",
|
|
5694
|
-
name: "Task Detail",
|
|
5695
|
-
title: "Task Detail",
|
|
5696
|
-
description: "Full content and comments for a specific task UUID",
|
|
5697
|
-
mimeType: "application/json",
|
|
5698
|
-
annotations: { audience: ["assistant"], priority: 0.8 }
|
|
5699
|
-
},
|
|
5700
|
-
// ── Repository extras ────────────────────────────────────────────────────
|
|
5701
|
-
{
|
|
5702
|
-
uriTemplate: "repository://{name}/summary",
|
|
5703
|
-
name: "Repository Summary",
|
|
5704
|
-
title: "Repository Summary",
|
|
5705
|
-
description: "High-level architectural summary for a repository",
|
|
5706
|
-
mimeType: "text/plain",
|
|
5707
|
-
annotations: { audience: ["assistant"], priority: 0.95 }
|
|
5708
|
-
},
|
|
5709
|
-
{
|
|
5710
|
-
uriTemplate: "repository://{name}/actions",
|
|
5711
|
-
name: "Repository Actions",
|
|
5712
|
-
title: "Repository Actions",
|
|
5713
|
-
description: "Audit log of agent tool actions scoped to a repository",
|
|
5714
|
-
mimeType: "application/json",
|
|
5715
|
-
annotations: { audience: ["assistant"], priority: 0.6 }
|
|
5716
|
-
},
|
|
5717
|
-
// ── Action detail ────────────────────────────────────────────────────────
|
|
5718
|
-
{
|
|
5719
|
-
uriTemplate: "action://{id}",
|
|
5720
|
-
name: "Action Detail",
|
|
5721
|
-
title: "Action Detail",
|
|
5722
|
-
description: "Full details of a specific audit log entry by integer ID",
|
|
5723
|
-
mimeType: "application/json",
|
|
5724
|
-
annotations: { audience: ["assistant"], priority: 0.55 }
|
|
5725
|
-
}
|
|
5726
|
-
];
|
|
5727
|
-
return paginateEntries("resourceTemplates", templates, params);
|
|
5728
|
-
}
|
|
5729
6166
|
function completeResourceArgument(resourceUri, argumentName, argumentValue, _contextArguments, dataSources) {
|
|
5730
6167
|
if (resourceUri === "repository://{name}/memories" || resourceUri === "repository://{name}/memories?search={search}&type={type}&tag={tag}" || resourceUri === "repository://{name}/tasks" || resourceUri === "repository://{name}/tasks?status={status}&priority={priority}" || resourceUri === "repository://{name}/summary" || resourceUri === "repository://{name}/actions") {
|
|
5731
6168
|
if (argumentName === "name") {
|
|
@@ -5739,234 +6176,6 @@ function completeResourceArgument(resourceUri, argumentName, argumentValue, _con
|
|
|
5739
6176
|
}
|
|
5740
6177
|
throw invalidCompletionParams(`Unknown resource template or argument: ${resourceUri} (${argumentName})`);
|
|
5741
6178
|
}
|
|
5742
|
-
function readResource(uri, db, session) {
|
|
5743
|
-
logger.info("[Tool] resource.read", { uri });
|
|
5744
|
-
if (uri === "repository://index") {
|
|
5745
|
-
const repos = db.system.listRepoNavigation();
|
|
5746
|
-
const payload = JSON.stringify(repos, null, 2);
|
|
5747
|
-
return {
|
|
5748
|
-
contents: [
|
|
5749
|
-
{
|
|
5750
|
-
uri,
|
|
5751
|
-
mimeType: "application/json",
|
|
5752
|
-
text: payload,
|
|
5753
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
5754
|
-
annotations: {
|
|
5755
|
-
audience: ["assistant"],
|
|
5756
|
-
priority: 1,
|
|
5757
|
-
lastModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
5758
|
-
}
|
|
5759
|
-
}
|
|
5760
|
-
]
|
|
5761
|
-
};
|
|
5762
|
-
}
|
|
5763
|
-
if (uri === "session://roots") {
|
|
5764
|
-
const payload = JSON.stringify({ roots: session?.roots ?? [] }, null, 2);
|
|
5765
|
-
return {
|
|
5766
|
-
contents: [
|
|
5767
|
-
{
|
|
5768
|
-
uri,
|
|
5769
|
-
mimeType: "application/json",
|
|
5770
|
-
text: payload,
|
|
5771
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
5772
|
-
annotations: {
|
|
5773
|
-
audience: ["assistant"],
|
|
5774
|
-
priority: 0.95,
|
|
5775
|
-
lastModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
5776
|
-
}
|
|
5777
|
-
}
|
|
5778
|
-
]
|
|
5779
|
-
};
|
|
5780
|
-
}
|
|
5781
|
-
const memoryIdMatch = uri.match(/^memory:\/\/([0-9a-f-]{36})$/i);
|
|
5782
|
-
if (memoryIdMatch) {
|
|
5783
|
-
const id = memoryIdMatch[1];
|
|
5784
|
-
const entry = db.memories.getByIdWithStats(id);
|
|
5785
|
-
if (!entry) throw resourceNotFound(`Memory with ID ${id} not found.`, uri);
|
|
5786
|
-
const payload = JSON.stringify(entry, null, 2);
|
|
5787
|
-
return {
|
|
5788
|
-
contents: [
|
|
5789
|
-
{
|
|
5790
|
-
uri,
|
|
5791
|
-
mimeType: "application/json",
|
|
5792
|
-
text: payload,
|
|
5793
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
5794
|
-
annotations: {
|
|
5795
|
-
audience: ["assistant"],
|
|
5796
|
-
priority: 0.75,
|
|
5797
|
-
lastModified: entry.updated_at || entry.created_at
|
|
5798
|
-
}
|
|
5799
|
-
}
|
|
5800
|
-
]
|
|
5801
|
-
};
|
|
5802
|
-
}
|
|
5803
|
-
const taskIdMatch = uri.match(/^task:\/\/([0-9a-f-]{36})$/i);
|
|
5804
|
-
if (taskIdMatch) {
|
|
5805
|
-
const id = taskIdMatch[1];
|
|
5806
|
-
const task = db.tasks.getTaskById(id);
|
|
5807
|
-
if (!task) throw resourceNotFound(`Task with ID ${id} not found.`, uri);
|
|
5808
|
-
const payload = JSON.stringify(task, null, 2);
|
|
5809
|
-
return {
|
|
5810
|
-
contents: [
|
|
5811
|
-
{
|
|
5812
|
-
uri,
|
|
5813
|
-
mimeType: "application/json",
|
|
5814
|
-
text: payload,
|
|
5815
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
5816
|
-
annotations: {
|
|
5817
|
-
audience: ["assistant"],
|
|
5818
|
-
priority: 0.8,
|
|
5819
|
-
lastModified: task.updated_at || task.created_at
|
|
5820
|
-
}
|
|
5821
|
-
}
|
|
5822
|
-
]
|
|
5823
|
-
};
|
|
5824
|
-
}
|
|
5825
|
-
const repoBase = parseRepoUri(uri);
|
|
5826
|
-
if (repoBase) {
|
|
5827
|
-
const { name, path: repoPath, query } = repoBase;
|
|
5828
|
-
if (repoPath === "summary") {
|
|
5829
|
-
const summary = db.summaries.getSummary("", name);
|
|
5830
|
-
const text = summary?.summary || `No summary available for repository: ${name}`;
|
|
5831
|
-
return {
|
|
5832
|
-
contents: [
|
|
5833
|
-
{
|
|
5834
|
-
uri,
|
|
5835
|
-
mimeType: "text/plain",
|
|
5836
|
-
text,
|
|
5837
|
-
size: Buffer.byteLength(text, "utf8"),
|
|
5838
|
-
annotations: {
|
|
5839
|
-
audience: ["assistant"],
|
|
5840
|
-
priority: 0.95,
|
|
5841
|
-
lastModified: summary?.updated_at || (/* @__PURE__ */ new Date()).toISOString()
|
|
5842
|
-
}
|
|
5843
|
-
}
|
|
5844
|
-
]
|
|
5845
|
-
};
|
|
5846
|
-
}
|
|
5847
|
-
if (repoPath === "memories") {
|
|
5848
|
-
const search = query.get("search") || "";
|
|
5849
|
-
const type = query.get("type");
|
|
5850
|
-
const tag = query.get("tag");
|
|
5851
|
-
const result = db.memories.listMemoriesForDashboard({
|
|
5852
|
-
repo: name,
|
|
5853
|
-
type: type || void 0,
|
|
5854
|
-
tag: tag || void 0,
|
|
5855
|
-
search: search || void 0,
|
|
5856
|
-
limit: 50
|
|
5857
|
-
});
|
|
5858
|
-
const entries = result.items;
|
|
5859
|
-
const payload = JSON.stringify(entries, null, 2);
|
|
5860
|
-
return {
|
|
5861
|
-
contents: [
|
|
5862
|
-
{
|
|
5863
|
-
uri,
|
|
5864
|
-
mimeType: "application/json",
|
|
5865
|
-
text: payload,
|
|
5866
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
5867
|
-
annotations: {
|
|
5868
|
-
audience: ["assistant"],
|
|
5869
|
-
priority: 0.85,
|
|
5870
|
-
lastModified: deriveLastModifiedFromCollection(
|
|
5871
|
-
entries.map((e) => e.updated_at || e.created_at)
|
|
5872
|
-
)
|
|
5873
|
-
}
|
|
5874
|
-
}
|
|
5875
|
-
]
|
|
5876
|
-
};
|
|
5877
|
-
}
|
|
5878
|
-
if (repoPath === "tasks") {
|
|
5879
|
-
const status = query.get("status");
|
|
5880
|
-
const priority = query.get("priority");
|
|
5881
|
-
const owner = parseRepoInput(name).owner;
|
|
5882
|
-
let tasks;
|
|
5883
|
-
if (status && status !== "all") {
|
|
5884
|
-
const statuses = status.split(",").map((s) => s.trim());
|
|
5885
|
-
tasks = db.tasks.getTasksByMultipleStatuses(owner, name, statuses);
|
|
5886
|
-
} else {
|
|
5887
|
-
tasks = db.tasks.getTasksByMultipleStatuses(owner, name, ["backlog", "pending", "in_progress", "blocked"]);
|
|
5888
|
-
}
|
|
5889
|
-
if (priority) {
|
|
5890
|
-
const p = Number(priority);
|
|
5891
|
-
if (!isNaN(p)) {
|
|
5892
|
-
tasks = tasks.filter((t) => t.priority === p);
|
|
5893
|
-
}
|
|
5894
|
-
}
|
|
5895
|
-
const payload = JSON.stringify(tasks, null, 2);
|
|
5896
|
-
return {
|
|
5897
|
-
contents: [
|
|
5898
|
-
{
|
|
5899
|
-
uri,
|
|
5900
|
-
mimeType: "application/json",
|
|
5901
|
-
text: payload,
|
|
5902
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
5903
|
-
annotations: {
|
|
5904
|
-
audience: ["assistant"],
|
|
5905
|
-
priority: 0.9,
|
|
5906
|
-
lastModified: deriveLastModifiedFromCollection(tasks.map((t) => t.updated_at))
|
|
5907
|
-
}
|
|
5908
|
-
}
|
|
5909
|
-
]
|
|
5910
|
-
};
|
|
5911
|
-
}
|
|
5912
|
-
if (repoPath === "actions") {
|
|
5913
|
-
const actions = db.actions.getRecentActions("", name, 100);
|
|
5914
|
-
const payload = JSON.stringify(actions, null, 2);
|
|
5915
|
-
return {
|
|
5916
|
-
contents: [
|
|
5917
|
-
{
|
|
5918
|
-
uri,
|
|
5919
|
-
mimeType: "application/json",
|
|
5920
|
-
text: payload,
|
|
5921
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
5922
|
-
annotations: {
|
|
5923
|
-
audience: ["assistant"],
|
|
5924
|
-
priority: 0.6,
|
|
5925
|
-
lastModified: deriveLastModifiedFromCollection(actions.map((a) => a.created_at))
|
|
5926
|
-
}
|
|
5927
|
-
}
|
|
5928
|
-
]
|
|
5929
|
-
};
|
|
5930
|
-
}
|
|
5931
|
-
}
|
|
5932
|
-
const actionIdMatch = uri.match(/^action:\/\/(\d+)$/);
|
|
5933
|
-
if (actionIdMatch) {
|
|
5934
|
-
const id = Number(actionIdMatch[1]);
|
|
5935
|
-
const action = db.actions.getActionById(id);
|
|
5936
|
-
if (!action) throw resourceNotFound(`Action with ID ${id} not found.`, uri);
|
|
5937
|
-
const payload = JSON.stringify(action, null, 2);
|
|
5938
|
-
return {
|
|
5939
|
-
contents: [
|
|
5940
|
-
{
|
|
5941
|
-
uri,
|
|
5942
|
-
mimeType: "application/json",
|
|
5943
|
-
text: payload,
|
|
5944
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
5945
|
-
annotations: {
|
|
5946
|
-
audience: ["assistant"],
|
|
5947
|
-
priority: 0.55,
|
|
5948
|
-
lastModified: action.created_at
|
|
5949
|
-
}
|
|
5950
|
-
}
|
|
5951
|
-
]
|
|
5952
|
-
};
|
|
5953
|
-
}
|
|
5954
|
-
throw resourceNotFound(`Unknown resource URI: ${uri}`, uri);
|
|
5955
|
-
}
|
|
5956
|
-
function parseRepoUri(uri) {
|
|
5957
|
-
const prefix = "repository://";
|
|
5958
|
-
if (!uri.startsWith(prefix)) return null;
|
|
5959
|
-
const rest = uri.slice(prefix.length);
|
|
5960
|
-
const queryStart = rest.indexOf("?");
|
|
5961
|
-
const withoutQuery = queryStart === -1 ? rest : rest.slice(0, queryStart);
|
|
5962
|
-
const queryString = queryStart === -1 ? "" : rest.slice(queryStart + 1);
|
|
5963
|
-
const slashIdx = withoutQuery.indexOf("/");
|
|
5964
|
-
if (slashIdx === -1) return null;
|
|
5965
|
-
const name = withoutQuery.slice(0, slashIdx);
|
|
5966
|
-
const path6 = withoutQuery.slice(slashIdx + 1);
|
|
5967
|
-
if (!name || !path6) return null;
|
|
5968
|
-
return { name, path: path6, query: new URLSearchParams(queryString) };
|
|
5969
|
-
}
|
|
5970
6179
|
function paginateEntries(key, entries, params) {
|
|
5971
6180
|
const limit = normalizeLimit(params?.limit);
|
|
5972
6181
|
const offset = decodeCursor(params?.cursor);
|
|
@@ -5983,16 +6192,6 @@ function normalizeLimit(limit) {
|
|
|
5983
6192
|
}
|
|
5984
6193
|
return Math.min(MAX_PAGE_SIZE, Math.max(1, Math.trunc(limit)));
|
|
5985
6194
|
}
|
|
5986
|
-
function deriveLastModifiedFromCollection(values) {
|
|
5987
|
-
const normalized = values.filter((value) => typeof value === "string" && value.length > 0);
|
|
5988
|
-
return normalized.sort().at(-1) ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
5989
|
-
}
|
|
5990
|
-
function resourceNotFound(message, uri) {
|
|
5991
|
-
const error = new Error(message);
|
|
5992
|
-
error.code = -32002;
|
|
5993
|
-
error.data = { uri };
|
|
5994
|
-
return error;
|
|
5995
|
-
}
|
|
5996
6195
|
function invalidCompletionParams(message) {
|
|
5997
6196
|
const error = new Error(message);
|
|
5998
6197
|
error.code = -32602;
|
|
@@ -6026,51 +6225,6 @@ for (const name of promptFiles) {
|
|
|
6026
6225
|
logger.warn(`Failed to load prompt ${name}: ${e}`);
|
|
6027
6226
|
}
|
|
6028
6227
|
}
|
|
6029
|
-
async function listPrompts(db, session, params) {
|
|
6030
|
-
const allPrompts = Object.values(PROMPTS).map((p) => ({
|
|
6031
|
-
name: p.name,
|
|
6032
|
-
description: p.description,
|
|
6033
|
-
arguments: p.arguments,
|
|
6034
|
-
metadata: p.agent ? { agent: p.agent } : void 0
|
|
6035
|
-
}));
|
|
6036
|
-
const rawLimit = typeof params?.limit === "number" && Number.isInteger(params?.limit) ? params.limit : 50;
|
|
6037
|
-
const limit = Math.max(1, Math.min(100, Math.trunc(rawLimit)));
|
|
6038
|
-
const offset = decodeCursor(params?.cursor);
|
|
6039
|
-
const sliced = allPrompts.slice(offset, offset + limit);
|
|
6040
|
-
const nextOffset = offset + sliced.length;
|
|
6041
|
-
return {
|
|
6042
|
-
prompts: sliced,
|
|
6043
|
-
nextCursor: nextOffset < allPrompts.length ? encodeCursor(nextOffset) : void 0
|
|
6044
|
-
};
|
|
6045
|
-
}
|
|
6046
|
-
async function getPrompt(name, args = {}, db, session) {
|
|
6047
|
-
const prompt = PROMPTS[name];
|
|
6048
|
-
if (!prompt) {
|
|
6049
|
-
throw new Error(`Prompt not found: ${name}`);
|
|
6050
|
-
}
|
|
6051
|
-
const inferredRepo = inferRepoFromSession(session);
|
|
6052
|
-
const inferredOwner = inferOwnerFromSession(session);
|
|
6053
|
-
const messages = prompt.messages.map((m) => {
|
|
6054
|
-
let text = m.content.text;
|
|
6055
|
-
for (const [key, value] of Object.entries(args)) {
|
|
6056
|
-
text = text.replace(new RegExp(`\\{{${key}\\}}`, "g"), value);
|
|
6057
|
-
}
|
|
6058
|
-
text = text.replace(/{{current_repo}}/g, inferredRepo || "unknown-repo");
|
|
6059
|
-
text = text.replace(/{{current_owner}}/g, inferredOwner || "unknown-owner");
|
|
6060
|
-
return {
|
|
6061
|
-
...m,
|
|
6062
|
-
content: {
|
|
6063
|
-
...m.content,
|
|
6064
|
-
text
|
|
6065
|
-
}
|
|
6066
|
-
};
|
|
6067
|
-
});
|
|
6068
|
-
return {
|
|
6069
|
-
description: prompt.description,
|
|
6070
|
-
messages,
|
|
6071
|
-
metadata: prompt.agent ? { agent: prompt.agent } : void 0
|
|
6072
|
-
};
|
|
6073
|
-
}
|
|
6074
6228
|
async function completePromptArgument(name, argName, value, contextArguments, dataSources) {
|
|
6075
6229
|
void name;
|
|
6076
6230
|
void contextArguments;
|
|
@@ -6216,7 +6370,7 @@ var SingleMemorySchema = z2.object({
|
|
|
6216
6370
|
ttlDays: z2.number().min(1).optional(),
|
|
6217
6371
|
supersedes: z2.string().optional(),
|
|
6218
6372
|
tags: z2.array(z2.string()).optional(),
|
|
6219
|
-
metadata: z2.record(z2.string(), z2.
|
|
6373
|
+
metadata: z2.record(z2.string(), z2.unknown()).optional(),
|
|
6220
6374
|
is_global: z2.boolean().default(false)
|
|
6221
6375
|
});
|
|
6222
6376
|
var SingleStandardSchema = z2.object({
|
|
@@ -6229,7 +6383,7 @@ var SingleStandardSchema = z2.object({
|
|
|
6229
6383
|
stack: z2.array(z2.string()).optional(),
|
|
6230
6384
|
is_global: z2.boolean().optional(),
|
|
6231
6385
|
tags: z2.array(z2.string().min(1)).min(1),
|
|
6232
|
-
metadata: z2.record(z2.string(), z2.
|
|
6386
|
+
metadata: z2.record(z2.string(), z2.unknown()).refine((value) => Object.keys(value).length > 0, {
|
|
6233
6387
|
message: "metadata must contain at least one key"
|
|
6234
6388
|
}),
|
|
6235
6389
|
agent: z2.string().optional(),
|
|
@@ -6252,7 +6406,7 @@ var MemoryStoreSchema = z3.object({
|
|
|
6252
6406
|
ttlDays: z3.number().min(1).optional(),
|
|
6253
6407
|
supersedes: z3.string().optional(),
|
|
6254
6408
|
tags: z3.array(z3.string()).optional(),
|
|
6255
|
-
metadata: z3.record(z3.string(), z3.
|
|
6409
|
+
metadata: z3.record(z3.string(), z3.unknown()).optional(),
|
|
6256
6410
|
is_global: z3.boolean().default(false),
|
|
6257
6411
|
structured: z3.boolean().default(false),
|
|
6258
6412
|
memories: z3.array(SingleMemorySchema).min(1).optional()
|
|
@@ -6279,7 +6433,7 @@ var MemoryUpdateSchema = z3.object({
|
|
|
6279
6433
|
status: z3.enum(["active", "archived"]).optional(),
|
|
6280
6434
|
supersedes: z3.string().optional(),
|
|
6281
6435
|
tags: z3.array(z3.string()).optional(),
|
|
6282
|
-
metadata: z3.record(z3.string(), z3.
|
|
6436
|
+
metadata: z3.record(z3.string(), z3.unknown()).optional(),
|
|
6283
6437
|
is_global: z3.boolean().optional(),
|
|
6284
6438
|
completed_at: z3.string().optional(),
|
|
6285
6439
|
structured: z3.boolean().default(false)
|
|
@@ -6367,7 +6521,7 @@ var MemorySynthesizeSchema = z3.object({
|
|
|
6367
6521
|
|
|
6368
6522
|
// src/mcp/tools/schemas/task.ts
|
|
6369
6523
|
import { z as z4 } from "zod";
|
|
6370
|
-
var TaskMetadataSchema = z4.record(z4.string(), z4.
|
|
6524
|
+
var TaskMetadataSchema = z4.record(z4.string(), z4.unknown()).optional().superRefine((metadata, ctx) => {
|
|
6371
6525
|
if (!metadata) return;
|
|
6372
6526
|
if (metadata.required_skills !== void 0) {
|
|
6373
6527
|
if (!Array.isArray(metadata.required_skills)) {
|
|
@@ -6453,7 +6607,7 @@ var TaskCreateSchema = z4.object({
|
|
|
6453
6607
|
doc_path: z4.string().optional(),
|
|
6454
6608
|
tags: z4.array(z4.string()).optional(),
|
|
6455
6609
|
suggested_skills: z4.array(z4.string()).optional(),
|
|
6456
|
-
metadata: z4.record(z4.string(), z4.
|
|
6610
|
+
metadata: z4.record(z4.string(), z4.unknown()).optional(),
|
|
6457
6611
|
parent_id: z4.string().optional(),
|
|
6458
6612
|
depends_on: z4.string().optional(),
|
|
6459
6613
|
est_tokens: z4.number().int().min(0).optional(),
|
|
@@ -6490,7 +6644,7 @@ var TaskUpdateSchema = z4.object({
|
|
|
6490
6644
|
comment: z4.string().min(1).optional(),
|
|
6491
6645
|
doc_path: z4.string().optional(),
|
|
6492
6646
|
tags: z4.array(z4.string()).optional(),
|
|
6493
|
-
metadata: z4.record(z4.string(), z4.
|
|
6647
|
+
metadata: z4.record(z4.string(), z4.unknown()).optional(),
|
|
6494
6648
|
suggested_skills: z4.array(z4.string()).optional(),
|
|
6495
6649
|
parent_id: z4.string().optional(),
|
|
6496
6650
|
depends_on: z4.string().optional(),
|
|
@@ -6559,7 +6713,7 @@ var HandoffCreateSchema = z5.object({
|
|
|
6559
6713
|
task_id: z5.string().uuid().optional(),
|
|
6560
6714
|
task_code: z5.string().optional(),
|
|
6561
6715
|
summary: z5.string().min(1),
|
|
6562
|
-
context: z5.record(z5.string(), z5.
|
|
6716
|
+
context: z5.record(z5.string(), z5.unknown()).optional(),
|
|
6563
6717
|
expires_at: z5.string().optional(),
|
|
6564
6718
|
structured: z5.boolean().default(false)
|
|
6565
6719
|
}).refine((data) => !(data.task_id && data.task_code), {
|
|
@@ -6592,7 +6746,7 @@ var TaskClaimSchema = z5.object({
|
|
|
6592
6746
|
task_code: z5.string().optional(),
|
|
6593
6747
|
agent: z5.string().min(1),
|
|
6594
6748
|
role: z5.string().optional(),
|
|
6595
|
-
metadata: z5.record(z5.string(), z5.
|
|
6749
|
+
metadata: z5.record(z5.string(), z5.unknown()).optional(),
|
|
6596
6750
|
structured: z5.boolean().default(false)
|
|
6597
6751
|
}).refine((data) => data.task_id !== void 0 || data.task_code !== void 0, {
|
|
6598
6752
|
message: "Either task_id or task_code must be provided"
|
|
@@ -6635,7 +6789,7 @@ var StandardStoreSchema = z6.object({
|
|
|
6635
6789
|
repo: z6.string().transform(normalizeRepo).optional(),
|
|
6636
6790
|
is_global: z6.boolean().optional(),
|
|
6637
6791
|
tags: z6.array(z6.string().min(1)).min(1).optional(),
|
|
6638
|
-
metadata: z6.record(z6.string(), z6.
|
|
6792
|
+
metadata: z6.record(z6.string(), z6.unknown()).refine((value) => Object.keys(value).length > 0, { message: "metadata must contain at least one key" }).optional(),
|
|
6639
6793
|
agent: z6.string().optional(),
|
|
6640
6794
|
model: z6.string().optional(),
|
|
6641
6795
|
structured: z6.boolean().default(false),
|
|
@@ -6663,7 +6817,7 @@ var StandardUpdateSchema = z6.object({
|
|
|
6663
6817
|
repo: z6.string().transform(normalizeRepo),
|
|
6664
6818
|
is_global: z6.boolean().optional(),
|
|
6665
6819
|
tags: z6.array(z6.string().min(1)).min(1).optional(),
|
|
6666
|
-
metadata: z6.record(z6.string(), z6.
|
|
6820
|
+
metadata: z6.record(z6.string(), z6.unknown()).refine((value) => Object.keys(value).length > 0, { message: "metadata must contain at least one key" }).optional(),
|
|
6667
6821
|
agent: z6.string().optional(),
|
|
6668
6822
|
model: z6.string().optional(),
|
|
6669
6823
|
structured: z6.boolean().default(false)
|
|
@@ -6713,6 +6867,75 @@ var StandardDetailSchema = z6.object({
|
|
|
6713
6867
|
message: "Either id or code must be provided"
|
|
6714
6868
|
});
|
|
6715
6869
|
|
|
6870
|
+
// src/mcp/tools/schemas/agent.ts
|
|
6871
|
+
import { z as z7 } from "zod";
|
|
6872
|
+
var AgentContextSchema = z7.object({
|
|
6873
|
+
owner: z7.string().min(1),
|
|
6874
|
+
repo: z7.string().min(1),
|
|
6875
|
+
objective: z7.string().optional(),
|
|
6876
|
+
type_filter: z7.enum(["code_fact", "decision", "mistake", "pattern", "task_archive"]).optional(),
|
|
6877
|
+
limit: z7.number().min(1).max(100).default(5),
|
|
6878
|
+
structured: z7.boolean().default(false)
|
|
6879
|
+
});
|
|
6880
|
+
var DecisionLogSchema = z7.object({
|
|
6881
|
+
summary: z7.string().min(3).max(255, { message: "Summary must be at most 255 characters" }),
|
|
6882
|
+
context: z7.string().min(10, { message: "Context must be at least 10 characters" }),
|
|
6883
|
+
rationale: z7.string().min(10, { message: "Rationale must be at least 10 characters" }),
|
|
6884
|
+
alternatives: z7.array(z7.string()).optional(),
|
|
6885
|
+
tags: z7.array(z7.string()).optional(),
|
|
6886
|
+
owner: z7.string().optional(),
|
|
6887
|
+
repo: z7.string().optional(),
|
|
6888
|
+
structured: z7.boolean().default(false)
|
|
6889
|
+
});
|
|
6890
|
+
var SessionSummarizeSchema = z7.object({
|
|
6891
|
+
summary: z7.string().min(10, { message: "Summary must be at least 10 characters" }),
|
|
6892
|
+
key_decisions: z7.array(z7.string()).optional(),
|
|
6893
|
+
next_steps: z7.array(z7.string()).optional(),
|
|
6894
|
+
tags: z7.array(z7.string()).optional(),
|
|
6895
|
+
owner: z7.string().optional(),
|
|
6896
|
+
repo: z7.string().optional(),
|
|
6897
|
+
structured: z7.boolean().default(false)
|
|
6898
|
+
});
|
|
6899
|
+
|
|
6900
|
+
// src/mcp/tools/schemas/knowledge-graph.ts
|
|
6901
|
+
import { z as z8 } from "zod";
|
|
6902
|
+
var CreateEntitySchema = z8.object({
|
|
6903
|
+
name: z8.string().min(1).max(255),
|
|
6904
|
+
type: z8.string().default("unknown"),
|
|
6905
|
+
description: z8.string().optional(),
|
|
6906
|
+
owner: z8.string().optional(),
|
|
6907
|
+
repo: z8.string().optional(),
|
|
6908
|
+
structured: z8.boolean().default(false)
|
|
6909
|
+
});
|
|
6910
|
+
var DeleteEntitySchema = z8.object({
|
|
6911
|
+
name: z8.string().min(1),
|
|
6912
|
+
owner: z8.string().optional(),
|
|
6913
|
+
repo: z8.string().optional(),
|
|
6914
|
+
structured: z8.boolean().default(false)
|
|
6915
|
+
});
|
|
6916
|
+
var CreateRelationSchema = z8.object({
|
|
6917
|
+
from_entity: z8.string().min(1),
|
|
6918
|
+
to_entity: z8.string().min(1),
|
|
6919
|
+
relation_type: z8.string().min(1),
|
|
6920
|
+
owner: z8.string().optional(),
|
|
6921
|
+
repo: z8.string().optional(),
|
|
6922
|
+
structured: z8.boolean().default(false)
|
|
6923
|
+
});
|
|
6924
|
+
var DeleteRelationSchema = z8.object({
|
|
6925
|
+
from_entity: z8.string().min(1),
|
|
6926
|
+
to_entity: z8.string().min(1),
|
|
6927
|
+
relation_type: z8.string().min(1),
|
|
6928
|
+
owner: z8.string().optional(),
|
|
6929
|
+
repo: z8.string().optional(),
|
|
6930
|
+
structured: z8.boolean().default(false)
|
|
6931
|
+
});
|
|
6932
|
+
var DeleteObservationSchema = z8.object({
|
|
6933
|
+
id: z8.string().min(1),
|
|
6934
|
+
owner: z8.string().optional(),
|
|
6935
|
+
repo: z8.string().optional(),
|
|
6936
|
+
structured: z8.boolean().default(false)
|
|
6937
|
+
});
|
|
6938
|
+
|
|
6716
6939
|
// src/mcp/tools/handoff.manage.ts
|
|
6717
6940
|
function buildHandoffListSummary(repo, count, status, fromAgent, toAgent) {
|
|
6718
6941
|
const parts = [`Found ${count} handoff${count === 1 ? "" : "s"} in repo "${repo}".`];
|
|
@@ -7013,37 +7236,27 @@ function buildStandardVectorText(standard) {
|
|
|
7013
7236
|
}
|
|
7014
7237
|
|
|
7015
7238
|
export {
|
|
7016
|
-
MCP_PROTOCOL_VERSION,
|
|
7017
|
-
CAPABILITIES,
|
|
7018
7239
|
logger,
|
|
7019
|
-
setLogLevel,
|
|
7020
|
-
getLogLevel,
|
|
7021
7240
|
addLogSink,
|
|
7022
|
-
LOG_LEVEL_VALUES,
|
|
7023
7241
|
createFileSink,
|
|
7024
7242
|
parseRepoInput,
|
|
7025
7243
|
normalizeRepo,
|
|
7026
7244
|
SQLiteStore,
|
|
7027
7245
|
RealVectorStore,
|
|
7028
7246
|
TOOL_DEFINITIONS,
|
|
7029
|
-
|
|
7030
|
-
decodeCursor,
|
|
7247
|
+
rankCompletionValues,
|
|
7031
7248
|
listResources,
|
|
7032
|
-
listResourceTemplates,
|
|
7033
7249
|
completeResourceArgument,
|
|
7034
|
-
readResource,
|
|
7035
7250
|
createSessionContext,
|
|
7036
|
-
updateSessionFromInitialize,
|
|
7037
|
-
updateSessionRoots,
|
|
7038
|
-
extractRootsFromResult,
|
|
7039
7251
|
getFilesystemRoots,
|
|
7040
7252
|
isPathWithinRoots,
|
|
7041
7253
|
findContainingRoot,
|
|
7042
7254
|
inferRepoFromSession,
|
|
7043
7255
|
inferOwnerFromSession,
|
|
7256
|
+
listPromptFiles,
|
|
7257
|
+
loadPromptFromMarkdown,
|
|
7258
|
+
loadServerInstructions,
|
|
7044
7259
|
PROMPTS,
|
|
7045
|
-
listPrompts,
|
|
7046
|
-
getPrompt,
|
|
7047
7260
|
completePromptArgument,
|
|
7048
7261
|
createMcpResponse,
|
|
7049
7262
|
getPrimaryTextContent,
|
|
@@ -7069,6 +7282,14 @@ export {
|
|
|
7069
7282
|
StandardSearchSchema,
|
|
7070
7283
|
StandardDeleteSchema,
|
|
7071
7284
|
StandardDetailSchema,
|
|
7285
|
+
AgentContextSchema,
|
|
7286
|
+
DecisionLogSchema,
|
|
7287
|
+
SessionSummarizeSchema,
|
|
7288
|
+
CreateEntitySchema,
|
|
7289
|
+
DeleteEntitySchema,
|
|
7290
|
+
CreateRelationSchema,
|
|
7291
|
+
DeleteRelationSchema,
|
|
7292
|
+
DeleteObservationSchema,
|
|
7072
7293
|
handleHandoffCreate,
|
|
7073
7294
|
handleHandoffList,
|
|
7074
7295
|
handleHandoffUpdate,
|