@contextstream/mcp-server 0.4.9 → 0.4.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -323,9 +323,10 @@ Set **one** of:
323
323
 
324
324
  | Variable | Description |
325
325
  |----------|-------------|
326
- | `CONTEXTSTREAM_CONSOLIDATED` | `true` (default in v0.4.x) uses consolidated domain tools |
327
- | `CONTEXTSTREAM_PROGRESSIVE_MODE` | Enables Router mode (~2 meta-tools) |
328
- | `CONTEXTSTREAM_TOOLSET` | Legacy granular tool bundle: `light` / `standard` / `complete` (only when consolidated is off) |
326
+ | `CONTEXTSTREAM_CONSOLIDATED` | `true` (default in v0.4.x) uses consolidated domain tools |
327
+ | `CONTEXTSTREAM_PROGRESSIVE_MODE` | Enables Router mode (~2 meta-tools) |
328
+ | `CONTEXTSTREAM_CONTEXT_PACK` | Enable Context Pack for `context_smart` (code + graph + distill). Defaults to `true` |
329
+ | `CONTEXTSTREAM_TOOLSET` | Legacy granular tool bundle: `light` / `standard` / `complete` (only when consolidated is off) |
329
330
  | `CONTEXTSTREAM_TOOL_ALLOWLIST` | Comma-separated tool names to expose (legacy granular mode) |
330
331
  | `CONTEXTSTREAM_SCHEMA_MODE` | Reduce schema verbosity; e.g., `compact` |
331
332
  | `CONTEXTSTREAM_OUTPUT_FORMAT` | Output formatting; e.g., `compact` / `pretty` |
package/dist/index.js CHANGED
@@ -4052,6 +4052,13 @@ var NEVER = INVALID;
4052
4052
 
4053
4053
  // src/config.ts
4054
4054
  var DEFAULT_API_URL = "https://api.contextstream.io";
