@contextstream/mcp-server 0.3.18 → 0.3.20

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.
Files changed (2) hide show
  1. package/dist/index.js +721 -63
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5431,6 +5431,17 @@ var ContextStreamClient = class {
5431
5431
  // ============================================
5432
5432
  // Token-Saving Context Tools
5433
5433
  // ============================================
5434
+ /**
5435
+ * Record a token savings event for user-facing dashboard analytics.
5436
+ * Best-effort: callers should not await this in latency-sensitive paths.
5437
+ */
5438
+ trackTokenSavings(body) {
5439
+ const payload = this.withDefaults({
5440
+ source: "mcp",
5441
+ ...body
5442
+ });
5443
+ return request(this.config, "/analytics/token-savings", { body: payload });
5444
+ }
5434
5445
  /**
5435
5446
  * Get a compact, token-efficient summary of workspace context.
5436
5447
  * Designed to be included in every AI prompt without consuming many tokens.
@@ -5519,7 +5530,31 @@ var ContextStreamClient = class {
5519
5530
  }
5520
5531
  parts.push("");
5521
5532
  parts.push('\u{1F4A1} Use session_recall("topic") for specific context');
5522
- const summary = parts.join("\n");
5533
+ const candidateSummary = parts.join("\n");
5534
+ const maxChars = maxTokens * 4;
5535
+ const candidateLines = candidateSummary.split("\n");
5536
+ const finalLines = [];
5537
+ let used = 0;
5538
+ for (const line of candidateLines) {
5539
+ const next = (finalLines.length ? "\n" : "") + line;
5540
+ if (used + next.length > maxChars) break;
5541
+ finalLines.push(line);
5542
+ used += next.length;
5543
+ }
5544
+ const summary = finalLines.join("\n");
5545
+ this.trackTokenSavings({
5546
+ tool: "session_summary",
5547
+ workspace_id: withDefaults.workspace_id,
5548
+ project_id: withDefaults.project_id,
5549
+ candidate_chars: candidateSummary.length,
5550
+ context_chars: summary.length,
5551
+ max_tokens: maxTokens,
5552
+ metadata: {
5553
+ decision_count: decisionCount,
5554
+ memory_count: memoryCount
5555
+ }
5556
+ }).catch(() => {
5557
+ });
5523
5558
  return {
5524
5559
  summary,
5525
5560
  workspace_name: workspaceName,
@@ -5654,6 +5689,7 @@ var ContextStreamClient = class {
5654
5689
  const charsPerToken = 4;
5655
5690
  const maxChars = maxTokens * charsPerToken;
5656
5691
  const parts = [];
5692
+ const candidateParts = [];
5657
5693
  const sources = [];
5658
5694
  let currentChars = 0;
5659
5695
  if (params.include_decisions !== false && withDefaults.workspace_id) {
@@ -5665,14 +5701,22 @@ var ContextStreamClient = class {
5665
5701
  });
5666
5702
  if (decisions.items) {
5667
5703
  parts.push("## Relevant Decisions\n");
5704
+ candidateParts.push("## Relevant Decisions\n");
5668
5705
  currentChars += 25;
5669
- for (const d of decisions.items) {
5670
- const entry = `\u2022 ${d.title || "Decision"}
5671
- `;
5672
- if (currentChars + entry.length > maxChars * 0.4) break;
5673
- parts.push(entry);
5674
- currentChars += entry.length;
5675
- sources.push({ type: "decision", title: d.title || "Decision" });
5706
+ const decisionEntries = decisions.items.map((d) => {
5707
+ const title = d.title || "Decision";
5708
+ return { title, entry: `\u2022 ${title}
5709
+ ` };
5710
+ });
5711
+ for (const d of decisionEntries) {
5712
+ candidateParts.push(d.entry);
5713
+ }
5714
+ candidateParts.push("\n");
5715
+ for (const d of decisionEntries) {
5716
+ if (currentChars + d.entry.length > maxChars * 0.4) break;
5717
+ parts.push(d.entry);
5718
+ currentChars += d.entry.length;
5719
+ sources.push({ type: "decision", title: d.title });
5676
5720
  }
5677
5721
  parts.push("\n");
5678
5722
  }
@@ -5689,16 +5733,23 @@ var ContextStreamClient = class {
5689
5733
  });
5690
5734
  if (memory.results) {
5691
5735
  parts.push("## Related Context\n");
5736
+ candidateParts.push("## Related Context\n");
5692
5737
  currentChars += 20;
5693
- for (const m of memory.results) {
5738
+ const memoryEntries = memory.results.map((m) => {
5694
5739
  const title = m.title || "Context";
5695
5740
  const content = m.content?.slice(0, 200) || "";
5696
- const entry = `\u2022 ${title}: ${content}...
5697
- `;
5698
- if (currentChars + entry.length > maxChars * 0.7) break;
5699
- parts.push(entry);
5700
- currentChars += entry.length;
5701
- sources.push({ type: "memory", title });
5741
+ return { title, entry: `\u2022 ${title}: ${content}...
5742
+ ` };
5743
+ });
5744
+ for (const m of memoryEntries) {
5745
+ candidateParts.push(m.entry);
5746
+ }
5747
+ candidateParts.push("\n");
5748
+ for (const m of memoryEntries) {
5749
+ if (currentChars + m.entry.length > maxChars * 0.7) break;
5750
+ parts.push(m.entry);
5751
+ currentChars += m.entry.length;
5752
+ sources.push({ type: "memory", title: m.title });
5702
5753
  }
5703
5754
  parts.push("\n");
5704
5755
  }
@@ -5715,23 +5766,45 @@ var ContextStreamClient = class {
5715
5766
  });
5716
5767
  if (code.results) {
5717
5768
  parts.push("## Relevant Code\n");
5769
+ candidateParts.push("## Relevant Code\n");
5718
5770
  currentChars += 18;
5719
- for (const c of code.results) {
5771
+ const codeEntries = code.results.map((c) => {
5720
5772
  const path3 = c.file_path || "file";
5721
5773
  const content = c.content?.slice(0, 150) || "";
5722
- const entry = `\u2022 ${path3}: ${content}...
5723
- `;
5724
- if (currentChars + entry.length > maxChars) break;
5725
- parts.push(entry);
5726
- currentChars += entry.length;
5727
- sources.push({ type: "code", title: path3 });
5774
+ return { path: path3, entry: `\u2022 ${path3}: ${content}...
5775
+ ` };
5776
+ });
5777
+ for (const c of codeEntries) {
5778
+ candidateParts.push(c.entry);
5779
+ }
5780
+ for (const c of codeEntries) {
5781
+ if (currentChars + c.entry.length > maxChars) break;
5782
+ parts.push(c.entry);
5783
+ currentChars += c.entry.length;
5784
+ sources.push({ type: "code", title: c.path });
5728
5785
  }
5729
5786
  }
5730
5787
  } catch {
5731
5788
  }
5732
5789
  }
5733
5790
  const context = parts.join("");
5791
+ const candidateContext = candidateParts.join("");
5734
5792
  const tokenEstimate = Math.ceil(context.length / charsPerToken);
5793
+ this.trackTokenSavings({
5794
+ tool: "ai_context_budget",
5795
+ workspace_id: withDefaults.workspace_id,
5796
+ project_id: withDefaults.project_id,
5797
+ candidate_chars: candidateContext.length,
5798
+ context_chars: context.length,
5799
+ max_tokens: maxTokens,
5800
+ metadata: {
5801
+ include_decisions: params.include_decisions !== false,
5802
+ include_memory: params.include_memory !== false,
5803
+ include_code: !!params.include_code,
5804
+ sources: sources.length
5805
+ }
5806
+ }).catch(() => {
5807
+ });
5735
5808
  return {
5736
5809
  context,
5737
5810
  token_estimate: tokenEstimate,
@@ -5908,6 +5981,7 @@ var ContextStreamClient = class {
5908
5981
  let context;
5909
5982
  let charsUsed = 0;
5910
5983
  const maxChars = maxTokens * 4;
5984
+ let candidateContext;
5911
5985
  if (format === "minified") {
5912
5986
  const parts = [];
5913
5987
  for (const item of items) {
@@ -5917,6 +5991,7 @@ var ContextStreamClient = class {
5917
5991
  charsUsed += entry.length + 1;
5918
5992
  }
5919
5993
  context = parts.join("|");
5994
+ candidateContext = items.map((i) => `${i.type}:${i.value}`).join("|");
5920
5995
  } else if (format === "structured") {
5921
5996
  const grouped = {};
5922
5997
  for (const item of items) {
@@ -5926,6 +6001,12 @@ var ContextStreamClient = class {
5926
6001
  charsUsed += item.value.length + 5;
5927
6002
  }
5928
6003
  context = JSON.stringify(grouped);
6004
+ const candidateGrouped = {};
6005
+ for (const item of items) {
6006
+ if (!candidateGrouped[item.type]) candidateGrouped[item.type] = [];
6007
+ candidateGrouped[item.type].push(item.value);
6008
+ }
6009
+ candidateContext = JSON.stringify(candidateGrouped);
5929
6010
  } else {
5930
6011
  const lines = ["[CTX]"];
5931
6012
  for (const item of items) {
@@ -5936,6 +6017,12 @@ var ContextStreamClient = class {
5936
6017
  }
5937
6018
  lines.push("[/CTX]");
5938
6019
  context = lines.join("\n");
6020
+ const candidateLines = ["[CTX]"];
6021
+ for (const item of items) {
6022
+ candidateLines.push(`${item.type}:${item.value}`);
6023
+ }
6024
+ candidateLines.push("[/CTX]");
6025
+ candidateContext = candidateLines.join("\n");
5939
6026
  }
5940
6027
  if (context.length === 0 && withDefaults.workspace_id) {
5941
6028
  const wsHint = items.find((i) => i.type === "W")?.value || withDefaults.workspace_id.slice(0, 8);
@@ -5943,7 +6030,23 @@ var ContextStreamClient = class {
5943
6030
  W:${wsHint}
5944
6031
  [NO_MATCHES]
5945
6032
  [/CTX]`;
6033
+ candidateContext = context;
5946
6034
  }
6035
+ this.trackTokenSavings({
6036
+ tool: "context_smart",
6037
+ workspace_id: withDefaults.workspace_id,
6038
+ project_id: withDefaults.project_id,
6039
+ candidate_chars: candidateContext.length,
6040
+ context_chars: context.length,
6041
+ max_tokens: maxTokens,
6042
+ metadata: {
6043
+ format,
6044
+ items: items.length,
6045
+ keywords: keywords.slice(0, 10),
6046
+ errors: errors.length
6047
+ }
6048
+ }).catch(() => {
6049
+ });
5947
6050
  return {
5948
6051
  context,
5949
6052
  token_estimate: Math.ceil(context.length / 4),
@@ -6134,6 +6237,8 @@ You have access to ContextStream MCP tools for persistent memory and context.
6134
6237
  | **1st message** | \`session_init(folder_path="...", context_hint="<user's message>")\` |
6135
6238
  | **2nd+ messages** | \`context_smart(user_message="<user's message>")\` |
6136
6239
  | **After completing task** | \`session_capture(...)\` - MUST capture decisions/insights |
6240
+ | **User frustration/correction** | \`session_capture_lesson(...)\` - MUST capture lessons |
6241
+ | **Command/tool error + fix** | \`session_capture_lesson(...)\` - MUST capture lessons |
6137
6242
 
6138
6243
  **NO EXCEPTIONS.** Do not skip even if you think you have enough context.
6139
6244
 
@@ -6189,6 +6294,52 @@ You have access to ContextStream MCP tools for persistent memory and context.
6189
6294
 
6190
6295
  ---
6191
6296
 
6297
+ ### Lesson Capture (MANDATORY)
6298
+
6299
+ When:
6300
+ 1. **Expresses frustration** (caps, profanity, "COME ON", "WTF", repeated corrections)
6301
+ 2. **Corrects you** ("No, you should...", "That's wrong", "Fix this")
6302
+ 3. **Points out a mistake** (broken code, wrong approach, production issue)
6303
+ 4. **A command/tool call fails and you learn the correct fix** (even if the user didn\u2019t explicitly correct you)
6304
+
6305
+ You MUST immediately call \`session_capture_lesson\` with:
6306
+
6307
+ | Field | Description | Example |
6308
+ |-------|-------------|---------|
6309
+ | \`title\` | What to remember | "Verify assets in git before pushing" |
6310
+ | \`severity\` | \`critical\`/\`high\`/\`medium\`/\`low\` | \`critical\` for production issues |
6311
+ | \`category\` | \`workflow\`/\`code_quality\`/\`verification\`/\`communication\`/\`project_specific\` | \`workflow\` |
6312
+ | \`trigger\` | What action caused the problem | "Pushed code referencing images without committing them" |
6313
+ | \`impact\` | What went wrong | "Production 404 errors - broken landing page" |
6314
+ | \`prevention\` | How to prevent in future | "Run git status to check untracked files before pushing" |
6315
+ | \`keywords\` | Keywords for matching | \`["git", "images", "assets", "push"]\` |
6316
+
6317
+ **Example call:**
6318
+ \`\`\`json
6319
+ {
6320
+ "title": "Always verify assets in git before pushing code references",
6321
+ "severity": "critical",
6322
+ "category": "workflow",
6323
+ "trigger": "Pushed code referencing /screenshots/*.png without committing images",
6324
+ "impact": "Production 404 errors - broken landing page",
6325
+ "prevention": "Run 'git status' to check untracked files before pushing code that references static assets",
6326
+ "keywords": ["git", "images", "assets", "push", "404", "static"]
6327
+ }
6328
+ \`\`\`
6329
+
6330
+ **Why this matters:**
6331
+ - Lessons are surfaced automatically in \`session_init\` and \`context_smart\`
6332
+ - Future sessions will warn you before repeating the same mistake
6333
+ - This prevents production issues and user frustration
6334
+
6335
+ **Severity guide:**
6336
+ - \`critical\`: Production outages, data loss, security issues
6337
+ - \`high\`: Breaking changes, significant user impact
6338
+ - \`medium\`: Workflow inefficiencies, minor bugs
6339
+ - \`low\`: Style/preference corrections
6340
+
6341
+ ---
6342
+
6192
6343
  ### Quick Examples
6193
6344
 
6194
6345
  \`\`\`
@@ -7182,7 +7333,7 @@ Automatically detects code files and skips ignored directories like node_modules
7182
7333
  title: "Initialize conversation session",
7183
7334
  description: `Initialize a new conversation session and automatically retrieve relevant context.
7184
7335
  This is the FIRST tool AI assistants should call when starting a conversation.
7185
- Returns: workspace info, project info, recent memory, recent decisions, and relevant context.
7336
+ Returns: workspace info, project info, recent memory, recent decisions, relevant context, and high-priority lessons.
7186
7337
  Automatically detects the IDE workspace/project path and can auto-index code.
7187
7338
 
7188
7339
  IMPORTANT: Pass the user's FIRST MESSAGE as context_hint to get semantically relevant context!
@@ -7929,7 +8080,7 @@ Format options:
7929
8080
  - 'readable': Line-separated with labels
7930
8081
  - 'structured': JSON-like grouped format
7931
8082
 
7932
- Type codes: W=Workspace, P=Project, D=Decision, M=Memory, I=Insight, T=Task
8083
+ Type codes: W=Workspace, P=Project, D=Decision, M=Memory, I=Insight, T=Task, L=Lesson
7933
8084
 
7934
8085
  Example usage:
7935
8086
  1. User asks "how should I implement auth?"
@@ -8027,7 +8178,7 @@ function registerPrompts(server) {
8027
8178
  title: "Explore Codebase",
8028
8179
  description: "Get an overview of a project codebase structure and key components",
8029
8180
  argsSchema: {
8030
- project_id: external_exports.string().uuid().describe("Project ID to explore"),
8181
+ project_id: external_exports.string().uuid().optional().describe("Project ID to explore (optional if session_init has set defaults)"),
8031
8182
  focus_area: external_exports.string().optional().describe('Optional area to focus on (e.g., "authentication", "api routes")')
8032
8183
  }
8033
8184
  },
@@ -8037,12 +8188,14 @@ function registerPrompts(server) {
8037
8188
  role: "user",
8038
8189
  content: {
8039
8190
  type: "text",
8040
- text: `I want to understand the codebase for project ${args.project_id}${args.focus_area ? ` with focus on ${args.focus_area}` : ""}.
8191
+ text: `I want to understand the codebase${args.project_id ? ` for project ${args.project_id}` : ""}${args.focus_area ? ` with focus on ${args.focus_area}` : ""}.
8192
+
8193
+ If project_id is not provided, first call \`session_init\` (or \`projects_list\`) to resolve the current project ID.
8041
8194
 
8042
8195
  Please help me by:
8043
- 1. First, use \`projects.overview\` to get the project summary
8044
- 2. Use \`projects.files\` to list the key files
8045
- 3. Use \`search.semantic\` to find relevant code${args.focus_area ? ` related to "${args.focus_area}"` : ""}
8196
+ 1. First, use \`projects_overview\` to get the project summary
8197
+ 2. Use \`projects_files\` to list the key files
8198
+ 3. Use \`search_semantic\` to find relevant code${args.focus_area ? ` related to "${args.focus_area}"` : ""}
8046
8199
  4. Summarize the architecture and key patterns you observe
8047
8200
 
8048
8201
  Provide a clear, structured overview that helps me navigate this codebase effectively.`
@@ -8057,7 +8210,7 @@ Provide a clear, structured overview that helps me navigate this codebase effect
8057
8210
  title: "Capture Decision",
8058
8211
  description: "Document an architectural or technical decision in workspace memory",
8059
8212
  argsSchema: {
8060
- workspace_id: external_exports.string().uuid().describe("Workspace ID"),
8213
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional if session_init has set defaults)"),
8061
8214
  decision_title: external_exports.string().describe("Brief title of the decision"),
8062
8215
  context: external_exports.string().describe("What prompted this decision"),
8063
8216
  decision: external_exports.string().describe("The decision made"),
@@ -8077,12 +8230,15 @@ Provide a clear, structured overview that helps me navigate this codebase effect
8077
8230
  **Decision:** ${args.decision}
8078
8231
  ${args.consequences ? `**Consequences:** ${args.consequences}` : ""}
8079
8232
 
8080
- Use \`memory.create_event\` with:
8233
+ If workspace_id is not provided, first call \`session_init\` to resolve the workspace, then capture the decision.
8234
+
8235
+ Use \`session_capture\` with:
8081
8236
  - event_type: "decision"
8082
- - workspace_id: "${args.workspace_id}"
8083
- - title: The decision title
8237
+ ${args.workspace_id ? `- workspace_id: "${args.workspace_id}"` : "- workspace_id: (omit to use session defaults)"}
8238
+ - title: "${args.decision_title}"
8084
8239
  - content: A well-formatted ADR (Architecture Decision Record) with context, decision, and consequences
8085
- - metadata: Include relevant tags and status
8240
+ - tags: Include relevant tags (e.g., "adr", "architecture")
8241
+ - importance: "high"
8086
8242
 
8087
8243
  After creating, confirm the decision was recorded and summarize it.`
8088
8244
  }
@@ -8096,7 +8252,7 @@ After creating, confirm the decision was recorded and summarize it.`
8096
8252
  title: "Code Review Context",
8097
8253
  description: "Build context for reviewing code changes",
8098
8254
  argsSchema: {
8099
- project_id: external_exports.string().uuid().describe("Project ID"),
8255
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional if session_init has set defaults)"),
8100
8256
  file_paths: external_exports.string().describe("Comma-separated file paths being changed"),
8101
8257
  change_description: external_exports.string().describe("Brief description of the changes")
8102
8258
  }
@@ -8112,10 +8268,10 @@ After creating, confirm the decision was recorded and summarize it.`
8112
8268
  Change description: ${args.change_description}
8113
8269
 
8114
8270
  Please help me understand the impact by:
8115
- 1. Use \`graph.dependencies\` to find what depends on these files
8116
- 2. Use \`graph.impact\` to analyze potential impact
8117
- 3. Use \`memory.search\` to find related decisions or notes about these areas
8118
- 4. Use \`search.semantic\` to find related code patterns
8271
+ 1. Use \`graph_dependencies\` to find what depends on these files
8272
+ 2. Use \`graph_impact\` to analyze potential impact
8273
+ 3. Use \`memory_search\` to find related decisions or notes about these areas
8274
+ 4. Use \`search_semantic\` to find related code patterns
8119
8275
 
8120
8276
  Provide:
8121
8277
  - Summary of what these files do
@@ -8133,7 +8289,7 @@ Provide:
8133
8289
  title: "Investigate Bug",
8134
8290
  description: "Build context for debugging an issue",
8135
8291
  argsSchema: {
8136
- project_id: external_exports.string().uuid().describe("Project ID"),
8292
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional if session_init has set defaults)"),
8137
8293
  error_message: external_exports.string().describe("Error message or symptom"),
8138
8294
  affected_area: external_exports.string().optional().describe("Known affected area or component")
8139
8295
  }
@@ -8150,10 +8306,10 @@ Provide:
8150
8306
  ${args.affected_area ? `**Affected Area:** ${args.affected_area}` : ""}
8151
8307
 
8152
8308
  Please help me investigate by:
8153
- 1. Use \`search.semantic\` to find code related to this error
8154
- 2. Use \`search.pattern\` to find where similar errors are thrown
8155
- 3. Use \`graph.call_path\` to trace call flows if we identify key functions
8156
- 4. Use \`memory.search\` to check if this issue has been encountered before
8309
+ 1. Use \`search_semantic\` to find code related to this error
8310
+ 2. Use \`search_pattern\` to find where similar errors are thrown
8311
+ 3. Use \`graph_call_path\` to trace call flows if we identify key functions
8312
+ 4. Use \`memory_search\` to check if this issue has been encountered before
8157
8313
 
8158
8314
  Provide:
8159
8315
  - Likely locations where this error originates
@@ -8171,7 +8327,7 @@ Provide:
8171
8327
  title: "Explore Knowledge Graph",
8172
8328
  description: "Navigate and understand the knowledge graph for a workspace",
8173
8329
  argsSchema: {
8174
- workspace_id: external_exports.string().uuid().describe("Workspace ID"),
8330
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional if session_init has set defaults)"),
8175
8331
  starting_topic: external_exports.string().optional().describe("Topic to start exploration from")
8176
8332
  }
8177
8333
  },
@@ -8181,13 +8337,15 @@ Provide:
8181
8337
  role: "user",
8182
8338
  content: {
8183
8339
  type: "text",
8184
- text: `Help me explore the knowledge captured in workspace ${args.workspace_id}${args.starting_topic ? ` starting from "${args.starting_topic}"` : ""}.
8340
+ text: `Help me explore the knowledge captured in the current workspace${args.workspace_id ? ` (${args.workspace_id})` : ""}${args.starting_topic ? ` starting from "${args.starting_topic}"` : ""}.
8341
+
8342
+ If workspace_id is not provided, first call \`session_init\` to resolve the workspace.
8185
8343
 
8186
8344
  Please:
8187
- 1. Use \`memory.list_nodes\` to see available knowledge nodes
8188
- 2. Use \`memory.decisions\` to see decision history
8189
- 3. ${args.starting_topic ? `Use \`memory.search\` to find nodes related to "${args.starting_topic}"` : "Use `memory.summary` to get an overview"}
8190
- 4. Use \`graph.related\` to explore connections between nodes
8345
+ 1. Use \`memory_list_nodes\` to see available knowledge nodes
8346
+ 2. Use \`memory_decisions\` to see decision history
8347
+ 3. ${args.starting_topic ? `Use \`memory_search\` to find nodes related to "${args.starting_topic}"` : "Use `memory_summary` to get an overview"}
8348
+ 4. Use \`graph_related\` to explore connections between nodes
8191
8349
 
8192
8350
  Provide:
8193
8351
  - Overview of knowledge captured
@@ -8205,8 +8363,8 @@ Provide:
8205
8363
  title: "Project Onboarding",
8206
8364
  description: "Generate onboarding context for a new team member",
8207
8365
  argsSchema: {
8208
- project_id: external_exports.string().uuid().describe("Project ID"),
8209
- workspace_id: external_exports.string().uuid().describe("Workspace ID"),
8366
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional if session_init has set defaults)"),
8367
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional if session_init has set defaults)"),
8210
8368
  role: external_exports.string().optional().describe('Role of the person being onboarded (e.g., "backend developer", "frontend developer")')
8211
8369
  }
8212
8370
  },
@@ -8220,11 +8378,11 @@ Provide:
8220
8378
  ${args.role ? `They will be working as a ${args.role}.` : ""}
8221
8379
 
8222
8380
  Please gather comprehensive context:
8223
- 1. Use \`projects.overview\` and \`projects.statistics\` for project summary
8224
- 2. Use \`projects.files\` to identify key entry points
8225
- 3. Use \`memory.timeline\` to see recent activity and changes
8226
- 4. Use \`memory.decisions\` to understand key architectural choices
8227
- 5. Use \`search.semantic\` to find documentation and READMEs
8381
+ 1. Use \`projects_overview\` and \`projects_statistics\` for project summary
8382
+ 2. Use \`projects_files\` to identify key entry points
8383
+ 3. Use \`memory_timeline\` to see recent activity and changes
8384
+ 4. Use \`memory_decisions\` to understand key architectural choices
8385
+ 5. Use \`search_semantic\` to find documentation and READMEs
8228
8386
 
8229
8387
  Provide an onboarding guide that includes:
8230
8388
  - Project overview and purpose
@@ -8244,7 +8402,7 @@ Provide an onboarding guide that includes:
8244
8402
  title: "Refactoring Analysis",
8245
8403
  description: "Analyze a codebase for refactoring opportunities",
8246
8404
  argsSchema: {
8247
- project_id: external_exports.string().uuid().describe("Project ID"),
8405
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional if session_init has set defaults)"),
8248
8406
  target_area: external_exports.string().optional().describe("Specific area to analyze")
8249
8407
  }
8250
8408
  },
@@ -8257,10 +8415,10 @@ Provide an onboarding guide that includes:
8257
8415
  text: `Analyze the codebase for refactoring opportunities${args.target_area ? ` in ${args.target_area}` : ""}.
8258
8416
 
8259
8417
  Please investigate:
8260
- 1. Use \`graph.circular_dependencies\` to find circular dependencies
8261
- 2. Use \`graph.unused_code\` to find dead code
8262
- 3. Use \`search.pattern\` to find code duplication patterns
8263
- 4. Use \`projects.statistics\` to identify complex areas
8418
+ 1. Use \`graph_circular_dependencies\` to find circular dependencies
8419
+ 2. Use \`graph_unused_code\` to find dead code
8420
+ 3. Use \`search_pattern\` to find code duplication patterns
8421
+ 4. Use \`projects_statistics\` to identify complex areas
8264
8422
 
8265
8423
  Provide:
8266
8424
  - Circular dependencies that should be broken
@@ -8295,7 +8453,7 @@ Provide:
8295
8453
 
8296
8454
  **Query:** ${args.query}
8297
8455
 
8298
- Please use \`ai.enhanced_context\` with:
8456
+ Please use \`ai_enhanced_context\` with:
8299
8457
  - query: "${args.query}"
8300
8458
  ${args.workspace_id ? `- workspace_id: "${args.workspace_id}"` : ""}
8301
8459
  ${args.project_id ? `- project_id: "${args.project_id}"` : ""}
@@ -8309,6 +8467,491 @@ Then synthesize the retrieved context into a coherent briefing that will help wi
8309
8467
  ]
8310
8468
  })
8311
8469
  );
8470
+ server.registerPrompt(
8471
+ "smart-search",
8472
+ {
8473
+ title: "Smart Search",
8474
+ description: "Search across memory, decisions, and code for a query",
8475
+ argsSchema: {
8476
+ query: external_exports.string().describe("What you want to find"),
8477
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional)"),
8478
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)")
8479
+ }
8480
+ },
8481
+ async (args) => ({
8482
+ messages: [
8483
+ {
8484
+ role: "user",
8485
+ content: {
8486
+ type: "text",
8487
+ text: `Find the most relevant context for: "${args.query}"
8488
+
8489
+ If workspace_id/project_id are not provided, call \`session_init\` first to resolve the current workspace/project.
8490
+
8491
+ Please:
8492
+ 1. Use \`session_smart_search\` with query "${args.query}"${args.workspace_id ? ` and workspace_id "${args.workspace_id}"` : ""}${args.project_id ? ` and project_id "${args.project_id}"` : ""}
8493
+ 2. If results are thin, follow up with \`search_hybrid\` and \`memory_search\`
8494
+ 3. Return the top results with file paths/links and a short synthesis of what matters`
8495
+ }
8496
+ }
8497
+ ]
8498
+ })
8499
+ );
8500
+ server.registerPrompt(
8501
+ "recall-context",
8502
+ {
8503
+ title: "Recall Context",
8504
+ description: "Retrieve relevant past decisions and memory for a query",
8505
+ argsSchema: {
8506
+ query: external_exports.string().describe("What to recall (natural language)"),
8507
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional)"),
8508
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)")
8509
+ }
8510
+ },
8511
+ async (args) => ({
8512
+ messages: [
8513
+ {
8514
+ role: "user",
8515
+ content: {
8516
+ type: "text",
8517
+ text: `Recall relevant context for: "${args.query}"
8518
+
8519
+ If workspace_id/project_id are not provided, call \`session_init\` first to resolve the current workspace/project.
8520
+
8521
+ Use \`session_recall\` with query "${args.query}"${args.workspace_id ? ` and workspace_id "${args.workspace_id}"` : ""}${args.project_id ? ` and project_id "${args.project_id}"` : ""}.
8522
+ Then summarize the key points and any relevant decisions/lessons.`
8523
+ }
8524
+ }
8525
+ ]
8526
+ })
8527
+ );
8528
+ server.registerPrompt(
8529
+ "session-summary",
8530
+ {
8531
+ title: "Session Summary",
8532
+ description: "Get a compact summary of workspace/project context",
8533
+ argsSchema: {
8534
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional)"),
8535
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)"),
8536
+ max_tokens: external_exports.string().optional().describe("Max tokens for summary (default: 500)")
8537
+ }
8538
+ },
8539
+ async (args) => ({
8540
+ messages: [
8541
+ {
8542
+ role: "user",
8543
+ content: {
8544
+ type: "text",
8545
+ text: `Generate a compact, token-efficient summary of the current workspace/project context.
8546
+
8547
+ If workspace_id/project_id are not provided, call \`session_init\` first to resolve the current workspace/project.
8548
+
8549
+ Use \`session_summary\`${args.workspace_id ? ` with workspace_id "${args.workspace_id}"` : ""}${args.project_id ? ` and project_id "${args.project_id}"` : ""}${args.max_tokens ? ` and max_tokens ${args.max_tokens} (number)` : ""}.
8550
+ Then list the top decisions (titles only) and any high-priority lessons to watch for.`
8551
+ }
8552
+ }
8553
+ ]
8554
+ })
8555
+ );
8556
+ server.registerPrompt(
8557
+ "capture-lesson",
8558
+ {
8559
+ title: "Capture Lesson",
8560
+ description: "Record a lesson learned from an error or correction",
8561
+ argsSchema: {
8562
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional)"),
8563
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)"),
8564
+ title: external_exports.string().describe("Lesson title (what to remember)"),
8565
+ severity: external_exports.string().optional().describe("low|medium|high|critical (default: medium)"),
8566
+ category: external_exports.string().describe("workflow|code_quality|verification|communication|project_specific"),
8567
+ trigger: external_exports.string().describe("What action caused the problem"),
8568
+ impact: external_exports.string().describe("What went wrong"),
8569
+ prevention: external_exports.string().describe("How to prevent in future"),
8570
+ keywords: external_exports.string().optional().describe("Comma-separated keywords (optional)")
8571
+ }
8572
+ },
8573
+ async (args) => ({
8574
+ messages: [
8575
+ {
8576
+ role: "user",
8577
+ content: {
8578
+ type: "text",
8579
+ text: `Capture this lesson so it is surfaced in future sessions:
8580
+
8581
+ Title: ${args.title}
8582
+ Severity: ${args.severity || "medium"}
8583
+ Category: ${args.category}
8584
+ Trigger: ${args.trigger}
8585
+ Impact: ${args.impact}
8586
+ Prevention: ${args.prevention}
8587
+ ${args.keywords ? `Keywords: ${args.keywords}` : ""}
8588
+
8589
+ If workspace_id/project_id are not provided, call \`session_init\` first to resolve the current workspace/project.
8590
+
8591
+ Use \`session_capture_lesson\` with the fields above. If keywords were provided, split the comma-separated list into an array of strings.`
8592
+ }
8593
+ }
8594
+ ]
8595
+ })
8596
+ );
8597
+ server.registerPrompt(
8598
+ "capture-preference",
8599
+ {
8600
+ title: "Capture Preference",
8601
+ description: "Save a user preference to memory",
8602
+ argsSchema: {
8603
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional)"),
8604
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)"),
8605
+ title: external_exports.string().optional().describe("Preference title (optional)"),
8606
+ preference: external_exports.string().describe("Preference details to remember")
8607
+ }
8608
+ },
8609
+ async (args) => ({
8610
+ messages: [
8611
+ {
8612
+ role: "user",
8613
+ content: {
8614
+ type: "text",
8615
+ text: `Save this preference to memory:
8616
+
8617
+ ${args.title ? `Title: ${args.title}
8618
+ ` : ""}Preference: ${args.preference}
8619
+
8620
+ If workspace_id/project_id are not provided, call \`session_init\` first to resolve the current workspace/project.
8621
+
8622
+ Use \`session_capture\` with:
8623
+ - event_type: "preference"
8624
+ - title: ${args.title ? `"${args.title}"` : "(choose a short title)"}
8625
+ - content: "${args.preference}"
8626
+ - importance: "medium"`
8627
+ }
8628
+ }
8629
+ ]
8630
+ })
8631
+ );
8632
+ server.registerPrompt(
8633
+ "capture-task",
8634
+ {
8635
+ title: "Capture Task",
8636
+ description: "Capture an action item into memory",
8637
+ argsSchema: {
8638
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional)"),
8639
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)"),
8640
+ title: external_exports.string().optional().describe("Task title (optional)"),
8641
+ task: external_exports.string().describe("Task details")
8642
+ }
8643
+ },
8644
+ async (args) => ({
8645
+ messages: [
8646
+ {
8647
+ role: "user",
8648
+ content: {
8649
+ type: "text",
8650
+ text: `Capture this task in memory for tracking:
8651
+
8652
+ ${args.title ? `Title: ${args.title}
8653
+ ` : ""}Task: ${args.task}
8654
+
8655
+ If workspace_id/project_id are not provided, call \`session_init\` first to resolve the current workspace/project.
8656
+
8657
+ Use \`session_capture\` with:
8658
+ - event_type: "task"
8659
+ - title: ${args.title ? `"${args.title}"` : "(choose a short title)"}
8660
+ - content: "${args.task}"
8661
+ - importance: "medium"`
8662
+ }
8663
+ }
8664
+ ]
8665
+ })
8666
+ );
8667
+ server.registerPrompt(
8668
+ "capture-bug",
8669
+ {
8670
+ title: "Capture Bug",
8671
+ description: "Capture a bug report into workspace memory",
8672
+ argsSchema: {
8673
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional)"),
8674
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)"),
8675
+ title: external_exports.string().describe("Bug title"),
8676
+ description: external_exports.string().describe("Bug description"),
8677
+ reproduction_steps: external_exports.string().optional().describe("Steps to reproduce (optional)"),
8678
+ expected: external_exports.string().optional().describe("Expected behavior (optional)"),
8679
+ actual: external_exports.string().optional().describe("Actual behavior (optional)")
8680
+ }
8681
+ },
8682
+ async (args) => ({
8683
+ messages: [
8684
+ {
8685
+ role: "user",
8686
+ content: {
8687
+ type: "text",
8688
+ text: `Capture this bug report in memory:
8689
+
8690
+ Title: ${args.title}
8691
+ Description: ${args.description}
8692
+ ${args.reproduction_steps ? `Steps to reproduce:
8693
+ ${args.reproduction_steps}
8694
+ ` : ""}${args.expected ? `Expected:
8695
+ ${args.expected}
8696
+ ` : ""}${args.actual ? `Actual:
8697
+ ${args.actual}
8698
+ ` : ""}
8699
+
8700
+ If workspace_id/project_id are not provided, call \`session_init\` first to resolve the current workspace/project.
8701
+
8702
+ Use \`session_capture\` with:
8703
+ - event_type: "bug"
8704
+ - title: "${args.title}"
8705
+ - content: A well-formatted bug report with the details above
8706
+ - tags: include relevant component/area tags
8707
+ - importance: "high"`
8708
+ }
8709
+ }
8710
+ ]
8711
+ })
8712
+ );
8713
+ server.registerPrompt(
8714
+ "capture-feature",
8715
+ {
8716
+ title: "Capture Feature",
8717
+ description: "Capture a feature request into workspace memory",
8718
+ argsSchema: {
8719
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional)"),
8720
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)"),
8721
+ title: external_exports.string().describe("Feature title"),
8722
+ description: external_exports.string().describe("Feature description"),
8723
+ rationale: external_exports.string().optional().describe("Why this matters (optional)"),
8724
+ acceptance_criteria: external_exports.string().optional().describe("Acceptance criteria (optional)")
8725
+ }
8726
+ },
8727
+ async (args) => ({
8728
+ messages: [
8729
+ {
8730
+ role: "user",
8731
+ content: {
8732
+ type: "text",
8733
+ text: `Capture this feature request in memory:
8734
+
8735
+ Title: ${args.title}
8736
+ Description: ${args.description}
8737
+ ${args.rationale ? `Rationale:
8738
+ ${args.rationale}
8739
+ ` : ""}${args.acceptance_criteria ? `Acceptance criteria:
8740
+ ${args.acceptance_criteria}
8741
+ ` : ""}
8742
+
8743
+ If workspace_id/project_id are not provided, call \`session_init\` first to resolve the current workspace/project.
8744
+
8745
+ Use \`session_capture\` with:
8746
+ - event_type: "feature"
8747
+ - title: "${args.title}"
8748
+ - content: A well-formatted feature request with the details above
8749
+ - tags: include relevant component/area tags
8750
+ - importance: "medium"`
8751
+ }
8752
+ }
8753
+ ]
8754
+ })
8755
+ );
8756
+ server.registerPrompt(
8757
+ "generate-plan",
8758
+ {
8759
+ title: "Generate Plan",
8760
+ description: "Generate a development plan from a description",
8761
+ argsSchema: {
8762
+ description: external_exports.string().describe("What you want to build/fix"),
8763
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)"),
8764
+ complexity: external_exports.string().optional().describe("low|medium|high (optional)")
8765
+ }
8766
+ },
8767
+ async (args) => ({
8768
+ messages: [
8769
+ {
8770
+ role: "user",
8771
+ content: {
8772
+ type: "text",
8773
+ text: `Generate a development plan for:
8774
+
8775
+ ${args.description}
8776
+
8777
+ Use \`ai_plan\` with:
8778
+ - description: "${args.description}"
8779
+ ${args.project_id ? `- project_id: "${args.project_id}"` : ""}
8780
+ ${args.complexity ? `- complexity: "${args.complexity}"` : ""}
8781
+
8782
+ Then present the plan as a concise ordered list with clear milestones and risks.`
8783
+ }
8784
+ }
8785
+ ]
8786
+ })
8787
+ );
8788
+ server.registerPrompt(
8789
+ "generate-tasks",
8790
+ {
8791
+ title: "Generate Tasks",
8792
+ description: "Generate actionable tasks from a plan or description",
8793
+ argsSchema: {
8794
+ plan_id: external_exports.string().optional().describe("Plan ID (optional)"),
8795
+ description: external_exports.string().optional().describe("Description to generate tasks from (optional if plan_id provided)"),
8796
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)"),
8797
+ granularity: external_exports.string().optional().describe("fine|medium|coarse (optional)")
8798
+ }
8799
+ },
8800
+ async (args) => ({
8801
+ messages: [
8802
+ {
8803
+ role: "user",
8804
+ content: {
8805
+ type: "text",
8806
+ text: `Generate actionable tasks.
8807
+
8808
+ ${args.plan_id ? `Use plan_id: ${args.plan_id}` : ""}${!args.plan_id && args.description ? `Use description: ${args.description}` : ""}
8809
+
8810
+ Use \`ai_tasks\` with:
8811
+ ${args.plan_id ? `- plan_id: "${args.plan_id}"` : ""}${!args.plan_id && args.description ? `- description: "${args.description}"` : ""}
8812
+ ${args.project_id ? `- project_id: "${args.project_id}"` : ""}
8813
+ ${args.granularity ? `- granularity: "${args.granularity}"` : ""}
8814
+
8815
+ Then output a checklist of tasks with clear acceptance criteria for each.`
8816
+ }
8817
+ }
8818
+ ]
8819
+ })
8820
+ );
8821
+ server.registerPrompt(
8822
+ "token-budget-context",
8823
+ {
8824
+ title: "Token-Budget Context",
8825
+ description: "Get the most relevant context that fits within a token budget",
8826
+ argsSchema: {
8827
+ query: external_exports.string().describe("What you need context for"),
8828
+ max_tokens: external_exports.string().describe("Max tokens for context (e.g., 500, 1000, 2000)"),
8829
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional)"),
8830
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)"),
8831
+ include_code: external_exports.string().optional().describe('Include code ("true" or "false")')
8832
+ }
8833
+ },
8834
+ async (args) => ({
8835
+ messages: [
8836
+ {
8837
+ role: "user",
8838
+ content: {
8839
+ type: "text",
8840
+ text: `Build the most relevant context for:
8841
+
8842
+ Query: ${args.query}
8843
+ Token budget: ${args.max_tokens}
8844
+
8845
+ Use \`ai_context_budget\` with:
8846
+ - query: "${args.query}"
8847
+ - max_tokens: ${args.max_tokens} (number)
8848
+ ${args.workspace_id ? `- workspace_id: "${args.workspace_id}"` : ""}
8849
+ ${args.project_id ? `- project_id: "${args.project_id}"` : ""}
8850
+ ${args.include_code ? `- include_code: ${args.include_code}` : ""}
8851
+
8852
+ Return the packed context plus a short note about what was included/excluded.`
8853
+ }
8854
+ }
8855
+ ]
8856
+ })
8857
+ );
8858
+ server.registerPrompt(
8859
+ "find-todos",
8860
+ {
8861
+ title: "Find TODOs",
8862
+ description: "Scan the codebase for TODO/FIXME/HACK notes and summarize",
8863
+ argsSchema: {
8864
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional)"),
8865
+ pattern: external_exports.string().optional().describe("Regex/pattern to search (default: TODO|FIXME|HACK)")
8866
+ }
8867
+ },
8868
+ async (args) => ({
8869
+ messages: [
8870
+ {
8871
+ role: "user",
8872
+ content: {
8873
+ type: "text",
8874
+ text: `Find TODO-style notes in the codebase.
8875
+
8876
+ If project_id is not provided, first call \`session_init\` (or \`projects_list\`) to resolve the current project ID.
8877
+
8878
+ Use \`search_pattern\` with query "${args.pattern || "TODO|FIXME|HACK"}"${args.project_id ? ` and project_id "${args.project_id}"` : ""}.
8879
+ Group results by file path, summarize themes, and propose a small prioritized cleanup list.`
8880
+ }
8881
+ }
8882
+ ]
8883
+ })
8884
+ );
8885
+ server.registerPrompt(
8886
+ "generate-editor-rules",
8887
+ {
8888
+ title: "Generate Editor Rules",
8889
+ description: "Generate ContextStream AI rule files for your editor",
8890
+ argsSchema: {
8891
+ folder_path: external_exports.string().describe("Project folder path (ideally absolute)"),
8892
+ editors: external_exports.string().optional().describe('Comma-separated editors or "all" (windsurf,cursor,cline,kilo,roo,claude,aider)'),
8893
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (optional)"),
8894
+ workspace_name: external_exports.string().optional().describe("Workspace name (optional)"),
8895
+ project_name: external_exports.string().optional().describe("Project name (optional)"),
8896
+ additional_rules: external_exports.string().optional().describe("Additional project-specific rules (optional)"),
8897
+ dry_run: external_exports.string().optional().describe('Dry run ("true" or "false", default: false)')
8898
+ }
8899
+ },
8900
+ async (args) => ({
8901
+ messages: [
8902
+ {
8903
+ role: "user",
8904
+ content: {
8905
+ type: "text",
8906
+ text: `Generate ContextStream editor rule files in: ${args.folder_path}
8907
+
8908
+ Use \`generate_editor_rules\` with:
8909
+ - folder_path: "${args.folder_path}"
8910
+ ${args.editors ? `- editors: "${args.editors}"` : ""}
8911
+ ${args.workspace_id ? `- workspace_id: "${args.workspace_id}"` : ""}
8912
+ ${args.workspace_name ? `- workspace_name: "${args.workspace_name}"` : ""}
8913
+ ${args.project_name ? `- project_name: "${args.project_name}"` : ""}
8914
+ ${args.additional_rules ? `- additional_rules: "${args.additional_rules}"` : ""}
8915
+ ${args.dry_run ? `- dry_run: ${args.dry_run}` : ""}
8916
+
8917
+ If editors is provided as a comma-separated string, split it into an array (or use ["all"] to generate for all editors). If dry_run is provided as a string, convert to boolean.`
8918
+ }
8919
+ }
8920
+ ]
8921
+ })
8922
+ );
8923
+ server.registerPrompt(
8924
+ "index-local-repo",
8925
+ {
8926
+ title: "Index Local Repo",
8927
+ description: "Ingest local files into ContextStream for indexing/search",
8928
+ argsSchema: {
8929
+ project_id: external_exports.string().uuid().optional().describe("Project ID (optional if session_init has set defaults)"),
8930
+ path: external_exports.string().describe("Local directory path to ingest")
8931
+ }
8932
+ },
8933
+ async (args) => ({
8934
+ messages: [
8935
+ {
8936
+ role: "user",
8937
+ content: {
8938
+ type: "text",
8939
+ text: `Ingest local files for indexing/search.
8940
+
8941
+ Path: ${args.path}
8942
+
8943
+ If project_id is not provided, call \`session_init\` first and use the resolved project_id (or use \`projects_list\` to select).
8944
+
8945
+ Use \`projects_ingest_local\` with:
8946
+ - project_id: ${args.project_id ? `"${args.project_id}"` : "(resolved from session_init)"}
8947
+ - path: "${args.path}"
8948
+
8949
+ Then advise how to monitor progress via \`projects_index_status\`.`
8950
+ }
8951
+ }
8952
+ ]
8953
+ })
8954
+ );
8312
8955
  }
8313
8956
 
8314
8957
  // src/session-manager.ts
@@ -8540,6 +9183,21 @@ var SessionManager = class {
8540
9183
  parts.push(` \u2022 [${type}] ${title}`);
8541
9184
  });
8542
9185
  }
9186
+ const lessonsWarning = typeof context.lessons_warning === "string" ? context.lessons_warning : void 0;
9187
+ const lessons = Array.isArray(context.lessons) ? context.lessons : [];
9188
+ if (lessonsWarning || lessons.length > 0) {
9189
+ parts.push("");
9190
+ parts.push("\u26A0\uFE0F Lessons (review before changes):");
9191
+ if (lessonsWarning) {
9192
+ parts.push(` ${lessonsWarning}`);
9193
+ }
9194
+ lessons.slice(0, 3).forEach((l) => {
9195
+ const title = l.title || "Lesson";
9196
+ const severity = l.severity || "unknown";
9197
+ parts.push(` \u2022 [${severity}] ${title}`);
9198
+ });
9199
+ parts.push(' Use session_get_lessons(query="...") for details.');
9200
+ }
8543
9201
  parts.push("");
8544
9202
  if (context.ide_roots && context.ide_roots.length > 0) {
8545
9203
  const roots = context.ide_roots;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contextstream/mcp-server",
3
- "version": "0.3.18",
3
+ "version": "0.3.20",
4
4
  "description": "MCP server exposing ContextStream public API - code context, memory, search, and AI tools for developers",
5
5
  "type": "module",
6
6
  "license": "MIT",