@vheins/local-memory-mcp 0.10.11 → 0.10.12
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/dist/{chunk-5ODTDJZP.js → chunk-WWVIDZ5P.js} +2049 -2036
- package/dist/dashboard/server.js +1 -1
- package/dist/mcp/server.js +2 -2
- package/dist/prompts/create-task.md +2 -2
- package/dist/prompts/review-and-audit.md +2 -2
- package/dist/prompts/review-and-post-issue.md +1 -1
- package/dist/prompts/session-planner.md +1 -1
- package/dist/prompts/task-memory-executor.md +1 -1
- package/package.json +1 -1
|
@@ -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.10.11") {
|
|
85
|
-
pkgVersion = "0.10.11";
|
|
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,
|
|
@@ -245,11 +119,11 @@ function addLogSink(sink) {
|
|
|
245
119
|
}
|
|
246
120
|
var LOG_LEVEL_VALUES = Object.keys(LEVELS);
|
|
247
121
|
function createFileSink(logDir, maxFiles = 5) {
|
|
248
|
-
|
|
249
|
-
const existing =
|
|
122
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
123
|
+
const existing = fs.readdirSync(logDir).filter((f) => f.startsWith("mcp-") && f.endsWith(".log")).sort();
|
|
250
124
|
while (existing.length >= maxFiles) {
|
|
251
125
|
try {
|
|
252
|
-
|
|
126
|
+
fs.unlinkSync(`${logDir}/${existing.shift()}`);
|
|
253
127
|
} catch {
|
|
254
128
|
}
|
|
255
129
|
}
|
|
@@ -259,16 +133,118 @@ function createFileSink(logDir, maxFiles = 5) {
|
|
|
259
133
|
const line = `${(/* @__PURE__ */ new Date()).toISOString()} [${payload.level.toUpperCase()}] [pid:${process.pid}] ${JSON.stringify(payload.data)}
|
|
260
134
|
`;
|
|
261
135
|
try {
|
|
262
|
-
|
|
136
|
+
fs.appendFileSync(logFile, line);
|
|
263
137
|
} catch {
|
|
264
138
|
}
|
|
265
139
|
};
|
|
266
140
|
}
|
|
267
141
|
|
|
142
|
+
// src/mcp/session.ts
|
|
143
|
+
import path from "path";
|
|
144
|
+
import { fileURLToPath } from "url";
|
|
145
|
+
function createSessionContext() {
|
|
146
|
+
return {
|
|
147
|
+
roots: [],
|
|
148
|
+
supportsRoots: false,
|
|
149
|
+
supportsSampling: false,
|
|
150
|
+
supportsSamplingTools: false,
|
|
151
|
+
supportsElicitation: false,
|
|
152
|
+
supportsElicitationForm: false,
|
|
153
|
+
supportsElicitationUrl: false
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function updateSessionFromInitialize(session, params) {
|
|
157
|
+
const capabilities = params?.capabilities || {};
|
|
158
|
+
session.clientInfo = params?.clientInfo;
|
|
159
|
+
session.clientCapabilities = capabilities;
|
|
160
|
+
session.supportsRoots = Boolean(capabilities.roots);
|
|
161
|
+
session.supportsSampling = Boolean(capabilities.sampling);
|
|
162
|
+
const sampling = capabilities.sampling;
|
|
163
|
+
session.supportsSamplingTools = Boolean(sampling?.tools);
|
|
164
|
+
session.supportsElicitation = Boolean(capabilities.elicitation);
|
|
165
|
+
session.supportsElicitationForm = supportsElicitationMode(capabilities.elicitation, "form");
|
|
166
|
+
session.supportsElicitationUrl = supportsElicitationMode(capabilities.elicitation, "url");
|
|
167
|
+
}
|
|
168
|
+
function supportsElicitationMode(capability, mode) {
|
|
169
|
+
if (!capability || typeof capability !== "object") {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
const cap = capability;
|
|
173
|
+
if (mode === "form") {
|
|
174
|
+
return Object.keys(cap).length === 0 || typeof cap.form === "object";
|
|
175
|
+
}
|
|
176
|
+
return typeof cap.url === "object";
|
|
177
|
+
}
|
|
178
|
+
function updateSessionRoots(session, roots) {
|
|
179
|
+
const normalized = normalizeRoots(roots);
|
|
180
|
+
const previous = JSON.stringify(session.roots);
|
|
181
|
+
const next = JSON.stringify(normalized);
|
|
182
|
+
session.roots = normalized;
|
|
183
|
+
return previous !== next;
|
|
184
|
+
}
|
|
185
|
+
function normalizeRoots(roots) {
|
|
186
|
+
if (!Array.isArray(roots)) return [];
|
|
187
|
+
const seen = /* @__PURE__ */ new Set();
|
|
188
|
+
const normalized = [];
|
|
189
|
+
for (const root of roots) {
|
|
190
|
+
if (!root || typeof root !== "object") continue;
|
|
191
|
+
const r = root;
|
|
192
|
+
const uri = typeof r.uri === "string" ? r.uri : void 0;
|
|
193
|
+
const name = typeof r.name === "string" ? r.name : void 0;
|
|
194
|
+
if (!uri || seen.has(uri)) continue;
|
|
195
|
+
seen.add(uri);
|
|
196
|
+
normalized.push({ uri, name });
|
|
197
|
+
}
|
|
198
|
+
return normalized;
|
|
199
|
+
}
|
|
200
|
+
function extractRootsFromResult(result) {
|
|
201
|
+
return normalizeRoots(result?.roots);
|
|
202
|
+
}
|
|
203
|
+
function getFilesystemRoots(session) {
|
|
204
|
+
if (!session) return [];
|
|
205
|
+
const resolved = [];
|
|
206
|
+
for (const root of session.roots) {
|
|
207
|
+
if (!root.uri.startsWith("file://")) continue;
|
|
208
|
+
try {
|
|
209
|
+
resolved.push(path.resolve(fileURLToPath(root.uri)));
|
|
210
|
+
} catch {
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return resolved;
|
|
214
|
+
}
|
|
215
|
+
function isPathWithinRoots(targetPath, session) {
|
|
216
|
+
const roots = getFilesystemRoots(session);
|
|
217
|
+
if (roots.length === 0) return true;
|
|
218
|
+
const normalizedTarget = path.resolve(targetPath);
|
|
219
|
+
return roots.some((rootPath) => {
|
|
220
|
+
const relative = path.relative(rootPath, normalizedTarget);
|
|
221
|
+
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
function findContainingRoot(targetPath, session) {
|
|
225
|
+
const roots = getFilesystemRoots(session);
|
|
226
|
+
if (roots.length === 0) return null;
|
|
227
|
+
const normalizedTarget = path.resolve(targetPath);
|
|
228
|
+
for (const rootPath of roots) {
|
|
229
|
+
const relative = path.relative(rootPath, normalizedTarget);
|
|
230
|
+
if (relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative)) {
|
|
231
|
+
return rootPath;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
function inferRepoFromSession(session) {
|
|
237
|
+
const roots = getFilesystemRoots(session);
|
|
238
|
+
if (roots.length === 1) {
|
|
239
|
+
return path.basename(roots[0]);
|
|
240
|
+
}
|
|
241
|
+
return void 0;
|
|
242
|
+
}
|
|
243
|
+
|
|
268
244
|
// src/mcp/storage/sqlite.ts
|
|
269
245
|
import Database from "better-sqlite3";
|
|
270
|
-
import
|
|
271
|
-
import
|
|
246
|
+
import path3 from "path";
|
|
247
|
+
import fs3 from "fs";
|
|
272
248
|
import os from "os";
|
|
273
249
|
|
|
274
250
|
// src/mcp/storage/migrations.ts
|
|
@@ -2760,8 +2736,8 @@ var HandoffEntity = class extends BaseEntity {
|
|
|
2760
2736
|
|
|
2761
2737
|
// src/mcp/storage/write-lock.ts
|
|
2762
2738
|
import lockfile from "proper-lockfile";
|
|
2763
|
-
import
|
|
2764
|
-
import
|
|
2739
|
+
import path2 from "path";
|
|
2740
|
+
import fs2 from "fs";
|
|
2765
2741
|
var LOCK_STALE_MS = 3e4;
|
|
2766
2742
|
var LOCK_RETRY_DELAY_MS = 200;
|
|
2767
2743
|
var LOCK_RETRY_COUNT = 250;
|
|
@@ -2770,9 +2746,9 @@ var WriteLock = class {
|
|
|
2770
2746
|
locked = false;
|
|
2771
2747
|
constructor(dbPath) {
|
|
2772
2748
|
this.lockTarget = dbPath;
|
|
2773
|
-
if (!
|
|
2774
|
-
|
|
2775
|
-
|
|
2749
|
+
if (!fs2.existsSync(dbPath)) {
|
|
2750
|
+
fs2.mkdirSync(path2.dirname(dbPath), { recursive: true });
|
|
2751
|
+
fs2.writeFileSync(dbPath, "");
|
|
2776
2752
|
}
|
|
2777
2753
|
}
|
|
2778
2754
|
/**
|
|
@@ -2824,13 +2800,13 @@ var WriteLock = class {
|
|
|
2824
2800
|
// src/mcp/storage/sqlite.ts
|
|
2825
2801
|
function resolveDbPath() {
|
|
2826
2802
|
if (process.env.MEMORY_DB_PATH) return process.env.MEMORY_DB_PATH;
|
|
2827
|
-
const standardConfigDir = process.platform === "win32" ?
|
|
2828
|
-
const standardPath =
|
|
2829
|
-
if (
|
|
2830
|
-
const legacyPath =
|
|
2831
|
-
if (
|
|
2832
|
-
const localCwdFile =
|
|
2833
|
-
if (
|
|
2803
|
+
const standardConfigDir = process.platform === "win32" ? path3.join(os.homedir(), ".local-memory-mcp") : process.platform === "darwin" ? path3.join(os.homedir(), "Library", "Application Support", "local-memory-mcp") : path3.join(os.homedir(), ".config", "local-memory-mcp");
|
|
2804
|
+
const standardPath = path3.join(standardConfigDir, "memory.db");
|
|
2805
|
+
if (fs3.existsSync(standardPath)) return standardPath;
|
|
2806
|
+
const legacyPath = path3.join(os.homedir(), ".config", "local-memory-mcp", "memory.db");
|
|
2807
|
+
if (fs3.existsSync(legacyPath)) return legacyPath;
|
|
2808
|
+
const localCwdFile = path3.join(process.cwd(), "storage", "memory.db");
|
|
2809
|
+
if (fs3.existsSync(localCwdFile)) return localCwdFile;
|
|
2834
2810
|
return standardPath;
|
|
2835
2811
|
}
|
|
2836
2812
|
var DB_PATH = resolveDbPath();
|
|
@@ -2849,9 +2825,9 @@ var SQLiteStore = class _SQLiteStore {
|
|
|
2849
2825
|
const finalPath = dbPath ?? DB_PATH;
|
|
2850
2826
|
this.dbPathInstance = finalPath;
|
|
2851
2827
|
if (finalPath !== ":memory:") {
|
|
2852
|
-
const dbDir =
|
|
2853
|
-
if (!
|
|
2854
|
-
|
|
2828
|
+
const dbDir = path3.dirname(finalPath);
|
|
2829
|
+
if (!fs3.existsSync(dbDir)) {
|
|
2830
|
+
fs3.mkdirSync(dbDir, { recursive: true });
|
|
2855
2831
|
}
|
|
2856
2832
|
}
|
|
2857
2833
|
this.db = new Database(finalPath);
|
|
@@ -2906,12 +2882,12 @@ var SQLiteStore = class _SQLiteStore {
|
|
|
2906
2882
|
*/
|
|
2907
2883
|
_attemptRecovery(dbPath) {
|
|
2908
2884
|
const backupPath = dbPath + ".backup";
|
|
2909
|
-
if (
|
|
2885
|
+
if (fs3.existsSync(backupPath)) {
|
|
2910
2886
|
logger.warn("[SQLiteStore] Attempting recovery from backup", { backupPath });
|
|
2911
2887
|
try {
|
|
2912
2888
|
const corruptPath = `${dbPath}.corrupt_${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").slice(0, 15)}`;
|
|
2913
|
-
|
|
2914
|
-
|
|
2889
|
+
fs3.copyFileSync(dbPath, corruptPath);
|
|
2890
|
+
fs3.copyFileSync(backupPath, dbPath);
|
|
2915
2891
|
logger.warn("[SQLiteStore] Recovery successful. Corrupt file saved to", { corruptPath });
|
|
2916
2892
|
} catch (err) {
|
|
2917
2893
|
logger.error("[SQLiteStore] Recovery failed", { error: String(err) });
|
|
@@ -2929,7 +2905,7 @@ var SQLiteStore = class _SQLiteStore {
|
|
|
2929
2905
|
try {
|
|
2930
2906
|
this.db.pragma("wal_checkpoint(PASSIVE)");
|
|
2931
2907
|
const backupPath = this.dbPathInstance + ".backup";
|
|
2932
|
-
|
|
2908
|
+
fs3.copyFileSync(this.dbPathInstance, backupPath);
|
|
2933
2909
|
} catch (err) {
|
|
2934
2910
|
logger.warn("[SQLiteStore] Backup failed", { error: String(err) });
|
|
2935
2911
|
}
|
|
@@ -3051,1128 +3027,1243 @@ var RealVectorStore = class {
|
|
|
3051
3027
|
}
|
|
3052
3028
|
};
|
|
3053
3029
|
|
|
3054
|
-
// src/mcp/
|
|
3055
|
-
import path5 from "path";
|
|
3030
|
+
// src/mcp/capabilities.ts
|
|
3056
3031
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3057
|
-
|
|
3032
|
+
import path5 from "path";
|
|
3033
|
+
|
|
3034
|
+
// src/mcp/prompts/loader.ts
|
|
3035
|
+
import fs4 from "fs";
|
|
3036
|
+
import path4 from "path";
|
|
3037
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3038
|
+
import matter from "gray-matter";
|
|
3039
|
+
var __filename = fileURLToPath2(import.meta.url);
|
|
3040
|
+
var __dirname = path4.dirname(__filename);
|
|
3041
|
+
function findPromptDir() {
|
|
3042
|
+
const candidates = [
|
|
3043
|
+
// Production if chunked into dist/
|
|
3044
|
+
"./prompts",
|
|
3045
|
+
// Production if inlined into dist/mcp/
|
|
3046
|
+
"../prompts",
|
|
3047
|
+
// Dev: /src/mcp/prompts/definitions (next to loader.ts)
|
|
3048
|
+
"./definitions"
|
|
3049
|
+
].map((relPath) => path4.resolve(__dirname, relPath));
|
|
3050
|
+
for (const dir of candidates) {
|
|
3051
|
+
if (fs4.existsSync(dir)) {
|
|
3052
|
+
const files = fs4.readdirSync(dir);
|
|
3053
|
+
if (files.some((f) => f.endsWith(".md"))) {
|
|
3054
|
+
return dir;
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
return path4.resolve(__dirname, "./definitions");
|
|
3059
|
+
}
|
|
3060
|
+
var PROMPT_DIR = findPromptDir();
|
|
3061
|
+
function listPromptFiles() {
|
|
3062
|
+
if (!fs4.existsSync(PROMPT_DIR)) return [];
|
|
3063
|
+
return fs4.readdirSync(PROMPT_DIR).filter((file) => file.endsWith(".md")).map((file) => file.replace(/\.md$/, "")).sort();
|
|
3064
|
+
}
|
|
3065
|
+
function loadPromptFromMarkdown(name) {
|
|
3066
|
+
const filePath = path4.join(PROMPT_DIR, `${name}.md`);
|
|
3067
|
+
if (!fs4.existsSync(filePath)) {
|
|
3068
|
+
throw new Error(`Prompt file not found: ${filePath}`);
|
|
3069
|
+
}
|
|
3070
|
+
const fileContent = fs4.readFileSync(filePath, "utf-8");
|
|
3071
|
+
const { data, content } = matter(fileContent);
|
|
3058
3072
|
return {
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
supportsElicitationForm: false,
|
|
3065
|
-
supportsElicitationUrl: false
|
|
3073
|
+
name: data.name || name,
|
|
3074
|
+
description: data.description || "",
|
|
3075
|
+
arguments: data.arguments || [],
|
|
3076
|
+
agent: data.agent,
|
|
3077
|
+
content: content.trim()
|
|
3066
3078
|
};
|
|
3067
3079
|
}
|
|
3068
|
-
function
|
|
3069
|
-
const
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
const cap = capability;
|
|
3085
|
-
if (mode === "form") {
|
|
3086
|
-
return Object.keys(cap).length === 0 || typeof cap.form === "object";
|
|
3080
|
+
function findServerInstructionsDir() {
|
|
3081
|
+
const candidates = [
|
|
3082
|
+
// Production if chunked into dist/
|
|
3083
|
+
"./prompts/server",
|
|
3084
|
+
// Production if inlined into dist/mcp/
|
|
3085
|
+
"../prompts/server",
|
|
3086
|
+
// Dev: /src/mcp/prompts/server (next to loader.ts)
|
|
3087
|
+
"./server"
|
|
3088
|
+
].map((relPath) => path4.resolve(__dirname, relPath));
|
|
3089
|
+
for (const dir of candidates) {
|
|
3090
|
+
if (fs4.existsSync(dir)) {
|
|
3091
|
+
const filePath = path4.join(dir, "instructions.md");
|
|
3092
|
+
if (fs4.existsSync(filePath)) {
|
|
3093
|
+
return dir;
|
|
3094
|
+
}
|
|
3095
|
+
}
|
|
3087
3096
|
}
|
|
3088
|
-
return
|
|
3089
|
-
}
|
|
3090
|
-
function updateSessionRoots(session, roots) {
|
|
3091
|
-
const normalized = normalizeRoots(roots);
|
|
3092
|
-
const previous = JSON.stringify(session.roots);
|
|
3093
|
-
const next = JSON.stringify(normalized);
|
|
3094
|
-
session.roots = normalized;
|
|
3095
|
-
return previous !== next;
|
|
3097
|
+
return path4.resolve(__dirname, "./server");
|
|
3096
3098
|
}
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
const
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
if (!root || typeof root !== "object") continue;
|
|
3103
|
-
const r = root;
|
|
3104
|
-
const uri = typeof r.uri === "string" ? r.uri : void 0;
|
|
3105
|
-
const name = typeof r.name === "string" ? r.name : void 0;
|
|
3106
|
-
if (!uri || seen.has(uri)) continue;
|
|
3107
|
-
seen.add(uri);
|
|
3108
|
-
normalized.push({ uri, name });
|
|
3099
|
+
var SERVER_DIR = findServerInstructionsDir();
|
|
3100
|
+
function loadServerInstructions() {
|
|
3101
|
+
const filePath = path4.join(SERVER_DIR, "instructions.md");
|
|
3102
|
+
if (!fs4.existsSync(filePath)) {
|
|
3103
|
+
throw new Error(`Server instructions file not found: ${filePath}`);
|
|
3109
3104
|
}
|
|
3110
|
-
|
|
3111
|
-
}
|
|
3112
|
-
|
|
3113
|
-
return normalizeRoots(result?.roots);
|
|
3105
|
+
const fileContent = fs4.readFileSync(filePath, "utf-8");
|
|
3106
|
+
const { content } = matter(fileContent);
|
|
3107
|
+
return content.trim();
|
|
3114
3108
|
}
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3109
|
+
|
|
3110
|
+
// src/mcp/capabilities.ts
|
|
3111
|
+
var __dirname2 = path5.dirname(fileURLToPath3(import.meta.url));
|
|
3112
|
+
var pkgVersion = "0.1.0";
|
|
3113
|
+
if ("0.10.12") {
|
|
3114
|
+
pkgVersion = "0.10.12";
|
|
3115
|
+
} else {
|
|
3116
|
+
let searchDir = __dirname2;
|
|
3117
|
+
for (let i = 0; i < 5; i++) {
|
|
3118
|
+
const candidate = path5.join(searchDir, "package.json");
|
|
3120
3119
|
try {
|
|
3121
|
-
|
|
3120
|
+
if (fs.existsSync(candidate)) {
|
|
3121
|
+
const pkg = JSON.parse(fs.readFileSync(candidate, "utf8"));
|
|
3122
|
+
if (pkg.name === "@vheins/local-memory-mcp" && pkg.version) {
|
|
3123
|
+
pkgVersion = pkg.version;
|
|
3124
|
+
break;
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
3122
3127
|
} catch {
|
|
3123
3128
|
}
|
|
3129
|
+
searchDir = path5.dirname(searchDir);
|
|
3124
3130
|
}
|
|
3125
|
-
return resolved;
|
|
3126
|
-
}
|
|
3127
|
-
function isPathWithinRoots(targetPath, session) {
|
|
3128
|
-
const roots = getFilesystemRoots(session);
|
|
3129
|
-
if (roots.length === 0) return true;
|
|
3130
|
-
const normalizedTarget = path5.resolve(targetPath);
|
|
3131
|
-
return roots.some((rootPath) => {
|
|
3132
|
-
const relative = path5.relative(rootPath, normalizedTarget);
|
|
3133
|
-
return relative === "" || !relative.startsWith("..") && !path5.isAbsolute(relative);
|
|
3134
|
-
});
|
|
3135
3131
|
}
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3132
|
+
var MCP_PROTOCOL_VERSION = "2025-03-26";
|
|
3133
|
+
var SERVER_INSTRUCTIONS = loadServerInstructions();
|
|
3134
|
+
var CAPABILITIES = {
|
|
3135
|
+
serverInfo: {
|
|
3136
|
+
name: "local-memory-mcp",
|
|
3137
|
+
version: pkgVersion,
|
|
3138
|
+
instructions: SERVER_INSTRUCTIONS
|
|
3139
|
+
},
|
|
3140
|
+
capabilities: {
|
|
3141
|
+
completions: {},
|
|
3142
|
+
logging: {},
|
|
3143
|
+
resources: {
|
|
3144
|
+
subscribe: true,
|
|
3145
|
+
listChanged: true
|
|
3146
|
+
},
|
|
3147
|
+
tools: {
|
|
3148
|
+
listChanged: false
|
|
3149
|
+
},
|
|
3150
|
+
prompts: {
|
|
3151
|
+
listChanged: true
|
|
3144
3152
|
}
|
|
3145
3153
|
}
|
|
3146
|
-
|
|
3154
|
+
};
|
|
3155
|
+
|
|
3156
|
+
// src/mcp/utils/pagination.ts
|
|
3157
|
+
function encodeCursor(offset) {
|
|
3158
|
+
return Buffer.from(String(offset), "utf8").toString("base64");
|
|
3147
3159
|
}
|
|
3148
|
-
function
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
return path5.basename(roots[0]);
|
|
3160
|
+
function decodeCursor(cursor) {
|
|
3161
|
+
if (cursor === void 0 || cursor === null || cursor === "") {
|
|
3162
|
+
return 0;
|
|
3152
3163
|
}
|
|
3153
|
-
|
|
3164
|
+
if (typeof cursor !== "string" || cursor.trim() === "") {
|
|
3165
|
+
throw invalidPaginationParams("Invalid cursor");
|
|
3166
|
+
}
|
|
3167
|
+
let decoded;
|
|
3168
|
+
try {
|
|
3169
|
+
decoded = Buffer.from(cursor, "base64").toString("utf8");
|
|
3170
|
+
} catch {
|
|
3171
|
+
throw invalidPaginationParams("Invalid cursor");
|
|
3172
|
+
}
|
|
3173
|
+
if (!/^\d+$/.test(decoded)) {
|
|
3174
|
+
throw invalidPaginationParams("Invalid cursor");
|
|
3175
|
+
}
|
|
3176
|
+
const offset = Number.parseInt(decoded, 10);
|
|
3177
|
+
if (!Number.isFinite(offset) || offset < 0) {
|
|
3178
|
+
throw invalidPaginationParams("Invalid cursor");
|
|
3179
|
+
}
|
|
3180
|
+
return offset;
|
|
3181
|
+
}
|
|
3182
|
+
function invalidPaginationParams(message) {
|
|
3183
|
+
const error = new Error(message);
|
|
3184
|
+
error.code = -32602;
|
|
3185
|
+
return error;
|
|
3154
3186
|
}
|
|
3155
3187
|
|
|
3156
|
-
// src/mcp/
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
});
|
|
3164
|
-
var MemoryTypeSchema = z.enum(["code_fact", "decision", "mistake", "pattern", "task_archive"]);
|
|
3165
|
-
var MemoryStoreSchema = z.object({
|
|
3166
|
-
code: z.string().max(20).optional(),
|
|
3167
|
-
type: MemoryTypeSchema,
|
|
3168
|
-
title: z.string().min(3).max(255),
|
|
3169
|
-
content: z.string().min(10),
|
|
3170
|
-
importance: z.number().min(1).max(5),
|
|
3171
|
-
agent: z.string().min(1),
|
|
3172
|
-
role: z.string().optional().default("unknown"),
|
|
3173
|
-
model: z.string().min(1),
|
|
3174
|
-
scope: MemoryScopeSchema,
|
|
3175
|
-
ttlDays: z.number().min(1).optional(),
|
|
3176
|
-
supersedes: z.string().uuid().optional(),
|
|
3177
|
-
tags: z.array(z.string()).optional(),
|
|
3178
|
-
metadata: z.record(z.string(), z.any()).optional(),
|
|
3179
|
-
is_global: z.boolean().default(false),
|
|
3180
|
-
structured: z.boolean().default(false)
|
|
3181
|
-
});
|
|
3182
|
-
var MemoryUpdateSchema = z.object({
|
|
3183
|
-
id: z.string().uuid(),
|
|
3184
|
-
type: MemoryTypeSchema.optional(),
|
|
3185
|
-
title: z.string().min(3).max(255).optional(),
|
|
3186
|
-
content: z.string().min(10).optional(),
|
|
3187
|
-
importance: z.number().min(1).max(5).optional(),
|
|
3188
|
-
agent: z.string().optional(),
|
|
3189
|
-
role: z.string().optional(),
|
|
3190
|
-
status: z.enum(["active", "archived"]).optional(),
|
|
3191
|
-
supersedes: z.string().uuid().optional(),
|
|
3192
|
-
tags: z.array(z.string()).optional(),
|
|
3193
|
-
metadata: z.record(z.string(), z.any()).optional(),
|
|
3194
|
-
is_global: z.boolean().optional(),
|
|
3195
|
-
completed_at: z.string().optional(),
|
|
3196
|
-
structured: z.boolean().default(false)
|
|
3197
|
-
}).refine(
|
|
3198
|
-
(data) => data.type !== void 0 || data.content !== void 0 || data.title !== void 0 || data.importance !== void 0 || data.status !== void 0 || data.supersedes !== void 0 || data.tags !== void 0 || data.metadata !== void 0 || data.is_global !== void 0 || data.agent !== void 0 || data.role !== void 0 || data.completed_at !== void 0,
|
|
3199
|
-
{ message: "At least one field must be provided for update" }
|
|
3200
|
-
);
|
|
3201
|
-
var MemorySearchSchema = z.object({
|
|
3202
|
-
query: z.string().min(3),
|
|
3203
|
-
prompt: z.string().optional(),
|
|
3204
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3205
|
-
types: z.array(MemoryTypeSchema).optional(),
|
|
3206
|
-
minImportance: z.number().min(1).max(5).optional(),
|
|
3207
|
-
limit: z.number().min(1).max(100).default(5),
|
|
3208
|
-
offset: z.number().min(0).default(0),
|
|
3209
|
-
includeRecap: z.boolean().default(false),
|
|
3210
|
-
current_file_path: z.string().optional(),
|
|
3211
|
-
include_archived: z.boolean().default(false),
|
|
3212
|
-
current_tags: z.array(z.string()).optional(),
|
|
3213
|
-
scope: MemoryScopeSchema.partial().optional(),
|
|
3214
|
-
structured: z.boolean().default(false)
|
|
3215
|
-
});
|
|
3216
|
-
var MemoryAcknowledgeSchema = z.object({
|
|
3217
|
-
memory_id: z.string().uuid(),
|
|
3218
|
-
status: z.enum(["used", "irrelevant", "contradictory"]),
|
|
3219
|
-
application_context: z.string().min(10).optional(),
|
|
3220
|
-
structured: z.boolean().default(false)
|
|
3221
|
-
});
|
|
3222
|
-
var MemoryRecapSchema = z.object({
|
|
3223
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3224
|
-
limit: z.number().min(1).max(50).default(20),
|
|
3225
|
-
offset: z.number().min(0).default(0),
|
|
3226
|
-
structured: z.boolean().default(false)
|
|
3227
|
-
});
|
|
3228
|
-
var MemoryDeleteSchema = z.object({
|
|
3229
|
-
repo: z.string().min(1).transform(normalizeRepo).optional(),
|
|
3230
|
-
id: z.string().uuid().optional(),
|
|
3231
|
-
ids: z.array(z.string().uuid()).min(1).optional(),
|
|
3232
|
-
structured: z.boolean().default(false)
|
|
3233
|
-
}).refine((data) => data.id !== void 0 || data.ids !== void 0, {
|
|
3234
|
-
message: "Either 'id' or 'ids' must be provided for deletion"
|
|
3235
|
-
});
|
|
3236
|
-
var MemorySummarizeSchema = z.object({
|
|
3237
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3238
|
-
signals: z.array(z.string().max(200)).min(1),
|
|
3239
|
-
structured: z.boolean().default(false)
|
|
3240
|
-
});
|
|
3241
|
-
var MemorySynthesizeSchema = z.object({
|
|
3242
|
-
repo: z.string().min(1).transform(normalizeRepo).optional(),
|
|
3243
|
-
objective: z.string().min(5),
|
|
3244
|
-
current_file_path: z.string().optional(),
|
|
3245
|
-
include_summary: z.boolean().default(true),
|
|
3246
|
-
include_tasks: z.boolean().default(true),
|
|
3247
|
-
use_tools: z.boolean().default(true),
|
|
3248
|
-
max_iterations: z.number().int().min(1).max(5).default(3),
|
|
3249
|
-
max_tokens: z.number().int().min(128).max(4e3).default(1200),
|
|
3250
|
-
structured: z.boolean().default(false)
|
|
3251
|
-
});
|
|
3252
|
-
var TaskStatusSchema = z.enum(["backlog", "pending", "in_progress", "completed", "canceled", "blocked"]);
|
|
3253
|
-
var TaskPrioritySchema = z.number().min(1).max(5);
|
|
3254
|
-
var SingleTaskCreateSchema = z.object({
|
|
3255
|
-
task_code: z.string().min(1),
|
|
3256
|
-
phase: z.string().min(1),
|
|
3257
|
-
title: z.string().min(3).max(100),
|
|
3258
|
-
description: z.string().min(1),
|
|
3259
|
-
status: TaskStatusSchema.default("backlog"),
|
|
3260
|
-
priority: TaskPrioritySchema.default(3),
|
|
3261
|
-
agent: z.string().optional(),
|
|
3262
|
-
role: z.string().optional(),
|
|
3263
|
-
doc_path: z.string().optional(),
|
|
3264
|
-
tags: z.array(z.string()).optional(),
|
|
3265
|
-
metadata: z.record(z.string(), z.any()).optional(),
|
|
3266
|
-
parent_id: z.string().optional(),
|
|
3267
|
-
depends_on: z.string().uuid().optional(),
|
|
3268
|
-
est_tokens: z.number().int().min(0).optional()
|
|
3269
|
-
});
|
|
3270
|
-
var TaskCreateSchema = z.object({
|
|
3271
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3272
|
-
// Allow single task fields at top level (backward compatibility & single use)
|
|
3273
|
-
task_code: z.string().min(1).optional(),
|
|
3274
|
-
phase: z.string().min(1).optional(),
|
|
3275
|
-
title: z.string().min(3).max(100).optional(),
|
|
3276
|
-
description: z.string().min(1).optional(),
|
|
3277
|
-
status: TaskStatusSchema.optional(),
|
|
3278
|
-
priority: TaskPrioritySchema.optional(),
|
|
3279
|
-
agent: z.string().optional(),
|
|
3280
|
-
role: z.string().optional(),
|
|
3281
|
-
doc_path: z.string().optional(),
|
|
3282
|
-
tags: z.array(z.string()).optional(),
|
|
3283
|
-
metadata: z.record(z.string(), z.any()).optional(),
|
|
3284
|
-
parent_id: z.string().optional(),
|
|
3285
|
-
depends_on: z.string().uuid().optional(),
|
|
3286
|
-
est_tokens: z.number().int().min(0).optional(),
|
|
3287
|
-
// Allow bulk tasks
|
|
3288
|
-
tasks: z.array(SingleTaskCreateSchema).min(1).optional(),
|
|
3289
|
-
structured: z.boolean().default(false)
|
|
3290
|
-
}).refine(
|
|
3291
|
-
(data) => {
|
|
3292
|
-
if (data.tasks) return true;
|
|
3293
|
-
return !!(data.task_code && data.phase && data.title && data.description);
|
|
3294
|
-
},
|
|
3295
|
-
{ message: "Either 'tasks' array or single task fields (task_code, phase, title, description) must be provided" }
|
|
3296
|
-
);
|
|
3297
|
-
var TaskCreateInteractiveSchema = SingleTaskCreateSchema.partial().extend({
|
|
3298
|
-
repo: z.string().min(1).transform(normalizeRepo).optional(),
|
|
3299
|
-
structured: z.boolean().default(false)
|
|
3300
|
-
});
|
|
3301
|
-
var TaskUpdateSchema = z.object({
|
|
3302
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3303
|
-
id: z.string().uuid().optional(),
|
|
3304
|
-
ids: z.array(z.string().uuid()).min(1).optional(),
|
|
3305
|
-
task_code: z.string().optional(),
|
|
3306
|
-
phase: z.string().optional(),
|
|
3307
|
-
title: z.string().min(3).max(100).optional(),
|
|
3308
|
-
description: z.string().optional(),
|
|
3309
|
-
status: TaskStatusSchema.optional(),
|
|
3310
|
-
priority: TaskPrioritySchema.optional(),
|
|
3311
|
-
agent: z.string().min(1, "agent name is required").optional(),
|
|
3312
|
-
role: z.string().min(1, "agent role is required").optional(),
|
|
3313
|
-
model: z.string().optional(),
|
|
3314
|
-
comment: z.string().min(1).optional(),
|
|
3315
|
-
doc_path: z.string().optional(),
|
|
3316
|
-
tags: z.array(z.string()).optional(),
|
|
3317
|
-
metadata: z.record(z.string(), z.any()).optional(),
|
|
3318
|
-
parent_id: z.string().optional(),
|
|
3319
|
-
depends_on: z.string().uuid().optional(),
|
|
3320
|
-
est_tokens: z.number().int().min(0).optional(),
|
|
3321
|
-
force: z.boolean().optional(),
|
|
3322
|
-
structured: z.boolean().default(false)
|
|
3323
|
-
}).refine((data) => data.id !== void 0 || data.ids !== void 0 || data.task_code !== void 0, {
|
|
3324
|
-
message: "Either 'id', 'ids', or 'task_code' must be provided for update"
|
|
3325
|
-
}).refine((data) => Object.keys(data).length > 2, {
|
|
3326
|
-
message: "At least one field besides repo and id/ids must be provided for update"
|
|
3327
|
-
});
|
|
3328
|
-
var TaskListSchema = z.object({
|
|
3329
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3330
|
-
status: z.string().optional(),
|
|
3331
|
-
phase: z.string().optional(),
|
|
3332
|
-
query: z.string().optional(),
|
|
3333
|
-
limit: z.number().min(1).max(100).default(15),
|
|
3334
|
-
offset: z.number().min(0).default(0),
|
|
3335
|
-
structured: z.boolean().default(false)
|
|
3336
|
-
});
|
|
3337
|
-
var TaskSearchSchema = z.object({
|
|
3338
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3339
|
-
query: z.string().min(1),
|
|
3340
|
-
status: z.string().optional(),
|
|
3341
|
-
limit: z.number().min(1).max(100).default(10),
|
|
3342
|
-
offset: z.number().min(0).default(0),
|
|
3343
|
-
structured: z.boolean().default(false)
|
|
3344
|
-
});
|
|
3345
|
-
var TaskDeleteSchema = z.object({
|
|
3346
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3347
|
-
id: z.string().uuid().optional(),
|
|
3348
|
-
ids: z.array(z.string().uuid()).min(1).optional(),
|
|
3349
|
-
structured: z.boolean().default(false)
|
|
3350
|
-
}).refine((data) => data.id !== void 0 || data.ids !== void 0, {
|
|
3351
|
-
message: "Either 'id' or 'ids' must be provided for deletion"
|
|
3352
|
-
});
|
|
3353
|
-
var MemoryDetailSchema = z.object({
|
|
3354
|
-
id: z.string().uuid().optional(),
|
|
3355
|
-
code: z.string().max(20).optional(),
|
|
3356
|
-
structured: z.boolean().default(false)
|
|
3357
|
-
}).refine((data) => data.id !== void 0 || data.code !== void 0, {
|
|
3358
|
-
message: "Either id or code must be provided"
|
|
3359
|
-
});
|
|
3360
|
-
var StandardDetailSchema = z.object({
|
|
3361
|
-
id: z.string().uuid().optional(),
|
|
3362
|
-
code: z.string().max(20).optional(),
|
|
3363
|
-
structured: z.boolean().default(false)
|
|
3364
|
-
}).refine((data) => data.id !== void 0 || data.code !== void 0, {
|
|
3365
|
-
message: "Either id or code must be provided"
|
|
3366
|
-
});
|
|
3367
|
-
var StandardDeleteSchema = z.object({
|
|
3368
|
-
repo: z.string().min(1).transform(normalizeRepo).optional(),
|
|
3369
|
-
id: z.string().uuid().optional(),
|
|
3370
|
-
ids: z.array(z.string().uuid()).min(1).optional(),
|
|
3371
|
-
structured: z.boolean().default(false)
|
|
3372
|
-
}).refine((data) => data.id !== void 0 || data.ids !== void 0, {
|
|
3373
|
-
message: "Either 'id' or 'ids' must be provided for deletion"
|
|
3374
|
-
});
|
|
3375
|
-
var TaskGetSchema = z.object({
|
|
3376
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3377
|
-
id: z.string().uuid().optional(),
|
|
3378
|
-
task_code: z.string().optional(),
|
|
3379
|
-
structured: z.boolean().default(false)
|
|
3380
|
-
}).refine((data) => data.id !== void 0 || data.task_code !== void 0, {
|
|
3381
|
-
message: "Either id or task_code must be provided"
|
|
3382
|
-
});
|
|
3383
|
-
var HandoffStatusSchema = z.enum(["pending", "accepted", "rejected", "expired"]);
|
|
3384
|
-
var HandoffCreateSchema = z.object({
|
|
3385
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3386
|
-
from_agent: z.string().min(1),
|
|
3387
|
-
to_agent: z.string().min(1).optional(),
|
|
3388
|
-
task_id: z.string().uuid().optional(),
|
|
3389
|
-
task_code: z.string().optional(),
|
|
3390
|
-
summary: z.string().min(1),
|
|
3391
|
-
context: z.record(z.string(), z.any()).optional(),
|
|
3392
|
-
expires_at: z.string().optional(),
|
|
3393
|
-
structured: z.boolean().default(false)
|
|
3394
|
-
}).refine((data) => !(data.task_id && data.task_code), {
|
|
3395
|
-
message: "Provide either task_id or task_code, not both"
|
|
3396
|
-
}).refine(
|
|
3397
|
-
(data) => data.to_agent || data.task_id || data.task_code || data.context?.next_steps || data.context?.blockers || data.context?.remaining_work,
|
|
3398
|
-
{
|
|
3399
|
-
message: "Handoffs must identify a target agent, linked task, next_steps, blockers, or remaining_work. Do not create pending handoffs for completed-work summaries."
|
|
3188
|
+
// src/mcp/utils/completion.ts
|
|
3189
|
+
var MAX_COMPLETION_VALUES = 100;
|
|
3190
|
+
function rankCompletionValues(candidates, input) {
|
|
3191
|
+
const unique = [...new Set(candidates.filter(Boolean))];
|
|
3192
|
+
const needle = input.trim().toLowerCase();
|
|
3193
|
+
if (!needle) {
|
|
3194
|
+
return unique.slice(0, MAX_COMPLETION_VALUES);
|
|
3400
3195
|
}
|
|
3401
|
-
);
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
var
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3431
|
-
agent: z.string().min(1).optional(),
|
|
3432
|
-
active_only: z.boolean().default(true),
|
|
3433
|
-
limit: z.number().min(1).max(100).default(20),
|
|
3434
|
-
offset: z.number().min(0).default(0),
|
|
3435
|
-
structured: z.boolean().default(false)
|
|
3436
|
-
});
|
|
3437
|
-
var ClaimReleaseSchema = z.object({
|
|
3438
|
-
repo: z.string().min(1).transform(normalizeRepo),
|
|
3439
|
-
task_id: z.string().uuid().optional(),
|
|
3440
|
-
task_code: z.string().optional(),
|
|
3441
|
-
agent: z.string().min(1).optional(),
|
|
3442
|
-
structured: z.boolean().default(false)
|
|
3443
|
-
}).refine((data) => data.task_id !== void 0 || data.task_code !== void 0, {
|
|
3444
|
-
message: "Either task_id or task_code must be provided"
|
|
3445
|
-
}).refine((data) => !(data.task_id && data.task_code), {
|
|
3446
|
-
message: "Provide either task_id or task_code, not both"
|
|
3447
|
-
});
|
|
3448
|
-
var StandardStoreSchema = z.object({
|
|
3449
|
-
name: z.string().min(3).max(255),
|
|
3450
|
-
content: z.string().min(10),
|
|
3451
|
-
parent_id: z.string().uuid().optional(),
|
|
3452
|
-
context: z.string().optional(),
|
|
3453
|
-
version: z.string().optional(),
|
|
3454
|
-
language: z.string().optional(),
|
|
3455
|
-
stack: z.array(z.string()).optional(),
|
|
3456
|
-
repo: z.string().transform(normalizeRepo).optional(),
|
|
3457
|
-
is_global: z.boolean().optional(),
|
|
3458
|
-
tags: z.array(z.string().min(1)).min(1),
|
|
3459
|
-
metadata: z.record(z.string(), z.any()).refine((value) => Object.keys(value).length > 0, {
|
|
3460
|
-
message: "metadata must contain at least one key"
|
|
3461
|
-
}),
|
|
3462
|
-
agent: z.string().optional(),
|
|
3463
|
-
model: z.string().optional(),
|
|
3464
|
-
structured: z.boolean().default(false)
|
|
3465
|
-
}).refine((data) => data.is_global !== false || !!data.repo, {
|
|
3466
|
-
message: "repo is required for repo-specific standards"
|
|
3467
|
-
});
|
|
3468
|
-
var StandardUpdateSchema = z.object({
|
|
3469
|
-
id: z.string().uuid(),
|
|
3470
|
-
name: z.string().min(3).max(255).optional(),
|
|
3471
|
-
content: z.string().min(10).optional(),
|
|
3472
|
-
parent_id: z.string().uuid().nullable().optional(),
|
|
3473
|
-
context: z.string().optional(),
|
|
3474
|
-
version: z.string().optional(),
|
|
3475
|
-
language: z.string().optional(),
|
|
3476
|
-
stack: z.array(z.string().min(1)).min(1).optional(),
|
|
3477
|
-
repo: z.string().transform(normalizeRepo).optional(),
|
|
3478
|
-
is_global: z.boolean().optional(),
|
|
3479
|
-
tags: z.array(z.string().min(1)).min(1).optional(),
|
|
3480
|
-
metadata: z.record(z.string(), z.any()).refine((value) => Object.keys(value).length > 0, { message: "metadata must contain at least one key" }).optional(),
|
|
3481
|
-
agent: z.string().optional(),
|
|
3482
|
-
model: z.string().optional(),
|
|
3483
|
-
structured: z.boolean().default(false)
|
|
3484
|
-
}).refine(
|
|
3485
|
-
(data) => data.name !== void 0 || data.content !== void 0 || data.parent_id !== void 0 || data.context !== void 0 || data.version !== void 0 || data.language !== void 0 || data.stack !== void 0 || data.repo !== void 0 || data.is_global !== void 0 || data.tags !== void 0 || data.metadata !== void 0 || data.agent !== void 0 || data.model !== void 0,
|
|
3486
|
-
{ message: "At least one field must be provided for update" }
|
|
3487
|
-
).refine((data) => data.is_global !== false || !!data.repo, {
|
|
3488
|
-
message: "repo is required for repo-specific standards"
|
|
3489
|
-
});
|
|
3490
|
-
var StandardSearchSchema = z.object({
|
|
3491
|
-
query: z.string().optional(),
|
|
3492
|
-
stack: z.array(z.string()).optional(),
|
|
3493
|
-
tags: z.array(z.string()).optional(),
|
|
3494
|
-
language: z.string().optional(),
|
|
3495
|
-
context: z.string().optional(),
|
|
3496
|
-
version: z.string().optional(),
|
|
3497
|
-
repo: z.string().transform(normalizeRepo).optional(),
|
|
3498
|
-
is_global: z.boolean().optional(),
|
|
3499
|
-
limit: z.number().min(1).max(100).default(20),
|
|
3500
|
-
offset: z.number().min(0).default(0),
|
|
3501
|
-
structured: z.boolean().default(false)
|
|
3502
|
-
});
|
|
3503
|
-
var TOOL_DEFINITIONS = [
|
|
3504
|
-
{
|
|
3505
|
-
name: "memory-synthesize",
|
|
3506
|
-
title: "Memory Synthesize",
|
|
3507
|
-
description: "Use client sampling to synthesize a grounded answer from local memory and tasks. Best for project briefings, tradeoff summaries, and context-aware answers.",
|
|
3508
|
-
annotations: {
|
|
3509
|
-
readOnlyHint: true,
|
|
3510
|
-
idempotentHint: true,
|
|
3511
|
-
openWorldHint: false
|
|
3196
|
+
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);
|
|
3197
|
+
}
|
|
3198
|
+
function scoreCompletionValue(value, needle) {
|
|
3199
|
+
const haystack = value.toLowerCase();
|
|
3200
|
+
if (haystack === needle) return 100;
|
|
3201
|
+
if (haystack.startsWith(needle)) return 75;
|
|
3202
|
+
if (haystack.includes(needle)) return 50;
|
|
3203
|
+
const compactNeedle = needle.replace(/[\s_-]+/g, "");
|
|
3204
|
+
const compactHaystack = haystack.replace(/[\s_-]+/g, "");
|
|
3205
|
+
if (compactNeedle && compactHaystack.includes(compactNeedle)) return 25;
|
|
3206
|
+
return 0;
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
// src/mcp/resources/index.ts
|
|
3210
|
+
var DEFAULT_PAGE_SIZE = 25;
|
|
3211
|
+
var MAX_PAGE_SIZE = 100;
|
|
3212
|
+
function listResources(session, params) {
|
|
3213
|
+
const resources = [
|
|
3214
|
+
{
|
|
3215
|
+
uri: "repository://index",
|
|
3216
|
+
name: "Repository Index",
|
|
3217
|
+
title: "Repository Index",
|
|
3218
|
+
description: "List of all known repositories with memory/task counts and last activity",
|
|
3219
|
+
mimeType: "application/json",
|
|
3220
|
+
annotations: {
|
|
3221
|
+
audience: ["assistant"],
|
|
3222
|
+
priority: 1,
|
|
3223
|
+
lastModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
3224
|
+
}
|
|
3512
3225
|
},
|
|
3513
|
-
|
|
3514
|
-
|
|
3226
|
+
{
|
|
3227
|
+
uri: "session://roots",
|
|
3228
|
+
name: "Session Roots",
|
|
3229
|
+
title: "Session Roots",
|
|
3230
|
+
description: session?.roots.length ? "Active workspace roots provided by the MCP client" : "No active workspace roots were provided by the MCP client",
|
|
3231
|
+
mimeType: "application/json",
|
|
3232
|
+
size: Buffer.byteLength(JSON.stringify({ roots: session?.roots ?? [] }), "utf8"),
|
|
3233
|
+
annotations: {
|
|
3234
|
+
audience: ["assistant"],
|
|
3235
|
+
priority: 0.95,
|
|
3236
|
+
lastModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
];
|
|
3240
|
+
return paginateEntries("resources", resources, params);
|
|
3241
|
+
}
|
|
3242
|
+
function listResourceTemplates(params) {
|
|
3243
|
+
const templates = [
|
|
3244
|
+
// ── Memory ──────────────────────────────────────────────────────────────
|
|
3245
|
+
{
|
|
3246
|
+
uriTemplate: "repository://{name}/memories",
|
|
3247
|
+
name: "Repository Memories",
|
|
3248
|
+
title: "Repository Memories",
|
|
3249
|
+
description: "All active memory entries for a specific repository",
|
|
3250
|
+
mimeType: "application/json",
|
|
3251
|
+
annotations: { audience: ["assistant"], priority: 0.85 }
|
|
3515
3252
|
},
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
description: "Optional absolute file path for workspace-local grounding."
|
|
3524
|
-
},
|
|
3525
|
-
include_summary: { type: "boolean", default: true },
|
|
3526
|
-
include_tasks: { type: "boolean", default: true },
|
|
3527
|
-
use_tools: {
|
|
3528
|
-
type: "boolean",
|
|
3529
|
-
default: true,
|
|
3530
|
-
description: "Allow the sampled model to call local memory/task tools during synthesis when the client supports sampling.tools."
|
|
3531
|
-
},
|
|
3532
|
-
max_iterations: { type: "number", minimum: 1, maximum: 5, default: 3 },
|
|
3533
|
-
max_tokens: { type: "number", minimum: 128, maximum: 4e3, default: 1200 },
|
|
3534
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON results." }
|
|
3535
|
-
},
|
|
3536
|
-
required: ["objective"]
|
|
3253
|
+
{
|
|
3254
|
+
uriTemplate: "repository://{name}/memories?search={search}&type={type}&tag={tag}",
|
|
3255
|
+
name: "Filtered Repository Memories",
|
|
3256
|
+
title: "Filtered Repository Memories",
|
|
3257
|
+
description: "Filter or search memories within a repository by keyword, type, or tag",
|
|
3258
|
+
mimeType: "application/json",
|
|
3259
|
+
annotations: { audience: ["assistant"], priority: 0.8 }
|
|
3537
3260
|
},
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
},
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3261
|
+
{
|
|
3262
|
+
uriTemplate: "memory://{id}",
|
|
3263
|
+
name: "Memory Detail",
|
|
3264
|
+
title: "Memory Detail",
|
|
3265
|
+
description: "Full content and statistics for a specific memory UUID",
|
|
3266
|
+
mimeType: "application/json",
|
|
3267
|
+
annotations: { audience: ["assistant"], priority: 0.75 }
|
|
3268
|
+
},
|
|
3269
|
+
// ── Tasks ────────────────────────────────────────────────────────────────
|
|
3270
|
+
{
|
|
3271
|
+
uriTemplate: "repository://{name}/tasks",
|
|
3272
|
+
name: "Repository Tasks",
|
|
3273
|
+
title: "Repository Tasks",
|
|
3274
|
+
description: "All active tasks for a specific repository",
|
|
3275
|
+
mimeType: "application/json",
|
|
3276
|
+
annotations: { audience: ["assistant"], priority: 0.9 }
|
|
3277
|
+
},
|
|
3278
|
+
{
|
|
3279
|
+
uriTemplate: "repository://{name}/tasks?status={status}&priority={priority}",
|
|
3280
|
+
name: "Filtered Repository Tasks",
|
|
3281
|
+
title: "Filtered Repository Tasks",
|
|
3282
|
+
description: "Filter tasks within a repository by status or priority level",
|
|
3283
|
+
mimeType: "application/json",
|
|
3284
|
+
annotations: { audience: ["assistant"], priority: 0.85 }
|
|
3561
3285
|
},
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
task_code: { type: "string" },
|
|
3570
|
-
phase: { type: "string" },
|
|
3571
|
-
title: { type: "string", minLength: 3, maxLength: 100 },
|
|
3572
|
-
description: { type: "string", minLength: 1 },
|
|
3573
|
-
status: { type: "string", enum: ["backlog", "pending"], default: "backlog" },
|
|
3574
|
-
priority: {
|
|
3575
|
-
type: "number",
|
|
3576
|
-
minimum: 1,
|
|
3577
|
-
maximum: 5,
|
|
3578
|
-
default: 3,
|
|
3579
|
-
description: "Task priority where 1=Low, 2=Normal, 3=Medium, 4=High, 5=Critical."
|
|
3580
|
-
},
|
|
3581
|
-
agent: { type: "string" },
|
|
3582
|
-
role: { type: "string" },
|
|
3583
|
-
doc_path: { type: "string" },
|
|
3584
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
3585
|
-
}
|
|
3286
|
+
{
|
|
3287
|
+
uriTemplate: "task://{id}",
|
|
3288
|
+
name: "Task Detail",
|
|
3289
|
+
title: "Task Detail",
|
|
3290
|
+
description: "Full content and comments for a specific task UUID",
|
|
3291
|
+
mimeType: "application/json",
|
|
3292
|
+
annotations: { audience: ["assistant"], priority: 0.8 }
|
|
3586
3293
|
},
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3294
|
+
// ── Repository extras ────────────────────────────────────────────────────
|
|
3295
|
+
{
|
|
3296
|
+
uriTemplate: "repository://{name}/summary",
|
|
3297
|
+
name: "Repository Summary",
|
|
3298
|
+
title: "Repository Summary",
|
|
3299
|
+
description: "High-level architectural summary for a repository",
|
|
3300
|
+
mimeType: "text/plain",
|
|
3301
|
+
annotations: { audience: ["assistant"], priority: 0.95 }
|
|
3302
|
+
},
|
|
3303
|
+
{
|
|
3304
|
+
uriTemplate: "repository://{name}/actions",
|
|
3305
|
+
name: "Repository Actions",
|
|
3306
|
+
title: "Repository Actions",
|
|
3307
|
+
description: "Audit log of agent tool actions scoped to a repository",
|
|
3308
|
+
mimeType: "application/json",
|
|
3309
|
+
annotations: { audience: ["assistant"], priority: 0.6 }
|
|
3310
|
+
},
|
|
3311
|
+
// ── Action detail ────────────────────────────────────────────────────────
|
|
3312
|
+
{
|
|
3313
|
+
uriTemplate: "action://{id}",
|
|
3314
|
+
name: "Action Detail",
|
|
3315
|
+
title: "Action Detail",
|
|
3316
|
+
description: "Full details of a specific audit log entry by integer ID",
|
|
3317
|
+
mimeType: "application/json",
|
|
3318
|
+
annotations: { audience: ["assistant"], priority: 0.55 }
|
|
3598
3319
|
}
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
properties: {
|
|
3607
|
-
id: { type: "string", format: "uuid", description: "Memory entry ID. Optional if code is provided." },
|
|
3608
|
-
code: { type: "string", description: "Short memory code. Optional if id is provided." },
|
|
3609
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON details." }
|
|
3610
|
-
}
|
|
3320
|
+
];
|
|
3321
|
+
return paginateEntries("resourceTemplates", templates, params);
|
|
3322
|
+
}
|
|
3323
|
+
function completeResourceArgument(resourceUri, argumentName, argumentValue, _contextArguments, dataSources) {
|
|
3324
|
+
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") {
|
|
3325
|
+
if (argumentName === "name") {
|
|
3326
|
+
return rankCompletionValues(dataSources.repos, argumentValue);
|
|
3611
3327
|
}
|
|
3612
|
-
}
|
|
3613
|
-
{
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
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.",
|
|
3617
|
-
inputSchema: {
|
|
3618
|
-
type: "object",
|
|
3619
|
-
properties: {
|
|
3620
|
-
id: { type: "string", format: "uuid", description: "Coding standard ID. Optional if code is provided." },
|
|
3621
|
-
code: { type: "string", description: "Short standard code (e.g. 'A3KPQ2'). Optional if id is provided." },
|
|
3622
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON details." }
|
|
3623
|
-
}
|
|
3328
|
+
}
|
|
3329
|
+
if (resourceUri === "repository://{name}/memories?search={search}&type={type}&tag={tag}") {
|
|
3330
|
+
if (argumentName === "tag") {
|
|
3331
|
+
return rankCompletionValues(dataSources.tags, argumentValue);
|
|
3624
3332
|
}
|
|
3625
|
-
}
|
|
3626
|
-
{
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3333
|
+
}
|
|
3334
|
+
throw invalidCompletionParams(`Unknown resource template or argument: ${resourceUri} (${argumentName})`);
|
|
3335
|
+
}
|
|
3336
|
+
function readResource(uri, db, session) {
|
|
3337
|
+
logger.info("[Tool] resource.read", { uri });
|
|
3338
|
+
if (uri === "repository://index") {
|
|
3339
|
+
const repos = db.system.listRepoNavigation();
|
|
3340
|
+
const payload = JSON.stringify(repos, null, 2);
|
|
3341
|
+
return {
|
|
3342
|
+
contents: [
|
|
3343
|
+
{
|
|
3344
|
+
uri,
|
|
3345
|
+
mimeType: "application/json",
|
|
3346
|
+
text: payload,
|
|
3347
|
+
size: Buffer.byteLength(payload, "utf8"),
|
|
3348
|
+
annotations: {
|
|
3349
|
+
audience: ["assistant"],
|
|
3350
|
+
priority: 1,
|
|
3351
|
+
lastModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
3352
|
+
}
|
|
3640
3353
|
}
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
agent: {
|
|
3681
|
-
type: "string",
|
|
3682
|
-
description: "Name of the agent creating this memory"
|
|
3683
|
-
},
|
|
3684
|
-
role: {
|
|
3685
|
-
type: "string",
|
|
3686
|
-
description: "Role of the agent creating this memory"
|
|
3687
|
-
},
|
|
3688
|
-
model: {
|
|
3689
|
-
type: "string",
|
|
3690
|
-
description: "AI model used by the agent"
|
|
3691
|
-
},
|
|
3692
|
-
scope: {
|
|
3693
|
-
type: "object",
|
|
3694
|
-
properties: {
|
|
3695
|
-
repo: { type: "string", description: "Repository name" },
|
|
3696
|
-
branch: { type: "string" },
|
|
3697
|
-
folder: { type: "string" },
|
|
3698
|
-
language: { type: "string" }
|
|
3699
|
-
},
|
|
3700
|
-
required: ["repo"]
|
|
3701
|
-
},
|
|
3702
|
-
tags: {
|
|
3703
|
-
type: "array",
|
|
3704
|
-
items: { type: "string" },
|
|
3705
|
-
description: "Technology stack tags (e.g., ['filament', 'laravel'])"
|
|
3706
|
-
},
|
|
3707
|
-
metadata: {
|
|
3708
|
-
type: "object",
|
|
3709
|
-
description: "Structured metadata for non-title context such as source agent, claim fields, or timestamps"
|
|
3710
|
-
},
|
|
3711
|
-
is_global: {
|
|
3712
|
-
type: "boolean",
|
|
3713
|
-
description: "If true, this memory is shared across all repositories"
|
|
3714
|
-
},
|
|
3715
|
-
ttlDays: { type: "number", minimum: 1 },
|
|
3716
|
-
supersedes: { type: "string", format: "uuid" },
|
|
3717
|
-
structured: {
|
|
3718
|
-
type: "boolean",
|
|
3719
|
-
default: false,
|
|
3720
|
-
description: "If true, returns structured JSON of the stored memory."
|
|
3354
|
+
]
|
|
3355
|
+
};
|
|
3356
|
+
}
|
|
3357
|
+
if (uri === "session://roots") {
|
|
3358
|
+
const payload = JSON.stringify({ roots: session?.roots ?? [] }, null, 2);
|
|
3359
|
+
return {
|
|
3360
|
+
contents: [
|
|
3361
|
+
{
|
|
3362
|
+
uri,
|
|
3363
|
+
mimeType: "application/json",
|
|
3364
|
+
text: payload,
|
|
3365
|
+
size: Buffer.byteLength(payload, "utf8"),
|
|
3366
|
+
annotations: {
|
|
3367
|
+
audience: ["assistant"],
|
|
3368
|
+
priority: 0.95,
|
|
3369
|
+
lastModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
]
|
|
3373
|
+
};
|
|
3374
|
+
}
|
|
3375
|
+
const memoryIdMatch = uri.match(/^memory:\/\/([0-9a-f-]{36})$/i);
|
|
3376
|
+
if (memoryIdMatch) {
|
|
3377
|
+
const id = memoryIdMatch[1];
|
|
3378
|
+
const entry = db.memories.getByIdWithStats(id);
|
|
3379
|
+
if (!entry) throw resourceNotFound(`Memory with ID ${id} not found.`, uri);
|
|
3380
|
+
const payload = JSON.stringify(entry, null, 2);
|
|
3381
|
+
return {
|
|
3382
|
+
contents: [
|
|
3383
|
+
{
|
|
3384
|
+
uri,
|
|
3385
|
+
mimeType: "application/json",
|
|
3386
|
+
text: payload,
|
|
3387
|
+
size: Buffer.byteLength(payload, "utf8"),
|
|
3388
|
+
annotations: {
|
|
3389
|
+
audience: ["assistant"],
|
|
3390
|
+
priority: 0.75,
|
|
3391
|
+
lastModified: entry.updated_at || entry.created_at
|
|
3392
|
+
}
|
|
3721
3393
|
}
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3394
|
+
]
|
|
3395
|
+
};
|
|
3396
|
+
}
|
|
3397
|
+
const taskIdMatch = uri.match(/^task:\/\/([0-9a-f-]{36})$/i);
|
|
3398
|
+
if (taskIdMatch) {
|
|
3399
|
+
const id = taskIdMatch[1];
|
|
3400
|
+
const task = db.tasks.getTaskById(id);
|
|
3401
|
+
if (!task) throw resourceNotFound(`Task with ID ${id} not found.`, uri);
|
|
3402
|
+
const payload = JSON.stringify(task, null, 2);
|
|
3403
|
+
return {
|
|
3404
|
+
contents: [
|
|
3405
|
+
{
|
|
3406
|
+
uri,
|
|
3407
|
+
mimeType: "application/json",
|
|
3408
|
+
text: payload,
|
|
3409
|
+
size: Buffer.byteLength(payload, "utf8"),
|
|
3410
|
+
annotations: {
|
|
3411
|
+
audience: ["assistant"],
|
|
3412
|
+
priority: 0.8,
|
|
3413
|
+
lastModified: task.updated_at || task.created_at
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3416
|
+
]
|
|
3417
|
+
};
|
|
3418
|
+
}
|
|
3419
|
+
const repoBase = parseRepoUri(uri);
|
|
3420
|
+
if (repoBase) {
|
|
3421
|
+
const { name, path: repoPath, query } = repoBase;
|
|
3422
|
+
if (repoPath === "summary") {
|
|
3423
|
+
const summary = db.summaries.getSummary(name);
|
|
3424
|
+
const text = summary?.summary || `No summary available for repository: ${name}`;
|
|
3425
|
+
return {
|
|
3426
|
+
contents: [
|
|
3427
|
+
{
|
|
3428
|
+
uri,
|
|
3429
|
+
mimeType: "text/plain",
|
|
3430
|
+
text,
|
|
3431
|
+
size: Buffer.byteLength(text, "utf8"),
|
|
3432
|
+
annotations: {
|
|
3433
|
+
audience: ["assistant"],
|
|
3434
|
+
priority: 0.95,
|
|
3435
|
+
lastModified: summary?.updated_at || (/* @__PURE__ */ new Date()).toISOString()
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3438
|
+
]
|
|
3439
|
+
};
|
|
3738
3440
|
}
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3441
|
+
if (repoPath === "memories") {
|
|
3442
|
+
const search = query.get("search") || "";
|
|
3443
|
+
const type = query.get("type");
|
|
3444
|
+
const tag = query.get("tag");
|
|
3445
|
+
const result = db.memories.listMemoriesForDashboard({
|
|
3446
|
+
repo: name,
|
|
3447
|
+
type: type || void 0,
|
|
3448
|
+
tag: tag || void 0,
|
|
3449
|
+
search: search || void 0,
|
|
3450
|
+
limit: 50
|
|
3451
|
+
});
|
|
3452
|
+
const entries = result.items;
|
|
3453
|
+
const payload = JSON.stringify(entries, null, 2);
|
|
3454
|
+
return {
|
|
3455
|
+
contents: [
|
|
3456
|
+
{
|
|
3457
|
+
uri,
|
|
3458
|
+
mimeType: "application/json",
|
|
3459
|
+
text: payload,
|
|
3460
|
+
size: Buffer.byteLength(payload, "utf8"),
|
|
3461
|
+
annotations: {
|
|
3462
|
+
audience: ["assistant"],
|
|
3463
|
+
priority: 0.85,
|
|
3464
|
+
lastModified: deriveLastModifiedFromCollection(
|
|
3465
|
+
entries.map((e) => e.updated_at || e.created_at)
|
|
3466
|
+
)
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
]
|
|
3470
|
+
};
|
|
3767
3471
|
}
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
id: { type: "string", format: "uuid" },
|
|
3783
|
-
type: {
|
|
3784
|
-
type: "string",
|
|
3785
|
-
enum: ["code_fact", "decision", "mistake", "pattern", "task_archive"]
|
|
3786
|
-
},
|
|
3787
|
-
title: { type: "string", minLength: 3, maxLength: 100 },
|
|
3788
|
-
content: { type: "string", minLength: 10 },
|
|
3789
|
-
importance: { type: "number", minimum: 1, maximum: 5 },
|
|
3790
|
-
agent: { type: "string" },
|
|
3791
|
-
role: { type: "string" },
|
|
3792
|
-
status: { type: "string", enum: ["active", "archived"] },
|
|
3793
|
-
supersedes: { type: "string", format: "uuid" },
|
|
3794
|
-
tags: { type: "array", items: { type: "string" } },
|
|
3795
|
-
metadata: { type: "object" },
|
|
3796
|
-
is_global: { type: "boolean" },
|
|
3797
|
-
completed_at: { type: "string" },
|
|
3798
|
-
structured: {
|
|
3799
|
-
type: "boolean",
|
|
3800
|
-
default: false,
|
|
3801
|
-
description: "If true, returns structured JSON of the updated memory."
|
|
3802
|
-
}
|
|
3803
|
-
},
|
|
3804
|
-
required: ["id"]
|
|
3805
|
-
},
|
|
3806
|
-
outputSchema: {
|
|
3807
|
-
type: "object",
|
|
3808
|
-
properties: {
|
|
3809
|
-
success: { type: "boolean" },
|
|
3810
|
-
id: { type: "string" },
|
|
3811
|
-
repo: { type: "string" },
|
|
3812
|
-
updatedFields: {
|
|
3813
|
-
type: "array",
|
|
3814
|
-
items: { type: "string" }
|
|
3472
|
+
if (repoPath === "tasks") {
|
|
3473
|
+
const status = query.get("status");
|
|
3474
|
+
const priority = query.get("priority");
|
|
3475
|
+
let tasks;
|
|
3476
|
+
if (status && status !== "all") {
|
|
3477
|
+
const statuses = status.split(",").map((s) => s.trim());
|
|
3478
|
+
tasks = db.tasks.getTasksByMultipleStatuses(name, statuses);
|
|
3479
|
+
} else {
|
|
3480
|
+
tasks = db.tasks.getTasksByMultipleStatuses(name, ["backlog", "pending", "in_progress", "blocked"]);
|
|
3481
|
+
}
|
|
3482
|
+
if (priority) {
|
|
3483
|
+
const p = Number(priority);
|
|
3484
|
+
if (!isNaN(p)) {
|
|
3485
|
+
tasks = tasks.filter((t) => t.priority === p);
|
|
3815
3486
|
}
|
|
3816
|
-
}
|
|
3817
|
-
|
|
3487
|
+
}
|
|
3488
|
+
const payload = JSON.stringify(tasks, null, 2);
|
|
3489
|
+
return {
|
|
3490
|
+
contents: [
|
|
3491
|
+
{
|
|
3492
|
+
uri,
|
|
3493
|
+
mimeType: "application/json",
|
|
3494
|
+
text: payload,
|
|
3495
|
+
size: Buffer.byteLength(payload, "utf8"),
|
|
3496
|
+
annotations: {
|
|
3497
|
+
audience: ["assistant"],
|
|
3498
|
+
priority: 0.9,
|
|
3499
|
+
lastModified: deriveLastModifiedFromCollection(tasks.map((t) => t.updated_at))
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
]
|
|
3503
|
+
};
|
|
3818
3504
|
}
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
repo: { type: "string" },
|
|
3835
|
-
current_tags: {
|
|
3836
|
-
type: "array",
|
|
3837
|
-
items: { type: "string" },
|
|
3838
|
-
description: "Active tech stack tags (e.g., ['filament', 'react'])"
|
|
3839
|
-
},
|
|
3840
|
-
types: {
|
|
3841
|
-
type: "array",
|
|
3842
|
-
items: {
|
|
3843
|
-
type: "string",
|
|
3844
|
-
enum: ["code_fact", "decision", "mistake", "pattern", "task_archive"]
|
|
3505
|
+
if (repoPath === "actions") {
|
|
3506
|
+
const actions = db.actions.getRecentActions(name, 100);
|
|
3507
|
+
const payload = JSON.stringify(actions, null, 2);
|
|
3508
|
+
return {
|
|
3509
|
+
contents: [
|
|
3510
|
+
{
|
|
3511
|
+
uri,
|
|
3512
|
+
mimeType: "application/json",
|
|
3513
|
+
text: payload,
|
|
3514
|
+
size: Buffer.byteLength(payload, "utf8"),
|
|
3515
|
+
annotations: {
|
|
3516
|
+
audience: ["assistant"],
|
|
3517
|
+
priority: 0.6,
|
|
3518
|
+
lastModified: deriveLastModifiedFromCollection(actions.map((a) => a.created_at))
|
|
3519
|
+
}
|
|
3845
3520
|
}
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3521
|
+
]
|
|
3522
|
+
};
|
|
3523
|
+
}
|
|
3524
|
+
}
|
|
3525
|
+
const actionIdMatch = uri.match(/^action:\/\/(\d+)$/);
|
|
3526
|
+
if (actionIdMatch) {
|
|
3527
|
+
const id = Number(actionIdMatch[1]);
|
|
3528
|
+
const action = db.actions.getActionById(id);
|
|
3529
|
+
if (!action) throw resourceNotFound(`Action with ID ${id} not found.`, uri);
|
|
3530
|
+
const payload = JSON.stringify(action, null, 2);
|
|
3531
|
+
return {
|
|
3532
|
+
contents: [
|
|
3533
|
+
{
|
|
3534
|
+
uri,
|
|
3535
|
+
mimeType: "application/json",
|
|
3536
|
+
text: payload,
|
|
3537
|
+
size: Buffer.byteLength(payload, "utf8"),
|
|
3538
|
+
annotations: {
|
|
3539
|
+
audience: ["assistant"],
|
|
3540
|
+
priority: 0.55,
|
|
3541
|
+
lastModified: action.created_at
|
|
3860
3542
|
}
|
|
3861
|
-
},
|
|
3862
|
-
structured: {
|
|
3863
|
-
type: "boolean",
|
|
3864
|
-
default: false,
|
|
3865
|
-
description: "If true, returns structured JSON without the text content summary."
|
|
3866
3543
|
}
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3544
|
+
]
|
|
3545
|
+
};
|
|
3546
|
+
}
|
|
3547
|
+
throw resourceNotFound(`Unknown resource URI: ${uri}`, uri);
|
|
3548
|
+
}
|
|
3549
|
+
function parseRepoUri(uri) {
|
|
3550
|
+
const prefix = "repository://";
|
|
3551
|
+
if (!uri.startsWith(prefix)) return null;
|
|
3552
|
+
const rest = uri.slice(prefix.length);
|
|
3553
|
+
const queryStart = rest.indexOf("?");
|
|
3554
|
+
const withoutQuery = queryStart === -1 ? rest : rest.slice(0, queryStart);
|
|
3555
|
+
const queryString = queryStart === -1 ? "" : rest.slice(queryStart + 1);
|
|
3556
|
+
const slashIdx = withoutQuery.indexOf("/");
|
|
3557
|
+
if (slashIdx === -1) return null;
|
|
3558
|
+
const name = withoutQuery.slice(0, slashIdx);
|
|
3559
|
+
const path6 = withoutQuery.slice(slashIdx + 1);
|
|
3560
|
+
if (!name || !path6) return null;
|
|
3561
|
+
return { name, path: path6, query: new URLSearchParams(queryString) };
|
|
3562
|
+
}
|
|
3563
|
+
function paginateEntries(key, entries, params) {
|
|
3564
|
+
const limit = normalizeLimit(params?.limit);
|
|
3565
|
+
const offset = decodeCursor(params?.cursor);
|
|
3566
|
+
const sliced = entries.slice(offset, offset + limit);
|
|
3567
|
+
const nextOffset = offset + sliced.length;
|
|
3568
|
+
return {
|
|
3569
|
+
[key]: sliced,
|
|
3570
|
+
nextCursor: nextOffset < entries.length ? encodeCursor(nextOffset) : void 0
|
|
3571
|
+
};
|
|
3572
|
+
}
|
|
3573
|
+
function normalizeLimit(limit) {
|
|
3574
|
+
if (typeof limit !== "number" || !Number.isFinite(limit)) {
|
|
3575
|
+
return DEFAULT_PAGE_SIZE;
|
|
3576
|
+
}
|
|
3577
|
+
return Math.min(MAX_PAGE_SIZE, Math.max(1, Math.trunc(limit)));
|
|
3578
|
+
}
|
|
3579
|
+
function deriveLastModifiedFromCollection(values) {
|
|
3580
|
+
const normalized = values.filter((value) => typeof value === "string" && value.length > 0);
|
|
3581
|
+
return normalized.sort().at(-1) ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
3582
|
+
}
|
|
3583
|
+
function resourceNotFound(message, uri) {
|
|
3584
|
+
const error = new Error(message);
|
|
3585
|
+
error.code = -32002;
|
|
3586
|
+
error.data = { uri };
|
|
3587
|
+
return error;
|
|
3588
|
+
}
|
|
3589
|
+
function invalidCompletionParams(message) {
|
|
3590
|
+
const error = new Error(message);
|
|
3591
|
+
error.code = -32602;
|
|
3592
|
+
return error;
|
|
3593
|
+
}
|
|
3594
|
+
|
|
3595
|
+
// src/mcp/prompts/registry.ts
|
|
3596
|
+
function createPromptDefinition(loaded) {
|
|
3597
|
+
return {
|
|
3598
|
+
name: loaded.name,
|
|
3599
|
+
description: loaded.description,
|
|
3600
|
+
arguments: loaded.arguments,
|
|
3601
|
+
agent: loaded.agent,
|
|
3602
|
+
messages: [
|
|
3603
|
+
{
|
|
3604
|
+
role: "user",
|
|
3605
|
+
content: {
|
|
3606
|
+
type: "text",
|
|
3607
|
+
text: loaded.content
|
|
3894
3608
|
}
|
|
3895
|
-
}
|
|
3896
|
-
|
|
3609
|
+
}
|
|
3610
|
+
]
|
|
3611
|
+
};
|
|
3612
|
+
}
|
|
3613
|
+
var PROMPTS = {};
|
|
3614
|
+
var promptFiles = listPromptFiles();
|
|
3615
|
+
for (const name of promptFiles) {
|
|
3616
|
+
try {
|
|
3617
|
+
PROMPTS[name] = createPromptDefinition(loadPromptFromMarkdown(name));
|
|
3618
|
+
} catch (e) {
|
|
3619
|
+
logger.warn(`Failed to load prompt ${name}: ${e}`);
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
async function listPrompts(db, session, params) {
|
|
3623
|
+
const allPrompts = Object.values(PROMPTS).map((p) => ({
|
|
3624
|
+
name: p.name,
|
|
3625
|
+
description: p.description,
|
|
3626
|
+
arguments: p.arguments,
|
|
3627
|
+
metadata: p.agent ? { agent: p.agent } : void 0
|
|
3628
|
+
}));
|
|
3629
|
+
const rawLimit = typeof params?.limit === "number" && Number.isInteger(params?.limit) ? params.limit : 25;
|
|
3630
|
+
const limit = Math.max(1, Math.min(100, Math.trunc(rawLimit)));
|
|
3631
|
+
const offset = decodeCursor(params?.cursor);
|
|
3632
|
+
const sliced = allPrompts.slice(offset, offset + limit);
|
|
3633
|
+
const nextOffset = offset + sliced.length;
|
|
3634
|
+
return {
|
|
3635
|
+
prompts: sliced,
|
|
3636
|
+
nextCursor: nextOffset < allPrompts.length ? encodeCursor(nextOffset) : void 0
|
|
3637
|
+
};
|
|
3638
|
+
}
|
|
3639
|
+
async function getPrompt(name, args = {}, db, session) {
|
|
3640
|
+
const prompt = PROMPTS[name];
|
|
3641
|
+
if (!prompt) {
|
|
3642
|
+
throw new Error(`Prompt not found: ${name}`);
|
|
3643
|
+
}
|
|
3644
|
+
const inferredRepo = inferRepoFromSession(session);
|
|
3645
|
+
const messages = prompt.messages.map((m) => {
|
|
3646
|
+
let text = m.content.text;
|
|
3647
|
+
for (const [key, value] of Object.entries(args)) {
|
|
3648
|
+
text = text.replace(new RegExp(`\\{{${key}\\}}`, "g"), value);
|
|
3897
3649
|
}
|
|
3650
|
+
text = text.replace(/{{current_repo}}/g, inferredRepo || "unknown-repo");
|
|
3651
|
+
return {
|
|
3652
|
+
...m,
|
|
3653
|
+
content: {
|
|
3654
|
+
...m.content,
|
|
3655
|
+
text
|
|
3656
|
+
}
|
|
3657
|
+
};
|
|
3658
|
+
});
|
|
3659
|
+
return {
|
|
3660
|
+
description: prompt.description,
|
|
3661
|
+
messages,
|
|
3662
|
+
metadata: prompt.agent ? { agent: prompt.agent } : void 0
|
|
3663
|
+
};
|
|
3664
|
+
}
|
|
3665
|
+
async function completePromptArgument(name, argName, value, contextArguments, dataSources) {
|
|
3666
|
+
void name;
|
|
3667
|
+
void contextArguments;
|
|
3668
|
+
if (argName === "task_id") {
|
|
3669
|
+
const values = dataSources.tasks.map((t) => t.id);
|
|
3670
|
+
return rankCompletionValues(values, value);
|
|
3671
|
+
}
|
|
3672
|
+
return [];
|
|
3673
|
+
}
|
|
3674
|
+
|
|
3675
|
+
// src/mcp/tools/schemas.ts
|
|
3676
|
+
import { z } from "zod";
|
|
3677
|
+
var MemoryScopeSchema = z.object({
|
|
3678
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3679
|
+
branch: z.string().optional(),
|
|
3680
|
+
folder: z.string().optional(),
|
|
3681
|
+
language: z.string().optional()
|
|
3682
|
+
});
|
|
3683
|
+
var MemoryTypeSchema = z.enum(["code_fact", "decision", "mistake", "pattern", "task_archive"]);
|
|
3684
|
+
var MemoryStoreSchema = z.object({
|
|
3685
|
+
code: z.string().max(20).optional(),
|
|
3686
|
+
type: MemoryTypeSchema,
|
|
3687
|
+
title: z.string().min(3).max(255),
|
|
3688
|
+
content: z.string().min(10),
|
|
3689
|
+
importance: z.number().min(1).max(5),
|
|
3690
|
+
agent: z.string().min(1),
|
|
3691
|
+
role: z.string().optional().default("unknown"),
|
|
3692
|
+
model: z.string().min(1),
|
|
3693
|
+
scope: MemoryScopeSchema,
|
|
3694
|
+
ttlDays: z.number().min(1).optional(),
|
|
3695
|
+
supersedes: z.string().uuid().optional(),
|
|
3696
|
+
tags: z.array(z.string()).optional(),
|
|
3697
|
+
metadata: z.record(z.string(), z.any()).optional(),
|
|
3698
|
+
is_global: z.boolean().default(false),
|
|
3699
|
+
structured: z.boolean().default(false)
|
|
3700
|
+
});
|
|
3701
|
+
var MemoryUpdateSchema = z.object({
|
|
3702
|
+
id: z.string().uuid(),
|
|
3703
|
+
type: MemoryTypeSchema.optional(),
|
|
3704
|
+
title: z.string().min(3).max(255).optional(),
|
|
3705
|
+
content: z.string().min(10).optional(),
|
|
3706
|
+
importance: z.number().min(1).max(5).optional(),
|
|
3707
|
+
agent: z.string().optional(),
|
|
3708
|
+
role: z.string().optional(),
|
|
3709
|
+
status: z.enum(["active", "archived"]).optional(),
|
|
3710
|
+
supersedes: z.string().uuid().optional(),
|
|
3711
|
+
tags: z.array(z.string()).optional(),
|
|
3712
|
+
metadata: z.record(z.string(), z.any()).optional(),
|
|
3713
|
+
is_global: z.boolean().optional(),
|
|
3714
|
+
completed_at: z.string().optional(),
|
|
3715
|
+
structured: z.boolean().default(false)
|
|
3716
|
+
}).refine(
|
|
3717
|
+
(data) => data.type !== void 0 || data.content !== void 0 || data.title !== void 0 || data.importance !== void 0 || data.status !== void 0 || data.supersedes !== void 0 || data.tags !== void 0 || data.metadata !== void 0 || data.is_global !== void 0 || data.agent !== void 0 || data.role !== void 0 || data.completed_at !== void 0,
|
|
3718
|
+
{ message: "At least one field must be provided for update" }
|
|
3719
|
+
);
|
|
3720
|
+
var MemorySearchSchema = z.object({
|
|
3721
|
+
query: z.string().min(3),
|
|
3722
|
+
prompt: z.string().optional(),
|
|
3723
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3724
|
+
types: z.array(MemoryTypeSchema).optional(),
|
|
3725
|
+
minImportance: z.number().min(1).max(5).optional(),
|
|
3726
|
+
limit: z.number().min(1).max(100).default(5),
|
|
3727
|
+
offset: z.number().min(0).default(0),
|
|
3728
|
+
includeRecap: z.boolean().default(false),
|
|
3729
|
+
current_file_path: z.string().optional(),
|
|
3730
|
+
include_archived: z.boolean().default(false),
|
|
3731
|
+
current_tags: z.array(z.string()).optional(),
|
|
3732
|
+
scope: MemoryScopeSchema.partial().optional(),
|
|
3733
|
+
structured: z.boolean().default(false)
|
|
3734
|
+
});
|
|
3735
|
+
var MemoryAcknowledgeSchema = z.object({
|
|
3736
|
+
memory_id: z.string().uuid(),
|
|
3737
|
+
status: z.enum(["used", "irrelevant", "contradictory"]),
|
|
3738
|
+
application_context: z.string().min(10).optional(),
|
|
3739
|
+
structured: z.boolean().default(false)
|
|
3740
|
+
});
|
|
3741
|
+
var MemoryRecapSchema = z.object({
|
|
3742
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3743
|
+
limit: z.number().min(1).max(50).default(20),
|
|
3744
|
+
offset: z.number().min(0).default(0),
|
|
3745
|
+
structured: z.boolean().default(false)
|
|
3746
|
+
});
|
|
3747
|
+
var MemoryDeleteSchema = z.object({
|
|
3748
|
+
repo: z.string().min(1).transform(normalizeRepo).optional(),
|
|
3749
|
+
id: z.string().uuid().optional(),
|
|
3750
|
+
ids: z.array(z.string().uuid()).min(1).optional(),
|
|
3751
|
+
structured: z.boolean().default(false)
|
|
3752
|
+
}).refine((data) => data.id !== void 0 || data.ids !== void 0, {
|
|
3753
|
+
message: "Either 'id' or 'ids' must be provided for deletion"
|
|
3754
|
+
});
|
|
3755
|
+
var MemorySummarizeSchema = z.object({
|
|
3756
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3757
|
+
signals: z.array(z.string().max(200)).min(1),
|
|
3758
|
+
structured: z.boolean().default(false)
|
|
3759
|
+
});
|
|
3760
|
+
var MemorySynthesizeSchema = z.object({
|
|
3761
|
+
repo: z.string().min(1).transform(normalizeRepo).optional(),
|
|
3762
|
+
objective: z.string().min(5),
|
|
3763
|
+
current_file_path: z.string().optional(),
|
|
3764
|
+
include_summary: z.boolean().default(true),
|
|
3765
|
+
include_tasks: z.boolean().default(true),
|
|
3766
|
+
use_tools: z.boolean().default(true),
|
|
3767
|
+
max_iterations: z.number().int().min(1).max(5).default(3),
|
|
3768
|
+
max_tokens: z.number().int().min(128).max(4e3).default(1200),
|
|
3769
|
+
structured: z.boolean().default(false)
|
|
3770
|
+
});
|
|
3771
|
+
var TaskStatusSchema = z.enum(["backlog", "pending", "in_progress", "completed", "canceled", "blocked"]);
|
|
3772
|
+
var TaskPrioritySchema = z.number().min(1).max(5);
|
|
3773
|
+
var SingleTaskCreateSchema = z.object({
|
|
3774
|
+
task_code: z.string().min(1),
|
|
3775
|
+
phase: z.string().min(1),
|
|
3776
|
+
title: z.string().min(3).max(100),
|
|
3777
|
+
description: z.string().min(1),
|
|
3778
|
+
status: TaskStatusSchema.default("backlog"),
|
|
3779
|
+
priority: TaskPrioritySchema.default(3),
|
|
3780
|
+
agent: z.string().optional(),
|
|
3781
|
+
role: z.string().optional(),
|
|
3782
|
+
doc_path: z.string().optional(),
|
|
3783
|
+
tags: z.array(z.string()).optional(),
|
|
3784
|
+
metadata: z.record(z.string(), z.any()).optional(),
|
|
3785
|
+
parent_id: z.string().optional(),
|
|
3786
|
+
depends_on: z.string().uuid().optional(),
|
|
3787
|
+
est_tokens: z.number().int().min(0).optional()
|
|
3788
|
+
});
|
|
3789
|
+
var TaskCreateSchema = z.object({
|
|
3790
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3791
|
+
// Allow single task fields at top level (backward compatibility & single use)
|
|
3792
|
+
task_code: z.string().min(1).optional(),
|
|
3793
|
+
phase: z.string().min(1).optional(),
|
|
3794
|
+
title: z.string().min(3).max(100).optional(),
|
|
3795
|
+
description: z.string().min(1).optional(),
|
|
3796
|
+
status: TaskStatusSchema.optional(),
|
|
3797
|
+
priority: TaskPrioritySchema.optional(),
|
|
3798
|
+
agent: z.string().optional(),
|
|
3799
|
+
role: z.string().optional(),
|
|
3800
|
+
doc_path: z.string().optional(),
|
|
3801
|
+
tags: z.array(z.string()).optional(),
|
|
3802
|
+
metadata: z.record(z.string(), z.any()).optional(),
|
|
3803
|
+
parent_id: z.string().optional(),
|
|
3804
|
+
depends_on: z.string().uuid().optional(),
|
|
3805
|
+
est_tokens: z.number().int().min(0).optional(),
|
|
3806
|
+
// Allow bulk tasks
|
|
3807
|
+
tasks: z.array(SingleTaskCreateSchema).min(1).optional(),
|
|
3808
|
+
structured: z.boolean().default(false)
|
|
3809
|
+
}).refine(
|
|
3810
|
+
(data) => {
|
|
3811
|
+
if (data.tasks) return true;
|
|
3812
|
+
return !!(data.task_code && data.phase && data.title && data.description);
|
|
3898
3813
|
},
|
|
3814
|
+
{ message: "Either 'tasks' array or single task fields (task_code, phase, title, description) must be provided" }
|
|
3815
|
+
);
|
|
3816
|
+
var TaskCreateInteractiveSchema = SingleTaskCreateSchema.partial().extend({
|
|
3817
|
+
repo: z.string().min(1).transform(normalizeRepo).optional(),
|
|
3818
|
+
structured: z.boolean().default(false)
|
|
3819
|
+
});
|
|
3820
|
+
var TaskUpdateSchema = z.object({
|
|
3821
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3822
|
+
id: z.string().uuid().optional(),
|
|
3823
|
+
ids: z.array(z.string().uuid()).min(1).optional(),
|
|
3824
|
+
task_code: z.string().optional(),
|
|
3825
|
+
phase: z.string().optional(),
|
|
3826
|
+
title: z.string().min(3).max(100).optional(),
|
|
3827
|
+
description: z.string().optional(),
|
|
3828
|
+
status: TaskStatusSchema.optional(),
|
|
3829
|
+
priority: TaskPrioritySchema.optional(),
|
|
3830
|
+
agent: z.string().min(1, "agent name is required").optional(),
|
|
3831
|
+
role: z.string().min(1, "agent role is required").optional(),
|
|
3832
|
+
model: z.string().optional(),
|
|
3833
|
+
comment: z.string().min(1).optional(),
|
|
3834
|
+
doc_path: z.string().optional(),
|
|
3835
|
+
tags: z.array(z.string()).optional(),
|
|
3836
|
+
metadata: z.record(z.string(), z.any()).optional(),
|
|
3837
|
+
parent_id: z.string().optional(),
|
|
3838
|
+
depends_on: z.string().uuid().optional(),
|
|
3839
|
+
est_tokens: z.number().int().min(0).optional(),
|
|
3840
|
+
force: z.boolean().optional(),
|
|
3841
|
+
structured: z.boolean().default(false)
|
|
3842
|
+
}).refine((data) => data.id !== void 0 || data.ids !== void 0 || data.task_code !== void 0, {
|
|
3843
|
+
message: "Either 'id', 'ids', or 'task_code' must be provided for update"
|
|
3844
|
+
}).refine((data) => Object.keys(data).length > 2, {
|
|
3845
|
+
message: "At least one field besides repo and id/ids must be provided for update"
|
|
3846
|
+
});
|
|
3847
|
+
var TaskListSchema = z.object({
|
|
3848
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3849
|
+
status: z.string().optional(),
|
|
3850
|
+
phase: z.string().optional(),
|
|
3851
|
+
query: z.string().optional(),
|
|
3852
|
+
limit: z.number().min(1).max(100).default(15),
|
|
3853
|
+
offset: z.number().min(0).default(0),
|
|
3854
|
+
structured: z.boolean().default(false)
|
|
3855
|
+
});
|
|
3856
|
+
var TaskSearchSchema = z.object({
|
|
3857
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3858
|
+
query: z.string().min(1),
|
|
3859
|
+
status: z.string().optional(),
|
|
3860
|
+
limit: z.number().min(1).max(100).default(10),
|
|
3861
|
+
offset: z.number().min(0).default(0),
|
|
3862
|
+
structured: z.boolean().default(false)
|
|
3863
|
+
});
|
|
3864
|
+
var TaskDeleteSchema = z.object({
|
|
3865
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3866
|
+
id: z.string().uuid().optional(),
|
|
3867
|
+
ids: z.array(z.string().uuid()).min(1).optional(),
|
|
3868
|
+
structured: z.boolean().default(false)
|
|
3869
|
+
}).refine((data) => data.id !== void 0 || data.ids !== void 0, {
|
|
3870
|
+
message: "Either 'id' or 'ids' must be provided for deletion"
|
|
3871
|
+
});
|
|
3872
|
+
var MemoryDetailSchema = z.object({
|
|
3873
|
+
id: z.string().uuid().optional(),
|
|
3874
|
+
code: z.string().max(20).optional(),
|
|
3875
|
+
structured: z.boolean().default(false)
|
|
3876
|
+
}).refine((data) => data.id !== void 0 || data.code !== void 0, {
|
|
3877
|
+
message: "Either id or code must be provided"
|
|
3878
|
+
});
|
|
3879
|
+
var StandardDetailSchema = z.object({
|
|
3880
|
+
id: z.string().uuid().optional(),
|
|
3881
|
+
code: z.string().max(20).optional(),
|
|
3882
|
+
structured: z.boolean().default(false)
|
|
3883
|
+
}).refine((data) => data.id !== void 0 || data.code !== void 0, {
|
|
3884
|
+
message: "Either id or code must be provided"
|
|
3885
|
+
});
|
|
3886
|
+
var StandardDeleteSchema = z.object({
|
|
3887
|
+
repo: z.string().min(1).transform(normalizeRepo).optional(),
|
|
3888
|
+
id: z.string().uuid().optional(),
|
|
3889
|
+
ids: z.array(z.string().uuid()).min(1).optional(),
|
|
3890
|
+
structured: z.boolean().default(false)
|
|
3891
|
+
}).refine((data) => data.id !== void 0 || data.ids !== void 0, {
|
|
3892
|
+
message: "Either 'id' or 'ids' must be provided for deletion"
|
|
3893
|
+
});
|
|
3894
|
+
var TaskGetSchema = z.object({
|
|
3895
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3896
|
+
id: z.string().uuid().optional(),
|
|
3897
|
+
task_code: z.string().optional(),
|
|
3898
|
+
structured: z.boolean().default(false)
|
|
3899
|
+
}).refine((data) => data.id !== void 0 || data.task_code !== void 0, {
|
|
3900
|
+
message: "Either id or task_code must be provided"
|
|
3901
|
+
});
|
|
3902
|
+
var HandoffStatusSchema = z.enum(["pending", "accepted", "rejected", "expired"]);
|
|
3903
|
+
var HandoffCreateSchema = z.object({
|
|
3904
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3905
|
+
from_agent: z.string().min(1),
|
|
3906
|
+
to_agent: z.string().min(1).optional(),
|
|
3907
|
+
task_id: z.string().uuid().optional(),
|
|
3908
|
+
task_code: z.string().optional(),
|
|
3909
|
+
summary: z.string().min(1),
|
|
3910
|
+
context: z.record(z.string(), z.any()).optional(),
|
|
3911
|
+
expires_at: z.string().optional(),
|
|
3912
|
+
structured: z.boolean().default(false)
|
|
3913
|
+
}).refine((data) => !(data.task_id && data.task_code), {
|
|
3914
|
+
message: "Provide either task_id or task_code, not both"
|
|
3915
|
+
}).refine(
|
|
3916
|
+
(data) => data.to_agent || data.task_id || data.task_code || data.context?.next_steps || data.context?.blockers || data.context?.remaining_work,
|
|
3917
|
+
{
|
|
3918
|
+
message: "Handoffs must identify a target agent, linked task, next_steps, blockers, or remaining_work. Do not create pending handoffs for completed-work summaries."
|
|
3919
|
+
}
|
|
3920
|
+
);
|
|
3921
|
+
var HandoffUpdateSchema = z.object({
|
|
3922
|
+
id: z.string().uuid(),
|
|
3923
|
+
status: HandoffStatusSchema,
|
|
3924
|
+
structured: z.boolean().default(false)
|
|
3925
|
+
});
|
|
3926
|
+
var HandoffListSchema = z.object({
|
|
3927
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3928
|
+
status: HandoffStatusSchema.optional(),
|
|
3929
|
+
from_agent: z.string().min(1).optional(),
|
|
3930
|
+
to_agent: z.string().min(1).optional(),
|
|
3931
|
+
limit: z.number().min(1).max(100).default(20),
|
|
3932
|
+
offset: z.number().min(0).default(0),
|
|
3933
|
+
structured: z.boolean().default(false)
|
|
3934
|
+
});
|
|
3935
|
+
var TaskClaimSchema = z.object({
|
|
3936
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3937
|
+
task_id: z.string().uuid().optional(),
|
|
3938
|
+
task_code: z.string().optional(),
|
|
3939
|
+
agent: z.string().min(1),
|
|
3940
|
+
role: z.string().optional(),
|
|
3941
|
+
metadata: z.record(z.string(), z.any()).optional(),
|
|
3942
|
+
structured: z.boolean().default(false)
|
|
3943
|
+
}).refine((data) => data.task_id !== void 0 || data.task_code !== void 0, {
|
|
3944
|
+
message: "Either task_id or task_code must be provided"
|
|
3945
|
+
}).refine((data) => !(data.task_id && data.task_code), {
|
|
3946
|
+
message: "Provide either task_id or task_code, not both"
|
|
3947
|
+
});
|
|
3948
|
+
var ClaimListSchema = z.object({
|
|
3949
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3950
|
+
agent: z.string().min(1).optional(),
|
|
3951
|
+
active_only: z.boolean().default(true),
|
|
3952
|
+
limit: z.number().min(1).max(100).default(20),
|
|
3953
|
+
offset: z.number().min(0).default(0),
|
|
3954
|
+
structured: z.boolean().default(false)
|
|
3955
|
+
});
|
|
3956
|
+
var ClaimReleaseSchema = z.object({
|
|
3957
|
+
repo: z.string().min(1).transform(normalizeRepo),
|
|
3958
|
+
task_id: z.string().uuid().optional(),
|
|
3959
|
+
task_code: z.string().optional(),
|
|
3960
|
+
agent: z.string().min(1).optional(),
|
|
3961
|
+
structured: z.boolean().default(false)
|
|
3962
|
+
}).refine((data) => data.task_id !== void 0 || data.task_code !== void 0, {
|
|
3963
|
+
message: "Either task_id or task_code must be provided"
|
|
3964
|
+
}).refine((data) => !(data.task_id && data.task_code), {
|
|
3965
|
+
message: "Provide either task_id or task_code, not both"
|
|
3966
|
+
});
|
|
3967
|
+
var StandardStoreSchema = z.object({
|
|
3968
|
+
name: z.string().min(3).max(255),
|
|
3969
|
+
content: z.string().min(10),
|
|
3970
|
+
parent_id: z.string().uuid().optional(),
|
|
3971
|
+
context: z.string().optional(),
|
|
3972
|
+
version: z.string().optional(),
|
|
3973
|
+
language: z.string().optional(),
|
|
3974
|
+
stack: z.array(z.string()).optional(),
|
|
3975
|
+
repo: z.string().transform(normalizeRepo).optional(),
|
|
3976
|
+
is_global: z.boolean().optional(),
|
|
3977
|
+
tags: z.array(z.string().min(1)).min(1),
|
|
3978
|
+
metadata: z.record(z.string(), z.any()).refine((value) => Object.keys(value).length > 0, {
|
|
3979
|
+
message: "metadata must contain at least one key"
|
|
3980
|
+
}),
|
|
3981
|
+
agent: z.string().optional(),
|
|
3982
|
+
model: z.string().optional(),
|
|
3983
|
+
structured: z.boolean().default(false)
|
|
3984
|
+
}).refine((data) => data.is_global !== false || !!data.repo, {
|
|
3985
|
+
message: "repo is required for repo-specific standards"
|
|
3986
|
+
});
|
|
3987
|
+
var StandardUpdateSchema = z.object({
|
|
3988
|
+
id: z.string().uuid(),
|
|
3989
|
+
name: z.string().min(3).max(255).optional(),
|
|
3990
|
+
content: z.string().min(10).optional(),
|
|
3991
|
+
parent_id: z.string().uuid().nullable().optional(),
|
|
3992
|
+
context: z.string().optional(),
|
|
3993
|
+
version: z.string().optional(),
|
|
3994
|
+
language: z.string().optional(),
|
|
3995
|
+
stack: z.array(z.string().min(1)).min(1).optional(),
|
|
3996
|
+
repo: z.string().transform(normalizeRepo).optional(),
|
|
3997
|
+
is_global: z.boolean().optional(),
|
|
3998
|
+
tags: z.array(z.string().min(1)).min(1).optional(),
|
|
3999
|
+
metadata: z.record(z.string(), z.any()).refine((value) => Object.keys(value).length > 0, { message: "metadata must contain at least one key" }).optional(),
|
|
4000
|
+
agent: z.string().optional(),
|
|
4001
|
+
model: z.string().optional(),
|
|
4002
|
+
structured: z.boolean().default(false)
|
|
4003
|
+
}).refine(
|
|
4004
|
+
(data) => data.name !== void 0 || data.content !== void 0 || data.parent_id !== void 0 || data.context !== void 0 || data.version !== void 0 || data.language !== void 0 || data.stack !== void 0 || data.repo !== void 0 || data.is_global !== void 0 || data.tags !== void 0 || data.metadata !== void 0 || data.agent !== void 0 || data.model !== void 0,
|
|
4005
|
+
{ message: "At least one field must be provided for update" }
|
|
4006
|
+
).refine((data) => data.is_global !== false || !!data.repo, {
|
|
4007
|
+
message: "repo is required for repo-specific standards"
|
|
4008
|
+
});
|
|
4009
|
+
var StandardSearchSchema = z.object({
|
|
4010
|
+
query: z.string().optional(),
|
|
4011
|
+
stack: z.array(z.string()).optional(),
|
|
4012
|
+
tags: z.array(z.string()).optional(),
|
|
4013
|
+
language: z.string().optional(),
|
|
4014
|
+
context: z.string().optional(),
|
|
4015
|
+
version: z.string().optional(),
|
|
4016
|
+
repo: z.string().transform(normalizeRepo).optional(),
|
|
4017
|
+
is_global: z.boolean().optional(),
|
|
4018
|
+
limit: z.number().min(1).max(100).default(20),
|
|
4019
|
+
offset: z.number().min(0).default(0),
|
|
4020
|
+
structured: z.boolean().default(false)
|
|
4021
|
+
});
|
|
4022
|
+
var TOOL_DEFINITIONS = [
|
|
3899
4023
|
{
|
|
3900
|
-
name: "memory-
|
|
3901
|
-
title: "Memory
|
|
3902
|
-
description: "
|
|
4024
|
+
name: "memory-synthesize",
|
|
4025
|
+
title: "Memory Synthesize",
|
|
4026
|
+
description: "Use client sampling to synthesize a grounded answer from local memory and tasks. Best for project briefings, tradeoff summaries, and context-aware answers.",
|
|
3903
4027
|
annotations: {
|
|
3904
|
-
readOnlyHint:
|
|
3905
|
-
idempotentHint:
|
|
4028
|
+
readOnlyHint: true,
|
|
4029
|
+
idempotentHint: true,
|
|
3906
4030
|
openWorldHint: false
|
|
3907
4031
|
},
|
|
4032
|
+
execution: {
|
|
4033
|
+
taskSupport: "optional"
|
|
4034
|
+
},
|
|
3908
4035
|
inputSchema: {
|
|
3909
4036
|
type: "object",
|
|
3910
4037
|
properties: {
|
|
3911
|
-
repo: { type: "string", description: "Repository name" },
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
description: "High-level signals to include in summary"
|
|
4038
|
+
repo: { type: "string", description: "Repository name. Optional when a single MCP root is active." },
|
|
4039
|
+
objective: { type: "string", minLength: 5, description: "Question or synthesis objective." },
|
|
4040
|
+
current_file_path: {
|
|
4041
|
+
type: "string",
|
|
4042
|
+
description: "Optional absolute file path for workspace-local grounding."
|
|
3917
4043
|
},
|
|
3918
|
-
|
|
4044
|
+
include_summary: { type: "boolean", default: true },
|
|
4045
|
+
include_tasks: { type: "boolean", default: true },
|
|
4046
|
+
use_tools: {
|
|
4047
|
+
type: "boolean",
|
|
4048
|
+
default: true,
|
|
4049
|
+
description: "Allow the sampled model to call local memory/task tools during synthesis when the client supports sampling.tools."
|
|
4050
|
+
},
|
|
4051
|
+
max_iterations: { type: "number", minimum: 1, maximum: 5, default: 3 },
|
|
4052
|
+
max_tokens: { type: "number", minimum: 128, maximum: 4e3, default: 1200 },
|
|
4053
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON results." }
|
|
3919
4054
|
},
|
|
3920
|
-
required: ["
|
|
4055
|
+
required: ["objective"]
|
|
3921
4056
|
},
|
|
3922
4057
|
outputSchema: {
|
|
3923
4058
|
type: "object",
|
|
3924
4059
|
properties: {
|
|
3925
|
-
success: { type: "boolean" },
|
|
3926
4060
|
repo: { type: "string" },
|
|
3927
|
-
|
|
3928
|
-
|
|
4061
|
+
objective: { type: "string" },
|
|
4062
|
+
answer: { type: "string" },
|
|
4063
|
+
model: { type: "string" },
|
|
4064
|
+
stopReason: { type: "string" },
|
|
4065
|
+
iterations: { type: "number" },
|
|
4066
|
+
toolCalls: { type: "number" }
|
|
3929
4067
|
},
|
|
3930
|
-
required: ["
|
|
4068
|
+
required: ["repo", "objective", "answer", "iterations", "toolCalls"]
|
|
3931
4069
|
}
|
|
3932
4070
|
},
|
|
3933
4071
|
{
|
|
3934
|
-
name: "
|
|
3935
|
-
title: "
|
|
3936
|
-
description: "
|
|
4072
|
+
name: "task-create-interactive",
|
|
4073
|
+
title: "Interactive Task Create",
|
|
4074
|
+
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.",
|
|
3937
4075
|
annotations: {
|
|
3938
4076
|
readOnlyHint: false,
|
|
3939
4077
|
idempotentHint: false,
|
|
3940
|
-
destructiveHint:
|
|
4078
|
+
destructiveHint: false,
|
|
3941
4079
|
openWorldHint: false
|
|
3942
4080
|
},
|
|
3943
4081
|
inputSchema: {
|
|
3944
4082
|
type: "object",
|
|
3945
4083
|
properties: {
|
|
3946
|
-
repo: {
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
4084
|
+
repo: {
|
|
4085
|
+
type: "string",
|
|
4086
|
+
description: "Repository name. Optional when it can be inferred from MCP roots or elicited from the user."
|
|
4087
|
+
},
|
|
4088
|
+
task_code: { type: "string" },
|
|
4089
|
+
phase: { type: "string" },
|
|
4090
|
+
title: { type: "string", minLength: 3, maxLength: 100 },
|
|
4091
|
+
description: {
|
|
4092
|
+
type: "string",
|
|
4093
|
+
minLength: 1,
|
|
4094
|
+
description: "Detailed description. MUST follow format: 1. Context & Analysis, 2. Step & Implementation, 3. Acceptance & Verification"
|
|
4095
|
+
},
|
|
4096
|
+
status: { type: "string", enum: ["backlog", "pending"], default: "backlog" },
|
|
4097
|
+
priority: {
|
|
4098
|
+
type: "number",
|
|
4099
|
+
minimum: 1,
|
|
4100
|
+
maximum: 5,
|
|
4101
|
+
default: 3,
|
|
4102
|
+
description: "Task priority where 1=Low, 2=Normal, 3=Medium, 4=High, 5=Critical."
|
|
3953
4103
|
},
|
|
4104
|
+
agent: { type: "string" },
|
|
4105
|
+
role: { type: "string" },
|
|
4106
|
+
doc_path: { type: "string" },
|
|
3954
4107
|
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
3955
4108
|
}
|
|
3956
4109
|
},
|
|
3957
4110
|
outputSchema: {
|
|
3958
4111
|
type: "object",
|
|
3959
4112
|
properties: {
|
|
3960
|
-
success: { type: "boolean" },
|
|
3961
|
-
id: { type: "string" },
|
|
3962
|
-
ids: { type: "array", items: { type: "string" } },
|
|
3963
4113
|
repo: { type: "string" },
|
|
3964
|
-
|
|
4114
|
+
task_code: { type: "string" },
|
|
4115
|
+
phase: { type: "string" },
|
|
4116
|
+
title: { type: "string" },
|
|
4117
|
+
status: { type: "string" },
|
|
4118
|
+
priority: { type: "number" }
|
|
3965
4119
|
},
|
|
3966
|
-
required: ["
|
|
4120
|
+
required: ["repo", "task_code", "phase", "title", "status", "priority"]
|
|
3967
4121
|
}
|
|
3968
4122
|
},
|
|
3969
4123
|
{
|
|
3970
|
-
name: "
|
|
3971
|
-
title: "
|
|
3972
|
-
description: "
|
|
3973
|
-
annotations: {
|
|
3974
|
-
readOnlyHint: false,
|
|
3975
|
-
idempotentHint: false,
|
|
3976
|
-
destructiveHint: true,
|
|
3977
|
-
openWorldHint: false
|
|
3978
|
-
},
|
|
4124
|
+
name: "memory-detail",
|
|
4125
|
+
title: "Memory Detail",
|
|
4126
|
+
description: "Fetch full details of a specific memory by ID or short code. Use after memory-recap or memory-search when a pointer row is relevant and full content is needed.",
|
|
3979
4127
|
inputSchema: {
|
|
3980
4128
|
type: "object",
|
|
3981
4129
|
properties: {
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
type: "array",
|
|
3986
|
-
items: { type: "string", format: "uuid" },
|
|
3987
|
-
minItems: 1,
|
|
3988
|
-
description: "Array of coding standard IDs to delete"
|
|
3989
|
-
},
|
|
3990
|
-
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4130
|
+
id: { type: "string", format: "uuid", description: "Memory entry ID. Optional if code is provided." },
|
|
4131
|
+
code: { type: "string", description: "Short memory code. Optional if id is provided." },
|
|
4132
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON details." }
|
|
3991
4133
|
}
|
|
3992
|
-
}
|
|
3993
|
-
|
|
4134
|
+
}
|
|
4135
|
+
},
|
|
4136
|
+
{
|
|
4137
|
+
name: "standard-detail",
|
|
4138
|
+
title: "Standard Detail",
|
|
4139
|
+
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.",
|
|
4140
|
+
inputSchema: {
|
|
3994
4141
|
type: "object",
|
|
3995
4142
|
properties: {
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
deletedCount: { type: "number" }
|
|
4001
|
-
},
|
|
4002
|
-
required: ["success"]
|
|
4143
|
+
id: { type: "string", format: "uuid", description: "Coding standard ID. Optional if code is provided." },
|
|
4144
|
+
code: { type: "string", description: "Short standard code (e.g. 'A3KPQ2'). Optional if id is provided." },
|
|
4145
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON details." }
|
|
4146
|
+
}
|
|
4003
4147
|
}
|
|
4004
4148
|
},
|
|
4005
4149
|
{
|
|
4006
|
-
name: "
|
|
4007
|
-
title: "
|
|
4008
|
-
description: "
|
|
4009
|
-
annotations: {
|
|
4010
|
-
readOnlyHint: true,
|
|
4011
|
-
idempotentHint: true,
|
|
4012
|
-
openWorldHint: false
|
|
4013
|
-
},
|
|
4150
|
+
name: "task-detail",
|
|
4151
|
+
title: "Task Detail",
|
|
4152
|
+
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.",
|
|
4014
4153
|
inputSchema: {
|
|
4015
4154
|
type: "object",
|
|
4016
4155
|
properties: {
|
|
4017
|
-
repo: { type: "string", description: "Repository name
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
minimum: 1,
|
|
4021
|
-
maximum: 50,
|
|
4022
|
-
default: 20,
|
|
4023
|
-
description: "Maximum number of top memories to return in the pointer table"
|
|
4024
|
-
},
|
|
4025
|
-
offset: {
|
|
4026
|
-
type: "number",
|
|
4027
|
-
minimum: 0,
|
|
4028
|
-
default: 0,
|
|
4029
|
-
description: "Number of memories to skip for pagination (optional, default 0)"
|
|
4030
|
-
},
|
|
4156
|
+
repo: { type: "string", description: "Repository name" },
|
|
4157
|
+
id: { type: "string", format: "uuid", description: "Task ID (optional if task_code is provided)" },
|
|
4158
|
+
task_code: { type: "string", description: "Task code (e.g. TASK-001) (optional if id is provided)" },
|
|
4031
4159
|
structured: {
|
|
4032
4160
|
type: "boolean",
|
|
4033
4161
|
default: false,
|
|
4034
|
-
description: "If true, returns structured JSON without the text content
|
|
4162
|
+
description: "If true, returns structured JSON without the text content details."
|
|
4035
4163
|
}
|
|
4036
4164
|
},
|
|
4037
4165
|
required: ["repo"]
|
|
4038
|
-
},
|
|
4039
|
-
outputSchema: {
|
|
4040
|
-
type: "object",
|
|
4041
|
-
properties: {
|
|
4042
|
-
schema: { type: "string", enum: ["memory-recap"] },
|
|
4043
|
-
repo: { type: "string" },
|
|
4044
|
-
count: { type: "number", description: "Number of rows in the top pointer table" },
|
|
4045
|
-
total: { type: "number", description: "Total active memories in repo" },
|
|
4046
|
-
offset: { type: "number" },
|
|
4047
|
-
limit: { type: "number" },
|
|
4048
|
-
stats: {
|
|
4049
|
-
type: "object",
|
|
4050
|
-
properties: {
|
|
4051
|
-
byType: {
|
|
4052
|
-
type: "object",
|
|
4053
|
-
description: "Count of active memories per type (e.g. { decision: 3, code_fact: 7 })"
|
|
4054
|
-
}
|
|
4055
|
-
},
|
|
4056
|
-
required: ["byType"]
|
|
4057
|
-
},
|
|
4058
|
-
top: {
|
|
4059
|
-
type: "object",
|
|
4060
|
-
properties: {
|
|
4061
|
-
columns: {
|
|
4062
|
-
type: "array",
|
|
4063
|
-
items: { type: "string" },
|
|
4064
|
-
description: "Column names: [id, code, title, type, importance]"
|
|
4065
|
-
},
|
|
4066
|
-
rows: {
|
|
4067
|
-
type: "array",
|
|
4068
|
-
items: { type: "array" },
|
|
4069
|
-
description: "Each row: [id, code, title, type, importance]. Fetch full content via memory-detail"
|
|
4070
|
-
}
|
|
4071
|
-
},
|
|
4072
|
-
required: ["columns", "rows"]
|
|
4073
|
-
}
|
|
4074
|
-
},
|
|
4075
|
-
required: ["schema", "repo", "count", "total", "offset", "limit", "stats", "top"]
|
|
4076
4166
|
}
|
|
4077
4167
|
},
|
|
4078
4168
|
{
|
|
4079
|
-
name: "
|
|
4080
|
-
title: "
|
|
4081
|
-
description: "
|
|
4169
|
+
name: "memory-store",
|
|
4170
|
+
title: "Memory Store",
|
|
4171
|
+
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'.",
|
|
4082
4172
|
annotations: {
|
|
4083
4173
|
readOnlyHint: false,
|
|
4084
4174
|
idempotentHint: false,
|
|
4175
|
+
destructiveHint: false,
|
|
4085
4176
|
openWorldHint: false
|
|
4086
4177
|
},
|
|
4087
4178
|
inputSchema: {
|
|
4088
4179
|
type: "object",
|
|
4089
4180
|
properties: {
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4181
|
+
type: {
|
|
4182
|
+
type: "string",
|
|
4183
|
+
enum: ["code_fact", "decision", "mistake", "pattern", "task_archive"],
|
|
4184
|
+
description: "Type of durable knowledge being stored. Coordination types such as file_claim are intentionally unsupported."
|
|
4185
|
+
},
|
|
4093
4186
|
title: {
|
|
4094
4187
|
type: "string",
|
|
4095
4188
|
minLength: 3,
|
|
4096
4189
|
maxLength: 100,
|
|
4097
|
-
description: "
|
|
4190
|
+
description: "Short human-readable title for the memory. Do not embed bracketed metadata like agent/role/date prefixes here."
|
|
4191
|
+
},
|
|
4192
|
+
content: {
|
|
4193
|
+
type: "string",
|
|
4194
|
+
minLength: 10,
|
|
4195
|
+
description: "The memory content"
|
|
4196
|
+
},
|
|
4197
|
+
importance: {
|
|
4198
|
+
type: "number",
|
|
4199
|
+
minimum: 1,
|
|
4200
|
+
maximum: 5,
|
|
4201
|
+
description: "Importance score (1-5)"
|
|
4202
|
+
},
|
|
4203
|
+
agent: {
|
|
4204
|
+
type: "string",
|
|
4205
|
+
description: "Name of the agent creating this memory"
|
|
4206
|
+
},
|
|
4207
|
+
role: {
|
|
4208
|
+
type: "string",
|
|
4209
|
+
description: "Role of the agent creating this memory"
|
|
4098
4210
|
},
|
|
4099
|
-
|
|
4100
|
-
status: {
|
|
4211
|
+
model: {
|
|
4101
4212
|
type: "string",
|
|
4102
|
-
|
|
4103
|
-
default: "backlog",
|
|
4104
|
-
description: "New tasks MUST start in 'backlog' if there are already 10 pending tasks. Otherwise can start in 'pending'."
|
|
4213
|
+
description: "AI model used by the agent"
|
|
4105
4214
|
},
|
|
4106
|
-
|
|
4107
|
-
type: "
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4215
|
+
scope: {
|
|
4216
|
+
type: "object",
|
|
4217
|
+
properties: {
|
|
4218
|
+
repo: { type: "string", description: "Repository name" },
|
|
4219
|
+
branch: { type: "string" },
|
|
4220
|
+
folder: { type: "string" },
|
|
4221
|
+
language: { type: "string" }
|
|
4222
|
+
},
|
|
4223
|
+
required: ["repo"]
|
|
4112
4224
|
},
|
|
4113
|
-
|
|
4114
|
-
role: { type: "string" },
|
|
4115
|
-
doc_path: { type: "string" },
|
|
4116
|
-
tags: { type: "array", items: { type: "string" } },
|
|
4117
|
-
metadata: { type: "object" },
|
|
4118
|
-
parent_id: { type: "string", description: "Optional parent task ID (UUID) or parent task code (e.g. TASK-001). Resolved to UUID before storing." },
|
|
4119
|
-
depends_on: { type: "string", format: "uuid" },
|
|
4120
|
-
est_tokens: { type: "number", minimum: 0, description: "Estimated tokens budget for this task" },
|
|
4121
|
-
tasks: {
|
|
4225
|
+
tags: {
|
|
4122
4226
|
type: "array",
|
|
4123
|
-
items: {
|
|
4124
|
-
|
|
4125
|
-
properties: {
|
|
4126
|
-
task_code: { type: "string" },
|
|
4127
|
-
phase: { type: "string" },
|
|
4128
|
-
title: { type: "string", minLength: 3, maxLength: 100 },
|
|
4129
|
-
description: { type: "string" },
|
|
4130
|
-
status: { type: "string", enum: ["backlog", "pending"], default: "backlog" },
|
|
4131
|
-
priority: {
|
|
4132
|
-
type: "number",
|
|
4133
|
-
minimum: 1,
|
|
4134
|
-
maximum: 5,
|
|
4135
|
-
default: 3,
|
|
4136
|
-
description: "Task priority where 1=Low, 2=Normal, 3=Medium, 4=High, 5=Critical."
|
|
4137
|
-
},
|
|
4138
|
-
agent: { type: "string" },
|
|
4139
|
-
role: { type: "string" },
|
|
4140
|
-
doc_path: { type: "string" },
|
|
4141
|
-
tags: { type: "array", items: { type: "string" } },
|
|
4142
|
-
metadata: { type: "object" },
|
|
4143
|
-
parent_id: { type: "string", description: "Optional parent task ID (UUID) or parent task code (e.g. TASK-001). Resolved to UUID before storing." },
|
|
4144
|
-
depends_on: { type: "string", format: "uuid" },
|
|
4145
|
-
est_tokens: { type: "number", minimum: 0 }
|
|
4146
|
-
},
|
|
4147
|
-
required: ["task_code", "phase", "title", "description"]
|
|
4148
|
-
},
|
|
4149
|
-
description: "Array of tasks for bulk creation"
|
|
4227
|
+
items: { type: "string" },
|
|
4228
|
+
description: "Technology stack tags (e.g., ['filament', 'laravel'])"
|
|
4150
4229
|
},
|
|
4151
|
-
|
|
4230
|
+
metadata: {
|
|
4231
|
+
type: "object",
|
|
4232
|
+
description: "Structured metadata for non-title context such as source agent, claim fields, or timestamps"
|
|
4233
|
+
},
|
|
4234
|
+
is_global: {
|
|
4235
|
+
type: "boolean",
|
|
4236
|
+
description: "If true, this memory is shared across all repositories"
|
|
4237
|
+
},
|
|
4238
|
+
ttlDays: { type: "number", minimum: 1 },
|
|
4239
|
+
supersedes: { type: "string", format: "uuid" },
|
|
4240
|
+
structured: {
|
|
4241
|
+
type: "boolean",
|
|
4242
|
+
default: false,
|
|
4243
|
+
description: "If true, returns structured JSON of the stored memory."
|
|
4244
|
+
}
|
|
4152
4245
|
},
|
|
4153
|
-
required: ["
|
|
4246
|
+
required: ["type", "title", "content", "importance", "scope", "agent", "model"]
|
|
4154
4247
|
},
|
|
4155
4248
|
outputSchema: {
|
|
4156
4249
|
type: "object",
|
|
4157
4250
|
properties: {
|
|
4158
4251
|
success: { type: "boolean" },
|
|
4159
4252
|
id: { type: "string" },
|
|
4160
|
-
|
|
4253
|
+
code: { type: "string" },
|
|
4161
4254
|
repo: { type: "string" },
|
|
4162
|
-
|
|
4255
|
+
type: { type: "string" },
|
|
4163
4256
|
title: { type: "string" },
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
createdCount: { type: "number" },
|
|
4167
|
-
taskCodes: { type: "array", items: { type: "string" } }
|
|
4257
|
+
error: { type: "string" },
|
|
4258
|
+
message: { type: "string" }
|
|
4168
4259
|
},
|
|
4169
|
-
required: ["success"
|
|
4260
|
+
required: ["success"]
|
|
4170
4261
|
}
|
|
4171
4262
|
},
|
|
4172
4263
|
{
|
|
4173
|
-
name: "
|
|
4174
|
-
title: "
|
|
4175
|
-
description: "
|
|
4264
|
+
name: "memory-acknowledge",
|
|
4265
|
+
title: "Memory Acknowledge",
|
|
4266
|
+
description: "Acknowledge the use of a memory or report its irrelevance/contradiction. Mandatory after using memory to generate code.",
|
|
4176
4267
|
annotations: {
|
|
4177
4268
|
readOnlyHint: false,
|
|
4178
4269
|
idempotentHint: false,
|
|
@@ -4181,103 +4272,78 @@ var TOOL_DEFINITIONS = [
|
|
|
4181
4272
|
inputSchema: {
|
|
4182
4273
|
type: "object",
|
|
4183
4274
|
properties: {
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
task_code: { type: "string" },
|
|
4188
|
-
phase: { type: "string" },
|
|
4189
|
-
title: { type: "string", minLength: 3, maxLength: 100 },
|
|
4190
|
-
description: { type: "string" },
|
|
4191
|
-
status: {
|
|
4192
|
-
type: "string",
|
|
4193
|
-
enum: ["backlog", "pending", "in_progress", "completed", "canceled", "blocked"],
|
|
4194
|
-
description: "New status. Transitions from 'backlog', 'pending' or 'blocked' to 'completed' are NOT allowed."
|
|
4195
|
-
},
|
|
4196
|
-
priority: {
|
|
4197
|
-
type: "number",
|
|
4198
|
-
minimum: 1,
|
|
4199
|
-
maximum: 5,
|
|
4200
|
-
description: "Task priority where 1=Low, 2=Normal, 3=Medium, 4=High, 5=Critical."
|
|
4201
|
-
},
|
|
4202
|
-
agent: { type: "string" },
|
|
4203
|
-
role: { type: "string" },
|
|
4204
|
-
model: { type: "string" },
|
|
4205
|
-
comment: {
|
|
4206
|
-
type: "string",
|
|
4207
|
-
description: "REQUIRED when changing task status. Explain WHY the status is changing (e.g., 'Starting implementation', 'Blocked by missing API docs', 'Verified fix')."
|
|
4208
|
-
},
|
|
4209
|
-
doc_path: { type: "string" },
|
|
4210
|
-
tags: { type: "array", items: { type: "string" } },
|
|
4211
|
-
metadata: { type: "object" },
|
|
4212
|
-
parent_id: { type: "string", description: "Optional parent task ID (UUID) or parent task code (e.g. TASK-001). Resolved to UUID before storing." },
|
|
4213
|
-
depends_on: { type: "string", format: "uuid" },
|
|
4214
|
-
est_tokens: {
|
|
4215
|
-
type: "number",
|
|
4216
|
-
minimum: 0,
|
|
4217
|
-
description: "Estimated total tokens actually used for this task. Required when status changes to 'completed'."
|
|
4218
|
-
},
|
|
4219
|
-
force: {
|
|
4220
|
-
type: "boolean",
|
|
4221
|
-
description: "If true, bypasses status transition validation (e.g. pending -> completed)."
|
|
4222
|
-
},
|
|
4275
|
+
memory_id: { type: "string", format: "uuid" },
|
|
4276
|
+
status: { type: "string", enum: ["used", "irrelevant", "contradictory"] },
|
|
4277
|
+
application_context: { type: "string", minLength: 10 },
|
|
4223
4278
|
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4224
4279
|
},
|
|
4225
|
-
required: ["
|
|
4280
|
+
required: ["memory_id", "status"]
|
|
4226
4281
|
},
|
|
4227
4282
|
outputSchema: {
|
|
4228
4283
|
type: "object",
|
|
4229
4284
|
properties: {
|
|
4230
4285
|
success: { type: "boolean" },
|
|
4231
4286
|
id: { type: "string" },
|
|
4232
|
-
|
|
4233
|
-
repo: { type: "string" },
|
|
4234
|
-
status: { type: "string" },
|
|
4235
|
-
archivedToMemory: { type: "boolean" },
|
|
4236
|
-
updatedFields: {
|
|
4237
|
-
type: "array",
|
|
4238
|
-
items: { type: "string" }
|
|
4239
|
-
},
|
|
4240
|
-
updatedCount: { type: "number" }
|
|
4287
|
+
status: { type: "string" }
|
|
4241
4288
|
},
|
|
4242
|
-
required: ["success", "
|
|
4289
|
+
required: ["success", "id", "status"]
|
|
4243
4290
|
}
|
|
4244
4291
|
},
|
|
4245
4292
|
{
|
|
4246
|
-
name: "
|
|
4247
|
-
title: "
|
|
4248
|
-
description: "
|
|
4293
|
+
name: "memory-update",
|
|
4294
|
+
title: "Memory Update",
|
|
4295
|
+
description: "Update an existing memory entry. Keep 'title' concise and move agent/role/date or claim context into 'metadata' instead of the title.",
|
|
4249
4296
|
annotations: {
|
|
4250
4297
|
readOnlyHint: false,
|
|
4251
4298
|
idempotentHint: false,
|
|
4252
|
-
destructiveHint:
|
|
4299
|
+
destructiveHint: false,
|
|
4253
4300
|
openWorldHint: false
|
|
4254
4301
|
},
|
|
4255
4302
|
inputSchema: {
|
|
4256
4303
|
type: "object",
|
|
4257
4304
|
properties: {
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4305
|
+
id: { type: "string", format: "uuid" },
|
|
4306
|
+
type: {
|
|
4307
|
+
type: "string",
|
|
4308
|
+
enum: ["code_fact", "decision", "mistake", "pattern", "task_archive"]
|
|
4309
|
+
},
|
|
4310
|
+
title: { type: "string", minLength: 3, maxLength: 100 },
|
|
4311
|
+
content: { type: "string", minLength: 10 },
|
|
4312
|
+
importance: { type: "number", minimum: 1, maximum: 5 },
|
|
4313
|
+
agent: { type: "string" },
|
|
4314
|
+
role: { type: "string" },
|
|
4315
|
+
status: { type: "string", enum: ["active", "archived"] },
|
|
4316
|
+
supersedes: { type: "string", format: "uuid" },
|
|
4317
|
+
tags: { type: "array", items: { type: "string" } },
|
|
4318
|
+
metadata: { type: "object" },
|
|
4319
|
+
is_global: { type: "boolean" },
|
|
4320
|
+
completed_at: { type: "string" },
|
|
4321
|
+
structured: {
|
|
4322
|
+
type: "boolean",
|
|
4323
|
+
default: false,
|
|
4324
|
+
description: "If true, returns structured JSON of the updated memory."
|
|
4325
|
+
}
|
|
4262
4326
|
},
|
|
4263
|
-
required: ["
|
|
4327
|
+
required: ["id"]
|
|
4264
4328
|
},
|
|
4265
4329
|
outputSchema: {
|
|
4266
4330
|
type: "object",
|
|
4267
4331
|
properties: {
|
|
4268
4332
|
success: { type: "boolean" },
|
|
4269
4333
|
id: { type: "string" },
|
|
4270
|
-
ids: { type: "array", items: { type: "string" } },
|
|
4271
4334
|
repo: { type: "string" },
|
|
4272
|
-
|
|
4335
|
+
updatedFields: {
|
|
4336
|
+
type: "array",
|
|
4337
|
+
items: { type: "string" }
|
|
4338
|
+
}
|
|
4273
4339
|
},
|
|
4274
|
-
required: ["success", "repo"]
|
|
4340
|
+
required: ["success", "id", "repo", "updatedFields"]
|
|
4275
4341
|
}
|
|
4276
4342
|
},
|
|
4277
4343
|
{
|
|
4278
|
-
name: "
|
|
4279
|
-
title: "
|
|
4280
|
-
description: "
|
|
4344
|
+
name: "memory-search",
|
|
4345
|
+
title: "Memory Search",
|
|
4346
|
+
description: "NAVIGATION LAYER: Returns a pointer table of matching memory IDs only. Returns columns [id, title, type, importance] \u2014 NO content. Retrieve full memory via memory-detail. Use 'current_tags' to find tech-stack specific knowledge from other projects.",
|
|
4281
4347
|
annotations: {
|
|
4282
4348
|
readOnlyHint: true,
|
|
4283
4349
|
idempotentHint: true,
|
|
@@ -4286,35 +4352,35 @@ var TOOL_DEFINITIONS = [
|
|
|
4286
4352
|
inputSchema: {
|
|
4287
4353
|
type: "object",
|
|
4288
4354
|
properties: {
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
type: "string",
|
|
4295
|
-
|
|
4296
|
-
description: "Comma-separated status filter (backlog, pending, in_progress, completed, canceled, blocked). Defaults to 'in_progress,pending'."
|
|
4297
|
-
},
|
|
4298
|
-
phase: {
|
|
4299
|
-
type: "string",
|
|
4300
|
-
description: "Filter by phase (e.g., 'research', 'implementation')"
|
|
4301
|
-
},
|
|
4302
|
-
query: {
|
|
4303
|
-
type: "string",
|
|
4304
|
-
description: "Search keyword matching task code, title, or description"
|
|
4355
|
+
query: { type: "string", minLength: 3 },
|
|
4356
|
+
prompt: { type: "string" },
|
|
4357
|
+
repo: { type: "string" },
|
|
4358
|
+
current_tags: {
|
|
4359
|
+
type: "array",
|
|
4360
|
+
items: { type: "string" },
|
|
4361
|
+
description: "Active tech stack tags (e.g., ['filament', 'react'])"
|
|
4305
4362
|
},
|
|
4306
|
-
|
|
4307
|
-
type: "
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4363
|
+
types: {
|
|
4364
|
+
type: "array",
|
|
4365
|
+
items: {
|
|
4366
|
+
type: "string",
|
|
4367
|
+
enum: ["code_fact", "decision", "mistake", "pattern", "task_archive"]
|
|
4368
|
+
}
|
|
4312
4369
|
},
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4370
|
+
minImportance: { type: "number", minimum: 1, maximum: 5 },
|
|
4371
|
+
limit: { type: "number", minimum: 1, maximum: 100, default: 5 },
|
|
4372
|
+
offset: { type: "number", minimum: 0, default: 0 },
|
|
4373
|
+
includeRecap: { type: "boolean", default: false },
|
|
4374
|
+
current_file_path: { type: "string" },
|
|
4375
|
+
include_archived: { type: "boolean", default: false },
|
|
4376
|
+
scope: {
|
|
4377
|
+
type: "object",
|
|
4378
|
+
properties: {
|
|
4379
|
+
repo: { type: "string" },
|
|
4380
|
+
branch: { type: "string" },
|
|
4381
|
+
folder: { type: "string" },
|
|
4382
|
+
language: { type: "string" }
|
|
4383
|
+
}
|
|
4318
4384
|
},
|
|
4319
4385
|
structured: {
|
|
4320
4386
|
type: "boolean",
|
|
@@ -4322,113 +4388,147 @@ var TOOL_DEFINITIONS = [
|
|
|
4322
4388
|
description: "If true, returns structured JSON without the text content summary."
|
|
4323
4389
|
}
|
|
4324
4390
|
},
|
|
4325
|
-
required: ["repo"]
|
|
4391
|
+
required: ["query", "repo"]
|
|
4326
4392
|
},
|
|
4327
4393
|
outputSchema: {
|
|
4328
4394
|
type: "object",
|
|
4329
4395
|
properties: {
|
|
4330
|
-
schema: { type: "string", enum: ["
|
|
4331
|
-
|
|
4396
|
+
schema: { type: "string", enum: ["memory-search"] },
|
|
4397
|
+
query: { type: "string" },
|
|
4398
|
+
count: { type: "number", description: "Number of rows returned" },
|
|
4399
|
+
total: { type: "number", description: "Total matching memories" },
|
|
4400
|
+
offset: { type: "number" },
|
|
4401
|
+
limit: { type: "number" },
|
|
4402
|
+
results: {
|
|
4332
4403
|
type: "object",
|
|
4333
4404
|
properties: {
|
|
4334
4405
|
columns: {
|
|
4335
4406
|
type: "array",
|
|
4336
4407
|
items: { type: "string" },
|
|
4337
|
-
description: "Column names
|
|
4408
|
+
description: "Column names: [id, title, type, importance]"
|
|
4338
4409
|
},
|
|
4339
4410
|
rows: {
|
|
4340
4411
|
type: "array",
|
|
4341
4412
|
items: { type: "array" },
|
|
4342
|
-
description: "Each row: [id,
|
|
4413
|
+
description: "Each row: [id, title, type, importance]. Fetch full content via memory-detail"
|
|
4343
4414
|
}
|
|
4344
4415
|
},
|
|
4345
4416
|
required: ["columns", "rows"]
|
|
4346
|
-
}
|
|
4347
|
-
count: { type: "number" },
|
|
4348
|
-
offset: { type: "number" }
|
|
4417
|
+
}
|
|
4349
4418
|
},
|
|
4350
|
-
required: ["schema", "
|
|
4419
|
+
required: ["schema", "query", "count", "total", "offset", "limit", "results"]
|
|
4351
4420
|
}
|
|
4352
4421
|
},
|
|
4353
4422
|
{
|
|
4354
|
-
name: "
|
|
4355
|
-
title: "
|
|
4356
|
-
description: "
|
|
4423
|
+
name: "memory-summarize",
|
|
4424
|
+
title: "Memory Summarize",
|
|
4425
|
+
description: "Update the summary for a repository",
|
|
4357
4426
|
annotations: {
|
|
4358
4427
|
readOnlyHint: false,
|
|
4359
4428
|
idempotentHint: false,
|
|
4360
|
-
destructiveHint: false,
|
|
4361
4429
|
openWorldHint: false
|
|
4362
4430
|
},
|
|
4363
4431
|
inputSchema: {
|
|
4364
4432
|
type: "object",
|
|
4365
4433
|
properties: {
|
|
4366
4434
|
repo: { type: "string", description: "Repository name" },
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
context: {
|
|
4373
|
-
type: "object",
|
|
4374
|
-
description: "Structured handoff context. Include next_steps, blockers, or remaining_work unless a target agent or task is provided."
|
|
4435
|
+
signals: {
|
|
4436
|
+
type: "array",
|
|
4437
|
+
items: { type: "string", maxLength: 200 },
|
|
4438
|
+
minItems: 1,
|
|
4439
|
+
description: "High-level signals to include in summary"
|
|
4375
4440
|
},
|
|
4376
|
-
|
|
4377
|
-
structured: { type: "boolean", default: false }
|
|
4441
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON of the summary." }
|
|
4378
4442
|
},
|
|
4379
|
-
required: ["repo", "
|
|
4443
|
+
required: ["repo", "signals"]
|
|
4380
4444
|
},
|
|
4381
4445
|
outputSchema: {
|
|
4382
4446
|
type: "object",
|
|
4383
4447
|
properties: {
|
|
4384
|
-
|
|
4448
|
+
success: { type: "boolean" },
|
|
4385
4449
|
repo: { type: "string" },
|
|
4386
|
-
from_agent: { type: "string" },
|
|
4387
|
-
to_agent: { type: "string", nullable: true },
|
|
4388
|
-
task_id: { type: "string", nullable: true },
|
|
4389
4450
|
summary: { type: "string" },
|
|
4390
|
-
|
|
4391
|
-
status: { type: "string", enum: ["pending", "accepted", "rejected", "expired"] },
|
|
4392
|
-
created_at: { type: "string" },
|
|
4393
|
-
updated_at: { type: "string" },
|
|
4394
|
-
expires_at: { type: "string", nullable: true }
|
|
4451
|
+
signalCount: { type: "number" }
|
|
4395
4452
|
},
|
|
4396
|
-
required: ["
|
|
4453
|
+
required: ["success", "repo", "summary", "signalCount"]
|
|
4397
4454
|
}
|
|
4398
4455
|
},
|
|
4399
4456
|
{
|
|
4400
|
-
name: "
|
|
4401
|
-
title: "
|
|
4402
|
-
description: "
|
|
4457
|
+
name: "memory-delete",
|
|
4458
|
+
title: "Memory Delete",
|
|
4459
|
+
description: "Soft-delete one or more memory entries. Supports single 'id' or bulk 'ids'.",
|
|
4403
4460
|
annotations: {
|
|
4404
4461
|
readOnlyHint: false,
|
|
4405
4462
|
idempotentHint: false,
|
|
4406
|
-
destructiveHint:
|
|
4463
|
+
destructiveHint: true,
|
|
4407
4464
|
openWorldHint: false
|
|
4408
4465
|
},
|
|
4409
4466
|
inputSchema: {
|
|
4410
4467
|
type: "object",
|
|
4411
4468
|
properties: {
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4469
|
+
repo: { type: "string", description: "Repository name (optional for single id)" },
|
|
4470
|
+
id: { type: "string", format: "uuid", description: "Memory entry ID to delete" },
|
|
4471
|
+
ids: {
|
|
4472
|
+
type: "array",
|
|
4473
|
+
items: { type: "string", format: "uuid" },
|
|
4474
|
+
minItems: 1,
|
|
4475
|
+
description: "Array of memory IDs to delete"
|
|
4476
|
+
},
|
|
4477
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4478
|
+
}
|
|
4479
|
+
},
|
|
4480
|
+
outputSchema: {
|
|
4481
|
+
type: "object",
|
|
4482
|
+
properties: {
|
|
4483
|
+
success: { type: "boolean" },
|
|
4484
|
+
id: { type: "string" },
|
|
4485
|
+
ids: { type: "array", items: { type: "string" } },
|
|
4486
|
+
repo: { type: "string" },
|
|
4487
|
+
deletedCount: { type: "number" }
|
|
4415
4488
|
},
|
|
4416
|
-
required: ["
|
|
4489
|
+
required: ["success"]
|
|
4490
|
+
}
|
|
4491
|
+
},
|
|
4492
|
+
{
|
|
4493
|
+
name: "standard-delete",
|
|
4494
|
+
title: "Standard Delete",
|
|
4495
|
+
description: "Delete one or more coding standards. Supports single 'id' or bulk 'ids'.",
|
|
4496
|
+
annotations: {
|
|
4497
|
+
readOnlyHint: false,
|
|
4498
|
+
idempotentHint: false,
|
|
4499
|
+
destructiveHint: true,
|
|
4500
|
+
openWorldHint: false
|
|
4501
|
+
},
|
|
4502
|
+
inputSchema: {
|
|
4503
|
+
type: "object",
|
|
4504
|
+
properties: {
|
|
4505
|
+
repo: { type: "string", description: "Repository name (optional for single id)" },
|
|
4506
|
+
id: { type: "string", format: "uuid", description: "Coding standard ID to delete" },
|
|
4507
|
+
ids: {
|
|
4508
|
+
type: "array",
|
|
4509
|
+
items: { type: "string", format: "uuid" },
|
|
4510
|
+
minItems: 1,
|
|
4511
|
+
description: "Array of coding standard IDs to delete"
|
|
4512
|
+
},
|
|
4513
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4514
|
+
}
|
|
4417
4515
|
},
|
|
4418
4516
|
outputSchema: {
|
|
4419
4517
|
type: "object",
|
|
4420
4518
|
properties: {
|
|
4421
4519
|
success: { type: "boolean" },
|
|
4422
4520
|
id: { type: "string" },
|
|
4423
|
-
|
|
4521
|
+
ids: { type: "array", items: { type: "string" } },
|
|
4522
|
+
repo: { type: "string" },
|
|
4523
|
+
deletedCount: { type: "number" }
|
|
4424
4524
|
},
|
|
4425
|
-
required: ["success"
|
|
4525
|
+
required: ["success"]
|
|
4426
4526
|
}
|
|
4427
4527
|
},
|
|
4428
4528
|
{
|
|
4429
|
-
name: "
|
|
4430
|
-
title: "
|
|
4431
|
-
description: "
|
|
4529
|
+
name: "memory-recap",
|
|
4530
|
+
title: "Memory Recap",
|
|
4531
|
+
description: "AGGREGATED OVERVIEW LAYER: Returns stats (counts by type) and a pointer table of top memories [id, code, title, type, importance]. NO content. Use for orientation only \u2014 retrieve full memory via memory-detail.",
|
|
4432
4532
|
annotations: {
|
|
4433
4533
|
readOnlyHint: true,
|
|
4434
4534
|
idempotentHint: true,
|
|
@@ -4437,155 +4537,260 @@ var TOOL_DEFINITIONS = [
|
|
|
4437
4537
|
inputSchema: {
|
|
4438
4538
|
type: "object",
|
|
4439
4539
|
properties: {
|
|
4440
|
-
repo: { type: "string", description: "Repository name" },
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4540
|
+
repo: { type: "string", description: "Repository name (required)" },
|
|
4541
|
+
limit: {
|
|
4542
|
+
type: "number",
|
|
4543
|
+
minimum: 1,
|
|
4544
|
+
maximum: 50,
|
|
4545
|
+
default: 20,
|
|
4546
|
+
description: "Maximum number of top memories to return in the pointer table"
|
|
4547
|
+
},
|
|
4548
|
+
offset: {
|
|
4549
|
+
type: "number",
|
|
4550
|
+
minimum: 0,
|
|
4551
|
+
default: 0,
|
|
4552
|
+
description: "Number of memories to skip for pagination (optional, default 0)"
|
|
4553
|
+
},
|
|
4554
|
+
structured: {
|
|
4555
|
+
type: "boolean",
|
|
4556
|
+
default: false,
|
|
4557
|
+
description: "If true, returns structured JSON without the text content summary."
|
|
4558
|
+
}
|
|
4447
4559
|
},
|
|
4448
4560
|
required: ["repo"]
|
|
4449
4561
|
},
|
|
4450
4562
|
outputSchema: {
|
|
4451
4563
|
type: "object",
|
|
4452
4564
|
properties: {
|
|
4453
|
-
schema: { type: "string", enum: ["
|
|
4454
|
-
|
|
4565
|
+
schema: { type: "string", enum: ["memory-recap"] },
|
|
4566
|
+
repo: { type: "string" },
|
|
4567
|
+
count: { type: "number", description: "Number of rows in the top pointer table" },
|
|
4568
|
+
total: { type: "number", description: "Total active memories in repo" },
|
|
4569
|
+
offset: { type: "number" },
|
|
4570
|
+
limit: { type: "number" },
|
|
4571
|
+
stats: {
|
|
4572
|
+
type: "object",
|
|
4573
|
+
properties: {
|
|
4574
|
+
byType: {
|
|
4575
|
+
type: "object",
|
|
4576
|
+
description: "Count of active memories per type (e.g. { decision: 3, code_fact: 7 })"
|
|
4577
|
+
}
|
|
4578
|
+
},
|
|
4579
|
+
required: ["byType"]
|
|
4580
|
+
},
|
|
4581
|
+
top: {
|
|
4455
4582
|
type: "object",
|
|
4456
4583
|
properties: {
|
|
4457
4584
|
columns: {
|
|
4458
4585
|
type: "array",
|
|
4459
4586
|
items: { type: "string" },
|
|
4460
|
-
description: "Column names: [id,
|
|
4587
|
+
description: "Column names: [id, code, title, type, importance]"
|
|
4461
4588
|
},
|
|
4462
4589
|
rows: {
|
|
4463
4590
|
type: "array",
|
|
4464
4591
|
items: { type: "array" },
|
|
4465
|
-
description: "Each row: [id,
|
|
4592
|
+
description: "Each row: [id, code, title, type, importance]. Fetch full content via memory-detail"
|
|
4466
4593
|
}
|
|
4467
4594
|
},
|
|
4468
4595
|
required: ["columns", "rows"]
|
|
4469
|
-
}
|
|
4470
|
-
count: { type: "number" },
|
|
4471
|
-
offset: { type: "number" }
|
|
4596
|
+
}
|
|
4472
4597
|
},
|
|
4473
|
-
required: ["schema", "
|
|
4598
|
+
required: ["schema", "repo", "count", "total", "offset", "limit", "stats", "top"]
|
|
4474
4599
|
}
|
|
4475
4600
|
},
|
|
4476
4601
|
{
|
|
4477
|
-
name: "task-
|
|
4478
|
-
title: "Task
|
|
4479
|
-
description: "
|
|
4602
|
+
name: "task-create",
|
|
4603
|
+
title: "Task Create",
|
|
4604
|
+
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.",
|
|
4480
4605
|
annotations: {
|
|
4481
4606
|
readOnlyHint: false,
|
|
4482
4607
|
idempotentHint: false,
|
|
4483
|
-
destructiveHint: false,
|
|
4484
4608
|
openWorldHint: false
|
|
4485
4609
|
},
|
|
4486
4610
|
inputSchema: {
|
|
4487
4611
|
type: "object",
|
|
4488
4612
|
properties: {
|
|
4489
4613
|
repo: { type: "string", description: "Repository name" },
|
|
4490
|
-
|
|
4614
|
+
task_code: { type: "string", description: "Unique task code (e.g. TASK-001) (Required for single task)" },
|
|
4615
|
+
phase: { type: "string", description: "Project phase (Required for single task)" },
|
|
4616
|
+
title: {
|
|
4491
4617
|
type: "string",
|
|
4492
|
-
|
|
4493
|
-
|
|
4618
|
+
minLength: 3,
|
|
4619
|
+
maxLength: 100,
|
|
4620
|
+
description: "Task objective (Required for single task)"
|
|
4494
4621
|
},
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4622
|
+
description: {
|
|
4623
|
+
type: "string",
|
|
4624
|
+
description: "Detailed description. MUST follow format: 1. Context & Analysis, 2. Step & Implementation, 3. Acceptance & Verification"
|
|
4625
|
+
},
|
|
4626
|
+
status: {
|
|
4627
|
+
type: "string",
|
|
4628
|
+
enum: ["backlog", "pending"],
|
|
4629
|
+
default: "backlog",
|
|
4630
|
+
description: "New tasks MUST start in 'backlog' if there are already 10 pending tasks. Otherwise can start in 'pending'."
|
|
4631
|
+
},
|
|
4632
|
+
priority: {
|
|
4633
|
+
type: "number",
|
|
4634
|
+
minimum: 1,
|
|
4635
|
+
maximum: 5,
|
|
4636
|
+
default: 3,
|
|
4637
|
+
description: "Task priority where 1=Low, 2=Normal, 3=Medium, 4=High, 5=Critical."
|
|
4638
|
+
},
|
|
4639
|
+
agent: { type: "string" },
|
|
4640
|
+
role: { type: "string" },
|
|
4641
|
+
doc_path: { type: "string" },
|
|
4642
|
+
tags: { type: "array", items: { type: "string" } },
|
|
4643
|
+
metadata: { type: "object" },
|
|
4644
|
+
parent_id: { type: "string", description: "Optional parent task ID (UUID) or parent task code (e.g. TASK-001). Resolved to UUID before storing." },
|
|
4645
|
+
depends_on: { type: "string", format: "uuid" },
|
|
4646
|
+
est_tokens: { type: "number", minimum: 0, description: "Estimated tokens budget for this task" },
|
|
4647
|
+
tasks: {
|
|
4648
|
+
type: "array",
|
|
4649
|
+
items: {
|
|
4650
|
+
type: "object",
|
|
4651
|
+
properties: {
|
|
4652
|
+
task_code: { type: "string" },
|
|
4653
|
+
phase: { type: "string" },
|
|
4654
|
+
title: { type: "string", minLength: 3, maxLength: 100 },
|
|
4655
|
+
description: {
|
|
4656
|
+
type: "string",
|
|
4657
|
+
description: "Detailed description. MUST follow format: 1. Context & Analysis, 2. Step & Implementation, 3. Acceptance & Verification"
|
|
4658
|
+
},
|
|
4659
|
+
status: { type: "string", enum: ["backlog", "pending"], default: "backlog" },
|
|
4660
|
+
priority: {
|
|
4661
|
+
type: "number",
|
|
4662
|
+
minimum: 1,
|
|
4663
|
+
maximum: 5,
|
|
4664
|
+
default: 3,
|
|
4665
|
+
description: "Task priority where 1=Low, 2=Normal, 3=Medium, 4=High, 5=Critical."
|
|
4666
|
+
},
|
|
4667
|
+
agent: { type: "string" },
|
|
4668
|
+
role: { type: "string" },
|
|
4669
|
+
doc_path: { type: "string" },
|
|
4670
|
+
tags: { type: "array", items: { type: "string" } },
|
|
4671
|
+
metadata: { type: "object" },
|
|
4672
|
+
parent_id: { type: "string", description: "Optional parent task ID (UUID) or parent task code (e.g. TASK-001). Resolved to UUID before storing." },
|
|
4673
|
+
depends_on: { type: "string", format: "uuid" },
|
|
4674
|
+
est_tokens: { type: "number", minimum: 0 }
|
|
4675
|
+
},
|
|
4676
|
+
required: ["task_code", "phase", "title", "description"]
|
|
4677
|
+
},
|
|
4678
|
+
description: "Array of tasks for bulk creation"
|
|
4679
|
+
},
|
|
4680
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4500
4681
|
},
|
|
4501
|
-
required: ["repo"
|
|
4682
|
+
required: ["repo"]
|
|
4502
4683
|
},
|
|
4503
4684
|
outputSchema: {
|
|
4504
4685
|
type: "object",
|
|
4505
4686
|
properties: {
|
|
4687
|
+
success: { type: "boolean" },
|
|
4506
4688
|
id: { type: "string" },
|
|
4689
|
+
task_code: { type: "string" },
|
|
4507
4690
|
repo: { type: "string" },
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
metadata: { type: "object" }
|
|
4691
|
+
phase: { type: "string" },
|
|
4692
|
+
title: { type: "string" },
|
|
4693
|
+
status: { type: "string" },
|
|
4694
|
+
priority: { type: "number" },
|
|
4695
|
+
createdCount: { type: "number" },
|
|
4696
|
+
taskCodes: { type: "array", items: { type: "string" } }
|
|
4515
4697
|
},
|
|
4516
|
-
required: ["
|
|
4698
|
+
required: ["success", "repo"]
|
|
4517
4699
|
}
|
|
4518
4700
|
},
|
|
4519
4701
|
{
|
|
4520
|
-
name: "
|
|
4521
|
-
title: "
|
|
4522
|
-
description: "
|
|
4702
|
+
name: "task-update",
|
|
4703
|
+
title: "Task Update",
|
|
4704
|
+
description: "Update one or more tasks. Supports single update via 'id' or bulk update via 'ids'. Provide only the fields that need to be changed. MANDATORY WORKFLOW: You cannot move a task from 'pending' or 'blocked' directly to 'completed'. You MUST move it to 'in_progress' first. When changing status to 'completed', include 'est_tokens' with the estimated total tokens actually used for the task.",
|
|
4523
4705
|
annotations: {
|
|
4524
|
-
readOnlyHint:
|
|
4525
|
-
idempotentHint:
|
|
4526
|
-
destructiveHint: false,
|
|
4706
|
+
readOnlyHint: false,
|
|
4707
|
+
idempotentHint: false,
|
|
4527
4708
|
openWorldHint: false
|
|
4528
4709
|
},
|
|
4529
4710
|
inputSchema: {
|
|
4530
4711
|
type: "object",
|
|
4531
4712
|
properties: {
|
|
4532
4713
|
repo: { type: "string", description: "Repository name" },
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4714
|
+
id: { type: "string", format: "uuid", description: "Task ID (for single update)" },
|
|
4715
|
+
ids: { type: "array", items: { type: "string", format: "uuid" }, description: "Task IDs (for bulk update)" },
|
|
4716
|
+
task_code: { type: "string" },
|
|
4717
|
+
phase: { type: "string" },
|
|
4718
|
+
title: { type: "string", minLength: 3, maxLength: 100 },
|
|
4719
|
+
description: {
|
|
4720
|
+
type: "string",
|
|
4721
|
+
description: "Detailed description. MUST follow format: 1. Context & Analysis, 2. Step & Implementation, 3. Acceptance & Verification"
|
|
4722
|
+
},
|
|
4723
|
+
status: {
|
|
4724
|
+
type: "string",
|
|
4725
|
+
enum: ["backlog", "pending", "in_progress", "completed", "canceled", "blocked"],
|
|
4726
|
+
description: "New status. Transitions from 'backlog', 'pending' or 'blocked' to 'completed' are NOT allowed."
|
|
4727
|
+
},
|
|
4728
|
+
priority: {
|
|
4729
|
+
type: "number",
|
|
4730
|
+
minimum: 1,
|
|
4731
|
+
maximum: 5,
|
|
4732
|
+
description: "Task priority where 1=Low, 2=Normal, 3=Medium, 4=High, 5=Critical."
|
|
4733
|
+
},
|
|
4734
|
+
agent: { type: "string" },
|
|
4735
|
+
role: { type: "string" },
|
|
4736
|
+
model: { type: "string" },
|
|
4737
|
+
comment: {
|
|
4738
|
+
type: "string",
|
|
4739
|
+
description: "REQUIRED when changing task status. Explain WHY the status is changing (e.g., 'Starting implementation', 'Blocked by missing API docs', 'Verified fix')."
|
|
4740
|
+
},
|
|
4741
|
+
doc_path: { type: "string" },
|
|
4742
|
+
tags: { type: "array", items: { type: "string" } },
|
|
4743
|
+
metadata: { type: "object" },
|
|
4744
|
+
parent_id: { type: "string", description: "Optional parent task ID (UUID) or parent task code (e.g. TASK-001). Resolved to UUID before storing." },
|
|
4745
|
+
depends_on: { type: "string", format: "uuid" },
|
|
4746
|
+
est_tokens: {
|
|
4747
|
+
type: "number",
|
|
4748
|
+
minimum: 0,
|
|
4749
|
+
description: "Estimated total tokens actually used for this task. Required when status changes to 'completed'."
|
|
4750
|
+
},
|
|
4751
|
+
force: {
|
|
4752
|
+
type: "boolean",
|
|
4753
|
+
description: "If true, bypasses status transition validation (e.g. pending -> completed)."
|
|
4754
|
+
},
|
|
4755
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4538
4756
|
},
|
|
4539
4757
|
required: ["repo"]
|
|
4540
4758
|
},
|
|
4541
4759
|
outputSchema: {
|
|
4542
4760
|
type: "object",
|
|
4543
4761
|
properties: {
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
rows: {
|
|
4554
|
-
type: "array",
|
|
4555
|
-
items: { type: "array" },
|
|
4556
|
-
description: "Each row: [id, task_id, task_code, agent, role, claimed_at, released_at, metadata]"
|
|
4557
|
-
}
|
|
4558
|
-
},
|
|
4559
|
-
required: ["columns", "rows"]
|
|
4762
|
+
success: { type: "boolean" },
|
|
4763
|
+
id: { type: "string" },
|
|
4764
|
+
ids: { type: "array", items: { type: "string" } },
|
|
4765
|
+
repo: { type: "string" },
|
|
4766
|
+
status: { type: "string" },
|
|
4767
|
+
archivedToMemory: { type: "boolean" },
|
|
4768
|
+
updatedFields: {
|
|
4769
|
+
type: "array",
|
|
4770
|
+
items: { type: "string" }
|
|
4560
4771
|
},
|
|
4561
|
-
|
|
4562
|
-
offset: { type: "number" }
|
|
4772
|
+
updatedCount: { type: "number" }
|
|
4563
4773
|
},
|
|
4564
|
-
required: ["
|
|
4774
|
+
required: ["success", "repo"]
|
|
4565
4775
|
}
|
|
4566
4776
|
},
|
|
4567
4777
|
{
|
|
4568
|
-
name: "
|
|
4569
|
-
title: "
|
|
4570
|
-
description: "
|
|
4778
|
+
name: "task-delete",
|
|
4779
|
+
title: "Task Delete",
|
|
4780
|
+
description: "Delete one or more tasks from a repository. Supports single 'id' or bulk 'ids'.",
|
|
4571
4781
|
annotations: {
|
|
4572
4782
|
readOnlyHint: false,
|
|
4573
4783
|
idempotentHint: false,
|
|
4574
|
-
destructiveHint:
|
|
4784
|
+
destructiveHint: true,
|
|
4575
4785
|
openWorldHint: false
|
|
4576
4786
|
},
|
|
4577
4787
|
inputSchema: {
|
|
4578
4788
|
type: "object",
|
|
4579
4789
|
properties: {
|
|
4580
4790
|
repo: { type: "string", description: "Repository name" },
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
description: "Task id to release. Optional if task_code is provided."
|
|
4585
|
-
},
|
|
4586
|
-
task_code: { type: "string", description: "Task code to release. Optional if task_id is provided." },
|
|
4587
|
-
agent: { type: "string", description: "Optional agent name to release only that claim" },
|
|
4588
|
-
structured: { type: "boolean", default: false }
|
|
4791
|
+
id: { type: "string", format: "uuid", description: "Task ID (for single deletion)" },
|
|
4792
|
+
ids: { type: "array", items: { type: "string", format: "uuid" }, description: "Task IDs (for bulk deletion)" },
|
|
4793
|
+
structured: { type: "boolean", default: false, description: "If true, returns structured JSON result." }
|
|
4589
4794
|
},
|
|
4590
4795
|
required: ["repo"]
|
|
4591
4796
|
},
|
|
@@ -4593,116 +4798,94 @@ var TOOL_DEFINITIONS = [
|
|
|
4593
4798
|
type: "object",
|
|
4594
4799
|
properties: {
|
|
4595
4800
|
success: { type: "boolean" },
|
|
4801
|
+
id: { type: "string" },
|
|
4802
|
+
ids: { type: "array", items: { type: "string" } },
|
|
4596
4803
|
repo: { type: "string" },
|
|
4597
|
-
|
|
4598
|
-
task_code: { type: "string", nullable: true },
|
|
4599
|
-
agent: { type: "string", nullable: true }
|
|
4804
|
+
deletedCount: { type: "number" }
|
|
4600
4805
|
},
|
|
4601
|
-
required: ["success", "repo"
|
|
4806
|
+
required: ["success", "repo"]
|
|
4602
4807
|
}
|
|
4603
4808
|
},
|
|
4604
4809
|
{
|
|
4605
|
-
name: "
|
|
4606
|
-
title: "
|
|
4607
|
-
description: "
|
|
4810
|
+
name: "task-list",
|
|
4811
|
+
title: "Task List",
|
|
4812
|
+
description: "PRIMARY navigation and search tool for tasks. Returns a compact tabular list of tasks (id, task_code, title, status, priority, updated_at, comments_count). Defaults to in_progress and pending tasks. Use 'query' to filter by code, title, or description. Use 'status' (comma-separated) for specific filters. AGENTS: call this once at start, pick ONE task, then call task-detail.",
|
|
4608
4813
|
annotations: {
|
|
4609
|
-
readOnlyHint:
|
|
4610
|
-
idempotentHint:
|
|
4611
|
-
destructiveHint: false,
|
|
4814
|
+
readOnlyHint: true,
|
|
4815
|
+
idempotentHint: true,
|
|
4612
4816
|
openWorldHint: false
|
|
4613
4817
|
},
|
|
4614
4818
|
inputSchema: {
|
|
4615
4819
|
type: "object",
|
|
4616
4820
|
properties: {
|
|
4617
|
-
|
|
4618
|
-
content: {
|
|
4821
|
+
repo: {
|
|
4619
4822
|
type: "string",
|
|
4620
|
-
|
|
4621
|
-
description: "One atomic, actionable standard written as concise Markdown"
|
|
4823
|
+
description: "Repository name (required)"
|
|
4622
4824
|
},
|
|
4623
|
-
|
|
4825
|
+
status: {
|
|
4624
4826
|
type: "string",
|
|
4625
|
-
|
|
4626
|
-
description: "
|
|
4827
|
+
default: "in_progress,pending",
|
|
4828
|
+
description: "Comma-separated status filter (backlog, pending, in_progress, completed, canceled, blocked). Defaults to 'in_progress,pending'."
|
|
4627
4829
|
},
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
stack: {
|
|
4632
|
-
type: "array",
|
|
4633
|
-
items: { type: "string" },
|
|
4634
|
-
description: "Technology stack (e.g., ['react', 'nextjs'])"
|
|
4830
|
+
phase: {
|
|
4831
|
+
type: "string",
|
|
4832
|
+
description: "Filter by phase (e.g., 'research', 'implementation')"
|
|
4635
4833
|
},
|
|
4636
|
-
|
|
4834
|
+
query: {
|
|
4637
4835
|
type: "string",
|
|
4638
|
-
description: "
|
|
4836
|
+
description: "Search keyword matching task code, title, or description"
|
|
4639
4837
|
},
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4838
|
+
limit: {
|
|
4839
|
+
type: "number",
|
|
4840
|
+
minimum: 1,
|
|
4841
|
+
maximum: 100,
|
|
4842
|
+
default: 5,
|
|
4843
|
+
description: "Maximum rows to return (default 5)"
|
|
4645
4844
|
},
|
|
4646
|
-
|
|
4647
|
-
type: "
|
|
4648
|
-
|
|
4845
|
+
offset: {
|
|
4846
|
+
type: "number",
|
|
4847
|
+
minimum: 0,
|
|
4848
|
+
default: 0,
|
|
4849
|
+
description: "Offset for pagination"
|
|
4649
4850
|
},
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4851
|
+
structured: {
|
|
4852
|
+
type: "boolean",
|
|
4853
|
+
default: false,
|
|
4854
|
+
description: "If true, returns structured JSON without the text content summary."
|
|
4855
|
+
}
|
|
4653
4856
|
},
|
|
4654
|
-
required: ["
|
|
4857
|
+
required: ["repo"]
|
|
4655
4858
|
},
|
|
4656
4859
|
outputSchema: {
|
|
4657
4860
|
type: "object",
|
|
4658
4861
|
properties: {
|
|
4659
|
-
|
|
4660
|
-
|
|
4862
|
+
schema: { type: "string", enum: ["task-list"] },
|
|
4863
|
+
tasks: {
|
|
4661
4864
|
type: "object",
|
|
4662
4865
|
properties: {
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
tags: { type: "array", items: { type: "string" } },
|
|
4674
|
-
metadata: { type: "object" },
|
|
4675
|
-
created_at: { type: "string" },
|
|
4676
|
-
updated_at: { type: "string" },
|
|
4677
|
-
agent: { type: "string" },
|
|
4678
|
-
model: { type: "string" }
|
|
4866
|
+
columns: {
|
|
4867
|
+
type: "array",
|
|
4868
|
+
items: { type: "string" },
|
|
4869
|
+
description: "Column names in order: id, task_code, title, status, priority, updated_at, comments_count"
|
|
4870
|
+
},
|
|
4871
|
+
rows: {
|
|
4872
|
+
type: "array",
|
|
4873
|
+
items: { type: "array" },
|
|
4874
|
+
description: "Each row: [id, task_code, title, status, priority, updated_at, comments_count]. Use task-detail to fetch full task."
|
|
4875
|
+
}
|
|
4679
4876
|
},
|
|
4680
|
-
required: [
|
|
4681
|
-
"id",
|
|
4682
|
-
"title",
|
|
4683
|
-
"content",
|
|
4684
|
-
"parent_id",
|
|
4685
|
-
"context",
|
|
4686
|
-
"version",
|
|
4687
|
-
"stack",
|
|
4688
|
-
"is_global",
|
|
4689
|
-
"tags",
|
|
4690
|
-
"metadata",
|
|
4691
|
-
"created_at",
|
|
4692
|
-
"updated_at",
|
|
4693
|
-
"agent",
|
|
4694
|
-
"model"
|
|
4695
|
-
]
|
|
4877
|
+
required: ["columns", "rows"]
|
|
4696
4878
|
},
|
|
4697
|
-
|
|
4879
|
+
count: { type: "number" },
|
|
4880
|
+
offset: { type: "number" }
|
|
4698
4881
|
},
|
|
4699
|
-
required: ["
|
|
4882
|
+
required: ["schema", "tasks", "count"]
|
|
4700
4883
|
}
|
|
4701
4884
|
},
|
|
4702
|
-
{
|
|
4703
|
-
name: "
|
|
4704
|
-
title: "
|
|
4705
|
-
description: "
|
|
4885
|
+
{
|
|
4886
|
+
name: "handoff-create",
|
|
4887
|
+
title: "Handoff Create",
|
|
4888
|
+
description: "Create a pending handoff only when unfinished work needs context transfer between agents. Do not use this for completed-work summaries, release notes, validation notes, or archives; put those on task-update/task comments or durable memory.",
|
|
4706
4889
|
annotations: {
|
|
4707
4890
|
readOnlyHint: false,
|
|
4708
4891
|
idempotentHint: false,
|
|
@@ -4712,616 +4895,446 @@ var TOOL_DEFINITIONS = [
|
|
|
4712
4895
|
inputSchema: {
|
|
4713
4896
|
type: "object",
|
|
4714
4897
|
properties: {
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
metadata: { type: "object" },
|
|
4727
|
-
agent: { type: "string" },
|
|
4728
|
-
model: { type: "string" },
|
|
4898
|
+
repo: { type: "string", description: "Repository name" },
|
|
4899
|
+
from_agent: { type: "string", description: "Agent creating the handoff" },
|
|
4900
|
+
to_agent: { type: "string", description: "Optional target agent" },
|
|
4901
|
+
task_id: { type: "string", format: "uuid", description: "Optional task id to associate" },
|
|
4902
|
+
task_code: { type: "string", description: "Optional task code to associate" },
|
|
4903
|
+
summary: { type: "string", minLength: 1, description: "Concise human-readable transfer summary" },
|
|
4904
|
+
context: {
|
|
4905
|
+
type: "object",
|
|
4906
|
+
description: "Structured handoff context. Include next_steps, blockers, or remaining_work unless a target agent or task is provided."
|
|
4907
|
+
},
|
|
4908
|
+
expires_at: { type: "string", description: "Optional expiration timestamp" },
|
|
4729
4909
|
structured: { type: "boolean", default: false }
|
|
4730
4910
|
},
|
|
4731
|
-
required: ["
|
|
4911
|
+
required: ["repo", "from_agent", "summary"]
|
|
4732
4912
|
},
|
|
4733
4913
|
outputSchema: {
|
|
4734
4914
|
type: "object",
|
|
4735
4915
|
properties: {
|
|
4736
|
-
success: { type: "boolean" },
|
|
4737
4916
|
id: { type: "string" },
|
|
4738
|
-
|
|
4917
|
+
repo: { type: "string" },
|
|
4918
|
+
from_agent: { type: "string" },
|
|
4919
|
+
to_agent: { type: "string", nullable: true },
|
|
4920
|
+
task_id: { type: "string", nullable: true },
|
|
4921
|
+
summary: { type: "string" },
|
|
4922
|
+
context: { type: "object" },
|
|
4923
|
+
status: { type: "string", enum: ["pending", "accepted", "rejected", "expired"] },
|
|
4924
|
+
created_at: { type: "string" },
|
|
4925
|
+
updated_at: { type: "string" },
|
|
4926
|
+
expires_at: { type: "string", nullable: true }
|
|
4739
4927
|
},
|
|
4740
|
-
required: ["
|
|
4928
|
+
required: ["id", "repo", "from_agent", "summary", "context", "status", "created_at", "updated_at"]
|
|
4741
4929
|
}
|
|
4742
4930
|
},
|
|
4743
4931
|
{
|
|
4744
|
-
name: "
|
|
4745
|
-
title: "
|
|
4746
|
-
description: "
|
|
4932
|
+
name: "handoff-update",
|
|
4933
|
+
title: "Handoff Update",
|
|
4934
|
+
description: "Close or reclassify a handoff after it has been consumed or found stale. Use accepted when transfer context was consumed, rejected when intentionally declined, and expired when the handoff is obsolete or only described completed work.",
|
|
4747
4935
|
annotations: {
|
|
4748
|
-
readOnlyHint:
|
|
4749
|
-
idempotentHint:
|
|
4936
|
+
readOnlyHint: false,
|
|
4937
|
+
idempotentHint: false,
|
|
4938
|
+
destructiveHint: false,
|
|
4750
4939
|
openWorldHint: false
|
|
4751
4940
|
},
|
|
4752
4941
|
inputSchema: {
|
|
4753
4942
|
type: "object",
|
|
4754
4943
|
properties: {
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
type: "array",
|
|
4758
|
-
items: { type: "string" },
|
|
4759
|
-
description: "Technology stack to filter by (e.g., ['react', 'nextjs'])"
|
|
4760
|
-
},
|
|
4761
|
-
tags: {
|
|
4762
|
-
type: "array",
|
|
4763
|
-
items: { type: "string" },
|
|
4764
|
-
description: "Tag filter"
|
|
4765
|
-
},
|
|
4766
|
-
language: { type: "string", description: "Programming language filter" },
|
|
4767
|
-
context: { type: "string", description: "Context/category filter" },
|
|
4768
|
-
version: { type: "string", description: "Version filter" },
|
|
4769
|
-
repo: { type: "string", description: "Repository filter (optional)" },
|
|
4770
|
-
is_global: { type: "boolean", description: "Filter by global/repo-specific" },
|
|
4771
|
-
limit: { type: "number", minimum: 1, maximum: 100, default: 20 },
|
|
4772
|
-
offset: { type: "number", minimum: 0, default: 0 },
|
|
4944
|
+
id: { type: "string", format: "uuid", description: "Handoff ID" },
|
|
4945
|
+
status: { type: "string", enum: ["pending", "accepted", "rejected", "expired"] },
|
|
4773
4946
|
structured: { type: "boolean", default: false }
|
|
4774
4947
|
},
|
|
4775
|
-
required: []
|
|
4948
|
+
required: ["id", "status"]
|
|
4776
4949
|
},
|
|
4777
4950
|
outputSchema: {
|
|
4778
4951
|
type: "object",
|
|
4779
4952
|
properties: {
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
total: { type: "number", description: "Total number of matches before pagination" },
|
|
4784
|
-
offset: { type: "number" },
|
|
4785
|
-
limit: { type: "number" },
|
|
4786
|
-
results: {
|
|
4787
|
-
type: "object",
|
|
4788
|
-
properties: {
|
|
4789
|
-
columns: {
|
|
4790
|
-
type: "array",
|
|
4791
|
-
items: { type: "string" }
|
|
4792
|
-
},
|
|
4793
|
-
rows: {
|
|
4794
|
-
type: "array",
|
|
4795
|
-
items: { type: "array" },
|
|
4796
|
-
description: "Each row includes standard id and pointer metadata. Fetch full content via standard-detail."
|
|
4797
|
-
}
|
|
4798
|
-
},
|
|
4799
|
-
required: ["columns", "rows"]
|
|
4800
|
-
}
|
|
4953
|
+
success: { type: "boolean" },
|
|
4954
|
+
id: { type: "string" },
|
|
4955
|
+
status: { type: "string", enum: ["pending", "accepted", "rejected", "expired"] }
|
|
4801
4956
|
},
|
|
4802
|
-
required: ["
|
|
4803
|
-
}
|
|
4804
|
-
}
|
|
4805
|
-
];
|
|
4806
|
-
|
|
4807
|
-
// src/mcp/utils/pagination.ts
|
|
4808
|
-
function encodeCursor(offset) {
|
|
4809
|
-
return Buffer.from(String(offset), "utf8").toString("base64");
|
|
4810
|
-
}
|
|
4811
|
-
function decodeCursor(cursor) {
|
|
4812
|
-
if (cursor === void 0 || cursor === null || cursor === "") {
|
|
4813
|
-
return 0;
|
|
4814
|
-
}
|
|
4815
|
-
if (typeof cursor !== "string" || cursor.trim() === "") {
|
|
4816
|
-
throw invalidPaginationParams("Invalid cursor");
|
|
4817
|
-
}
|
|
4818
|
-
let decoded;
|
|
4819
|
-
try {
|
|
4820
|
-
decoded = Buffer.from(cursor, "base64").toString("utf8");
|
|
4821
|
-
} catch {
|
|
4822
|
-
throw invalidPaginationParams("Invalid cursor");
|
|
4823
|
-
}
|
|
4824
|
-
if (!/^\d+$/.test(decoded)) {
|
|
4825
|
-
throw invalidPaginationParams("Invalid cursor");
|
|
4826
|
-
}
|
|
4827
|
-
const offset = Number.parseInt(decoded, 10);
|
|
4828
|
-
if (!Number.isFinite(offset) || offset < 0) {
|
|
4829
|
-
throw invalidPaginationParams("Invalid cursor");
|
|
4830
|
-
}
|
|
4831
|
-
return offset;
|
|
4832
|
-
}
|
|
4833
|
-
function invalidPaginationParams(message) {
|
|
4834
|
-
const error = new Error(message);
|
|
4835
|
-
error.code = -32602;
|
|
4836
|
-
return error;
|
|
4837
|
-
}
|
|
4838
|
-
|
|
4839
|
-
// src/mcp/utils/completion.ts
|
|
4840
|
-
var MAX_COMPLETION_VALUES = 100;
|
|
4841
|
-
function rankCompletionValues(candidates, input) {
|
|
4842
|
-
const unique = [...new Set(candidates.filter(Boolean))];
|
|
4843
|
-
const needle = input.trim().toLowerCase();
|
|
4844
|
-
if (!needle) {
|
|
4845
|
-
return unique.slice(0, MAX_COMPLETION_VALUES);
|
|
4846
|
-
}
|
|
4847
|
-
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);
|
|
4848
|
-
}
|
|
4849
|
-
function scoreCompletionValue(value, needle) {
|
|
4850
|
-
const haystack = value.toLowerCase();
|
|
4851
|
-
if (haystack === needle) return 100;
|
|
4852
|
-
if (haystack.startsWith(needle)) return 75;
|
|
4853
|
-
if (haystack.includes(needle)) return 50;
|
|
4854
|
-
const compactNeedle = needle.replace(/[\s_-]+/g, "");
|
|
4855
|
-
const compactHaystack = haystack.replace(/[\s_-]+/g, "");
|
|
4856
|
-
if (compactNeedle && compactHaystack.includes(compactNeedle)) return 25;
|
|
4857
|
-
return 0;
|
|
4858
|
-
}
|
|
4859
|
-
|
|
4860
|
-
// src/mcp/resources/index.ts
|
|
4861
|
-
var DEFAULT_PAGE_SIZE = 25;
|
|
4862
|
-
var MAX_PAGE_SIZE = 100;
|
|
4863
|
-
function listResources(session, params) {
|
|
4864
|
-
const resources = [
|
|
4865
|
-
{
|
|
4866
|
-
uri: "repository://index",
|
|
4867
|
-
name: "Repository Index",
|
|
4868
|
-
title: "Repository Index",
|
|
4869
|
-
description: "List of all known repositories with memory/task counts and last activity",
|
|
4870
|
-
mimeType: "application/json",
|
|
4871
|
-
annotations: {
|
|
4872
|
-
audience: ["assistant"],
|
|
4873
|
-
priority: 1,
|
|
4874
|
-
lastModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
4875
|
-
}
|
|
4876
|
-
},
|
|
4877
|
-
{
|
|
4878
|
-
uri: "session://roots",
|
|
4879
|
-
name: "Session Roots",
|
|
4880
|
-
title: "Session Roots",
|
|
4881
|
-
description: session?.roots.length ? "Active workspace roots provided by the MCP client" : "No active workspace roots were provided by the MCP client",
|
|
4882
|
-
mimeType: "application/json",
|
|
4883
|
-
size: Buffer.byteLength(JSON.stringify({ roots: session?.roots ?? [] }), "utf8"),
|
|
4884
|
-
annotations: {
|
|
4885
|
-
audience: ["assistant"],
|
|
4886
|
-
priority: 0.95,
|
|
4887
|
-
lastModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
4888
|
-
}
|
|
4957
|
+
required: ["success", "id", "status"]
|
|
4889
4958
|
}
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
title: "Repository Memories",
|
|
4900
|
-
description: "All active memory entries for a specific repository",
|
|
4901
|
-
mimeType: "application/json",
|
|
4902
|
-
annotations: { audience: ["assistant"], priority: 0.85 }
|
|
4903
|
-
},
|
|
4904
|
-
{
|
|
4905
|
-
uriTemplate: "repository://{name}/memories?search={search}&type={type}&tag={tag}",
|
|
4906
|
-
name: "Filtered Repository Memories",
|
|
4907
|
-
title: "Filtered Repository Memories",
|
|
4908
|
-
description: "Filter or search memories within a repository by keyword, type, or tag",
|
|
4909
|
-
mimeType: "application/json",
|
|
4910
|
-
annotations: { audience: ["assistant"], priority: 0.8 }
|
|
4911
|
-
},
|
|
4912
|
-
{
|
|
4913
|
-
uriTemplate: "memory://{id}",
|
|
4914
|
-
name: "Memory Detail",
|
|
4915
|
-
title: "Memory Detail",
|
|
4916
|
-
description: "Full content and statistics for a specific memory UUID",
|
|
4917
|
-
mimeType: "application/json",
|
|
4918
|
-
annotations: { audience: ["assistant"], priority: 0.75 }
|
|
4919
|
-
},
|
|
4920
|
-
// ── Tasks ────────────────────────────────────────────────────────────────
|
|
4921
|
-
{
|
|
4922
|
-
uriTemplate: "repository://{name}/tasks",
|
|
4923
|
-
name: "Repository Tasks",
|
|
4924
|
-
title: "Repository Tasks",
|
|
4925
|
-
description: "All active tasks for a specific repository",
|
|
4926
|
-
mimeType: "application/json",
|
|
4927
|
-
annotations: { audience: ["assistant"], priority: 0.9 }
|
|
4928
|
-
},
|
|
4929
|
-
{
|
|
4930
|
-
uriTemplate: "repository://{name}/tasks?status={status}&priority={priority}",
|
|
4931
|
-
name: "Filtered Repository Tasks",
|
|
4932
|
-
title: "Filtered Repository Tasks",
|
|
4933
|
-
description: "Filter tasks within a repository by status or priority level",
|
|
4934
|
-
mimeType: "application/json",
|
|
4935
|
-
annotations: { audience: ["assistant"], priority: 0.85 }
|
|
4936
|
-
},
|
|
4937
|
-
{
|
|
4938
|
-
uriTemplate: "task://{id}",
|
|
4939
|
-
name: "Task Detail",
|
|
4940
|
-
title: "Task Detail",
|
|
4941
|
-
description: "Full content and comments for a specific task UUID",
|
|
4942
|
-
mimeType: "application/json",
|
|
4943
|
-
annotations: { audience: ["assistant"], priority: 0.8 }
|
|
4944
|
-
},
|
|
4945
|
-
// ── Repository extras ────────────────────────────────────────────────────
|
|
4946
|
-
{
|
|
4947
|
-
uriTemplate: "repository://{name}/summary",
|
|
4948
|
-
name: "Repository Summary",
|
|
4949
|
-
title: "Repository Summary",
|
|
4950
|
-
description: "High-level architectural summary for a repository",
|
|
4951
|
-
mimeType: "text/plain",
|
|
4952
|
-
annotations: { audience: ["assistant"], priority: 0.95 }
|
|
4959
|
+
},
|
|
4960
|
+
{
|
|
4961
|
+
name: "handoff-list",
|
|
4962
|
+
title: "Handoff List",
|
|
4963
|
+
description: "Navigation layer for handoff queues. List repository handoffs with optional status and agent filters, then inspect selected rows before acting.",
|
|
4964
|
+
annotations: {
|
|
4965
|
+
readOnlyHint: true,
|
|
4966
|
+
idempotentHint: true,
|
|
4967
|
+
openWorldHint: false
|
|
4953
4968
|
},
|
|
4954
|
-
{
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4969
|
+
inputSchema: {
|
|
4970
|
+
type: "object",
|
|
4971
|
+
properties: {
|
|
4972
|
+
repo: { type: "string", description: "Repository name" },
|
|
4973
|
+
status: { type: "string", enum: ["pending", "accepted", "rejected", "expired"] },
|
|
4974
|
+
from_agent: { type: "string" },
|
|
4975
|
+
to_agent: { type: "string" },
|
|
4976
|
+
limit: { type: "number", minimum: 1, maximum: 100, default: 20 },
|
|
4977
|
+
offset: { type: "number", minimum: 0, default: 0 },
|
|
4978
|
+
structured: { type: "boolean", default: false }
|
|
4979
|
+
},
|
|
4980
|
+
required: ["repo"]
|
|
4961
4981
|
},
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
}
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
}
|
|
4979
|
-
}
|
|
4980
|
-
if (resourceUri === "repository://{name}/memories?search={search}&type={type}&tag={tag}") {
|
|
4981
|
-
if (argumentName === "tag") {
|
|
4982
|
-
return rankCompletionValues(dataSources.tags, argumentValue);
|
|
4983
|
-
}
|
|
4984
|
-
}
|
|
4985
|
-
throw invalidCompletionParams(`Unknown resource template or argument: ${resourceUri} (${argumentName})`);
|
|
4986
|
-
}
|
|
4987
|
-
function readResource(uri, db, session) {
|
|
4988
|
-
logger.info("[Tool] resource.read", { uri });
|
|
4989
|
-
if (uri === "repository://index") {
|
|
4990
|
-
const repos = db.system.listRepoNavigation();
|
|
4991
|
-
const payload = JSON.stringify(repos, null, 2);
|
|
4992
|
-
return {
|
|
4993
|
-
contents: [
|
|
4994
|
-
{
|
|
4995
|
-
uri,
|
|
4996
|
-
mimeType: "application/json",
|
|
4997
|
-
text: payload,
|
|
4998
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
4999
|
-
annotations: {
|
|
5000
|
-
audience: ["assistant"],
|
|
5001
|
-
priority: 1,
|
|
5002
|
-
lastModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
5003
|
-
}
|
|
5004
|
-
}
|
|
5005
|
-
]
|
|
5006
|
-
};
|
|
5007
|
-
}
|
|
5008
|
-
if (uri === "session://roots") {
|
|
5009
|
-
const payload = JSON.stringify({ roots: session?.roots ?? [] }, null, 2);
|
|
5010
|
-
return {
|
|
5011
|
-
contents: [
|
|
5012
|
-
{
|
|
5013
|
-
uri,
|
|
5014
|
-
mimeType: "application/json",
|
|
5015
|
-
text: payload,
|
|
5016
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
5017
|
-
annotations: {
|
|
5018
|
-
audience: ["assistant"],
|
|
5019
|
-
priority: 0.95,
|
|
5020
|
-
lastModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
5021
|
-
}
|
|
5022
|
-
}
|
|
5023
|
-
]
|
|
5024
|
-
};
|
|
5025
|
-
}
|
|
5026
|
-
const memoryIdMatch = uri.match(/^memory:\/\/([0-9a-f-]{36})$/i);
|
|
5027
|
-
if (memoryIdMatch) {
|
|
5028
|
-
const id = memoryIdMatch[1];
|
|
5029
|
-
const entry = db.memories.getByIdWithStats(id);
|
|
5030
|
-
if (!entry) throw resourceNotFound(`Memory with ID ${id} not found.`, uri);
|
|
5031
|
-
const payload = JSON.stringify(entry, null, 2);
|
|
5032
|
-
return {
|
|
5033
|
-
contents: [
|
|
5034
|
-
{
|
|
5035
|
-
uri,
|
|
5036
|
-
mimeType: "application/json",
|
|
5037
|
-
text: payload,
|
|
5038
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
5039
|
-
annotations: {
|
|
5040
|
-
audience: ["assistant"],
|
|
5041
|
-
priority: 0.75,
|
|
5042
|
-
lastModified: entry.updated_at || entry.created_at
|
|
5043
|
-
}
|
|
5044
|
-
}
|
|
5045
|
-
]
|
|
5046
|
-
};
|
|
5047
|
-
}
|
|
5048
|
-
const taskIdMatch = uri.match(/^task:\/\/([0-9a-f-]{36})$/i);
|
|
5049
|
-
if (taskIdMatch) {
|
|
5050
|
-
const id = taskIdMatch[1];
|
|
5051
|
-
const task = db.tasks.getTaskById(id);
|
|
5052
|
-
if (!task) throw resourceNotFound(`Task with ID ${id} not found.`, uri);
|
|
5053
|
-
const payload = JSON.stringify(task, null, 2);
|
|
5054
|
-
return {
|
|
5055
|
-
contents: [
|
|
5056
|
-
{
|
|
5057
|
-
uri,
|
|
5058
|
-
mimeType: "application/json",
|
|
5059
|
-
text: payload,
|
|
5060
|
-
size: Buffer.byteLength(payload, "utf8"),
|
|
5061
|
-
annotations: {
|
|
5062
|
-
audience: ["assistant"],
|
|
5063
|
-
priority: 0.8,
|
|
5064
|
-
lastModified: task.updated_at || task.created_at
|
|
5065
|
-
}
|
|
5066
|
-
}
|
|
5067
|
-
]
|
|
5068
|
-
};
|
|
5069
|
-
}
|
|
5070
|
-
const repoBase = parseRepoUri(uri);
|
|
5071
|
-
if (repoBase) {
|
|
5072
|
-
const { name, path: repoPath, query } = repoBase;
|
|
5073
|
-
if (repoPath === "summary") {
|
|
5074
|
-
const summary = db.summaries.getSummary(name);
|
|
5075
|
-
const text = summary?.summary || `No summary available for repository: ${name}`;
|
|
5076
|
-
return {
|
|
5077
|
-
contents: [
|
|
5078
|
-
{
|
|
5079
|
-
uri,
|
|
5080
|
-
mimeType: "text/plain",
|
|
5081
|
-
text,
|
|
5082
|
-
size: Buffer.byteLength(text, "utf8"),
|
|
5083
|
-
annotations: {
|
|
5084
|
-
audience: ["assistant"],
|
|
5085
|
-
priority: 0.95,
|
|
5086
|
-
lastModified: summary?.updated_at || (/* @__PURE__ */ new Date()).toISOString()
|
|
4982
|
+
outputSchema: {
|
|
4983
|
+
type: "object",
|
|
4984
|
+
properties: {
|
|
4985
|
+
schema: { type: "string", enum: ["handoff-list"] },
|
|
4986
|
+
handoffs: {
|
|
4987
|
+
type: "object",
|
|
4988
|
+
properties: {
|
|
4989
|
+
columns: {
|
|
4990
|
+
type: "array",
|
|
4991
|
+
items: { type: "string" },
|
|
4992
|
+
description: "Column names: [id, from_agent, to_agent, task_id, task_code, status, created_at, updated_at, expires_at, summary, context]"
|
|
4993
|
+
},
|
|
4994
|
+
rows: {
|
|
4995
|
+
type: "array",
|
|
4996
|
+
items: { type: "array" },
|
|
4997
|
+
description: "Each row: [id, from_agent, to_agent, task_id, task_code, status, created_at, updated_at, expires_at, summary, context]"
|
|
5087
4998
|
}
|
|
5088
|
-
}
|
|
5089
|
-
|
|
5090
|
-
|
|
4999
|
+
},
|
|
5000
|
+
required: ["columns", "rows"]
|
|
5001
|
+
},
|
|
5002
|
+
count: { type: "number" },
|
|
5003
|
+
offset: { type: "number" }
|
|
5004
|
+
},
|
|
5005
|
+
required: ["schema", "handoffs", "count", "offset"]
|
|
5091
5006
|
}
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5007
|
+
},
|
|
5008
|
+
{
|
|
5009
|
+
name: "task-claim",
|
|
5010
|
+
title: "Task Claim",
|
|
5011
|
+
description: "Claim task ownership for an agent using the dedicated claims table. Use this before taking work from task-list; provide either task_id or task_code.",
|
|
5012
|
+
annotations: {
|
|
5013
|
+
readOnlyHint: false,
|
|
5014
|
+
idempotentHint: false,
|
|
5015
|
+
destructiveHint: false,
|
|
5016
|
+
openWorldHint: false
|
|
5017
|
+
},
|
|
5018
|
+
inputSchema: {
|
|
5019
|
+
type: "object",
|
|
5020
|
+
properties: {
|
|
5021
|
+
repo: { type: "string", description: "Repository name" },
|
|
5022
|
+
task_id: {
|
|
5023
|
+
type: "string",
|
|
5024
|
+
format: "uuid",
|
|
5025
|
+
description: "Task id to claim. Optional if task_code is provided."
|
|
5026
|
+
},
|
|
5027
|
+
task_code: { type: "string", description: "Task code to claim. Optional if task_id is provided." },
|
|
5028
|
+
agent: { type: "string", description: "Claiming agent name" },
|
|
5029
|
+
role: { type: "string", description: "Claiming agent role" },
|
|
5030
|
+
metadata: { type: "object", description: "Optional claim metadata" },
|
|
5031
|
+
structured: { type: "boolean", default: false }
|
|
5032
|
+
},
|
|
5033
|
+
required: ["repo", "agent"]
|
|
5034
|
+
},
|
|
5035
|
+
outputSchema: {
|
|
5036
|
+
type: "object",
|
|
5037
|
+
properties: {
|
|
5038
|
+
id: { type: "string" },
|
|
5039
|
+
repo: { type: "string" },
|
|
5040
|
+
task_id: { type: "string" },
|
|
5041
|
+
task_code: { type: "string", nullable: true },
|
|
5042
|
+
agent: { type: "string" },
|
|
5043
|
+
role: { type: "string" },
|
|
5044
|
+
claimed_at: { type: "string" },
|
|
5045
|
+
released_at: { type: "string", nullable: true },
|
|
5046
|
+
metadata: { type: "object" }
|
|
5047
|
+
},
|
|
5048
|
+
required: ["id", "repo", "task_id", "agent", "role", "claimed_at", "metadata"]
|
|
5049
|
+
}
|
|
5050
|
+
},
|
|
5051
|
+
{
|
|
5052
|
+
name: "claim-list",
|
|
5053
|
+
title: "Claim List",
|
|
5054
|
+
description: "List task claims in a repository. Use this to inspect active ownership, optionally filtered by agent.",
|
|
5055
|
+
annotations: {
|
|
5056
|
+
readOnlyHint: true,
|
|
5057
|
+
idempotentHint: true,
|
|
5058
|
+
destructiveHint: false,
|
|
5059
|
+
openWorldHint: false
|
|
5060
|
+
},
|
|
5061
|
+
inputSchema: {
|
|
5062
|
+
type: "object",
|
|
5063
|
+
properties: {
|
|
5064
|
+
repo: { type: "string", description: "Repository name" },
|
|
5065
|
+
agent: { type: "string", description: "Optional agent filter" },
|
|
5066
|
+
active_only: { type: "boolean", description: "When true, return only unreleased claims" },
|
|
5067
|
+
limit: { type: "number", minimum: 1, maximum: 100, default: 20 },
|
|
5068
|
+
offset: { type: "number", minimum: 0, default: 0 },
|
|
5069
|
+
structured: { type: "boolean", default: false }
|
|
5070
|
+
},
|
|
5071
|
+
required: ["repo"]
|
|
5072
|
+
},
|
|
5073
|
+
outputSchema: {
|
|
5074
|
+
type: "object",
|
|
5075
|
+
properties: {
|
|
5076
|
+
schema: { type: "string", enum: ["claim-list"] },
|
|
5077
|
+
claims: {
|
|
5078
|
+
type: "object",
|
|
5079
|
+
properties: {
|
|
5080
|
+
columns: {
|
|
5081
|
+
type: "array",
|
|
5082
|
+
items: { type: "string" },
|
|
5083
|
+
description: "Column names: [id, task_id, task_code, agent, role, claimed_at, released_at, metadata]"
|
|
5084
|
+
},
|
|
5085
|
+
rows: {
|
|
5086
|
+
type: "array",
|
|
5087
|
+
items: { type: "array" },
|
|
5088
|
+
description: "Each row: [id, task_id, task_code, agent, role, claimed_at, released_at, metadata]"
|
|
5118
5089
|
}
|
|
5119
|
-
}
|
|
5120
|
-
|
|
5121
|
-
|
|
5090
|
+
},
|
|
5091
|
+
required: ["columns", "rows"]
|
|
5092
|
+
},
|
|
5093
|
+
count: { type: "number" },
|
|
5094
|
+
offset: { type: "number" }
|
|
5095
|
+
},
|
|
5096
|
+
required: ["schema", "claims", "count", "offset"]
|
|
5122
5097
|
}
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
}
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5098
|
+
},
|
|
5099
|
+
{
|
|
5100
|
+
name: "claim-release",
|
|
5101
|
+
title: "Claim Release",
|
|
5102
|
+
description: "Release an active claim for a task. Optionally restrict the release to a specific agent.",
|
|
5103
|
+
annotations: {
|
|
5104
|
+
readOnlyHint: false,
|
|
5105
|
+
idempotentHint: false,
|
|
5106
|
+
destructiveHint: false,
|
|
5107
|
+
openWorldHint: false
|
|
5108
|
+
},
|
|
5109
|
+
inputSchema: {
|
|
5110
|
+
type: "object",
|
|
5111
|
+
properties: {
|
|
5112
|
+
repo: { type: "string", description: "Repository name" },
|
|
5113
|
+
task_id: {
|
|
5114
|
+
type: "string",
|
|
5115
|
+
format: "uuid",
|
|
5116
|
+
description: "Task id to release. Optional if task_code is provided."
|
|
5117
|
+
},
|
|
5118
|
+
task_code: { type: "string", description: "Task code to release. Optional if task_id is provided." },
|
|
5119
|
+
agent: { type: "string", description: "Optional agent name to release only that claim" },
|
|
5120
|
+
structured: { type: "boolean", default: false }
|
|
5121
|
+
},
|
|
5122
|
+
required: ["repo"]
|
|
5123
|
+
},
|
|
5124
|
+
outputSchema: {
|
|
5125
|
+
type: "object",
|
|
5126
|
+
properties: {
|
|
5127
|
+
success: { type: "boolean" },
|
|
5128
|
+
repo: { type: "string" },
|
|
5129
|
+
task_id: { type: "string" },
|
|
5130
|
+
task_code: { type: "string", nullable: true },
|
|
5131
|
+
agent: { type: "string", nullable: true }
|
|
5132
|
+
},
|
|
5133
|
+
required: ["success", "repo", "task_id"]
|
|
5155
5134
|
}
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5135
|
+
},
|
|
5136
|
+
{
|
|
5137
|
+
name: "standard-store",
|
|
5138
|
+
title: "Standard Store",
|
|
5139
|
+
description: "Store one atomic coding standard. Use for durable implementation rules with explicit context, stack/language filters, and repo/global scope.",
|
|
5140
|
+
annotations: {
|
|
5141
|
+
readOnlyHint: false,
|
|
5142
|
+
idempotentHint: false,
|
|
5143
|
+
destructiveHint: false,
|
|
5144
|
+
openWorldHint: false
|
|
5145
|
+
},
|
|
5146
|
+
inputSchema: {
|
|
5147
|
+
type: "object",
|
|
5148
|
+
properties: {
|
|
5149
|
+
name: { type: "string", minLength: 3, maxLength: 255, description: "Human-readable standard name" },
|
|
5150
|
+
content: {
|
|
5151
|
+
type: "string",
|
|
5152
|
+
minLength: 10,
|
|
5153
|
+
description: "One atomic, actionable standard written as concise Markdown"
|
|
5154
|
+
},
|
|
5155
|
+
parent_id: {
|
|
5156
|
+
type: "string",
|
|
5157
|
+
format: "uuid",
|
|
5158
|
+
description: "Optional parent standard ID when this rule is a child/specialization."
|
|
5159
|
+
},
|
|
5160
|
+
context: { type: "string", description: "Context or category (e.g., 'error-handling', 'security')" },
|
|
5161
|
+
version: { type: "string", description: "Version of the standard (e.g., '1.0.0')" },
|
|
5162
|
+
language: { type: "string", description: "Programming language (e.g., 'typescript', 'python')" },
|
|
5163
|
+
stack: {
|
|
5164
|
+
type: "array",
|
|
5165
|
+
items: { type: "string" },
|
|
5166
|
+
description: "Technology stack (e.g., ['react', 'nextjs'])"
|
|
5167
|
+
},
|
|
5168
|
+
repo: {
|
|
5169
|
+
type: "string",
|
|
5170
|
+
description: "Repository name for repo-specific standards. Omit only for global standards."
|
|
5171
|
+
},
|
|
5172
|
+
is_global: { type: "boolean", description: "Whether standard applies globally or repo-specific" },
|
|
5173
|
+
tags: {
|
|
5174
|
+
type: "array",
|
|
5175
|
+
items: { type: "string" },
|
|
5176
|
+
description: "Tags for categorization"
|
|
5177
|
+
},
|
|
5178
|
+
metadata: {
|
|
5179
|
+
type: "object",
|
|
5180
|
+
description: "Additional metadata"
|
|
5181
|
+
},
|
|
5182
|
+
agent: { type: "string", description: "Agent creating the standard" },
|
|
5183
|
+
model: { type: "string", description: "AI model used" },
|
|
5184
|
+
structured: { type: "boolean", default: false }
|
|
5185
|
+
},
|
|
5186
|
+
required: ["name", "content", "tags", "metadata"]
|
|
5187
|
+
},
|
|
5188
|
+
outputSchema: {
|
|
5189
|
+
type: "object",
|
|
5190
|
+
properties: {
|
|
5191
|
+
success: { type: "boolean" },
|
|
5192
|
+
standard: {
|
|
5193
|
+
type: "object",
|
|
5194
|
+
properties: {
|
|
5195
|
+
id: { type: "string" },
|
|
5196
|
+
title: { type: "string" },
|
|
5197
|
+
content: { type: "string" },
|
|
5198
|
+
parent_id: { type: "string", nullable: true },
|
|
5199
|
+
context: { type: "string" },
|
|
5200
|
+
version: { type: "string" },
|
|
5201
|
+
language: { type: "string", nullable: true },
|
|
5202
|
+
stack: { type: "array", items: { type: "string" } },
|
|
5203
|
+
is_global: { type: "boolean" },
|
|
5204
|
+
repo: { type: "string", nullable: true },
|
|
5205
|
+
tags: { type: "array", items: { type: "string" } },
|
|
5206
|
+
metadata: { type: "object" },
|
|
5207
|
+
created_at: { type: "string" },
|
|
5208
|
+
updated_at: { type: "string" },
|
|
5209
|
+
agent: { type: "string" },
|
|
5210
|
+
model: { type: "string" }
|
|
5211
|
+
},
|
|
5212
|
+
required: [
|
|
5213
|
+
"id",
|
|
5214
|
+
"title",
|
|
5215
|
+
"content",
|
|
5216
|
+
"parent_id",
|
|
5217
|
+
"context",
|
|
5218
|
+
"version",
|
|
5219
|
+
"stack",
|
|
5220
|
+
"is_global",
|
|
5221
|
+
"tags",
|
|
5222
|
+
"metadata",
|
|
5223
|
+
"created_at",
|
|
5224
|
+
"updated_at",
|
|
5225
|
+
"agent",
|
|
5226
|
+
"model"
|
|
5227
|
+
]
|
|
5228
|
+
},
|
|
5229
|
+
message: { type: "string" }
|
|
5230
|
+
},
|
|
5231
|
+
required: ["success", "standard", "message"]
|
|
5232
|
+
}
|
|
5233
|
+
},
|
|
5234
|
+
{
|
|
5235
|
+
name: "standard-update",
|
|
5236
|
+
title: "Standard Update",
|
|
5237
|
+
description: "Update an existing coding standard. Use this when the rule changes, expands scope, or metadata/tags need correction.",
|
|
5238
|
+
annotations: {
|
|
5239
|
+
readOnlyHint: false,
|
|
5240
|
+
idempotentHint: false,
|
|
5241
|
+
destructiveHint: false,
|
|
5242
|
+
openWorldHint: false
|
|
5243
|
+
},
|
|
5244
|
+
inputSchema: {
|
|
5245
|
+
type: "object",
|
|
5246
|
+
properties: {
|
|
5247
|
+
id: { type: "string", description: "Standard ID to update" },
|
|
5248
|
+
name: { type: "string", minLength: 3, maxLength: 255 },
|
|
5249
|
+
content: { type: "string", minLength: 10 },
|
|
5250
|
+
parent_id: { type: "string", format: "uuid", nullable: true },
|
|
5251
|
+
context: { type: "string" },
|
|
5252
|
+
version: { type: "string" },
|
|
5253
|
+
language: { type: "string" },
|
|
5254
|
+
stack: { type: "array", items: { type: "string" } },
|
|
5255
|
+
repo: { type: "string" },
|
|
5256
|
+
is_global: { type: "boolean" },
|
|
5257
|
+
tags: { type: "array", items: { type: "string" } },
|
|
5258
|
+
metadata: { type: "object" },
|
|
5259
|
+
agent: { type: "string" },
|
|
5260
|
+
model: { type: "string" },
|
|
5261
|
+
structured: { type: "boolean", default: false }
|
|
5262
|
+
},
|
|
5263
|
+
required: ["id"]
|
|
5264
|
+
},
|
|
5265
|
+
outputSchema: {
|
|
5266
|
+
type: "object",
|
|
5267
|
+
properties: {
|
|
5268
|
+
success: { type: "boolean" },
|
|
5269
|
+
id: { type: "string" },
|
|
5270
|
+
updatedFields: { type: "array", items: { type: "string" } }
|
|
5271
|
+
},
|
|
5272
|
+
required: ["success", "id", "updatedFields"]
|
|
5174
5273
|
}
|
|
5175
|
-
}
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
}
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
}
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
}
|
|
5234
|
-
function resourceNotFound(message, uri) {
|
|
5235
|
-
const error = new Error(message);
|
|
5236
|
-
error.code = -32002;
|
|
5237
|
-
error.data = { uri };
|
|
5238
|
-
return error;
|
|
5239
|
-
}
|
|
5240
|
-
function invalidCompletionParams(message) {
|
|
5241
|
-
const error = new Error(message);
|
|
5242
|
-
error.code = -32602;
|
|
5243
|
-
return error;
|
|
5244
|
-
}
|
|
5245
|
-
|
|
5246
|
-
// src/mcp/prompts/registry.ts
|
|
5247
|
-
function createPromptDefinition(loaded) {
|
|
5248
|
-
return {
|
|
5249
|
-
name: loaded.name,
|
|
5250
|
-
description: loaded.description,
|
|
5251
|
-
arguments: loaded.arguments,
|
|
5252
|
-
agent: loaded.agent,
|
|
5253
|
-
messages: [
|
|
5254
|
-
{
|
|
5255
|
-
role: "user",
|
|
5256
|
-
content: {
|
|
5257
|
-
type: "text",
|
|
5258
|
-
text: loaded.content
|
|
5274
|
+
},
|
|
5275
|
+
{
|
|
5276
|
+
name: "standard-search",
|
|
5277
|
+
title: "Standard Search",
|
|
5278
|
+
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.",
|
|
5279
|
+
annotations: {
|
|
5280
|
+
readOnlyHint: true,
|
|
5281
|
+
idempotentHint: true,
|
|
5282
|
+
openWorldHint: false
|
|
5283
|
+
},
|
|
5284
|
+
inputSchema: {
|
|
5285
|
+
type: "object",
|
|
5286
|
+
properties: {
|
|
5287
|
+
query: { type: "string", description: "Search query (optional, searches title/content)" },
|
|
5288
|
+
stack: {
|
|
5289
|
+
type: "array",
|
|
5290
|
+
items: { type: "string" },
|
|
5291
|
+
description: "Technology stack to filter by (e.g., ['react', 'nextjs'])"
|
|
5292
|
+
},
|
|
5293
|
+
tags: {
|
|
5294
|
+
type: "array",
|
|
5295
|
+
items: { type: "string" },
|
|
5296
|
+
description: "Tag filter"
|
|
5297
|
+
},
|
|
5298
|
+
language: { type: "string", description: "Programming language filter" },
|
|
5299
|
+
context: { type: "string", description: "Context/category filter" },
|
|
5300
|
+
version: { type: "string", description: "Version filter" },
|
|
5301
|
+
repo: { type: "string", description: "Repository filter (optional)" },
|
|
5302
|
+
is_global: { type: "boolean", description: "Filter by global/repo-specific" },
|
|
5303
|
+
limit: { type: "number", minimum: 1, maximum: 100, default: 20 },
|
|
5304
|
+
offset: { type: "number", minimum: 0, default: 0 },
|
|
5305
|
+
structured: { type: "boolean", default: false }
|
|
5306
|
+
},
|
|
5307
|
+
required: []
|
|
5308
|
+
},
|
|
5309
|
+
outputSchema: {
|
|
5310
|
+
type: "object",
|
|
5311
|
+
properties: {
|
|
5312
|
+
schema: { type: "string", enum: ["standard-search"] },
|
|
5313
|
+
query: { type: "string" },
|
|
5314
|
+
count: { type: "number", description: "Number of rows returned" },
|
|
5315
|
+
total: { type: "number", description: "Total number of matches before pagination" },
|
|
5316
|
+
offset: { type: "number" },
|
|
5317
|
+
limit: { type: "number" },
|
|
5318
|
+
results: {
|
|
5319
|
+
type: "object",
|
|
5320
|
+
properties: {
|
|
5321
|
+
columns: {
|
|
5322
|
+
type: "array",
|
|
5323
|
+
items: { type: "string" }
|
|
5324
|
+
},
|
|
5325
|
+
rows: {
|
|
5326
|
+
type: "array",
|
|
5327
|
+
items: { type: "array" },
|
|
5328
|
+
description: "Each row includes standard id and pointer metadata. Fetch full content via standard-detail."
|
|
5329
|
+
}
|
|
5330
|
+
},
|
|
5331
|
+
required: ["columns", "rows"]
|
|
5259
5332
|
}
|
|
5260
|
-
}
|
|
5261
|
-
|
|
5262
|
-
};
|
|
5263
|
-
}
|
|
5264
|
-
var PROMPTS = {};
|
|
5265
|
-
var promptFiles = listPromptFiles();
|
|
5266
|
-
for (const name of promptFiles) {
|
|
5267
|
-
try {
|
|
5268
|
-
PROMPTS[name] = createPromptDefinition(loadPromptFromMarkdown(name));
|
|
5269
|
-
} catch (e) {
|
|
5270
|
-
logger.warn(`Failed to load prompt ${name}: ${e}`);
|
|
5271
|
-
}
|
|
5272
|
-
}
|
|
5273
|
-
async function listPrompts(db, session, params) {
|
|
5274
|
-
const allPrompts = Object.values(PROMPTS).map((p) => ({
|
|
5275
|
-
name: p.name,
|
|
5276
|
-
description: p.description,
|
|
5277
|
-
arguments: p.arguments,
|
|
5278
|
-
metadata: p.agent ? { agent: p.agent } : void 0
|
|
5279
|
-
}));
|
|
5280
|
-
const rawLimit = typeof params?.limit === "number" && Number.isInteger(params?.limit) ? params.limit : 25;
|
|
5281
|
-
const limit = Math.max(1, Math.min(100, Math.trunc(rawLimit)));
|
|
5282
|
-
const offset = decodeCursor(params?.cursor);
|
|
5283
|
-
const sliced = allPrompts.slice(offset, offset + limit);
|
|
5284
|
-
const nextOffset = offset + sliced.length;
|
|
5285
|
-
return {
|
|
5286
|
-
prompts: sliced,
|
|
5287
|
-
nextCursor: nextOffset < allPrompts.length ? encodeCursor(nextOffset) : void 0
|
|
5288
|
-
};
|
|
5289
|
-
}
|
|
5290
|
-
async function getPrompt(name, args = {}, db, session) {
|
|
5291
|
-
const prompt = PROMPTS[name];
|
|
5292
|
-
if (!prompt) {
|
|
5293
|
-
throw new Error(`Prompt not found: ${name}`);
|
|
5294
|
-
}
|
|
5295
|
-
const inferredRepo = inferRepoFromSession(session);
|
|
5296
|
-
const messages = prompt.messages.map((m) => {
|
|
5297
|
-
let text = m.content.text;
|
|
5298
|
-
for (const [key, value] of Object.entries(args)) {
|
|
5299
|
-
text = text.replace(new RegExp(`\\{{${key}\\}}`, "g"), value);
|
|
5333
|
+
},
|
|
5334
|
+
required: ["schema", "query", "count", "total", "offset", "limit", "results"]
|
|
5300
5335
|
}
|
|
5301
|
-
text = text.replace(/{{current_repo}}/g, inferredRepo || "unknown-repo");
|
|
5302
|
-
return {
|
|
5303
|
-
...m,
|
|
5304
|
-
content: {
|
|
5305
|
-
...m.content,
|
|
5306
|
-
text
|
|
5307
|
-
}
|
|
5308
|
-
};
|
|
5309
|
-
});
|
|
5310
|
-
return {
|
|
5311
|
-
description: prompt.description,
|
|
5312
|
-
messages,
|
|
5313
|
-
metadata: prompt.agent ? { agent: prompt.agent } : void 0
|
|
5314
|
-
};
|
|
5315
|
-
}
|
|
5316
|
-
async function completePromptArgument(name, argName, value, contextArguments, dataSources) {
|
|
5317
|
-
void name;
|
|
5318
|
-
void contextArguments;
|
|
5319
|
-
if (argName === "task_id") {
|
|
5320
|
-
const values = dataSources.tasks.map((t) => t.id);
|
|
5321
|
-
return rankCompletionValues(values, value);
|
|
5322
5336
|
}
|
|
5323
|
-
|
|
5324
|
-
}
|
|
5337
|
+
];
|
|
5325
5338
|
|
|
5326
5339
|
// src/mcp/tools/standard.shared.ts
|
|
5327
5340
|
function toContextSlug(value) {
|
|
@@ -5341,17 +5354,31 @@ function buildStandardVectorText(standard) {
|
|
|
5341
5354
|
}
|
|
5342
5355
|
|
|
5343
5356
|
export {
|
|
5344
|
-
MCP_PROTOCOL_VERSION,
|
|
5345
|
-
CAPABILITIES,
|
|
5346
5357
|
logger,
|
|
5347
5358
|
setLogLevel,
|
|
5348
5359
|
getLogLevel,
|
|
5349
5360
|
addLogSink,
|
|
5350
5361
|
LOG_LEVEL_VALUES,
|
|
5351
5362
|
createFileSink,
|
|
5363
|
+
encodeCursor,
|
|
5364
|
+
decodeCursor,
|
|
5365
|
+
listResources,
|
|
5366
|
+
listResourceTemplates,
|
|
5367
|
+
completeResourceArgument,
|
|
5368
|
+
readResource,
|
|
5369
|
+
createSessionContext,
|
|
5370
|
+
updateSessionFromInitialize,
|
|
5371
|
+
updateSessionRoots,
|
|
5372
|
+
extractRootsFromResult,
|
|
5373
|
+
getFilesystemRoots,
|
|
5374
|
+
isPathWithinRoots,
|
|
5375
|
+
findContainingRoot,
|
|
5376
|
+
inferRepoFromSession,
|
|
5377
|
+
PROMPTS,
|
|
5378
|
+
listPrompts,
|
|
5379
|
+
getPrompt,
|
|
5380
|
+
completePromptArgument,
|
|
5352
5381
|
normalizeRepo,
|
|
5353
|
-
SQLiteStore,
|
|
5354
|
-
RealVectorStore,
|
|
5355
5382
|
MemoryStoreSchema,
|
|
5356
5383
|
MemoryUpdateSchema,
|
|
5357
5384
|
MemorySearchSchema,
|
|
@@ -5379,24 +5406,10 @@ export {
|
|
|
5379
5406
|
StandardUpdateSchema,
|
|
5380
5407
|
StandardSearchSchema,
|
|
5381
5408
|
TOOL_DEFINITIONS,
|
|
5382
|
-
encodeCursor,
|
|
5383
|
-
decodeCursor,
|
|
5384
|
-
listResources,
|
|
5385
|
-
listResourceTemplates,
|
|
5386
|
-
completeResourceArgument,
|
|
5387
|
-
readResource,
|
|
5388
|
-
createSessionContext,
|
|
5389
|
-
updateSessionFromInitialize,
|
|
5390
|
-
updateSessionRoots,
|
|
5391
|
-
extractRootsFromResult,
|
|
5392
|
-
getFilesystemRoots,
|
|
5393
|
-
isPathWithinRoots,
|
|
5394
|
-
findContainingRoot,
|
|
5395
|
-
inferRepoFromSession,
|
|
5396
|
-
PROMPTS,
|
|
5397
|
-
listPrompts,
|
|
5398
|
-
getPrompt,
|
|
5399
|
-
completePromptArgument,
|
|
5400
5409
|
toContextSlug,
|
|
5401
|
-
buildStandardVectorText
|
|
5410
|
+
buildStandardVectorText,
|
|
5411
|
+
SQLiteStore,
|
|
5412
|
+
RealVectorStore,
|
|
5413
|
+
MCP_PROTOCOL_VERSION,
|
|
5414
|
+
CAPABILITIES
|
|
5402
5415
|
};
|