4055
+ function parseBooleanEnv(value) {
4056
+ if (value === void 0) return void 0;
4057
+ const normalized = value.trim().toLowerCase();
4058
+ if (["1", "true", "yes", "on"].includes(normalized)) return true;
4059
+ if (["0", "false", "no", "off"].includes(normalized)) return false;
4060
+ return void 0;
4061
+ }
4055
4062
  var configSchema = external_exports.object({
4056
4063
  apiUrl: external_exports.string().url().default(DEFAULT_API_URL),
4057
4064
  apiKey: external_exports.string().min(1).optional(),
@@ -4059,7 +4066,8 @@ var configSchema = external_exports.object({
4059
4066
  defaultWorkspaceId: external_exports.string().uuid().optional(),
4060
4067
  defaultProjectId: external_exports.string().uuid().optional(),
4061
4068
  userAgent: external_exports.string().default("contextstream-mcp/0.1.0"),
4062
- allowHeaderAuth: external_exports.boolean().optional()
4069
+ allowHeaderAuth: external_exports.boolean().optional(),
4070
+ contextPackEnabled: external_exports.boolean().default(true)
4063
4071
  });
4064
4072
  var MISSING_CREDENTIALS_ERROR = "Set CONTEXTSTREAM_API_KEY or CONTEXTSTREAM_JWT for authentication (or CONTEXTSTREAM_ALLOW_HEADER_AUTH=true for header-based auth).";
4065
4073
  function isMissingCredentialsError(err) {
@@ -4070,6 +4078,9 @@ function isMissingCredentialsError(err) {
4070
4078
  }
4071
4079
  function loadConfig() {
4072
4080
  const allowHeaderAuth = process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "1" || process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "true" || process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "yes";
4081
+ const contextPackEnabled = parseBooleanEnv(
4082
+ process.env.CONTEXTSTREAM_CONTEXT_PACK ?? process.env.CONTEXTSTREAM_CONTEXT_PACK_ENABLED
4083
+ );
4073
4084
  const parsed = configSchema.safeParse({
4074
4085
  apiUrl: process.env.CONTEXTSTREAM_API_URL,
4075
4086
  apiKey: process.env.CONTEXTSTREAM_API_KEY,
@@ -4077,7 +4088,8 @@ function loadConfig() {
4077
4088
  defaultWorkspaceId: process.env.CONTEXTSTREAM_WORKSPACE_ID,
4078
4089
  defaultProjectId: process.env.CONTEXTSTREAM_PROJECT_ID,
4079
4090
  userAgent: process.env.CONTEXTSTREAM_USER_AGENT,
4080
- allowHeaderAuth
4091
+ allowHeaderAuth,
4092
+ contextPackEnabled
4081
4093
  });
4082
4094
  if (!parsed.success) {
4083
4095
  const missing = parsed.error.errors.map((e) => e.path.join(".")).join(", ");
@@ -6552,6 +6564,8 @@ var ContextStreamClient = class {
6552
6564
  const withDefaults = this.withDefaults(params);
6553
6565
  const maxTokens = params.max_tokens || 800;
6554
6566
  const format = params.format || "minified";
6567
+ const usePackDefault = this.config.contextPackEnabled !== false && !!withDefaults.project_id;
6568
+ const mode = params.mode || (usePackDefault ? "pack" : "standard");
6555
6569
  if (!withDefaults.workspace_id) {
6556
6570
  return {
6557
6571
  context: "[NO_WORKSPACE]",
@@ -6560,6 +6574,38 @@ var ContextStreamClient = class {
6560
6574
  sources_used: 0
6561
6575
  };
6562
6576
  }
6577
+ try {
6578
+ const apiResult = await request(this.config, "/context/smart", {
6579
+ body: {
6580
+ user_message: params.user_message,
6581
+ workspace_id: withDefaults.workspace_id,
6582
+ project_id: withDefaults.project_id,
6583
+ max_tokens: maxTokens,
6584
+ format,
6585
+ mode,
6586
+ distill: params.distill
6587
+ }
6588
+ });
6589
+ const data = unwrapApiResponse(apiResult);
6590
+ let versionNotice2 = null;
6591
+ try {
6592
+ versionNotice2 = await getUpdateNotice();
6593
+ } catch {
6594
+ }
6595
+ return {
6596
+ context: String(data?.context ?? ""),
6597
+ token_estimate: Number(data?.token_estimate ?? Math.ceil(String(data?.context ?? "").length / 4)),
6598
+ format: String(data?.format ?? format),
6599
+ sources_used: Number(data?.sources_used ?? 0),
6600
+ workspace_id: withDefaults.workspace_id,
6601
+ project_id: withDefaults.project_id,
6602
+ ...versionNotice2 ? { version_notice: versionNotice2 } : {},
6603
+ ...Array.isArray(data?.errors) ? { errors: data.errors } : {}
6604
+ };
6605
+ } catch (err) {
6606
+ const message2 = err instanceof Error ? err.message : String(err);
6607
+ console.warn(`[ContextStream] context_smart remote failed, using local fallback: ${message2}`);
6608
+ }
6563
6609
  const message = params.user_message.toLowerCase();
6564
6610
  const keywords = this.extractKeywords(message);
6565
6611
  const items = [];
@@ -7288,6 +7334,131 @@ W:${wsHint}
7288
7334
  uuidSchema.parse(params.reminder_id);
7289
7335
  return request(this.config, `/reminders/${params.reminder_id}`, { method: "DELETE" });
7290
7336
  }
7337
+ // ============================================
7338
+ // Plans & Tasks
7339
+ // ============================================
7340
+ /**
7341
+ * Create a new implementation plan
7342
+ */
7343
+ async createPlan(params) {
7344
+ const withDefaults = this.withDefaults(params);
7345
+ if (!withDefaults.workspace_id) {
7346
+ throw new Error("workspace_id is required for creating plans");
7347
+ }
7348
+ return request(this.config, "/plans", { body: withDefaults });
7349
+ }
7350
+ /**
7351
+ * List plans with optional filters
7352
+ */
7353
+ async listPlans(params) {
7354
+ const withDefaults = this.withDefaults(params || {});
7355
+ const query = new URLSearchParams();
7356
+ if (withDefaults.workspace_id) query.set("workspace_id", withDefaults.workspace_id);
7357
+ if (withDefaults.project_id) query.set("project_id", withDefaults.project_id);
7358
+ if (params?.status) query.set("status", params.status);
7359
+ if (params?.limit) query.set("limit", String(params.limit));
7360
+ if (params?.offset) query.set("offset", String(params.offset));
7361
+ const suffix = query.toString() ? `?${query.toString()}` : "";
7362
+ return request(this.config, `/plans${suffix}`, { method: "GET" });
7363
+ }
7364
+ /**
7365
+ * Get a plan by ID, optionally including its tasks
7366
+ */
7367
+ async getPlan(params) {
7368
+ uuidSchema.parse(params.plan_id);
7369
+ const query = new URLSearchParams();
7370
+ if (params.include_tasks !== false) query.set("include_tasks", "true");
7371
+ const suffix = query.toString() ? `?${query.toString()}` : "";
7372
+ return request(this.config, `/plans/${params.plan_id}${suffix}`, { method: "GET" });
7373
+ }
7374
+ /**
7375
+ * Update an existing plan
7376
+ */
7377
+ async updatePlan(params) {
7378
+ uuidSchema.parse(params.plan_id);
7379
+ const { plan_id, ...updates } = params;
7380
+ return request(this.config, `/plans/${plan_id}`, { method: "PATCH", body: updates });
7381
+ }
7382
+ /**
7383
+ * Delete a plan
7384
+ */
7385
+ async deletePlan(params) {
7386
+ uuidSchema.parse(params.plan_id);
7387
+ return request(this.config, `/plans/${params.plan_id}`, { method: "DELETE" });
7388
+ }
7389
+ /**
7390
+ * Get tasks for a specific plan
7391
+ */
7392
+ async getPlanTasks(params) {
7393
+ uuidSchema.parse(params.plan_id);
7394
+ return request(this.config, `/plans/${params.plan_id}/tasks`, { method: "GET" });
7395
+ }
7396
+ /**
7397
+ * Create a task within a plan
7398
+ */
7399
+ async createPlanTask(params) {
7400
+ uuidSchema.parse(params.plan_id);
7401
+ const { plan_id, ...taskData } = params;
7402
+ return request(this.config, `/plans/${plan_id}/tasks`, { body: taskData });
7403
+ }
7404
+ /**
7405
+ * Reorder tasks within a plan
7406
+ */
7407
+ async reorderPlanTasks(params) {
7408
+ uuidSchema.parse(params.plan_id);
7409
+ return request(this.config, `/plans/${params.plan_id}/tasks/reorder`, {
7410
+ method: "PATCH",
7411
+ body: { task_ids: params.task_ids }
7412
+ });
7413
+ }
7414
+ /**
7415
+ * Create a standalone task (optionally linked to a plan)
7416
+ */
7417
+ async createTask(params) {
7418
+ const withDefaults = this.withDefaults(params);
7419
+ if (!withDefaults.workspace_id) {
7420
+ throw new Error("workspace_id is required for creating tasks");
7421
+ }
7422
+ return request(this.config, "/tasks", { body: withDefaults });
7423
+ }
7424
+ /**
7425
+ * List tasks with optional filters
7426
+ */
7427
+ async listTasks(params) {
7428
+ const withDefaults = this.withDefaults(params || {});
7429
+ const query = new URLSearchParams();
7430
+ if (withDefaults.workspace_id) query.set("workspace_id", withDefaults.workspace_id);
7431
+ if (withDefaults.project_id) query.set("project_id", withDefaults.project_id);
7432
+ if (params?.plan_id) query.set("plan_id", params.plan_id);
7433
+ if (params?.status) query.set("status", params.status);
7434
+ if (params?.priority) query.set("priority", params.priority);
7435
+ if (params?.limit) query.set("limit", String(params.limit));
7436
+ if (params?.offset) query.set("offset", String(params.offset));
7437
+ const suffix = query.toString() ? `?${query.toString()}` : "";
7438
+ return request(this.config, `/tasks${suffix}`, { method: "GET" });
7439
+ }
7440
+ /**
7441
+ * Get a task by ID
7442
+ */
7443
+ async getTask(params) {
7444
+ uuidSchema.parse(params.task_id);
7445
+ return request(this.config, `/tasks/${params.task_id}`, { method: "GET" });
7446
+ }
7447
+ /**
7448
+ * Update an existing task
7449
+ */
7450
+ async updateTask(params) {
7451
+ uuidSchema.parse(params.task_id);
7452
+ const { task_id, ...updates } = params;
7453
+ return request(this.config, `/tasks/${task_id}`, { method: "PATCH", body: updates });
7454
+ }
7455
+ /**
7456
+ * Delete a task
7457
+ */
7458
+ async deleteTask(params) {
7459
+ uuidSchema.parse(params.task_id);
7460
+ return request(this.config, `/tasks/${params.task_id}`, { method: "DELETE" });
7461
+ }
7291
7462
  };
7292
7463
 
7293
7464
  // src/tools.ts
@@ -7345,6 +7516,8 @@ v0.4.x uses **~11 consolidated domain tools** for ~75% token reduction vs previo
7345
7516
 
7346
7517
  **NO EXCEPTIONS.** Do not skip even if you think you have enough context.
7347
7518
 
7519
+ **Context Pack (Pro+):** If enabled, use \`context_smart(..., mode="pack", distill=true)\` for code/file queries. If unavailable, omit \`mode\` and use standard \`context_smart\`.
7520
+
7348
7521
  ---
7349
7522
 
7350
7523
  ## Consolidated Domain Tools Architecture
@@ -7408,6 +7581,18 @@ If context still feels missing, use \`session(action="recall", query="...")\` fo
7408
7581
 
7409
7582
  ---
7410
7583
 
7584
+ ### Index & Graph Preflight (REQUIRED for code/file search)
7585
+
7586
+ Before searching files or code, confirm the project is indexed and the graph is available:
7587
+
7588
+ 1. \`project(action="index_status")\` for the current project
7589
+ 2. If missing/stale:
7590
+ - Local repo: \`project(action="ingest_local", path="<cwd>")\`
7591
+ - Otherwise: \`project(action="index")\`
7592
+ 3. If graph queries are empty/unavailable: \`graph(action="ingest")\`
7593
+
7594
+ Only after this preflight, proceed with search/analysis below.
7595
+
7411
7596
  ### Search & Code Intelligence (ContextStream-first)
7412
7597
 
7413
7598
  **Search order:**
@@ -7488,6 +7673,8 @@ v0.4.x uses ~11 consolidated domain tools for ~75% token reduction vs previous v
7488
7673
  | **Before risky work** | \`session(action="get_lessons", query="<topic>")\` |
7489
7674
  | **On user frustration** | \`session(action="capture_lesson", title="...", trigger="...", impact="...", prevention="...")\` |
7490
7675
 
7676
+ **Context Pack (Pro+):** If enabled, use \`context_smart(..., mode="pack", distill=true)\` for code/file queries. If unavailable, omit \`mode\`.
7677
+
7491
7678
  ### Quick Reference: Domain Tools
7492
7679
 
7493
7680
  | Tool | Common Usage |
@@ -7505,6 +7692,7 @@ v0.4.x uses ~11 consolidated domain tools for ~75% token reduction vs previous v
7505
7692
 
7506
7693
  - **First message**: Always call \`session_init\` with context_hint
7507
7694
  - **Every message after**: Always call \`context_smart\` BEFORE responding (semantic search for relevant context)
7695
+ - **Before searching files/code**: Check \`project(action="index_status")\`; if missing/stale run \`project(action="ingest_local", path="<cwd>")\` or \`project(action="index")\`, and use \`graph(action="ingest")\` if needed
7508
7696
  - **For discovery**: Use \`session(action="smart_search")\` or \`search(mode="hybrid")\` before local repo scans
7509
7697
  - **For code analysis**: Use \`graph(action="dependencies")\` or \`graph(action="impact")\` for call/dependency analysis
7510
7698
  - **After completing work**: Always capture decisions/insights with \`session(action="capture")\`
@@ -7630,7 +7818,12 @@ var TOOL_CATALOG = [
7630
7818
  { name: "get_lessons", hint: "learn" },
7631
7819
  { name: "capture_lesson", hint: "mistake" },
7632
7820
  { name: "get_user_context", hint: "prefs" },
7633
- { name: "smart_search", hint: "deep-find" }
7821
+ { name: "smart_search", hint: "deep-find" },
7822
+ // Plan actions
7823
+ { name: "capture_plan", hint: "save-plan" },
7824
+ { name: "get_plan", hint: "get-plan" },
7825
+ { name: "update_plan", hint: "edit-plan" },
7826
+ { name: "list_plans", hint: "list-plans" }
7634
7827
  ]
7635
7828
  },
7636
7829
  {
@@ -7653,7 +7846,14 @@ var TOOL_CATALOG = [
7653
7846
  { name: "search", hint: "find" },
7654
7847
  { name: "decisions", hint: "choices" },
7655
7848
  { name: "timeline", hint: "history" },
7656
- { name: "distill_event", hint: "extract" }
7849
+ { name: "distill_event", hint: "extract" },
7850
+ // Task actions
7851
+ { name: "create_task", hint: "new-task" },
7852
+ { name: "get_task", hint: "get-task" },
7853
+ { name: "update_task", hint: "edit-task" },
7854
+ { name: "delete_task", hint: "rm-task" },
7855
+ { name: "list_tasks", hint: "list-tasks" },
7856
+ { name: "reorder_tasks", hint: "sort-tasks" }
7657
7857
  ]
7658
7858
  },
7659
7859
  {
@@ -11478,6 +11678,9 @@ Format options:
11478
11678
 
11479
11679
  Type codes: W=Workspace, P=Project, D=Decision, M=Memory, I=Insight, T=Task, L=Lesson
11480
11680
 
11681
+ Context Pack:
11682
+ - mode='pack' adds code context + distillation (higher credit cost)
11683
+
11481
11684
  Example usage:
11482
11685
  1. User asks "how should I implement auth?"
11483
11686
  2. AI calls context_smart(user_message="how should I implement auth?")
@@ -11490,7 +11693,9 @@ This saves ~80% tokens compared to including full chat history.`,
11490
11693
  workspace_id: external_exports.string().uuid().optional(),
11491
11694
  project_id: external_exports.string().uuid().optional(),
11492
11695
  max_tokens: external_exports.number().optional().describe("Maximum tokens for context (default: 800)"),
11493
- format: external_exports.enum(["minified", "readable", "structured"]).optional().describe("Context format (default: minified)")
11696
+ format: external_exports.enum(["minified", "readable", "structured"]).optional().describe("Context format (default: minified)"),
11697
+ mode: external_exports.enum(["standard", "pack"]).optional().describe("Context pack mode (default: pack when enabled)"),
11698
+ distill: external_exports.boolean().optional().describe("Use distillation for context pack (default: true)")
11494
11699
  })
11495
11700
  },
11496
11701
  async (input) => {
@@ -11511,7 +11716,9 @@ This saves ~80% tokens compared to including full chat history.`,
11511
11716
  workspace_id: workspaceId,
11512
11717
  project_id: projectId,
11513
11718
  max_tokens: input.max_tokens,
11514
- format: input.format
11719
+ format: input.format,
11720
+ mode: input.mode,
11721
+ distill: input.distill
11515
11722
  });
11516
11723
  const footer = `
11517
11724
  ---
@@ -12344,7 +12551,7 @@ Use this to remove a reminder that is no longer relevant.`,
12344
12551
  "session",
12345
12552
  {
12346
12553
  title: "Session",
12347
- description: `Session management operations. Actions: capture (save decision/insight), capture_lesson (save lesson from mistake), get_lessons (retrieve lessons), recall (natural language recall), remember (quick save), user_context (get preferences), summary (workspace summary), compress (compress chat), delta (changes since timestamp), smart_search (context-enriched search), decision_trace (trace decision provenance).`,
12554
+ description: `Session management operations. Actions: capture (save decision/insight), capture_lesson (save lesson from mistake), get_lessons (retrieve lessons), recall (natural language recall), remember (quick save), user_context (get preferences), summary (workspace summary), compress (compress chat), delta (changes since timestamp), smart_search (context-enriched search), decision_trace (trace decision provenance). Plan actions: capture_plan (save implementation plan), get_plan (retrieve plan with tasks), update_plan (modify plan), list_plans (list all plans).`,
12348
12555
  inputSchema: external_exports.object({
12349
12556
  action: external_exports.enum([
12350
12557
  "capture",
@@ -12357,14 +12564,19 @@ Use this to remove a reminder that is no longer relevant.`,
12357
12564
  "compress",
12358
12565
  "delta",
12359
12566
  "smart_search",
12360
- "decision_trace"
12567
+ "decision_trace",
12568
+ // Plan actions
12569
+ "capture_plan",
12570
+ "get_plan",
12571
+ "update_plan",
12572
+ "list_plans"
12361
12573
  ]).describe("Action to perform"),
12362
12574
  workspace_id: external_exports.string().uuid().optional(),
12363
12575
  project_id: external_exports.string().uuid().optional(),
12364
12576
  // Content params
12365
12577
  query: external_exports.string().optional().describe("Query for recall/search/lessons/decision_trace"),
12366
12578
  content: external_exports.string().optional().describe("Content for capture/remember/compress"),
12367
- title: external_exports.string().optional().describe("Title for capture/capture_lesson"),
12579
+ title: external_exports.string().optional().describe("Title for capture/capture_lesson/capture_plan"),
12368
12580
  event_type: external_exports.enum(["decision", "preference", "insight", "task", "bug", "feature", "correction", "lesson", "warning", "frustration", "conversation"]).optional().describe("Event type for capture"),
12369
12581
  importance: external_exports.enum(["low", "medium", "high", "critical"]).optional(),
12370
12582
  tags: external_exports.array(external_exports.string()).optional(),
@@ -12395,7 +12607,22 @@ Use this to remove a reminder that is no longer relevant.`,
12395
12607
  pr_url: external_exports.string().url().optional(),
12396
12608
  issue_url: external_exports.string().url().optional(),
12397
12609
  slack_thread_url: external_exports.string().url().optional()
12398
- }).optional()
12610
+ }).optional(),
12611
+ // Plan-specific params
12612
+ plan_id: external_exports.string().uuid().optional().describe("Plan ID for get_plan/update_plan"),
12613
+ description: external_exports.string().optional().describe("Description for capture_plan"),
12614
+ goals: external_exports.array(external_exports.string()).optional().describe("Goals for capture_plan"),
12615
+ steps: external_exports.array(external_exports.object({
12616
+ id: external_exports.string(),
12617
+ title: external_exports.string(),
12618
+ description: external_exports.string().optional(),
12619
+ order: external_exports.number(),
12620
+ estimated_effort: external_exports.enum(["small", "medium", "large"]).optional()
12621
+ })).optional().describe("Implementation steps for capture_plan"),
12622
+ status: external_exports.enum(["draft", "active", "completed", "archived", "abandoned"]).optional().describe("Plan status"),
12623
+ due_at: external_exports.string().optional().describe("Due date for plan (ISO timestamp)"),
12624
+ source_tool: external_exports.string().optional().describe("Tool that generated this plan"),
12625
+ include_tasks: external_exports.boolean().optional().describe("Include tasks when getting plan")
12399
12626
  })
12400
12627
  },
12401
12628
  async (input) => {
@@ -12559,6 +12786,68 @@ Use this to remove a reminder that is no longer relevant.`,
12559
12786
  });
