@contextstream/mcp-server 0.3.14 → 0.3.15
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 +291 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5085,6 +5085,19 @@ var ContextStreamClient = class {
|
|
|
5085
5085
|
if (batchedContext.relevant_context) {
|
|
5086
5086
|
context.relevant_context = batchedContext.relevant_context;
|
|
5087
5087
|
}
|
|
5088
|
+
try {
|
|
5089
|
+
const lessons = await this.getHighPriorityLessons({
|
|
5090
|
+
workspace_id: workspaceId,
|
|
5091
|
+
project_id: projectId,
|
|
5092
|
+
context_hint: params.context_hint,
|
|
5093
|
+
limit: 5
|
|
5094
|
+
});
|
|
5095
|
+
if (lessons.length > 0) {
|
|
5096
|
+
context.lessons = lessons;
|
|
5097
|
+
context.lessons_warning = `\u26A0\uFE0F ${lessons.length} lesson(s) from past mistakes. Review before making changes.`;
|
|
5098
|
+
}
|
|
5099
|
+
} catch {
|
|
5100
|
+
}
|
|
5088
5101
|
} catch (e) {
|
|
5089
5102
|
console.error("[ContextStream] Batched endpoint failed, falling back to individual calls:", e);
|
|
5090
5103
|
await this._fetchSessionContextFallback(context, workspaceId, projectId, params);
|
|
@@ -5158,6 +5171,19 @@ var ContextStreamClient = class {
|
|
|
5158
5171
|
} catch {
|
|
5159
5172
|
}
|
|
5160
5173
|
}
|
|
5174
|
+
try {
|
|
5175
|
+
const lessons = await this.getHighPriorityLessons({
|
|
5176
|
+
workspace_id: workspaceId,
|
|
5177
|
+
project_id: projectId,
|
|
5178
|
+
context_hint: params.context_hint,
|
|
5179
|
+
limit: 5
|
|
5180
|
+
});
|
|
5181
|
+
if (lessons.length > 0) {
|
|
5182
|
+
context.lessons = lessons;
|
|
5183
|
+
context.lessons_warning = `\u26A0\uFE0F ${lessons.length} lesson(s) from past mistakes. Review before making changes.`;
|
|
5184
|
+
}
|
|
5185
|
+
} catch {
|
|
5186
|
+
}
|
|
5161
5187
|
}
|
|
5162
5188
|
/**
|
|
5163
5189
|
* Associate a folder with a workspace (called after user selects from candidates).
|
|
@@ -5236,6 +5262,17 @@ var ContextStreamClient = class {
|
|
|
5236
5262
|
apiEventType = "manual_note";
|
|
5237
5263
|
tags.push(params.event_type);
|
|
5238
5264
|
break;
|
|
5265
|
+
// Lesson system types - all stored as manual_note with specific tags
|
|
5266
|
+
case "correction":
|
|
5267
|
+
case "lesson":
|
|
5268
|
+
case "warning":
|
|
5269
|
+
case "frustration":
|
|
5270
|
+
apiEventType = "manual_note";
|
|
5271
|
+
tags.push(params.event_type);
|
|
5272
|
+
if (!tags.includes("lesson_system")) {
|
|
5273
|
+
tags.push("lesson_system");
|
|
5274
|
+
}
|
|
5275
|
+
break;
|
|
5239
5276
|
default:
|
|
5240
5277
|
apiEventType = "manual_note";
|
|
5241
5278
|
tags.push(params.event_type);
|
|
@@ -5740,6 +5777,25 @@ var ContextStreamClient = class {
|
|
|
5740
5777
|
} catch {
|
|
5741
5778
|
}
|
|
5742
5779
|
}
|
|
5780
|
+
try {
|
|
5781
|
+
const lessons = await this.getHighPriorityLessons({
|
|
5782
|
+
workspace_id: withDefaults.workspace_id,
|
|
5783
|
+
project_id: withDefaults.project_id,
|
|
5784
|
+
context_hint: params.user_message,
|
|
5785
|
+
limit: 3
|
|
5786
|
+
});
|
|
5787
|
+
for (const lesson of lessons) {
|
|
5788
|
+
const prefix = lesson.severity === "critical" ? "\u26A0\uFE0F " : "";
|
|
5789
|
+
items.push({
|
|
5790
|
+
type: "L",
|
|
5791
|
+
key: "lesson",
|
|
5792
|
+
value: `${prefix}${lesson.title}: ${lesson.prevention.slice(0, 100)}`,
|
|
5793
|
+
relevance: lesson.severity === "critical" ? 1 : 0.9
|
|
5794
|
+
// Lessons are high priority
|
|
5795
|
+
});
|
|
5796
|
+
}
|
|
5797
|
+
} catch {
|
|
5798
|
+
}
|
|
5743
5799
|
items.sort((a, b) => b.relevance - a.relevance);
|
|
5744
5800
|
let context;
|
|
5745
5801
|
let charsUsed = 0;
|
|
@@ -5780,6 +5836,51 @@ var ContextStreamClient = class {
|
|
|
5780
5836
|
sources_used: items.filter((i) => context.includes(i.value.slice(0, 20))).length
|
|
5781
5837
|
};
|
|
5782
5838
|
}
|
|
5839
|
+
/**
|
|
5840
|
+
* Get high-priority lessons that should be surfaced proactively.
|
|
5841
|
+
* Returns critical and high severity lessons for warnings.
|
|
5842
|
+
*/
|
|
5843
|
+
async getHighPriorityLessons(params) {
|
|
5844
|
+
const limit = params.limit || 5;
|
|
5845
|
+
try {
|
|
5846
|
+
const searchQuery = params.context_hint ? `${params.context_hint} lesson warning prevention mistake` : "lesson warning prevention mistake critical high";
|
|
5847
|
+
const searchResult = await this.memorySearch({
|
|
5848
|
+
query: searchQuery,
|
|
5849
|
+
workspace_id: params.workspace_id,
|
|
5850
|
+
project_id: params.project_id,
|
|
5851
|
+
limit: limit * 2
|
|
5852
|
+
// Fetch more to filter
|
|
5853
|
+
});
|
|
5854
|
+
if (!searchResult?.results) return [];
|
|
5855
|
+
const lessons = searchResult.results.filter((item) => {
|
|
5856
|
+
const tags = item.metadata?.tags || [];
|
|
5857
|
+
const isLesson = tags.includes("lesson") || tags.includes("lesson_system");
|
|
5858
|
+
if (!isLesson) return false;
|
|
5859
|
+
const severityTag = tags.find((t) => t.startsWith("severity:"));
|
|
5860
|
+
const severity = severityTag?.split(":")[1] || item.metadata?.importance || "medium";
|
|
5861
|
+
return severity === "critical" || severity === "high";
|
|
5862
|
+
}).slice(0, limit).map((item) => {
|
|
5863
|
+
const tags = item.metadata?.tags || [];
|
|
5864
|
+
const severityTag = tags.find((t) => t.startsWith("severity:"));
|
|
5865
|
+
const severity = severityTag?.split(":")[1] || item.metadata?.importance || "medium";
|
|
5866
|
+
const category = tags.find(
|
|
5867
|
+
(t) => ["workflow", "code_quality", "verification", "communication", "project_specific"].includes(t)
|
|
5868
|
+
) || "unknown";
|
|
5869
|
+
const content = item.content || "";
|
|
5870
|
+
const preventionMatch = content.match(/### Prevention\n([\s\S]*?)(?:\n\n|\n\*\*|$)/);
|
|
5871
|
+
const prevention = preventionMatch?.[1]?.trim() || content.slice(0, 200);
|
|
5872
|
+
return {
|
|
5873
|
+
title: item.title || "Lesson",
|
|
5874
|
+
severity,
|
|
5875
|
+
category,
|
|
5876
|
+
prevention
|
|
5877
|
+
};
|
|
5878
|
+
});
|
|
5879
|
+
return lessons;
|
|
5880
|
+
} catch {
|
|
5881
|
+
return [];
|
|
5882
|
+
}
|
|
5883
|
+
}
|
|
5783
5884
|
/**
|
|
5784
5885
|
* Extract keywords from a message for relevance matching
|
|
5785
5886
|
*/
|
|
@@ -7081,7 +7182,24 @@ Use this to persist decisions, insights, preferences, or important information.`
|
|
|
7081
7182
|
workspace_id: external_exports.string().uuid().optional(),
|
|
7082
7183
|
project_id: external_exports.string().uuid().optional(),
|
|
7083
7184
|
session_id: external_exports.string().optional().describe("Session ID to associate with this capture"),
|
|
7084
|
-
event_type: external_exports.enum([
|
|
7185
|
+
event_type: external_exports.enum([
|
|
7186
|
+
"conversation",
|
|
7187
|
+
"decision",
|
|
7188
|
+
"insight",
|
|
7189
|
+
"preference",
|
|
7190
|
+
"task",
|
|
7191
|
+
"bug",
|
|
7192
|
+
"feature",
|
|
7193
|
+
// Lesson system types
|
|
7194
|
+
"correction",
|
|
7195
|
+
// User corrected the AI
|
|
7196
|
+
"lesson",
|
|
7197
|
+
// Extracted lesson from correction
|
|
7198
|
+
"warning",
|
|
7199
|
+
// Proactive reminder
|
|
7200
|
+
"frustration"
|
|
7201
|
+
// User expressed frustration
|
|
7202
|
+
]).describe("Type of context being captured"),
|
|
7085
7203
|
title: external_exports.string().describe("Brief title for the captured context"),
|
|
7086
7204
|
content: external_exports.string().describe("Full content/details to capture"),
|
|
7087
7205
|
tags: external_exports.array(external_exports.string()).optional().describe("Tags for categorization"),
|
|
@@ -7115,6 +7233,178 @@ Use this to persist decisions, insights, preferences, or important information.`
|
|
|
7115
7233
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
7116
7234
|
}
|
|
7117
7235
|
);
|
|
7236
|
+
registerTool(
|
|
7237
|
+
"session_capture_lesson",
|
|
7238
|
+
{
|
|
7239
|
+
title: "Capture a lesson learned",
|
|
7240
|
+
description: `Capture a lesson learned from a mistake or correction.
|
|
7241
|
+
Use this when the user corrects you, expresses frustration, or points out an error.
|
|
7242
|
+
These lessons are surfaced in future sessions to prevent repeating the same mistakes.
|
|
7243
|
+
|
|
7244
|
+
Example triggers:
|
|
7245
|
+
- User says "No, you should..." or "That's wrong"
|
|
7246
|
+
- User expresses frustration (caps, "COME ON", "WTF")
|
|
7247
|
+
- Code breaks due to a preventable mistake
|
|
7248
|
+
|
|
7249
|
+
The lesson will be tagged with 'lesson' and stored with structured metadata for easy retrieval.`,
|
|
7250
|
+
inputSchema: external_exports.object({
|
|
7251
|
+
workspace_id: external_exports.string().uuid().optional(),
|
|
7252
|
+
project_id: external_exports.string().uuid().optional(),
|
|
7253
|
+
title: external_exports.string().describe('Lesson title - what to remember (e.g., "Always verify assets in git before pushing")'),
|
|
7254
|
+
severity: external_exports.enum(["low", "medium", "high", "critical"]).default("medium").describe("Severity: critical for production issues, high for breaking changes, medium for workflow, low for minor"),
|
|
7255
|
+
category: external_exports.enum(["workflow", "code_quality", "verification", "communication", "project_specific"]).describe("Category of the lesson"),
|
|
7256
|
+
trigger: external_exports.string().describe('What action caused the problem (e.g., "Pushed code referencing images without committing them")'),
|
|
7257
|
+
impact: external_exports.string().describe('What went wrong (e.g., "Production 404 errors - broken landing page")'),
|
|
7258
|
+
prevention: external_exports.string().describe('How to prevent in future (e.g., "Run git status to check untracked files before pushing")'),
|
|
7259
|
+
keywords: external_exports.array(external_exports.string()).optional().describe('Keywords for matching in future contexts (e.g., ["git", "images", "assets", "push"])')
|
|
7260
|
+
})
|
|
7261
|
+
},
|
|
7262
|
+
async (input) => {
|
|
7263
|
+
let workspaceId = input.workspace_id;
|
|
7264
|
+
let projectId = input.project_id;
|
|
7265
|
+
if (!workspaceId && sessionManager) {
|
|
7266
|
+
const ctx = sessionManager.getContext();
|
|
7267
|
+
if (ctx) {
|
|
7268
|
+
workspaceId = ctx.workspace_id;
|
|
7269
|
+
projectId = projectId || ctx.project_id;
|
|
7270
|
+
}
|
|
7271
|
+
}
|
|
7272
|
+
if (!workspaceId) {
|
|
7273
|
+
return {
|
|
7274
|
+
content: [{
|
|
7275
|
+
type: "text",
|
|
7276
|
+
text: "Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly."
|
|
7277
|
+
}],
|
|
7278
|
+
isError: true
|
|
7279
|
+
};
|
|
7280
|
+
}
|
|
7281
|
+
const lessonContent = [
|
|
7282
|
+
`## ${input.title}`,
|
|
7283
|
+
"",
|
|
7284
|
+
`**Severity:** ${input.severity}`,
|
|
7285
|
+
`**Category:** ${input.category}`,
|
|
7286
|
+
"",
|
|
7287
|
+
"### Trigger",
|
|
7288
|
+
input.trigger,
|
|
7289
|
+
"",
|
|
7290
|
+
"### Impact",
|
|
7291
|
+
input.impact,
|
|
7292
|
+
"",
|
|
7293
|
+
"### Prevention",
|
|
7294
|
+
input.prevention,
|
|
7295
|
+
input.keywords?.length ? `
|
|
7296
|
+
**Keywords:** ${input.keywords.join(", ")}` : ""
|
|
7297
|
+
].filter(Boolean).join("\n");
|
|
7298
|
+
const result = await client.captureContext({
|
|
7299
|
+
workspace_id: workspaceId,
|
|
7300
|
+
project_id: projectId,
|
|
7301
|
+
event_type: "lesson",
|
|
7302
|
+
title: input.title,
|
|
7303
|
+
content: lessonContent,
|
|
7304
|
+
importance: input.severity,
|
|
7305
|
+
tags: [
|
|
7306
|
+
"lesson",
|
|
7307
|
+
input.category,
|
|
7308
|
+
`severity:${input.severity}`,
|
|
7309
|
+
...input.keywords || []
|
|
7310
|
+
]
|
|
7311
|
+
});
|
|
7312
|
+
return {
|
|
7313
|
+
content: [{
|
|
7314
|
+
type: "text",
|
|
7315
|
+
text: `\u2705 Lesson captured: "${input.title}"
|
|
7316
|
+
|
|
7317
|
+
This lesson will be surfaced in future sessions when relevant context is detected.`
|
|
7318
|
+
}],
|
|
7319
|
+
structuredContent: toStructured(result)
|
|
7320
|
+
};
|
|
7321
|
+
}
|
|
7322
|
+
);
|
|
7323
|
+
registerTool(
|
|
7324
|
+
"session_get_lessons",
|
|
7325
|
+
{
|
|
7326
|
+
title: "Get lessons learned",
|
|
7327
|
+
description: `Retrieve lessons learned from past mistakes and corrections.
|
|
7328
|
+
Use this to check for relevant warnings before taking actions that have caused problems before.
|
|
7329
|
+
|
|
7330
|
+
Returns lessons filtered by:
|
|
7331
|
+
- Query: semantic search for relevant lessons
|
|
7332
|
+
- Category: workflow, code_quality, verification, communication, project_specific
|
|
7333
|
+
- Severity: low, medium, high, critical`,
|
|
7334
|
+
inputSchema: external_exports.object({
|
|
7335
|
+
workspace_id: external_exports.string().uuid().optional(),
|
|
7336
|
+
project_id: external_exports.string().uuid().optional(),
|
|
7337
|
+
query: external_exports.string().optional().describe('Search for relevant lessons (e.g., "git push images")'),
|
|
7338
|
+
category: external_exports.enum(["workflow", "code_quality", "verification", "communication", "project_specific"]).optional().describe("Filter by category"),
|
|
7339
|
+
severity: external_exports.enum(["low", "medium", "high", "critical"]).optional().describe("Filter by minimum severity"),
|
|
7340
|
+
limit: external_exports.number().default(10).describe("Maximum lessons to return")
|
|
7341
|
+
})
|
|
7342
|
+
},
|
|
7343
|
+
async (input) => {
|
|
7344
|
+
let workspaceId = input.workspace_id;
|
|
7345
|
+
let projectId = input.project_id;
|
|
7346
|
+
if (!workspaceId && sessionManager) {
|
|
7347
|
+
const ctx = sessionManager.getContext();
|
|
7348
|
+
if (ctx) {
|
|
7349
|
+
workspaceId = ctx.workspace_id;
|
|
7350
|
+
projectId = projectId || ctx.project_id;
|
|
7351
|
+
}
|
|
7352
|
+
}
|
|
7353
|
+
const searchQuery = input.query ? `${input.query} lesson prevention warning` : "lesson prevention warning mistake";
|
|
7354
|
+
const searchResult = await client.memorySearch({
|
|
7355
|
+
query: searchQuery,
|
|
7356
|
+
workspace_id: workspaceId,
|
|
7357
|
+
project_id: projectId,
|
|
7358
|
+
limit: input.limit * 2
|
|
7359
|
+
// Fetch more to filter
|
|
7360
|
+
});
|
|
7361
|
+
let lessons = (searchResult?.results || []).filter((item) => {
|
|
7362
|
+
const tags = item.metadata?.tags || [];
|
|
7363
|
+
const isLesson = tags.includes("lesson");
|
|
7364
|
+
if (!isLesson) return false;
|
|
7365
|
+
if (input.category && !tags.includes(input.category)) {
|
|
7366
|
+
return false;
|
|
7367
|
+
}
|
|
7368
|
+
if (input.severity) {
|
|
7369
|
+
const severityOrder = ["low", "medium", "high", "critical"];
|
|
7370
|
+
const minSeverityIndex = severityOrder.indexOf(input.severity);
|
|
7371
|
+
const itemSeverity = tags.find((t) => t.startsWith("severity:"))?.split(":")[1] || "medium";
|
|
7372
|
+
const itemSeverityIndex = severityOrder.indexOf(itemSeverity);
|
|
7373
|
+
if (itemSeverityIndex < minSeverityIndex) return false;
|
|
7374
|
+
}
|
|
7375
|
+
return true;
|
|
7376
|
+
}).slice(0, input.limit);
|
|
7377
|
+
if (lessons.length === 0) {
|
|
7378
|
+
return {
|
|
7379
|
+
content: [{ type: "text", text: "No lessons found matching your criteria." }],
|
|
7380
|
+
structuredContent: toStructured({ lessons: [], count: 0 })
|
|
7381
|
+
};
|
|
7382
|
+
}
|
|
7383
|
+
const formattedLessons = lessons.map((lesson, i) => {
|
|
7384
|
+
const tags = lesson.metadata?.tags || [];
|
|
7385
|
+
const severity = tags.find((t) => t.startsWith("severity:"))?.split(":")[1] || "medium";
|
|
7386
|
+
const category = tags.find((t) => ["workflow", "code_quality", "verification", "communication", "project_specific"].includes(t)) || "unknown";
|
|
7387
|
+
const severityEmoji = {
|
|
7388
|
+
low: "\u{1F7E2}",
|
|
7389
|
+
medium: "\u{1F7E1}",
|
|
7390
|
+
high: "\u{1F7E0}",
|
|
7391
|
+
critical: "\u{1F534}"
|
|
7392
|
+
}[severity] || "\u26AA";
|
|
7393
|
+
return `${i + 1}. ${severityEmoji} **${lesson.title}**
|
|
7394
|
+
Category: ${category} | Severity: ${severity}
|
|
7395
|
+
${lesson.content?.slice(0, 200)}...`;
|
|
7396
|
+
}).join("\n\n");
|
|
7397
|
+
return {
|
|
7398
|
+
content: [{
|
|
7399
|
+
type: "text",
|
|
7400
|
+
text: `\u{1F4DA} Found ${lessons.length} lesson(s):
|
|
7401
|
+
|
|
7402
|
+
${formattedLessons}`
|
|
7403
|
+
}],
|
|
7404
|
+
structuredContent: toStructured({ lessons, count: lessons.length })
|
|
7405
|
+
};
|
|
7406
|
+
}
|
|
7407
|
+
);
|
|
7118
7408
|
registerTool(
|
|
7119
7409
|
"session_smart_search",
|
|
7120
7410
|
{
|
package/package.json
CHANGED