@contextstream/mcp-server 0.3.46 → 0.3.48

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
@@ -69,6 +69,16 @@ npm install -g @contextstream/mcp-server
69
69
  contextstream-mcp
70
70
  ```
71
71
 
72
+ ### Keeping updated
73
+
74
+ To get the latest features and bug fixes, update periodically:
75
+
76
+ ```bash
77
+ npm update -g @contextstream/mcp-server
78
+ ```
79
+
80
+ The MCP server will warn you when a newer version is available. After updating, restart your AI tool to use the new version.
81
+
72
82
  ## Configure your MCP client
73
83
 
74
84
  ### Manual setup
package/dist/index.js CHANGED
@@ -4698,6 +4698,9 @@ var globalCache = new MemoryCache();
4698
4698
 
4699
4699
  // src/version.ts
4700
4700
  import { createRequire } from "module";
4701
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
4702
+ import { homedir } from "os";
4703
+ import { join as join3 } from "path";
4701
4704
  function getVersion() {
4702
4705
  try {
4703
4706
  const require2 = createRequire(import.meta.url);
@@ -4709,6 +4712,86 @@ function getVersion() {
4709
4712
  return "unknown";
4710
4713
  }
4711
4714
  var VERSION = getVersion();
4715
+ function compareVersions(v1, v2) {
4716
+ const parts1 = v1.split(".").map(Number);
4717
+ const parts2 = v2.split(".").map(Number);
4718
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
4719
+ const p1 = parts1[i] ?? 0;
4720
+ const p2 = parts2[i] ?? 0;
4721
+ if (p1 < p2) return -1;
4722
+ if (p1 > p2) return 1;
4723
+ }
4724
+ return 0;
4725
+ }
4726
+ var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
4727
+ function getCacheFilePath() {
4728
+ return join3(homedir(), ".contextstream", "version-cache.json");
4729
+ }
4730
+ function readCache() {
4731
+ try {
4732
+ const cacheFile = getCacheFilePath();
4733
+ if (!existsSync2(cacheFile)) return null;
4734
+ const data = JSON.parse(readFileSync2(cacheFile, "utf-8"));
4735
+ if (Date.now() - data.checkedAt > CACHE_TTL_MS) return null;
4736
+ return data;
4737
+ } catch {
4738
+ return null;
4739
+ }
4740
+ }
4741
+ function writeCache(latestVersion) {
4742
+ try {
4743
+ const configDir = join3(homedir(), ".contextstream");
4744
+ if (!existsSync2(configDir)) {
4745
+ mkdirSync2(configDir, { recursive: true });
4746
+ }
4747
+ const cacheFile = getCacheFilePath();
4748
+ writeFileSync2(cacheFile, JSON.stringify({
4749
+ latestVersion,
4750
+ checkedAt: Date.now()
4751
+ }));
4752
+ } catch {
4753
+ }
4754
+ }
4755
+ async function checkForUpdates() {
4756
+ const currentVersion = VERSION;
4757
+ if (currentVersion === "unknown") return;
4758
+ try {
4759
+ const cached = readCache();
4760
+ if (cached) {
4761
+ if (compareVersions(currentVersion, cached.latestVersion) < 0) {
4762
+ showUpdateWarning(currentVersion, cached.latestVersion);
4763
+ }
4764
+ return;
4765
+ }
4766
+ const controller = new AbortController();
4767
+ const timeout = setTimeout(() => controller.abort(), 5e3);
4768
+ const response = await fetch("https://registry.npmjs.org/@contextstream/mcp-server/latest", {
4769
+ signal: controller.signal,
4770
+ headers: { "Accept": "application/json" }
4771
+ });
4772
+ clearTimeout(timeout);
4773
+ if (!response.ok) return;
4774
+ const data = await response.json();
4775
+ const latestVersion = data.version;
4776
+ if (typeof latestVersion !== "string") return;
4777
+ writeCache(latestVersion);
4778
+ if (compareVersions(currentVersion, latestVersion) < 0) {
4779
+ showUpdateWarning(currentVersion, latestVersion);
4780
+ }
4781
+ } catch {
4782
+ }
4783
+ }
4784
+ function showUpdateWarning(currentVersion, latestVersion) {
4785
+ console.error("");
4786
+ console.error("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
4787
+ console.error(`\u26A0\uFE0F Update available: v${currentVersion} \u2192 v${latestVersion}`);
4788
+ console.error("");
4789
+ console.error(" Run: npm update -g @contextstream/mcp-server");
4790
+ console.error("");
4791
+ console.error(" Then restart your AI tool to use the new version.");
4792
+ console.error("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
4793
+ console.error("");
4794
+ }
4712
4795
 
4713
4796
  // src/client.ts
4714
4797
  var uuidSchema = external_exports.string().uuid();
@@ -4775,10 +4858,12 @@ var ContextStreamClient = class {
4775
4858
  }
4776
4859
  withDefaults(input) {
4777
4860
  const { defaultWorkspaceId, defaultProjectId } = this.config;
4861
+ const workspaceId = input.workspace_id || defaultWorkspaceId;
4862
+ const useDefaultProject = !input.project_id && (!input.workspace_id || input.workspace_id === defaultWorkspaceId);
4778
4863
  return {
4779
4864
  ...input,
4780
- workspace_id: input.workspace_id || defaultWorkspaceId,
4781
- project_id: input.project_id || defaultProjectId
4865
+ workspace_id: workspaceId,
4866
+ project_id: input.project_id || (useDefaultProject ? defaultProjectId : void 0)
4782
4867
  };
4783
4868
  }
4784
4869
  coerceUuid(value) {
@@ -5626,6 +5711,29 @@ var ContextStreamClient = class {
5626
5711
  });
5627
5712
  if (batchedContext.workspace) {
5628
5713
  context.workspace = batchedContext.workspace;
5714
+ if (batchedContext.workspace.id && batchedContext.workspace.id !== workspaceId) {
5715
+ console.error(`[ContextStream] Workspace mismatch: config=${workspaceId}, API returned=${batchedContext.workspace.id}. Using API workspace.`);
5716
+ const oldWorkspaceId = workspaceId;
5717
+ workspaceId = batchedContext.workspace.id;
5718
+ workspaceName = batchedContext.workspace.name;
5719
+ context.workspace_id = workspaceId;
5720
+ context.workspace_name = workspaceName;
5721
+ context.workspace_source = "api_fallback";
5722
+ context.workspace_mismatch_warning = `Config had workspace ${oldWorkspaceId} but you don't have access. Using ${workspaceId} instead.`;
5723
+ projectId = batchedContext.project?.id;
5724
+ context.project_id = projectId;
5725
+ this.config.defaultProjectId = projectId;
5726
+ if (rootPath) {
5727
+ writeLocalConfig(rootPath, {
5728
+ workspace_id: workspaceId,
5729
+ workspace_name: workspaceName,
5730
+ project_id: projectId,
5731
+ // Use API-returned project or undefined
5732
+ associated_at: (/* @__PURE__ */ new Date()).toISOString()
5733
+ });
5734
+ console.error(`[ContextStream] Updated local config with accessible workspace: ${workspaceId}`);
5735
+ }
5736
+ }
5629
5737
  }