12560
12787
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12561
12788
  }
12789
+ // Plan actions
12790
+ case "capture_plan": {
12791
+ if (!input.title) {
12792
+ return errorResult("capture_plan requires: title");
12793
+ }
12794
+ if (!workspaceId) {
12795
+ return errorResult("capture_plan requires workspace_id. Call session_init first.");
12796
+ }
12797
+ const result = await client.createPlan({
12798
+ workspace_id: workspaceId,
12799
+ project_id: projectId,
12800
+ title: input.title,
12801
+ content: input.content,
12802
+ description: input.description,
12803
+ goals: input.goals,
12804
+ steps: input.steps,
12805
+ status: input.status || "draft",
12806
+ tags: input.tags,
12807
+ due_at: input.due_at,
12808
+ source_tool: input.source_tool || "mcp"
12809
+ });
12810
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12811
+ }
12812
+ case "get_plan": {
12813
+ if (!input.plan_id) {
12814
+ return errorResult("get_plan requires: plan_id");
12815
+ }
12816
+ const result = await client.getPlan({
12817
+ plan_id: input.plan_id,
12818
+ include_tasks: input.include_tasks !== false
12819
+ });
12820
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12821
+ }
12822
+ case "update_plan": {
12823
+ if (!input.plan_id) {
12824
+ return errorResult("update_plan requires: plan_id");
12825
+ }
12826
+ const result = await client.updatePlan({
12827
+ plan_id: input.plan_id,
12828
+ title: input.title,
12829
+ content: input.content,
12830
+ description: input.description,
12831
+ goals: input.goals,
12832
+ steps: input.steps,
12833
+ status: input.status,
12834
+ tags: input.tags,
12835
+ due_at: input.due_at
12836
+ });
12837
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12838
+ }
12839
+ case "list_plans": {
12840
+ if (!workspaceId) {
12841
+ return errorResult("list_plans requires workspace_id. Call session_init first.");
12842
+ }
12843
+ const result = await client.listPlans({
12844
+ workspace_id: workspaceId,
12845
+ project_id: projectId,
12846
+ status: input.status,
12847
+ limit: input.limit
12848
+ });
12849
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12850
+ }
12562
12851
  default:
