@cognistore/mcp-server 0.9.14 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +255 -57
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ var KnowledgeType;
|
|
|
21
21
|
KnowledgeType2["FIX"] = "fix";
|
|
22
22
|
KnowledgeType2["CONSTRAINT"] = "constraint";
|
|
23
23
|
KnowledgeType2["GOTCHA"] = "gotcha";
|
|
24
|
+
KnowledgeType2["SYSTEM"] = "system";
|
|
24
25
|
})(KnowledgeType || (KnowledgeType = {}));
|
|
25
26
|
var KnowledgeStatus;
|
|
26
27
|
(function(KnowledgeStatus2) {
|
|
@@ -134,7 +135,7 @@ __export(schema_exports, {
|
|
|
134
135
|
|
|
135
136
|
// ../../packages/core/dist/db/schema/knowledge.js
|
|
136
137
|
import { sqliteTable, text, integer, real, index } from "drizzle-orm/sqlite-core";
|
|
137
|
-
var knowledgeTypeEnum = ["decision", "pattern", "fix", "constraint", "gotcha"];
|
|
138
|
+
var knowledgeTypeEnum = ["decision", "pattern", "fix", "constraint", "gotcha", "system"];
|
|
138
139
|
var knowledgeEntries = sqliteTable("knowledge_entries", {
|
|
139
140
|
id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
|
|
140
141
|
title: text("title").notNull().default(""),
|
|
@@ -376,7 +377,7 @@ function createPlansEmbeddingsTable(sqlite) {
|
|
|
376
377
|
}
|
|
377
378
|
|
|
378
379
|
// ../../packages/core/dist/repositories/knowledge.repository.js
|
|
379
|
-
import { eq, sql, and, or, isNull } from "drizzle-orm";
|
|
380
|
+
import { eq, ne, sql, and, or, isNull } from "drizzle-orm";
|
|
380
381
|
var KnowledgeRepository = class {
|
|
381
382
|
db;
|
|
382
383
|
sqlite;
|
|
@@ -461,6 +462,7 @@ var KnowledgeRepository = class {
|
|
|
461
462
|
if (options?.type) {
|
|
462
463
|
conditions.push(eq(knowledgeEntries.type, options.type));
|
|
463
464
|
}
|
|
465
|
+
conditions.push(ne(knowledgeEntries.type, "system"));
|
|
464
466
|
conditions.push(or(isNull(knowledgeEntries.expiresAt), sql`${knowledgeEntries.expiresAt} > ${(/* @__PURE__ */ new Date()).toISOString()}`));
|
|
465
467
|
const whereClause = and(...conditions);
|
|
466
468
|
const entries = await this.db.select().from(knowledgeEntries).where(whereClause);
|
|
@@ -470,27 +472,23 @@ var KnowledgeRepository = class {
|
|
|
470
472
|
})).filter((r) => r.similarity >= threshold).sort((a, b) => b.similarity - a.similarity).slice(0, limit);
|
|
471
473
|
}
|
|
472
474
|
async listRecent(limit = 20, filters) {
|
|
473
|
-
const conditions = [];
|
|
475
|
+
const conditions = [ne(knowledgeEntries.type, "system")];
|
|
474
476
|
if (filters?.type)
|
|
475
477
|
conditions.push(sql`${knowledgeEntries.type} = ${filters.type}`);
|
|
476
478
|
if (filters?.scope)
|
|
477
479
|
conditions.push(sql`${knowledgeEntries.scope} = ${filters.scope}`);
|
|
478
|
-
|
|
479
|
-
return this.db.select().from(knowledgeEntries).orderBy(sql`${knowledgeEntries.createdAt} DESC`).limit(limit);
|
|
480
|
-
}
|
|
481
|
-
const where = conditions.length === 1 ? conditions[0] : sql`${conditions[0]} AND ${conditions[1]}`;
|
|
482
|
-
return this.db.select().from(knowledgeEntries).where(where).orderBy(sql`${knowledgeEntries.createdAt} DESC`).limit(limit);
|
|
480
|
+
return this.db.select().from(knowledgeEntries).where(and(...conditions)).orderBy(sql`${knowledgeEntries.createdAt} DESC`).limit(limit);
|
|
483
481
|
}
|
|
484
482
|
async listTags() {
|
|
485
|
-
const result = await this.db.all(sql`SELECT DISTINCT value FROM knowledge_entries, json_each(knowledge_entries.tags)`);
|
|
483
|
+
const result = await this.db.all(sql`SELECT DISTINCT value FROM knowledge_entries, json_each(knowledge_entries.tags) WHERE knowledge_entries.type != 'system'`);
|
|
486
484
|
return result.map((r) => r.value);
|
|
487
485
|
}
|
|
488
486
|
async topTags(limit = 10) {
|
|
489
|
-
const result = await this.db.all(sql`SELECT value as tag, COUNT(*) as count FROM knowledge_entries, json_each(knowledge_entries.tags) GROUP BY value ORDER BY count DESC LIMIT ${limit}`);
|
|
487
|
+
const result = await this.db.all(sql`SELECT value as tag, COUNT(*) as count FROM knowledge_entries, json_each(knowledge_entries.tags) WHERE knowledge_entries.type != 'system' GROUP BY value ORDER BY count DESC LIMIT ${limit}`);
|
|
490
488
|
return result;
|
|
491
489
|
}
|
|
492
490
|
async count() {
|
|
493
|
-
const [result] = await this.db.select({ count: sql`count(*)` }).from(knowledgeEntries);
|
|
491
|
+
const [result] = await this.db.select({ count: sql`count(*)` }).from(knowledgeEntries).where(ne(knowledgeEntries.type, "system"));
|
|
494
492
|
return Number(result.count);
|
|
495
493
|
}
|
|
496
494
|
async lastUpdatedAt() {
|
|
@@ -501,18 +499,18 @@ var KnowledgeRepository = class {
|
|
|
501
499
|
const results = await this.db.select({
|
|
502
500
|
type: knowledgeEntries.type,
|
|
503
501
|
count: sql`count(*)`
|
|
504
|
-
}).from(knowledgeEntries).groupBy(knowledgeEntries.type);
|
|
502
|
+
}).from(knowledgeEntries).where(ne(knowledgeEntries.type, "system")).groupBy(knowledgeEntries.type);
|
|
505
503
|
return results.map((r) => ({ type: r.type, count: Number(r.count) }));
|
|
506
504
|
}
|
|
507
505
|
async countByScope() {
|
|
508
506
|
const results = await this.db.select({
|
|
509
507
|
scope: knowledgeEntries.scope,
|
|
510
508
|
count: sql`count(*)`
|
|
511
|
-
}).from(knowledgeEntries).groupBy(knowledgeEntries.scope);
|
|
509
|
+
}).from(knowledgeEntries).where(ne(knowledgeEntries.type, "system")).groupBy(knowledgeEntries.scope);
|
|
512
510
|
return results.map((r) => ({ scope: r.scope, count: Number(r.count) }));
|
|
513
511
|
}
|
|
514
512
|
async listAll() {
|
|
515
|
-
return this.db.select().from(knowledgeEntries).orderBy(sql`${knowledgeEntries.createdAt} DESC`);
|
|
513
|
+
return this.db.select().from(knowledgeEntries).where(ne(knowledgeEntries.type, "system")).orderBy(sql`${knowledgeEntries.createdAt} DESC`);
|
|
516
514
|
}
|
|
517
515
|
async listScopes() {
|
|
518
516
|
const rows = this.sqlite.prepare(`SELECT DISTINCT scope FROM knowledge_entries
|
|
@@ -638,6 +636,14 @@ var KnowledgeRepository = class {
|
|
|
638
636
|
getPlanTaskById(id) {
|
|
639
637
|
return this.sqlite.prepare("SELECT * FROM plan_tasks WHERE id = ?").get(id) ?? null;
|
|
640
638
|
}
|
|
639
|
+
getTaskPlanId(taskId) {
|
|
640
|
+
const row = this.sqlite.prepare("SELECT plan_id FROM plan_tasks WHERE id = ?").get(taskId);
|
|
641
|
+
return row?.plan_id ?? null;
|
|
642
|
+
}
|
|
643
|
+
countIncompleteTasks(planId) {
|
|
644
|
+
const row = this.sqlite.prepare("SELECT COUNT(*) as cnt FROM plan_tasks WHERE plan_id = ? AND status != 'completed'").get(planId);
|
|
645
|
+
return row?.cnt ?? 0;
|
|
646
|
+
}
|
|
641
647
|
getPlanTaskStats() {
|
|
642
648
|
const result = this.sqlite.prepare(`
|
|
643
649
|
SELECT
|
|
@@ -766,6 +772,11 @@ var KnowledgeService = class {
|
|
|
766
772
|
const errors = [];
|
|
767
773
|
for (const id of ids) {
|
|
768
774
|
try {
|
|
775
|
+
const entry = await this.repository.findById(id);
|
|
776
|
+
if (entry?.type === "system") {
|
|
777
|
+
errors.push(`Skipped ${id}: system knowledge cannot be deleted`);
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
769
780
|
const result = await this.repository.delete(id);
|
|
770
781
|
if (result) {
|
|
771
782
|
deleted++;
|
|
@@ -858,7 +869,17 @@ var KnowledgeService = class {
|
|
|
858
869
|
}
|
|
859
870
|
updatePlan(id, updates) {
|
|
860
871
|
const row = this.repository.updatePlan(id, updates);
|
|
861
|
-
|
|
872
|
+
if (!row)
|
|
873
|
+
return null;
|
|
874
|
+
if (updates.status === "completed") {
|
|
875
|
+
const tasks = this.repository.listPlanTasks(id);
|
|
876
|
+
for (const t of tasks) {
|
|
877
|
+
if (t.status !== "completed") {
|
|
878
|
+
this.repository.updatePlanTask(t.id, { status: "completed" });
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
return this.toPlan(row);
|
|
862
883
|
}
|
|
863
884
|
deletePlan(id) {
|
|
864
885
|
return this.repository.deletePlan(id);
|
|
@@ -934,7 +955,38 @@ var KnowledgeService = class {
|
|
|
934
955
|
}
|
|
935
956
|
updatePlanTask(id, updates) {
|
|
936
957
|
const row = this.repository.updatePlanTask(id, updates);
|
|
937
|
-
|
|
958
|
+
if (!row)
|
|
959
|
+
return null;
|
|
960
|
+
const task = this.toPlanTask(row);
|
|
961
|
+
const planId = this.repository.getTaskPlanId(id);
|
|
962
|
+
const autoActions = [];
|
|
963
|
+
if (planId) {
|
|
964
|
+
if (updates.status === "in_progress") {
|
|
965
|
+
const plan = this.repository.getPlanById(planId);
|
|
966
|
+
if (plan && (plan.status === "draft" || plan.status === "completed")) {
|
|
967
|
+
this.repository.updatePlan(planId, { status: "active" });
|
|
968
|
+
autoActions.push(`Plan auto-activated from ${plan.status} to active`);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
if (updates.status === "completed") {
|
|
972
|
+
const incomplete = this.repository.countIncompleteTasks(planId);
|
|
973
|
+
if (incomplete === 0) {
|
|
974
|
+
this.repository.updatePlan(planId, { status: "completed" });
|
|
975
|
+
autoActions.push("Plan auto-completed \u2014 all tasks done");
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
const currentPlan = planId ? this.repository.getPlanById(planId) : null;
|
|
980
|
+
const allTasks = planId ? this.repository.listPlanTasks(planId) : [];
|
|
981
|
+
const completedCount = allTasks.filter((t) => t.status === "completed").length;
|
|
982
|
+
const progress = `${completedCount}/${allTasks.length} completed`;
|
|
983
|
+
return {
|
|
984
|
+
task,
|
|
985
|
+
planId: planId ?? "",
|
|
986
|
+
planStatus: currentPlan?.status ?? "unknown",
|
|
987
|
+
progress,
|
|
988
|
+
autoActions
|
|
989
|
+
};
|
|
938
990
|
}
|
|
939
991
|
deletePlanTask(id) {
|
|
940
992
|
return this.repository.deletePlanTask(id);
|
|
@@ -1262,16 +1314,28 @@ var KnowledgeSDK = class {
|
|
|
1262
1314
|
throw new ValidationError(`Invalid updates: ${parsed.error.message}`);
|
|
1263
1315
|
}
|
|
1264
1316
|
try {
|
|
1317
|
+
const existing = await this.service.getById(id);
|
|
1318
|
+
if (existing?.type === "system" && updates.type && updates.type !== "system") {
|
|
1319
|
+
throw new ValidationError("System knowledge type cannot be changed");
|
|
1320
|
+
}
|
|
1265
1321
|
return await this.service.update(id, parsed.data);
|
|
1266
1322
|
} catch (error) {
|
|
1323
|
+
if (error instanceof ValidationError)
|
|
1324
|
+
throw error;
|
|
1267
1325
|
throw this.wrapError(error, "Failed to update knowledge");
|
|
1268
1326
|
}
|
|
1269
1327
|
}
|
|
1270
1328
|
async deleteKnowledge(id) {
|
|
1271
1329
|
this.ensureInitialized();
|
|
1272
1330
|
try {
|
|
1331
|
+
const existing = await this.service.getById(id);
|
|
1332
|
+
if (existing?.type === "system") {
|
|
1333
|
+
throw new ValidationError("System knowledge cannot be deleted");
|
|
1334
|
+
}
|
|
1273
1335
|
return await this.service.delete(id);
|
|
1274
1336
|
} catch (error) {
|
|
1337
|
+
if (error instanceof ValidationError)
|
|
1338
|
+
throw error;
|
|
1275
1339
|
throw this.wrapError(error, "Failed to delete knowledge");
|
|
1276
1340
|
}
|
|
1277
1341
|
}
|
|
@@ -1390,8 +1454,12 @@ var KnowledgeSDK = class {
|
|
|
1390
1454
|
this.ensureInitialized();
|
|
1391
1455
|
return this.service.listPlans(limit, status);
|
|
1392
1456
|
}
|
|
1393
|
-
addPlanRelation(planId, knowledgeId, relationType) {
|
|
1457
|
+
async addPlanRelation(planId, knowledgeId, relationType) {
|
|
1394
1458
|
this.ensureInitialized();
|
|
1459
|
+
const entry = await this.service.getById(knowledgeId);
|
|
1460
|
+
if (entry?.type === "system") {
|
|
1461
|
+
return;
|
|
1462
|
+
}
|
|
1395
1463
|
this.service.addPlanRelation(planId, knowledgeId, relationType);
|
|
1396
1464
|
}
|
|
1397
1465
|
async getPlanRelations(planId) {
|
|
@@ -1411,6 +1479,16 @@ var KnowledgeSDK = class {
|
|
|
1411
1479
|
this.ensureInitialized();
|
|
1412
1480
|
return this.service.updatePlanTask(id, updates);
|
|
1413
1481
|
}
|
|
1482
|
+
updatePlanTasks(updates) {
|
|
1483
|
+
this.ensureInitialized();
|
|
1484
|
+
const results = [];
|
|
1485
|
+
for (const u of updates) {
|
|
1486
|
+
const result = this.service.updatePlanTask(u.taskId, { status: u.status, notes: u.notes });
|
|
1487
|
+
if (result)
|
|
1488
|
+
results.push(result);
|
|
1489
|
+
}
|
|
1490
|
+
return results;
|
|
1491
|
+
}
|
|
1414
1492
|
deletePlanTask(id) {
|
|
1415
1493
|
this.ensureInitialized();
|
|
1416
1494
|
return this.service.deletePlanTask(id);
|
|
@@ -1520,20 +1598,22 @@ var DESTRUCTIVE = { readOnlyHint: false, destructiveHint: true };
|
|
|
1520
1598
|
function createServer(sdk) {
|
|
1521
1599
|
const server = new McpServer({
|
|
1522
1600
|
name: "cognistore",
|
|
1523
|
-
version: "
|
|
1601
|
+
version: "1.0.0"
|
|
1524
1602
|
});
|
|
1603
|
+
let lastSearchResultIds = [];
|
|
1525
1604
|
server.tool(
|
|
1526
1605
|
"addKnowledge",
|
|
1527
|
-
"Store a
|
|
1606
|
+
"Store a knowledge entry. If you have an active plan, ALWAYS pass planId to auto-link as output.",
|
|
1528
1607
|
{
|
|
1529
|
-
title: z2.string().describe("Short descriptive title
|
|
1530
|
-
content: z2.string().describe("The knowledge content text
|
|
1531
|
-
tags: z2.array(z2.string()).describe("
|
|
1532
|
-
type: z2.enum(knowledgeTypeValues).describe("Type
|
|
1608
|
+
title: z2.string().describe("Short descriptive title"),
|
|
1609
|
+
content: z2.string().describe("The knowledge content text"),
|
|
1610
|
+
tags: z2.array(z2.string()).describe("Categorical tags for filtering"),
|
|
1611
|
+
type: z2.enum(knowledgeTypeValues).describe("Type: decision, pattern, fix, constraint, or gotcha"),
|
|
1533
1612
|
scope: z2.string().describe('Scope: "global" or "workspace:<project-name>"'),
|
|
1534
1613
|
source: z2.string().describe("Source of the knowledge"),
|
|
1535
1614
|
confidenceScore: z2.number().min(0).max(1).optional().describe("Confidence score 0-1"),
|
|
1536
|
-
agentId: z2.string().optional().describe("ID of the agent that created this")
|
|
1615
|
+
agentId: z2.string().optional().describe("ID of the agent that created this"),
|
|
1616
|
+
planId: z2.string().optional().describe("Plan ID to auto-link this knowledge as output. ALWAYS pass this if you have an active plan.")
|
|
1537
1617
|
},
|
|
1538
1618
|
WRITE,
|
|
1539
1619
|
async (params) => {
|
|
@@ -1547,12 +1627,69 @@ function createServer(sdk) {
|
|
|
1547
1627
|
confidenceScore: params.confidenceScore,
|
|
1548
1628
|
agentId: params.agentId
|
|
1549
1629
|
});
|
|
1550
|
-
|
|
1630
|
+
let linked = false;
|
|
1631
|
+
let linkWarning = "";
|
|
1632
|
+
if (params.planId && result.type !== "system") {
|
|
1633
|
+
try {
|
|
1634
|
+
await sdk.addPlanRelation(params.planId, result.id, "output");
|
|
1635
|
+
linked = true;
|
|
1636
|
+
} catch (e) {
|
|
1637
|
+
linkWarning = e instanceof Error ? e.message : "Unknown linking error";
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
const response = { entry: result };
|
|
1641
|
+
if (params.planId) {
|
|
1642
|
+
response.linked = linked;
|
|
1643
|
+
response.planId = params.planId;
|
|
1644
|
+
if (linkWarning) response.linkWarning = linkWarning;
|
|
1645
|
+
}
|
|
1646
|
+
return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] };
|
|
1647
|
+
}
|
|
1648
|
+
);
|
|
1649
|
+
server.tool(
|
|
1650
|
+
"addKnowledgeBatch",
|
|
1651
|
+
"Create multiple knowledge entries at once. Pass planId per entry for output linking. Reduces tool calls.",
|
|
1652
|
+
{
|
|
1653
|
+
entries: z2.array(z2.object({
|
|
1654
|
+
title: z2.string(),
|
|
1655
|
+
content: z2.string(),
|
|
1656
|
+
tags: z2.array(z2.string()),
|
|
1657
|
+
type: z2.enum(knowledgeTypeValues),
|
|
1658
|
+
scope: z2.string(),
|
|
1659
|
+
source: z2.string(),
|
|
1660
|
+
planId: z2.string().optional()
|
|
1661
|
+
})).describe("Array of knowledge entries to create")
|
|
1662
|
+
},
|
|
1663
|
+
WRITE,
|
|
1664
|
+
async (params) => {
|
|
1665
|
+
const results = [];
|
|
1666
|
+
for (const e of params.entries) {
|
|
1667
|
+
const entry = await sdk.addKnowledge({
|
|
1668
|
+
title: e.title,
|
|
1669
|
+
content: e.content,
|
|
1670
|
+
tags: e.tags,
|
|
1671
|
+
type: e.type,
|
|
1672
|
+
scope: e.scope,
|
|
1673
|
+
source: e.source
|
|
1674
|
+
});
|
|
1675
|
+
let linked = false;
|
|
1676
|
+
let linkWarning = "";
|
|
1677
|
+
if (e.planId && entry.type !== "system") {
|
|
1678
|
+
try {
|
|
1679
|
+
await sdk.addPlanRelation(e.planId, entry.id, "output");
|
|
1680
|
+
linked = true;
|
|
1681
|
+
} catch (err) {
|
|
1682
|
+
linkWarning = err instanceof Error ? err.message : "Unknown linking error";
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
results.push({ entry, linked, ...e.planId ? { planId: e.planId } : {}, ...linkWarning ? { linkWarning } : {} });
|
|
1686
|
+
}
|
|
1687
|
+
return { content: [{ type: "text", text: JSON.stringify({ created: results.length, entries: results }, null, 2) }] };
|
|
1551
1688
|
}
|
|
1552
1689
|
);
|
|
1553
1690
|
server.tool(
|
|
1554
1691
|
"getKnowledge",
|
|
1555
|
-
"Search knowledge semantically.
|
|
1692
|
+
"Search knowledge semantically. SAVE returned entry IDs \u2014 pass them as relatedKnowledgeIds when calling createPlan.",
|
|
1556
1693
|
{
|
|
1557
1694
|
query: z2.string().describe("Natural language query to search for"),
|
|
1558
1695
|
tags: z2.array(z2.string()).optional().describe("Optional tag filters"),
|
|
@@ -1570,7 +1707,23 @@ function createServer(sdk) {
|
|
|
1570
1707
|
limit: params.limit,
|
|
1571
1708
|
threshold: params.threshold
|
|
1572
1709
|
});
|
|
1573
|
-
|
|
1710
|
+
lastSearchResultIds = results.map((r) => r.entry.id);
|
|
1711
|
+
const response = { results };
|
|
1712
|
+
try {
|
|
1713
|
+
const activePlans = sdk.listPlans(1, "active");
|
|
1714
|
+
const draftPlans = sdk.listPlans(1, "draft");
|
|
1715
|
+
const currentPlan = activePlans[0] || draftPlans[0];
|
|
1716
|
+
if (currentPlan) {
|
|
1717
|
+
response.activePlan = {
|
|
1718
|
+
id: currentPlan.id,
|
|
1719
|
+
title: currentPlan.title,
|
|
1720
|
+
status: currentPlan.status,
|
|
1721
|
+
hint: "Pass this planId to addKnowledge calls for output linking."
|
|
1722
|
+
};
|
|
1723
|
+
}
|
|
1724
|
+
} catch {
|
|
1725
|
+
}
|
|
1726
|
+
return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] };
|
|
1574
1727
|
}
|
|
1575
1728
|
);
|
|
1576
1729
|
server.tool(
|
|
@@ -1598,8 +1751,8 @@ function createServer(sdk) {
|
|
|
1598
1751
|
source: updates.source,
|
|
1599
1752
|
confidenceScore: updates.confidenceScore
|
|
1600
1753
|
});
|
|
1601
|
-
|
|
1602
|
-
return { content: [{ type: "text", text:
|
|
1754
|
+
if (!result) return { content: [{ type: "text", text: JSON.stringify({ error: "not_found", type: "knowledge_entry", id }) }] };
|
|
1755
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1603
1756
|
}
|
|
1604
1757
|
);
|
|
1605
1758
|
server.tool(
|
|
@@ -1611,9 +1764,8 @@ function createServer(sdk) {
|
|
|
1611
1764
|
DESTRUCTIVE,
|
|
1612
1765
|
async (params) => {
|
|
1613
1766
|
const deleted = await sdk.deleteKnowledge(params.id);
|
|
1614
|
-
return {
|
|
1615
|
-
|
|
1616
|
-
};
|
|
1767
|
+
if (!deleted) return { content: [{ type: "text", text: JSON.stringify({ error: "not_found", type: "knowledge_entry", id: params.id }) }] };
|
|
1768
|
+
return { content: [{ type: "text", text: JSON.stringify({ deleted: true, id: params.id }) }] };
|
|
1617
1769
|
}
|
|
1618
1770
|
);
|
|
1619
1771
|
server.tool(
|
|
@@ -1638,70 +1790,83 @@ function createServer(sdk) {
|
|
|
1638
1790
|
);
|
|
1639
1791
|
server.tool(
|
|
1640
1792
|
"createPlan",
|
|
1641
|
-
"Create a
|
|
1793
|
+
"Create a plan with tasks. Plan auto-activates when the first task starts. Returns planId \u2014 SAVE IT and pass to addKnowledge calls.",
|
|
1642
1794
|
{
|
|
1643
1795
|
title: z2.string().describe("Plan title (short, descriptive)"),
|
|
1644
1796
|
content: z2.string().describe("Full plan content (steps, approach, considerations)"),
|
|
1645
1797
|
tags: z2.array(z2.string()).describe("Tags for categorization"),
|
|
1646
1798
|
scope: z2.string().describe('Scope: "global" or "workspace:<project-name>"'),
|
|
1647
1799
|
source: z2.string().describe("Source/context of the plan"),
|
|
1648
|
-
relatedKnowledgeIds: z2.array(z2.string()).optional().describe("IDs of knowledge entries consulted during planning (input
|
|
1800
|
+
relatedKnowledgeIds: z2.array(z2.string()).optional().describe("IDs of knowledge entries consulted during planning (auto-linked as input)"),
|
|
1649
1801
|
tasks: z2.array(z2.object({
|
|
1650
1802
|
description: z2.string(),
|
|
1651
1803
|
priority: z2.enum(["low", "medium", "high"]).optional()
|
|
1652
|
-
})).optional().describe("
|
|
1804
|
+
})).optional().describe("Tasks for the plan. ALWAYS include tasks for multi-step work.")
|
|
1653
1805
|
},
|
|
1654
1806
|
WRITE,
|
|
1655
1807
|
async (params) => {
|
|
1808
|
+
const inputIds = /* @__PURE__ */ new Set([
|
|
1809
|
+
...params.relatedKnowledgeIds || [],
|
|
1810
|
+
...lastSearchResultIds
|
|
1811
|
+
]);
|
|
1656
1812
|
const result = await sdk.createPlan({
|
|
1657
1813
|
title: params.title,
|
|
1658
1814
|
content: params.content,
|
|
1659
1815
|
tags: params.tags,
|
|
1660
1816
|
scope: params.scope,
|
|
1661
1817
|
source: params.source,
|
|
1662
|
-
relatedKnowledgeIds:
|
|
1818
|
+
relatedKnowledgeIds: inputIds.size > 0 ? [...inputIds] : void 0,
|
|
1663
1819
|
tasks: params.tasks
|
|
1664
1820
|
});
|
|
1665
|
-
|
|
1821
|
+
lastSearchResultIds = [];
|
|
1822
|
+
const response = {
|
|
1823
|
+
...result,
|
|
1824
|
+
reminder: `Your plan ID is "${result.id}". Pass planId: "${result.id}" to every addKnowledge call for output linking. Plan auto-activates when you start the first task.`
|
|
1825
|
+
};
|
|
1826
|
+
return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] };
|
|
1666
1827
|
}
|
|
1667
1828
|
);
|
|
1668
1829
|
server.tool(
|
|
1669
1830
|
"updatePlan",
|
|
1670
|
-
"Update
|
|
1831
|
+
"Update a plan. Status lifecycle: draft \u2192 active \u2192 completed. Plan auto-activates and auto-completes via task updates \u2014 usually you do not need to call this manually.",
|
|
1671
1832
|
{
|
|
1672
1833
|
planId: z2.string().describe("UUID of the plan to update"),
|
|
1673
1834
|
title: z2.string().optional().describe("New title"),
|
|
1674
1835
|
content: z2.string().optional().describe("New content"),
|
|
1675
1836
|
tags: z2.array(z2.string()).optional().describe("New tags"),
|
|
1676
1837
|
scope: z2.string().optional().describe("New scope"),
|
|
1677
|
-
status: z2.enum(knowledgeStatusValues).optional().describe("New status"),
|
|
1838
|
+
status: z2.enum(knowledgeStatusValues).optional().describe("New status (usually auto-managed)"),
|
|
1678
1839
|
source: z2.string().optional().describe("New source")
|
|
1679
1840
|
},
|
|
1680
1841
|
WRITE,
|
|
1681
1842
|
async (params) => {
|
|
1682
1843
|
const { planId, ...updates } = params;
|
|
1683
1844
|
const result = sdk.updatePlan(planId, updates);
|
|
1684
|
-
|
|
1685
|
-
return { content: [{ type: "text", text:
|
|
1845
|
+
if (!result) return { content: [{ type: "text", text: JSON.stringify({ error: "not_found", type: "plan", id: planId }) }] };
|
|
1846
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1686
1847
|
}
|
|
1687
1848
|
);
|
|
1688
1849
|
server.tool(
|
|
1689
1850
|
"addPlanRelation",
|
|
1690
|
-
|
|
1851
|
+
"Link a knowledge entry to a plan. Input = consulted during planning, output = created during execution. Usually auto-handled \u2014 use only for manual linking.",
|
|
1691
1852
|
{
|
|
1692
1853
|
planId: z2.string().describe("UUID of the plan"),
|
|
1693
1854
|
knowledgeId: z2.string().describe("UUID of the knowledge entry to link"),
|
|
1694
|
-
relationType: z2.enum(["input", "output"]).describe('"input" = consulted
|
|
1855
|
+
relationType: z2.enum(["input", "output"]).describe('"input" = consulted, "output" = produced')
|
|
1695
1856
|
},
|
|
1696
1857
|
WRITE,
|
|
1697
1858
|
async (params) => {
|
|
1698
|
-
|
|
1699
|
-
|
|
1859
|
+
try {
|
|
1860
|
+
sdk.addPlanRelation(params.planId, params.knowledgeId, params.relationType);
|
|
1861
|
+
return { content: [{ type: "text", text: JSON.stringify({ success: true, ...params }) }] };
|
|
1862
|
+
} catch (e) {
|
|
1863
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: "link_failed", message: e instanceof Error ? e.message : "Unknown error", ...params }) }] };
|
|
1864
|
+
}
|
|
1700
1865
|
}
|
|
1701
1866
|
);
|
|
1702
1867
|
server.tool(
|
|
1703
1868
|
"addPlanTask",
|
|
1704
|
-
"Add a task to a plan
|
|
1869
|
+
"Add a task to a plan. Position is auto-calculated.",
|
|
1705
1870
|
{
|
|
1706
1871
|
planId: z2.string().describe("UUID of the plan"),
|
|
1707
1872
|
description: z2.string().describe("Task description"),
|
|
@@ -1716,7 +1881,7 @@ function createServer(sdk) {
|
|
|
1716
1881
|
);
|
|
1717
1882
|
server.tool(
|
|
1718
1883
|
"updatePlanTask",
|
|
1719
|
-
"Update a
|
|
1884
|
+
"Update a task status. Plan auto-activates on first in_progress and auto-completes when all tasks are done.",
|
|
1720
1885
|
{
|
|
1721
1886
|
taskId: z2.string().describe("UUID of the task"),
|
|
1722
1887
|
status: z2.enum(["pending", "in_progress", "completed"]).optional().describe("New status"),
|
|
@@ -1727,21 +1892,58 @@ function createServer(sdk) {
|
|
|
1727
1892
|
WRITE,
|
|
1728
1893
|
async (params) => {
|
|
1729
1894
|
const { taskId, ...updates } = params;
|
|
1730
|
-
const
|
|
1731
|
-
|
|
1732
|
-
|
|
1895
|
+
const result = sdk.updatePlanTask(taskId, updates);
|
|
1896
|
+
if (!result) return { content: [{ type: "text", text: JSON.stringify({ error: "not_found", type: "plan_task", id: taskId }) }] };
|
|
1897
|
+
const response = {
|
|
1898
|
+
task: result.task,
|
|
1899
|
+
plan: { id: result.planId, status: result.planStatus, progress: result.progress },
|
|
1900
|
+
...result.autoActions.length > 0 ? { autoActions: result.autoActions } : {},
|
|
1901
|
+
reminder: `Plan ID: "${result.planId}". Pass this planId to addKnowledge calls for output linking.`
|
|
1902
|
+
};
|
|
1903
|
+
return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] };
|
|
1904
|
+
}
|
|
1905
|
+
);
|
|
1906
|
+
server.tool(
|
|
1907
|
+
"updatePlanTasks",
|
|
1908
|
+
"Update multiple tasks at once. Reduces tool calls. Plan auto-activates and auto-completes automatically.",
|
|
1909
|
+
{
|
|
1910
|
+
updates: z2.array(z2.object({
|
|
1911
|
+
taskId: z2.string().describe("UUID of the task"),
|
|
1912
|
+
status: z2.enum(["pending", "in_progress", "completed"]).optional(),
|
|
1913
|
+
notes: z2.string().nullable().optional()
|
|
1914
|
+
})).describe("Array of task updates")
|
|
1915
|
+
},
|
|
1916
|
+
WRITE,
|
|
1917
|
+
async (params) => {
|
|
1918
|
+
const results = sdk.updatePlanTasks(params.updates);
|
|
1919
|
+
const allAutoActions = results.flatMap((r) => r.autoActions);
|
|
1920
|
+
const lastResult = results[results.length - 1];
|
|
1921
|
+
const response = {
|
|
1922
|
+
updated: results.length,
|
|
1923
|
+
tasks: results.map((r) => ({ id: r.task.id, status: r.task.status, description: r.task.description })),
|
|
1924
|
+
plan: lastResult ? { id: lastResult.planId, status: lastResult.planStatus, progress: lastResult.progress } : void 0,
|
|
1925
|
+
...allAutoActions.length > 0 ? { autoActions: allAutoActions } : {},
|
|
1926
|
+
reminder: lastResult ? `Plan ID: "${lastResult.planId}". Pass this planId to addKnowledge calls.` : void 0
|
|
1927
|
+
};
|
|
1928
|
+
return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] };
|
|
1733
1929
|
}
|
|
1734
1930
|
);
|
|
1735
1931
|
server.tool(
|
|
1736
1932
|
"listPlanTasks",
|
|
1737
|
-
"List all tasks for a plan, ordered by position.
|
|
1933
|
+
"List all tasks for a plan, ordered by position. Shows progress.",
|
|
1738
1934
|
{
|
|
1739
1935
|
planId: z2.string().describe("UUID of the plan")
|
|
1740
1936
|
},
|
|
1741
1937
|
READ_ONLY,
|
|
1742
1938
|
async (params) => {
|
|
1743
1939
|
const tasks = sdk.listPlanTasks(params.planId);
|
|
1744
|
-
|
|
1940
|
+
const completed = tasks.filter((t) => t.status === "completed").length;
|
|
1941
|
+
const response = {
|
|
1942
|
+
tasks,
|
|
1943
|
+
progress: `${completed}/${tasks.length} completed`,
|
|
1944
|
+
reminder: `Plan ID: "${params.planId}". Pass this planId to addKnowledge calls for output linking.`
|
|
1945
|
+
};
|
|
1946
|
+
return { content: [{ type: "text", text: JSON.stringify(response, null, 2) }] };
|
|
1745
1947
|
}
|
|
1746
1948
|
);
|
|
1747
1949
|
server.resource(
|
|
@@ -1753,11 +1955,7 @@ function createServer(sdk) {
|
|
|
1753
1955
|
const scopeFilter = scope === "global" ? void 0 : `workspace:${scope}`;
|
|
1754
1956
|
let knowledgeSection = "";
|
|
1755
1957
|
try {
|
|
1756
|
-
const results = await sdk.getKnowledge("*", {
|
|
1757
|
-
scope: scopeFilter,
|
|
1758
|
-
limit: 10,
|
|
1759
|
-
threshold: 0
|
|
1760
|
-
});
|
|
1958
|
+
const results = await sdk.getKnowledge("*", { scope: scopeFilter, limit: 10, threshold: 0 });
|
|
1761
1959
|
if (results.length > 0) {
|
|
1762
1960
|
knowledgeSection = "## Recent Knowledge\n\n" + results.map(
|
|
1763
1961
|
(r) => `- **${r.entry.title}** (${r.entry.type}, ${r.entry.scope})
|