5630
5738
  if (batchedContext.project) {
5631
5739
  context.project = batchedContext.project;
@@ -7569,7 +7677,17 @@ function getCoreToolsHint() {
7569
7677
  // src/tools.ts
7570
7678
  var LESSON_DEDUP_WINDOW_MS = 2 * 60 * 1e3;
7571
7679
  var recentLessonCaptures = /* @__PURE__ */ new Map();
7572
- var CORE_TOOLSET = /* @__PURE__ */ new Set([
7680
+ var LIGHT_TOOLSET = /* @__PURE__ */ new Set([
7681
+ "session_init",
7682
+ "context_smart",
7683
+ "session_capture",
7684
+ "session_recall",
7685
+ "session_remember",
7686
+ "auth_me",
7687
+ "mcp_server_version"
7688
+ ]);
7689
+ var STANDARD_TOOLSET = /* @__PURE__ */ new Set([
7690
+ // Core session tools
7573
7691
  "session_init",
7574
7692
  "session_tools",
7575
7693
  "context_smart",
@@ -7583,18 +7701,33 @@ var CORE_TOOLSET = /* @__PURE__ */ new Set([
7583
7701
  "session_smart_search",
7584
7702
  "session_compress",
7585
7703
  "session_delta",
7704
+ // Setup and configuration
7586
7705
  "generate_editor_rules",
7587
7706
  "workspace_associate",
7588
7707
  "workspace_bootstrap",
7589
7708
  "projects_create",
7590
7709
  "projects_list",
7710
+ // Project indexing - essential for code context
7711
+ "projects_ingest_local",
7712
+ "projects_index",
7713
+ "projects_index_status",
7714
+ "projects_files",
7715
+ // Utility
7591
7716
  "auth_me",
7592
7717
  "mcp_server_version"
7593
7718
  ]);
7594
7719
  var TOOLSET_ALIASES = {
7595
- core: CORE_TOOLSET,
7596
- minimal: CORE_TOOLSET,
7597
- essential: CORE_TOOLSET
7720
+ // Light mode - minimal, fastest
7721
+ light: LIGHT_TOOLSET,
7722
+ minimal: LIGHT_TOOLSET,
7723
+ // Standard mode - balanced (default)
7724
+ standard: STANDARD_TOOLSET,
7725
+ core: STANDARD_TOOLSET,
7726
+ essential: STANDARD_TOOLSET,
7727
+ // Complete mode - all tools
7728
+ complete: null,
7729
+ full: null,
7730
+ all: null
7598
7731
  };
7599
7732
  function parseToolList(raw) {
7600
7733
  return new Set(
@@ -7602,30 +7735,29 @@ function parseToolList(raw) {
7602
7735
  );
7603
7736
  }
7604
7737
  function resolveToolFilter() {
7605
- const defaultToolset = CORE_TOOLSET;
7606
7738
  const allowlistRaw = process.env.CONTEXTSTREAM_TOOL_ALLOWLIST;
7607
7739
  if (allowlistRaw) {
7608
7740
  const allowlist = parseToolList(allowlistRaw);
7609
7741
  if (allowlist.size === 0) {
7610
- console.error("[ContextStream] CONTEXTSTREAM_TOOL_ALLOWLIST is empty; using core tool list.");
7611
- return { allowlist: defaultToolset, source: "core" };
7742
+ console.error("[ContextStream] CONTEXTSTREAM_TOOL_ALLOWLIST is empty; using standard toolset.");
7743
+ return { allowlist: STANDARD_TOOLSET, source: "standard" };
7612
7744
  }
7613
7745
  return { allowlist, source: "allowlist" };
7614
7746
  }
7615
7747
  const toolsetRaw = process.env.CONTEXTSTREAM_TOOLSET;
7616
7748
  if (!toolsetRaw) {
7617
- return { allowlist: defaultToolset, source: "core" };
7749
+ return { allowlist: STANDARD_TOOLSET, source: "standard" };
7618
7750
  }
7619
7751
  const key = toolsetRaw.trim().toLowerCase();
7620
- if (!key || key === "full" || key === "all") {
7621
- return { allowlist: null, source: "full" };
7622
- }
7623
- const resolved = TOOLSET_ALIASES[key];
7624
- if (resolved) {
7752
+ if (key in TOOLSET_ALIASES) {
7753
+ const resolved = TOOLSET_ALIASES[key];
7754
+ if (resolved === null) {
7755
+ return { allowlist: null, source: "complete" };
7756
+ }
7625
7757
  return { allowlist: resolved, source: key };
7626
7758
  }
7627
- console.error(`[ContextStream] Unknown CONTEXTSTREAM_TOOLSET "${toolsetRaw}". Using core tool list.`);
7628
- return { allowlist: defaultToolset, source: "core" };
7759
+ console.error(`[ContextStream] Unknown CONTEXTSTREAM_TOOLSET "${toolsetRaw}". Using standard toolset.`);
7760
+ return { allowlist: STANDARD_TOOLSET, source: "standard" };
7629
7761
  }
7630
7762
  function formatContent(data) {
7631
7763
  return JSON.stringify(data, null, 2);
@@ -7670,9 +7802,11 @@ function registerTools(server, client, sessionManager) {
7670
7802
  const toolFilter = resolveToolFilter();
7671
7803
  const toolAllowlist = toolFilter.allowlist;
7672
7804
  if (toolAllowlist) {
7673
- const source = toolFilter.source ?? "custom";
7674
- const hint = source === "core" ? " Set CONTEXTSTREAM_TOOLSET=full to expose all tools." : "";
7675
- console.error(`[ContextStream] Toolset limited (${source}): ${toolAllowlist.size} tools.${hint}`);
7805
+ const source = toolFilter.source;
7806
+ const hint = source === "light" ? " Set CONTEXTSTREAM_TOOLSET=standard or complete for more tools." : source === "standard" ? " Set CONTEXTSTREAM_TOOLSET=complete for all tools." : "";
7807
+ console.error(`[ContextStream] Toolset: ${source} (${toolAllowlist.size} tools).${hint}`);
7808
+ } else {
7809
+ console.error(`[ContextStream] Toolset: complete (all tools).`);
7676
7810
  }
7677
7811
  const defaultProTools = /* @__PURE__ */ new Set([
7678
7812
  // AI endpoints (typically paid/credit-metered)
@@ -8008,7 +8142,7 @@ Access: Free`,
8008
8142
  }
8009
8143
  }
8010
8144
  const response = {
8011
- ...result,
8145
+ ...result && typeof result === "object" ? result : {},
8012
8146
  folder_path: input.folder_path,
8013
8147
  config_written: input.folder_path ? true : void 0,
8014
8148
  editor_rules_generated: rulesGenerated.length > 0 ? rulesGenerated : void 0
@@ -10745,26 +10879,26 @@ var SessionManager = class {
10745
10879
  };
10746
10880
 
10747
10881
  // src/index.ts
10748
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
10749
- import { homedir as homedir3 } from "os";
10750
- import { join as join7 } from "path";
10882
+ import { existsSync as existsSync4, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
10883
+ import { homedir as homedir4 } from "os";
10884
+ import { join as join8 } from "path";
10751
10885
 
10752
10886
  // src/setup.ts
10753
10887
  import * as fs5 from "node:fs/promises";
10754
10888
  import * as path6 from "node:path";
10755
- import { homedir as homedir2 } from "node:os";
10889
+ import { homedir as homedir3 } from "node:os";
10756
10890
  import { stdin, stdout } from "node:process";
10757
10891
  import { createInterface } from "node:readline/promises";
10758
10892
 
10759
10893
  // src/credentials.ts
10760
10894
  import * as fs4 from "node:fs/promises";
10761
10895
  import * as path5 from "node:path";
10762
- import { homedir } from "node:os";
10896
+ import { homedir as homedir2 } from "node:os";
10763
10897
  function normalizeApiUrl(input) {
10764
10898
  return String(input ?? "").trim().replace(/\/+$/, "");
10765
10899
  }
10766
10900
  function credentialsFilePath() {
10767
- return path5.join(homedir(), ".contextstream", "credentials.json");
10901
+ return path5.join(homedir2(), ".contextstream", "credentials.json");
10768
10902
  }
10769
10903
  function isRecord(value) {
10770
10904
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -10862,21 +10996,42 @@ async function fileExists(filePath) {
10862
10996
  return false;
10863
10997
  }
10864
10998
  }
10865
- async function upsertTextFile(filePath, content, marker) {
10999
+ var CONTEXTSTREAM_START_MARKER = "<!-- BEGIN ContextStream -->";
11000
+ var CONTEXTSTREAM_END_MARKER = "<!-- END ContextStream -->";
11001
+ function wrapWithMarkers(content) {
11002
+ return `${CONTEXTSTREAM_START_MARKER}
11003
+ ${content.trim()}
11004
+ ${CONTEXTSTREAM_END_MARKER}`;
11005
+ }
11006
+ async function upsertTextFile(filePath, content, _marker) {
10866
11007
  await fs5.mkdir(path6.dirname(filePath), { recursive: true });
10867
11008
  const exists = await fileExists(filePath);
11009
+ const wrappedContent = wrapWithMarkers(content);
10868
11010
  if (!exists) {
10869
- await fs5.writeFile(filePath, content, "utf8");
11011
+ await fs5.writeFile(filePath, wrappedContent + "\n", "utf8");
10870
11012
  return "created";
10871
11013
  }
10872
11014
  const existing = await fs5.readFile(filePath, "utf8").catch(() => "");
10873
- if (existing.includes(marker)) return "skipped";
10874
- const joined = existing.trimEnd() + "\n\n" + content.trim() + "\n";
11015
+ const startIdx = existing.indexOf(CONTEXTSTREAM_START_MARKER);
11016
+ const endIdx = existing.indexOf(CONTEXTSTREAM_END_MARKER);
11017
+ if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
11018
+ const before = existing.substring(0, startIdx);
11019
+ const after = existing.substring(endIdx + CONTEXTSTREAM_END_MARKER.length);
11020
+ const updated = before.trimEnd() + "\n\n" + wrappedContent + "\n" + after.trimStart();
11021
+ await fs5.writeFile(filePath, updated.trim() + "\n", "utf8");
11022
+ return "updated";
11023
+ }
11024
+ if (existing.includes("ContextStream")) {
11025
+ const joined2 = existing.trimEnd() + "\n\n" + wrappedContent + "\n";
11026
+ await fs5.writeFile(filePath, joined2, "utf8");
11027
+ return "updated";
11028
+ }
11029
+ const joined = existing.trimEnd() + "\n\n" + wrappedContent + "\n";
10875
11030
  await fs5.writeFile(filePath, joined, "utf8");
10876
11031
  return "appended";
10877
11032
  }
10878
11033
  function globalRulesPathForEditor(editor) {
10879
- const home = homedir2();
11034
+ const home = homedir3();
10880
11035
  switch (editor) {
10881
11036
  case "codex":
10882
11037
  return path6.join(home, ".codex", "AGENTS.md");
@@ -10984,7 +11139,7 @@ async function upsertJsonVsCodeMcpConfig(filePath, server) {
10984
11139
  return before === after ? "skipped" : "updated";
10985
11140
  }
10986
11141
  function claudeDesktopConfigPath() {
10987
- const home = homedir2();
11142
+ const home = homedir3();
10988
11143
  if (process.platform === "darwin") {
10989
11144
  return path6.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
10990
11145
  }
@@ -11282,16 +11437,16 @@ Created API key: ${maskApiKey(apiKey)}
11282
11437
  const modeChoice = normalizeInput(await rl.question("Choose [1/2] (default 1): ")) || "1";
11283
11438
  const mode = modeChoice === "2" ? "full" : "minimal";
11284
11439
  console.log("\nMCP toolset (which tools to expose to the AI):");
11285
- console.log(" 1) Core (recommended) \u2014 essential session/context tools (~17 tools, lower token overhead)");
11286
- console.log(" Best for: most users, Claude Code, Claude Desktop (avoids large-context warnings)");
11287
- console.log(" 2) Full \u2014 all tools including workspaces, projects, search, memory, graph, AI, integrations (~86 tools)");
11288
- console.log(" Best for: power users needing direct access to all workspace/project/graph/AI tools");
11289
- console.log(" Note: Claude Code/Desktop may warn about large tool lists when using full toolset.");
11440
+ console.log(" 1) Light \u2014 minimal essential tools for fastest responses (~7 tools)");
11441
+ console.log(" Best for: simple tasks, resource-constrained environments");
11442
+ console.log(" 2) Standard (recommended) \u2014 balanced set of session and context tools (~20 tools)");
11443
+ console.log(" Best for: most users, balances speed with capabilities");
11444
+ console.log(" 3) Complete \u2014 all tools including memory, knowledge graph, AI, integrations (~86 tools)");
11445
+ console.log(" Best for: power users needing full workspace/project/graph capabilities");
11290
11446
  console.log("");
11291
- console.log(" Tip: You can switch toolsets later by editing the MCP config and setting CONTEXTSTREAM_TOOLSET=full");
11292
- console.log(" See https://contextstream.io/docs/mcp/tools for the full tool catalog.");
11293
- const toolsetChoice = normalizeInput(await rl.question("Choose [1/2] (default 1): ")) || "1";
11294
- const toolset = toolsetChoice === "2" ? "full" : "core";
11447
+ console.log(" Tip: Change later by setting CONTEXTSTREAM_TOOLSET=light|standard|complete");
11448
+ const toolsetChoice = normalizeInput(await rl.question("Choose [1/2/3] (default 2): ")) || "2";
11449
+ const toolset = toolsetChoice === "1" ? "light" : toolsetChoice === "3" ? "complete" : "standard";
11295
11450
  const editors = ["codex", "claude", "cursor", "windsurf", "cline", "kilo", "roo", "aider"];
11296
11451
  console.log('\nSelect editors to configure (comma-separated numbers, or "all"):');
11297
11452
  editors.forEach((e, i) => console.log(` ${i + 1}) ${EDITOR_LABELS[e]}`));
@@ -11322,9 +11477,9 @@ Created API key: ${maskApiKey(apiKey)}
11322
11477
  const mcpChoiceDefault = hasCodex && !hasProjectMcpEditors ? "1" : "3";
11323
11478
  const mcpChoice = normalizeInput(await rl.question(`Choose [${hasCodex && !hasProjectMcpEditors ? "1/2" : "1/2/3/4"}] (default ${mcpChoiceDefault}): `)) || mcpChoiceDefault;
11324
11479
  const mcpScope = mcpChoice === "2" && hasCodex && !hasProjectMcpEditors ? "skip" : mcpChoice === "4" ? "skip" : mcpChoice === "1" ? "global" : mcpChoice === "2" ? "project" : "both";
11325
- const mcpServer = toolset === "full" ? buildContextStreamMcpServer({ apiUrl, apiKey, toolset: "full" }) : buildContextStreamMcpServer({ apiUrl, apiKey });
11480
+ const mcpServer = toolset === "complete" ? buildContextStreamMcpServer({ apiUrl, apiKey, toolset: "complete" }) : buildContextStreamMcpServer({ apiUrl, apiKey });
11326
11481
  const mcpServerClaude = buildContextStreamMcpServer({ apiUrl, apiKey, toolset });
11327
- const vsCodeServer = toolset === "full" ? buildContextStreamVsCodeServer({ apiUrl, apiKey, toolset: "full" }) : buildContextStreamVsCodeServer({ apiUrl, apiKey });
11482
+ const vsCodeServer = toolset === "complete" ? buildContextStreamVsCodeServer({ apiUrl, apiKey, toolset: "complete" }) : buildContextStreamVsCodeServer({ apiUrl, apiKey });
11328
11483
  const needsGlobalMcpConfig = mcpScope === "global" || mcpScope === "both" || mcpScope === "project" && hasCodex;
11329
11484
  if (needsGlobalMcpConfig) {
11330
11485
  console.log("\nInstalling global MCP config...");
@@ -11332,20 +11487,20 @@ Created API key: ${maskApiKey(apiKey)}
11332
11487
  if (mcpScope === "project" && editor !== "codex") continue;
11333
11488
  try {
11334
11489
  if (editor === "codex") {
11335
- const filePath = path6.join(homedir2(), ".codex", "config.toml");
11490
+ const filePath = path6.join(homedir3(), ".codex", "config.toml");
11336
11491
  if (dryRun) {
11337
11492
  writeActions.push({ kind: "mcp-config", target: filePath, status: "dry-run" });
11338
11493
  console.log(`- ${EDITOR_LABELS[editor]}: would update ${filePath}`);
11339
11494
  continue;
11340
11495
  }
11341
- const codexParams = toolset === "full" ? { apiUrl, apiKey, toolset: "full" } : { apiUrl, apiKey };
11496
+ const codexParams = toolset === "complete" ? { apiUrl, apiKey, toolset: "complete" } : { apiUrl, apiKey };
11342
11497
  const status = await upsertCodexTomlConfig(filePath, codexParams);
11343
11498
  writeActions.push({ kind: "mcp-config", target: filePath, status });
11344
11499
  console.log(`- ${EDITOR_LABELS[editor]}: ${status} ${filePath}`);
11345
11500
  continue;
11346
11501
  }
11347
11502
  if (editor === "windsurf") {
11348
- const filePath = path6.join(homedir2(), ".codeium", "windsurf", "mcp_config.json");
11503
+ const filePath = path6.join(homedir3(), ".codeium", "windsurf", "mcp_config.json");
11349
11504
  if (dryRun) {
11350
11505
  writeActions.push({ kind: "mcp-config", target: filePath, status: "dry-run" });
11351
11506
  console.log(`- ${EDITOR_LABELS[editor]}: would update ${filePath}`);
@@ -11377,7 +11532,7 @@ Created API key: ${maskApiKey(apiKey)}
11377
11532
  continue;
11378
11533
  }
11379
11534
  if (editor === "cursor") {
11380
- const filePath = path6.join(homedir2(), ".cursor", "mcp.json");
11535
+ const filePath = path6.join(homedir3(), ".cursor", "mcp.json");
11381
11536
  if (dryRun) {
11382
11537
  writeActions.push({ kind: "mcp-config", target: filePath, status: "dry-run" });
11383
11538
  console.log(`- ${EDITOR_LABELS[editor]}: would update ${filePath}`);
@@ -11575,14 +11730,15 @@ Applying to ${projects.length} project(s)...`);
11575
11730
  const skipped = writeActions.filter((a) => a.status === "skipped").length;
11576
11731
  const dry = writeActions.filter((a) => a.status === "dry-run").length;
11577
11732
  console.log(`Summary: ${created} created, ${updated} updated, ${appended} appended, ${skipped} skipped, ${dry} dry-run.`);
11578
- console.log(`Toolset: ${toolset} (${toolset === "full" ? "~86 tools" : "~17 core tools"})`);
11733
+ const toolsetDesc = toolset === "light" ? "~7 tools" : toolset === "complete" ? "~86 tools" : "~20 tools";
11734
+ console.log(`Toolset: ${toolset} (${toolsetDesc})`);
11579
11735
  }
11580
11736
  console.log("\nNext steps:");
11581
11737
  console.log("- Restart your editor/CLI after changing MCP config or rules.");
11582
11738
  console.log("- Prefer ContextStream search first: use session_smart_search (or mcp__contextstream__session_smart_search) before raw repo scans (rg/ls/find).");
11583
11739
  console.log("- If any tools require UI-based MCP setup (e.g. Cline/Kilo/Roo global), follow https://contextstream.io/docs/mcp.");
11584
- if (toolset === "full") {
11585
- console.log("- Note: Claude Code/Desktop may warn about large tool contexts. This is expected with the full toolset.");
11740
+ if (toolset === "complete") {
11741
+ console.log("- Note: Claude Code/Desktop may warn about large tool contexts. This is expected with the complete toolset.");
11586
11742
  }
11587
11743
  } finally {
11588
11744
  rl.close();
@@ -11591,14 +11747,14 @@ Applying to ${projects.length} project(s)...`);
11591
11747
 
11592
11748
  // src/index.ts
11593
11749
  function showFirstRunMessage() {
11594
- const configDir = join7(homedir3(), ".contextstream");
11595
- const starShownFile = join7(configDir, ".star-shown");
11596
- if (existsSync3(starShownFile)) {
11750
+ const configDir = join8(homedir4(), ".contextstream");
11751
+ const starShownFile = join8(configDir, ".star-shown");
11752
+ if (existsSync4(starShownFile)) {
11597
11753
  return;
11598
11754
  }
11599
- if (!existsSync3(configDir)) {
11755
+ if (!existsSync4(configDir)) {
11600
11756
  try {
11601
- mkdirSync3(configDir, { recursive: true });
11757
+ mkdirSync4(configDir, { recursive: true });
11602
11758
  } catch {
11603
11759
  return;
11604
11760
  }
@@ -11611,7 +11767,7 @@ function showFirstRunMessage() {
11611
11767
  console.error("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
11612
11768
  console.error("");
11613
11769
  try {
11614
- writeFileSync3(starShownFile, (/* @__PURE__ */ new Date()).toISOString());
11770
+ writeFileSync4(starShownFile, (/* @__PURE__ */ new Date()).toISOString());
11615
11771
  } catch {
11616
11772
  }
11617
11773
  }
@@ -11632,7 +11788,7 @@ Environment variables:
11632
11788
  CONTEXTSTREAM_JWT JWT for authentication (alternative to API key)
11633
11789
  CONTEXTSTREAM_WORKSPACE_ID Optional default workspace ID
11634
11790
  CONTEXTSTREAM_PROJECT_ID Optional default project ID
11635
- CONTEXTSTREAM_TOOLSET Optional tool bundle (core|full). Defaults to core to reduce tool context size.
11791
+ CONTEXTSTREAM_TOOLSET Tool mode: light|standard|complete (default: standard)
11636
11792
  CONTEXTSTREAM_TOOL_ALLOWLIST Optional comma-separated tool names to expose (overrides toolset)
11637
11793
  CONTEXTSTREAM_PRO_TOOLS Optional comma-separated PRO tool names (default: AI tools)
11638
11794
  CONTEXTSTREAM_UPGRADE_URL Optional upgrade URL shown for PRO tools on Free plan
@@ -11681,6 +11837,8 @@ async function main() {
11681
11837
  await server.connect(transport);
11682
11838
  console.error("ContextStream MCP server connected and ready");
11683
11839
  showFirstRunMessage();
11840
+ checkForUpdates().catch(() => {
11841
+ });
11684
11842
  }
11685
11843
  main().catch((err) => {
11686
11844
  console.error("ContextStream MCP server failed to start:", err?.message || err);
@@ -4093,6 +4093,7 @@ function getVersion() {
4093
4093
  return "unknown";
4094
4094
  }
4095
4095
  var VERSION = getVersion();
4096
+ var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
4096
4097
 
4097
4098
  // src/test-server.ts
4098
4099
  var PORT = parseInt(process.env.MCP_TEST_PORT || "3099", 10);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contextstream/mcp-server",
3
- "version": "0.3.46",
3
+ "version": "0.3.48",
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",