12563
12852
  return errorResult(`Unknown action: ${input.action}`);
12564
12853
  }
@@ -12568,7 +12857,7 @@ Use this to remove a reminder that is no longer relevant.`,
12568
12857
  "memory",
12569
12858
  {
12570
12859
  title: "Memory",
12571
- description: `Memory operations for events and nodes. Event actions: create_event, get_event, update_event, delete_event, list_events, distill_event. Node actions: create_node, get_node, update_node, delete_node, list_nodes, supersede_node. Query actions: search, decisions, timeline, summary.`,
12860
+ description: `Memory operations for events and nodes. Event actions: create_event, get_event, update_event, delete_event, list_events, distill_event. Node actions: create_node, get_node, update_node, delete_node, list_nodes, supersede_node. Query actions: search, decisions, timeline, summary. Task actions: create_task (create task, optionally linked to plan), get_task, update_task, delete_task, list_tasks, reorder_tasks.`,
12572
12861
  inputSchema: external_exports.object({
12573
12862
  action: external_exports.enum([
12574
12863
  "create_event",
@@ -12586,7 +12875,14 @@ Use this to remove a reminder that is no longer relevant.`,
12586
12875
  "search",
12587
12876
  "decisions",
12588
12877
  "timeline",
12589
- "summary"
12878
+ "summary",
12879
+ // Task actions
12880
+ "create_task",
12881
+ "get_task",
12882
+ "update_task",
12883
+ "delete_task",
12884
+ "list_tasks",
12885
+ "reorder_tasks"
12590
12886
  ]).describe("Action to perform"),
12591
12887
  workspace_id: external_exports.string().uuid().optional(),
12592
12888
  project_id: external_exports.string().uuid().optional(),
@@ -12622,7 +12918,18 @@ Use this to remove a reminder that is no longer relevant.`,
12622
12918
  file_path: external_exports.string(),
12623
12919
  symbol_id: external_exports.string().optional(),
12624
12920
  symbol_name: external_exports.string().optional()
12625
- })).optional()
12921
+ })).optional(),
12922
+ // Task-specific params
12923
+ task_id: external_exports.string().uuid().optional().describe("Task ID for get_task/update_task/delete_task"),
12924
+ plan_id: external_exports.string().uuid().optional().describe("Parent plan ID for create_task/list_tasks"),
12925
+ plan_step_id: external_exports.string().optional().describe("Which plan step this task implements"),
12926
+ description: external_exports.string().optional().describe("Description for task"),
12927
+ task_status: external_exports.enum(["pending", "in_progress", "completed", "blocked", "cancelled"]).optional().describe("Task status"),
12928
+ priority: external_exports.enum(["low", "medium", "high", "urgent"]).optional().describe("Task priority"),
12929
+ order: external_exports.number().optional().describe("Task order within plan"),
12930
+ task_ids: external_exports.array(external_exports.string().uuid()).optional().describe("Task IDs for reorder_tasks"),
12931
+ blocked_reason: external_exports.string().optional().describe("Reason when task is blocked"),
12932
+ tags: external_exports.array(external_exports.string()).optional().describe("Tags for task")
12626
12933
  })
12627
12934
  },
12628
12935
  async (input) => {
@@ -12776,6 +13083,94 @@ Use this to remove a reminder that is no longer relevant.`,
12776
13083
  });
12777
13084
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12778
13085
  }
13086
+ // Task actions
13087
+ case "create_task": {
13088
+ if (!input.title) {
13089
+ return errorResult("create_task requires: title");
13090
+ }
13091
+ if (!workspaceId) {
13092
+ return errorResult("create_task requires workspace_id. Call session_init first.");
13093
+ }
13094
+ const result = await client.createTask({
13095
+ workspace_id: workspaceId,
13096
+ project_id: projectId,
13097
+ title: input.title,
13098
+ content: input.content,
13099
+ description: input.description,
13100
+ plan_id: input.plan_id,
13101
+ plan_step_id: input.plan_step_id,
13102
+ status: input.task_status,
13103
+ priority: input.priority,
13104
+ order: input.order,
13105
+ code_refs: input.code_refs,
13106
+ tags: input.tags
13107
+ });
13108
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13109
+ }
13110
+ case "get_task": {
13111
+ if (!input.task_id) {
13112
+ return errorResult("get_task requires: task_id");
13113
+ }
13114
+ const result = await client.getTask({
13115
+ task_id: input.task_id
13116
+ });
13117
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13118
+ }
13119
+ case "update_task": {
13120
+ if (!input.task_id) {
13121
+ return errorResult("update_task requires: task_id");
13122
+ }
13123
+ const result = await client.updateTask({
13124
+ task_id: input.task_id,
13125
+ title: input.title,
13126
+ content: input.content,
13127
+ description: input.description,
13128
+ status: input.task_status,
13129
+ priority: input.priority,
13130
+ order: input.order,
13131
+ plan_step_id: input.plan_step_id,
13132
+ code_refs: input.code_refs,
13133
+ tags: input.tags,
13134
+ blocked_reason: input.blocked_reason
13135
+ });
13136
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13137
+ }
13138
+ case "delete_task": {
13139
+ if (!input.task_id) {
13140
+ return errorResult("delete_task requires: task_id");
13141
+ }
13142
+ const result = await client.deleteTask({
13143
+ task_id: input.task_id
13144
+ });
13145
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13146
+ }
13147
+ case "list_tasks": {
13148
+ if (!workspaceId) {
13149
+ return errorResult("list_tasks requires workspace_id. Call session_init first.");
13150
+ }
13151
+ const result = await client.listTasks({
13152
+ workspace_id: workspaceId,
13153
+ project_id: projectId,
13154
+ plan_id: input.plan_id,
13155
+ status: input.task_status,
13156
+ priority: input.priority,
13157
+ limit: input.limit
13158
+ });
13159
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13160
+ }
13161
+ case "reorder_tasks": {
13162
+ if (!input.plan_id) {
13163
+ return errorResult("reorder_tasks requires: plan_id");
13164
+ }
13165
+ if (!input.task_ids || input.task_ids.length === 0) {
13166
+ return errorResult("reorder_tasks requires: task_ids (array of task IDs in new order)");
13167
+ }
13168
+ const result = await client.reorderPlanTasks({
13169
+ plan_id: input.plan_id,
13170
+ task_ids: input.task_ids
13171
+ });
13172
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13173
+ }
12779
13174
  default:
12780
13175
  return errorResult(`Unknown action: ${input.action}`);
12781
13176
  }
@@ -13046,19 +13441,30 @@ Use this to remove a reminder that is no longer relevant.`,
13046
13441
  if (!input.path) {
13047
13442
  return errorResult("ingest_local requires: path");
13048
13443
  }
13444
+ if (!projectId) {
13445
+ return errorResult("ingest_local requires: project_id");
13446
+ }
13049
13447
  const validPath = await validateReadableDirectory(input.path);
13050
13448
  if (!validPath.ok) {
13051
13449
  return errorResult(validPath.error);
13052
13450
  }
13053
- const files = await readAllFilesInBatches(validPath.resolvedPath, async (batch) => {
13054
- await client.ingestLocalFiles({
13055
- project_id: projectId,
13056
- files: batch,
13451
+ let totalFiles = 0;
13452
+ let batches = 0;
13453
+ for await (const batch of readAllFilesInBatches(validPath.resolvedPath, { batchSize: 50 })) {
13454
+ if (batch.length === 0) continue;
13455
+ await client.ingestFiles(projectId, batch, {
13057
13456
  overwrite: input.overwrite,
13058
13457
  write_to_disk: input.write_to_disk
13059
13458
  });
13060
- });
13061
- const result = { files_ingested: files, project_id: projectId };
13459
+ totalFiles += batch.length;
13460
+ batches += 1;
13461
+ }
13462
+ const result = {
13463
+ project_id: projectId,
13464
+ files_ingested: totalFiles,
13465
+ batches,
13466
+ path: validPath.resolvedPath
13467
+ };
13062
13468
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13063
13469
  }
13064
13470
  default:
@@ -15231,6 +15637,7 @@ function buildContextStreamMcpServer(params) {
15231
15637
  if (params.toolset === "router") {
15232
15638
  env.CONTEXTSTREAM_PROGRESSIVE_MODE = "true";
15233
15639
  }
15640
+ env.CONTEXTSTREAM_CONTEXT_PACK = params.contextPackEnabled === false ? "false" : "true";
15234
15641
  if (IS_WINDOWS) {
15235
15642
  return {
15236
15643
  command: "cmd",
@@ -15252,6 +15659,7 @@ function buildContextStreamVsCodeServer(params) {
15252
15659
  if (params.toolset === "router") {
15253
15660
  env.CONTEXTSTREAM_PROGRESSIVE_MODE = "true";
15254
15661
  }
15662
+ env.CONTEXTSTREAM_CONTEXT_PACK = params.contextPackEnabled === false ? "false" : "true";
15255
15663
  if (IS_WINDOWS) {
15256
15664
  return {
15257
15665
  type: "stdio",
@@ -15342,6 +15750,8 @@ async function upsertCodexTomlConfig(filePath, params) {
15342
15750
  const envMarker = "[mcp_servers.contextstream.env]";
15343
15751
  const toolsetLine = params.toolset === "router" ? `CONTEXTSTREAM_PROGRESSIVE_MODE = "true"
15344
15752
  ` : "";
15753
+ const contextPackLine = `CONTEXTSTREAM_CONTEXT_PACK = "${params.contextPackEnabled === false ? "false" : "true"}"
15754
+ `;
15345
15755
  const commandLine = IS_WINDOWS ? `command = "cmd"
15346
15756
  args = ["/c", "npx", "-y", "@contextstream/mcp-server"]
15347
15757
  ` : `command = "npx"
@@ -15355,7 +15765,7 @@ args = ["-y", "@contextstream/mcp-server"]
15355
15765
  [mcp_servers.contextstream.env]
15356
15766
  CONTEXTSTREAM_API_URL = "${params.apiUrl}"
15357
15767
  CONTEXTSTREAM_API_KEY = "${params.apiKey}"
15358
- ` + toolsetLine;
15768
+ ` + toolsetLine + contextPackLine;
15359
15769
  if (!exists) {
15360
15770
  await fs5.writeFile(filePath, block.trimStart(), "utf8");
15361
15771
  return "created";
@@ -15365,10 +15775,14 @@ CONTEXTSTREAM_API_KEY = "${params.apiKey}"
15365
15775
  return "updated";
15366
15776
  }
15367
15777
  if (!existing.includes(envMarker)) {
15368
- await fs5.writeFile(filePath, existing.trimEnd() + "\n\n" + envMarker + `
15778
+ await fs5.writeFile(
15779
+ filePath,
15780
+ existing.trimEnd() + "\n\n" + envMarker + `
15369
15781
  CONTEXTSTREAM_API_URL = "${params.apiUrl}"
15370
15782
  CONTEXTSTREAM_API_KEY = "${params.apiKey}"
15371
- `, "utf8");
15783
+ ` + toolsetLine + contextPackLine,
15784
+ "utf8"
15785
+ );
15372
15786
  return "updated";
15373
15787
  }
15374
15788
  const lines = existing.split(/\r?\n/);
@@ -15376,12 +15790,14 @@ CONTEXTSTREAM_API_KEY = "${params.apiKey}"
15376
15790
  let inEnv = false;
15377
15791
  let sawUrl = false;
15378
15792
  let sawKey = false;
15793
+ let sawContextPack = false;
15379
15794
  for (const line of lines) {
15380
15795
  const trimmed = line.trim();
15381
15796
  if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
15382
15797
  if (inEnv && trimmed !== envMarker) {
15383
15798
  if (!sawUrl) out.push(`CONTEXTSTREAM_API_URL = "${params.apiUrl}"`);
15384
15799
  if (!sawKey) out.push(`CONTEXTSTREAM_API_KEY = "${params.apiKey}"`);
15800
+ if (!sawContextPack) out.push(`CONTEXTSTREAM_CONTEXT_PACK = "${params.contextPackEnabled === false ? "false" : "true"}"`);
15385
15801
  inEnv = false;
15386
15802
  }
15387
15803
  if (trimmed === envMarker) inEnv = true;
@@ -15398,11 +15814,17 @@ CONTEXTSTREAM_API_KEY = "${params.apiKey}"
15398
15814
  sawKey = true;
15399
15815
  continue;
15400
15816
  }
15817
+ if (inEnv && /^\s*CONTEXTSTREAM_CONTEXT_PACK\s*=/.test(line)) {
15818
+ out.push(`CONTEXTSTREAM_CONTEXT_PACK = "${params.contextPackEnabled === false ? "false" : "true"}"`);
15819
+ sawContextPack = true;
15820
+ continue;
15821
+ }
15401
15822
  out.push(line);
15402
15823
  }
15403
15824
  if (inEnv) {
15404
15825
  if (!sawUrl) out.push(`CONTEXTSTREAM_API_URL = "${params.apiUrl}"`);
15405
15826
  if (!sawKey) out.push(`CONTEXTSTREAM_API_KEY = "${params.apiKey}"`);
15827
+ if (!sawContextPack) out.push(`CONTEXTSTREAM_CONTEXT_PACK = "${params.contextPackEnabled === false ? "false" : "true"}"`);
15406
15828
  }
15407
15829
  const updated = out.join("\n");
15408
15830
  if (updated === existing) return "skipped";
@@ -15643,6 +16065,11 @@ Detected plan: ${planLabel} (graph: ${graphTierLabel})`);
15643
16065
  console.log(" Tip: Change later by setting CONTEXTSTREAM_CONSOLIDATED=true|false");
15644
16066
  const toolsetChoice = normalizeInput(await rl.question("Choose [1/2] (default 1): ")) || "1";
15645
16067
  const toolset = toolsetChoice === "2" ? "router" : "consolidated";
16068
+ console.log("\nContext Pack (Pro+ plans):");
16069
+ console.log(" Fast indexed code + graph context with optional distillation.");
16070
+ console.log(" Uses more operations/credits; can be disabled in settings or via env.");
16071
+ const contextPackChoice = normalizeInput(await rl.question("Enable Context Pack? [Y/n]: "));
16072
+ const contextPackEnabled = !(contextPackChoice.toLowerCase() === "n" || contextPackChoice.toLowerCase() === "no");
15646
16073
  const editors = ["codex", "claude", "cursor", "windsurf", "cline", "kilo", "roo", "aider"];
15647
16074
  console.log('\nSelect editors to configure (comma-separated numbers, or "all"):');
15648
16075
  editors.forEach((e, i) => console.log(` ${i + 1}) ${EDITOR_LABELS[e]}`));
@@ -15699,9 +16126,9 @@ Detected plan: ${planLabel} (graph: ${graphTierLabel})`);
15699
16126
  const mcpChoiceDefault = hasCodex && !hasProjectMcpEditors ? "1" : "3";
15700
16127
  const mcpChoice = normalizeInput(await rl.question(`Choose [${hasCodex && !hasProjectMcpEditors ? "1/2" : "1/2/3/4"}] (default ${mcpChoiceDefault}): `)) || mcpChoiceDefault;
15701
16128
  const mcpScope = mcpChoice === "2" && hasCodex && !hasProjectMcpEditors ? "skip" : mcpChoice === "4" ? "skip" : mcpChoice === "1" ? "global" : mcpChoice === "2" ? "project" : "both";
15702
- const mcpServer = buildContextStreamMcpServer({ apiUrl, apiKey, toolset });
15703
- const mcpServerClaude = buildContextStreamMcpServer({ apiUrl, apiKey, toolset });
15704
- const vsCodeServer = buildContextStreamVsCodeServer({ apiUrl, apiKey, toolset });
16129
+ const mcpServer = buildContextStreamMcpServer({ apiUrl, apiKey, toolset, contextPackEnabled });
16130
+ const mcpServerClaude = buildContextStreamMcpServer({ apiUrl, apiKey, toolset, contextPackEnabled });
16131
+ const vsCodeServer = buildContextStreamVsCodeServer({ apiUrl, apiKey, toolset, contextPackEnabled });
15705
16132
  const needsGlobalMcpConfig = mcpScope === "global" || mcpScope === "both" || mcpScope === "project" && hasCodex;
15706
16133
  if (needsGlobalMcpConfig) {
15707
16134
  console.log("\nInstalling global MCP config...");
@@ -15715,7 +16142,7 @@ Detected plan: ${planLabel} (graph: ${graphTierLabel})`);
15715
16142
  console.log(`- ${EDITOR_LABELS[editor]}: would update ${filePath}`);
15716
16143
  continue;
15717
16144
  }
15718
- const status = await upsertCodexTomlConfig(filePath, { apiUrl, apiKey, toolset });
16145
+ const status = await upsertCodexTomlConfig(filePath, { apiUrl, apiKey, toolset, contextPackEnabled });
15719
16146
  writeActions.push({ kind: "mcp-config", target: filePath, status });
15720
16147
  console.log(`- ${EDITOR_LABELS[editor]}: ${status} ${filePath}`);
15721
16148
  continue;
@@ -15749,7 +16176,8 @@ Detected plan: ${planLabel} (graph: ${graphTierLabel})`);
15749
16176
  }
15750
16177
  console.log("- Claude Code: global MCP config is best done via `claude mcp add --transport stdio ...` (see docs).");
15751
16178
  const envHint = toolset === "router" ? " --env CONTEXTSTREAM_PROGRESSIVE_MODE=true" : "";
15752
- console.log(` macOS/Linux: claude mcp add --transport stdio contextstream --scope user --env CONTEXTSTREAM_API_URL=... --env CONTEXTSTREAM_API_KEY=...${envHint} -- npx -y @contextstream/mcp-server`);
16179
+ const packHint = contextPackEnabled === false ? " --env CONTEXTSTREAM_CONTEXT_PACK=false" : " --env CONTEXTSTREAM_CONTEXT_PACK=true";
16180
+ console.log(` macOS/Linux: claude mcp add --transport stdio contextstream --scope user --env CONTEXTSTREAM_API_URL=... --env CONTEXTSTREAM_API_KEY=...${envHint}${packHint} -- npx -y @contextstream/mcp-server`);
15753
16181
  console.log(" Windows (native): use `cmd /c npx -y @contextstream/mcp-server` after `--` if `npx` is not found.");
15754
16182
  continue;
15755
16183
  }
@@ -15956,6 +16384,7 @@ Applying to ${projects.length} project(s)...`);
15956
16384
  const toolsetDesc = toolset === "router" ? "~2 meta-tools (router mode)" : "~11 domain tools (consolidated)";
15957
16385
  console.log(`Toolset: ${toolset} (${toolsetDesc})`);
15958
16386
  console.log(`Token reduction: ~75% compared to previous versions.`);
16387
+ console.log(`Context Pack: ${contextPackEnabled ? "enabled" : "disabled"}`);
15959
16388
  }
15960
16389
  console.log("\nNext steps:");
15961
16390
  console.log("- Restart your editor/CLI after changing MCP config or rules.");
@@ -15964,6 +16393,7 @@ Applying to ${projects.length} project(s)...`);
15964
16393
  if (toolset === "router") {
15965
16394
  console.log("- Router mode uses 2 meta-tools (session_init + context_smart) for ultra-minimal token usage.");
15966
16395
  }
16396
+ console.log("- Toggle Context Pack with CONTEXTSTREAM_CONTEXT_PACK=true|false (and in dashboard settings).");
15967
16397
  console.log("");
15968
16398
  console.log("You're set up! Now try these prompts in your AI tool:");
15969
16399
  console.log(' 1) "session summary"');
@@ -16032,6 +16462,7 @@ Environment variables:
16032
16462
  CONTEXTSTREAM_ROUTER_MODE Router pattern: true|false (default: false, exposes only 2 meta-tools)
16033
16463
  CONTEXTSTREAM_OUTPUT_FORMAT Output verbosity: compact|pretty (default: compact, ~30% fewer tokens)
16034
16464
  CONTEXTSTREAM_CONSOLIDATED Consolidated domain tools: true|false (default: true in v0.4.x, ~75% token reduction)
16465
+ CONTEXTSTREAM_CONTEXT_PACK Enable Context Pack in context_smart: true|false (default: true)
16035
16466
  CONTEXTSTREAM_PRO_TOOLS Optional comma-separated PRO tool names (default: AI tools)
16036
16467
  CONTEXTSTREAM_UPGRADE_URL Optional upgrade URL shown for PRO tools on Free plan
16037
16468
  CONTEXTSTREAM_ENABLE_PROMPTS Enable MCP prompts list (default: true)
@@ -4052,6 +4052,13 @@ var NEVER = INVALID;
4052
4052
 
4053
4053
  // src/config.ts
4054
4054
  var DEFAULT_API_URL = "https://api.contextstream.io";
4055
+ function parseBooleanEnv(value) {
4056
+ if (value === void 0) return void 0;
4057
+ const normalized = value.trim().toLowerCase();
4058
+ if (["1", "true", "yes", "on"].includes(normalized)) return true;
4059
+ if (["0", "false", "no", "off"].includes(normalized)) return false;
4060
+ return void 0;
4061
+ }
4055
4062
  var configSchema = external_exports.object({
4056
4063
  apiUrl: external_exports.string().url().default(DEFAULT_API_URL),
4057
4064
  apiKey: external_exports.string().min(1).optional(),
@@ -4059,11 +4066,15 @@ var configSchema = external_exports.object({
4059
4066
  defaultWorkspaceId: external_exports.string().uuid().optional(),
4060
4067
  defaultProjectId: external_exports.string().uuid().optional(),
4061
4068
  userAgent: external_exports.string().default("contextstream-mcp/0.1.0"),
4062
- allowHeaderAuth: external_exports.boolean().optional()
4069
+ allowHeaderAuth: external_exports.boolean().optional(),
4070
+ contextPackEnabled: external_exports.boolean().default(true)
4063
4071
  });
4064
4072
  var MISSING_CREDENTIALS_ERROR = "Set CONTEXTSTREAM_API_KEY or CONTEXTSTREAM_JWT for authentication (or CONTEXTSTREAM_ALLOW_HEADER_AUTH=true for header-based auth).";
4065
4073
  function loadConfig() {
4066
4074
  const allowHeaderAuth = process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "1" || process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "true" || process.env.CONTEXTSTREAM_ALLOW_HEADER_AUTH === "yes";
4075
+ const contextPackEnabled = parseBooleanEnv(
4076
+ process.env.CONTEXTSTREAM_CONTEXT_PACK ?? process.env.CONTEXTSTREAM_CONTEXT_PACK_ENABLED
4077
+ );
4067
4078
  const parsed = configSchema.safeParse({
4068
4079
  apiUrl: process.env.CONTEXTSTREAM_API_URL,
4069
4080
  apiKey: process.env.CONTEXTSTREAM_API_KEY,
@@ -4071,7 +4082,8 @@ function loadConfig() {
4071
4082
  defaultWorkspaceId: process.env.CONTEXTSTREAM_WORKSPACE_ID,
4072
4083
  defaultProjectId: process.env.CONTEXTSTREAM_PROJECT_ID,
4073
4084
  userAgent: process.env.CONTEXTSTREAM_USER_AGENT,
4074
- allowHeaderAuth
4085
+ allowHeaderAuth,
4086
+ contextPackEnabled
4075
4087
  });
4076
4088
  if (!parsed.success) {
4077
4089
  const missing = parsed.error.errors.map((e) => e.path.join(".")).join(", ");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@contextstream/mcp-server",
3
3
  "mcpName": "io.github.contextstreamio/mcp-server",
4
- "version": "0.4.9",
4
+ "version": "0.4.11",
5
5
  "description": "ContextStream MCP server - v0.4.x with consolidated domain tools (~11 tools, ~75% token reduction). Code context, memory, search, and AI tools.",
6
6
  "type": "module",
7
7
  "license": "MIT",