@contextstream/mcp-server 0.3.47 → 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();
@@ -7594,7 +7677,17 @@ function getCoreToolsHint() {
7594
7677
  // src/tools.ts
7595
7678
  var LESSON_DEDUP_WINDOW_MS = 2 * 60 * 1e3;
7596
7679
  var recentLessonCaptures = /* @__PURE__ */ new Map();
7597
- 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
7598
7691
  "session_init",
7599
7692
  "session_tools",
7600
7693
  "context_smart",
@@ -7608,18 +7701,33 @@ var CORE_TOOLSET = /* @__PURE__ */ new Set([
7608
7701
  "session_smart_search",
7609
7702
  "session_compress",
7610
7703
  "session_delta",
7704
+ // Setup and configuration
7611
7705
  "generate_editor_rules",
7612
7706
  "workspace_associate",
7613
7707
  "workspace_bootstrap",
7614
7708
  "projects_create",
7615
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
7616
7716
  "auth_me",
7617
7717
  "mcp_server_version"
7618
7718
  ]);
7619
7719
  var TOOLSET_ALIASES = {
7620
- core: CORE_TOOLSET,
7621
- minimal: CORE_TOOLSET,
7622
- 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
7623
7731
  };
7624
7732
  function parseToolList(raw) {
7625
7733
  return new Set(
@@ -7627,30 +7735,29 @@ function parseToolList(raw) {
7627
7735
  );
7628
7736
  }
7629
7737
  function resolveToolFilter() {
7630
- const defaultToolset = CORE_TOOLSET;
7631
7738
  const allowlistRaw = process.env.CONTEXTSTREAM_TOOL_ALLOWLIST;
7632
7739
  if (allowlistRaw) {
7633
7740
  const allowlist = parseToolList(allowlistRaw);
7634
7741
  if (allowlist.size === 0) {
7635
- console.error("[ContextStream] CONTEXTSTREAM_TOOL_ALLOWLIST is empty; using core tool list.");
7636
- return { allowlist: defaultToolset, source: "core" };
7742
+ console.error("[ContextStream] CONTEXTSTREAM_TOOL_ALLOWLIST is empty; using standard toolset.");
7743
+ return { allowlist: STANDARD_TOOLSET, source: "standard" };
7637
7744
  }
7638
7745
  return { allowlist, source: "allowlist" };
7639
7746
  }
7640
7747
  const toolsetRaw = process.env.CONTEXTSTREAM_TOOLSET;
7641
7748
  if (!toolsetRaw) {
7642
- return { allowlist: defaultToolset, source: "core" };
7749
+ return { allowlist: STANDARD_TOOLSET, source: "standard" };
7643
7750
  }
7644
7751
  const key = toolsetRaw.trim().toLowerCase();
7645
- if (!key || key === "full" || key === "all") {
7646
- return { allowlist: null, source: "full" };
7647
- }
7648
- const resolved = TOOLSET_ALIASES[key];
7649
- 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
+ }
7650
7757
  return { allowlist: resolved, source: key };
7651
7758
  }
7652
- console.error(`[ContextStream] Unknown CONTEXTSTREAM_TOOLSET "${toolsetRaw}". Using core tool list.`);
7653
- return { allowlist: defaultToolset, source: "core" };
7759
+ console.error(`[ContextStream] Unknown CONTEXTSTREAM_TOOLSET "${toolsetRaw}". Using standard toolset.`);
7760
+ return { allowlist: STANDARD_TOOLSET, source: "standard" };
7654
7761
  }
7655
7762
  function formatContent(data) {
7656
7763
  return JSON.stringify(data, null, 2);
@@ -7695,9 +7802,11 @@ function registerTools(server, client, sessionManager) {
7695
7802
  const toolFilter = resolveToolFilter();
7696
7803
  const toolAllowlist = toolFilter.allowlist;
7697
7804
  if (toolAllowlist) {
7698
- const source = toolFilter.source ?? "custom";
7699
- const hint = source === "core" ? " Set CONTEXTSTREAM_TOOLSET=full to expose all tools." : "";
7700
- 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).`);
7701
7810
  }
7702
7811
  const defaultProTools = /* @__PURE__ */ new Set([
7703
7812
  // AI endpoints (typically paid/credit-metered)
@@ -10770,26 +10879,26 @@ var SessionManager = class {
10770
10879
  };
10771
10880
 
10772
10881
  // src/index.ts
10773
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
10774
- import { homedir as homedir3 } from "os";
10775
- 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";
10776
10885
 
10777
10886
  // src/setup.ts
10778
10887
  import * as fs5 from "node:fs/promises";
10779
10888
  import * as path6 from "node:path";
10780
- import { homedir as homedir2 } from "node:os";
10889
+ import { homedir as homedir3 } from "node:os";
10781
10890
  import { stdin, stdout } from "node:process";
10782
10891
  import { createInterface } from "node:readline/promises";
10783
10892
 
10784
10893
  // src/credentials.ts
10785
10894
  import * as fs4 from "node:fs/promises";
10786
10895
  import * as path5 from "node:path";
10787
- import { homedir } from "node:os";
10896
+ import { homedir as homedir2 } from "node:os";
10788
10897
  function normalizeApiUrl(input) {
10789
10898
  return String(input ?? "").trim().replace(/\/+$/, "");
10790
10899
  }
10791
10900
  function credentialsFilePath() {
10792
- return path5.join(homedir(), ".contextstream", "credentials.json");
10901
+ return path5.join(homedir2(), ".contextstream", "credentials.json");
10793
10902
  }
10794
10903
  function isRecord(value) {
10795
10904
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -10887,21 +10996,42 @@ async function fileExists(filePath) {
10887
10996
  return false;
10888
10997
  }
10889
10998
  }
10890
- 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) {
10891
11007
  await fs5.mkdir(path6.dirname(filePath), { recursive: true });
10892
11008
  const exists = await fileExists(filePath);
11009
+ const wrappedContent = wrapWithMarkers(content);
10893
11010
  if (!exists) {
10894
- await fs5.writeFile(filePath, content, "utf8");
11011
+ await fs5.writeFile(filePath, wrappedContent + "\n", "utf8");
10895
11012
  return "created";
10896
11013
  }
10897
11014
  const existing = await fs5.readFile(filePath, "utf8").catch(() => "");
10898
- if (existing.includes(marker)) return "skipped";
10899
- 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";
10900
11030
  await fs5.writeFile(filePath, joined, "utf8");
10901
11031
  return "appended";
10902
11032
  }
10903
11033
  function globalRulesPathForEditor(editor) {
10904
- const home = homedir2();
11034
+ const home = homedir3();
10905
11035
  switch (editor) {
10906
11036
  case "codex":
10907
11037
  return path6.join(home, ".codex", "AGENTS.md");
@@ -11009,7 +11139,7 @@ async function upsertJsonVsCodeMcpConfig(filePath, server) {
11009
11139
  return before === after ? "skipped" : "updated";
11010
11140
  }
11011
11141
  function claudeDesktopConfigPath() {
11012
- const home = homedir2();
11142
+ const home = homedir3();
11013
11143
  if (process.platform === "darwin") {
11014
11144
  return path6.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
11015
11145
  }
@@ -11307,16 +11437,16 @@ Created API key: ${maskApiKey(apiKey)}
11307
11437
  const modeChoice = normalizeInput(await rl.question("Choose [1/2] (default 1): ")) || "1";
11308
11438
  const mode = modeChoice === "2" ? "full" : "minimal";
11309
11439
  console.log("\nMCP toolset (which tools to expose to the AI):");
11310
- console.log(" 1) Core (recommended) \u2014 essential session/context tools (~17 tools, lower token overhead)");
11311
- console.log(" Best for: most users, Claude Code, Claude Desktop (avoids large-context warnings)");
11312
- console.log(" 2) Full \u2014 all tools including workspaces, projects, search, memory, graph, AI, integrations (~86 tools)");
11313
- console.log(" Best for: power users needing direct access to all workspace/project/graph/AI tools");
11314
- 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");
11315
11446
  console.log("");
11316
- console.log(" Tip: You can switch toolsets later by editing the MCP config and setting CONTEXTSTREAM_TOOLSET=full");
11317
- console.log(" See https://contextstream.io/docs/mcp/tools for the full tool catalog.");
11318
- const toolsetChoice = normalizeInput(await rl.question("Choose [1/2] (default 1): ")) || "1";
11319
- 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";
11320
11450
  const editors = ["codex", "claude", "cursor", "windsurf", "cline", "kilo", "roo", "aider"];
11321
11451
  console.log('\nSelect editors to configure (comma-separated numbers, or "all"):');
11322
11452
  editors.forEach((e, i) => console.log(` ${i + 1}) ${EDITOR_LABELS[e]}`));
@@ -11347,9 +11477,9 @@ Created API key: ${maskApiKey(apiKey)}
11347
11477
  const mcpChoiceDefault = hasCodex && !hasProjectMcpEditors ? "1" : "3";
11348
11478
  const mcpChoice = normalizeInput(await rl.question(`Choose [${hasCodex && !hasProjectMcpEditors ? "1/2" : "1/2/3/4"}] (default ${mcpChoiceDefault}): `)) || mcpChoiceDefault;
11349
11479
  const mcpScope = mcpChoice === "2" && hasCodex && !hasProjectMcpEditors ? "skip" : mcpChoice === "4" ? "skip" : mcpChoice === "1" ? "global" : mcpChoice === "2" ? "project" : "both";
11350
- 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 });
11351
11481
  const mcpServerClaude = buildContextStreamMcpServer({ apiUrl, apiKey, toolset });
11352
- 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 });
11353
11483
  const needsGlobalMcpConfig = mcpScope === "global" || mcpScope === "both" || mcpScope === "project" && hasCodex;
11354
11484
  if (needsGlobalMcpConfig) {
11355
11485
  console.log("\nInstalling global MCP config...");
@@ -11357,20 +11487,20 @@ Created API key: ${maskApiKey(apiKey)}
11357
11487
  if (mcpScope === "project" && editor !== "codex") continue;
11358
11488
  try {
11359
11489
  if (editor === "codex") {
11360
- const filePath = path6.join(homedir2(), ".codex", "config.toml");
11490
+ const filePath = path6.join(homedir3(), ".codex", "config.toml");
11361
11491
  if (dryRun) {
11362
11492
  writeActions.push({ kind: "mcp-config", target: filePath, status: "dry-run" });
11363
11493
  console.log(`- ${EDITOR_LABELS[editor]}: would update ${filePath}`);
11364
11494
  continue;
11365
11495
  }
11366
- const codexParams = toolset === "full" ? { apiUrl, apiKey, toolset: "full" } : { apiUrl, apiKey };
11496
+ const codexParams = toolset === "complete" ? { apiUrl, apiKey, toolset: "complete" } : { apiUrl, apiKey };
11367
11497
  const status = await upsertCodexTomlConfig(filePath, codexParams);
11368
11498
  writeActions.push({ kind: "mcp-config", target: filePath, status });
11369
11499
  console.log(`- ${EDITOR_LABELS[editor]}: ${status} ${filePath}`);
11370
11500
  continue;
11371
11501
  }
11372
11502
  if (editor === "windsurf") {
11373
- const filePath = path6.join(homedir2(), ".codeium", "windsurf", "mcp_config.json");
11503
+ const filePath = path6.join(homedir3(), ".codeium", "windsurf", "mcp_config.json");
11374
11504
  if (dryRun) {
11375
11505
  writeActions.push({ kind: "mcp-config", target: filePath, status: "dry-run" });
11376
11506
  console.log(`- ${EDITOR_LABELS[editor]}: would update ${filePath}`);
@@ -11402,7 +11532,7 @@ Created API key: ${maskApiKey(apiKey)}
11402
11532
  continue;
11403
11533
  }
11404
11534
  if (editor === "cursor") {
11405
- const filePath = path6.join(homedir2(), ".cursor", "mcp.json");
11535
+ const filePath = path6.join(homedir3(), ".cursor", "mcp.json");
11406
11536
  if (dryRun) {
11407
11537
  writeActions.push({ kind: "mcp-config", target: filePath, status: "dry-run" });
11408
11538
  console.log(`- ${EDITOR_LABELS[editor]}: would update ${filePath}`);
@@ -11600,14 +11730,15 @@ Applying to ${projects.length} project(s)...`);
11600
11730
  const skipped = writeActions.filter((a) => a.status === "skipped").length;
11601
11731
  const dry = writeActions.filter((a) => a.status === "dry-run").length;
11602
11732
  console.log(`Summary: ${created} created, ${updated} updated, ${appended} appended, ${skipped} skipped, ${dry} dry-run.`);
11603
- 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})`);
11604
11735
  }
11605
11736
  console.log("\nNext steps:");
11606
11737
  console.log("- Restart your editor/CLI after changing MCP config or rules.");
11607
11738
  console.log("- Prefer ContextStream search first: use session_smart_search (or mcp__contextstream__session_smart_search) before raw repo scans (rg/ls/find).");
11608
11739
  console.log("- If any tools require UI-based MCP setup (e.g. Cline/Kilo/Roo global), follow https://contextstream.io/docs/mcp.");
11609
- if (toolset === "full") {
11610
- 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.");
11611
11742
  }
11612
11743
  } finally {
11613
11744
  rl.close();
@@ -11616,14 +11747,14 @@ Applying to ${projects.length} project(s)...`);
11616
11747
 
11617
11748
  // src/index.ts
11618
11749
  function showFirstRunMessage() {
11619
- const configDir = join7(homedir3(), ".contextstream");
11620
- const starShownFile = join7(configDir, ".star-shown");
11621
- if (existsSync3(starShownFile)) {
11750
+ const configDir = join8(homedir4(), ".contextstream");
11751
+ const starShownFile = join8(configDir, ".star-shown");
11752
+ if (existsSync4(starShownFile)) {
11622
11753
  return;
11623
11754
  }
11624
- if (!existsSync3(configDir)) {
11755
+ if (!existsSync4(configDir)) {
11625
11756
  try {
11626
- mkdirSync3(configDir, { recursive: true });
11757
+ mkdirSync4(configDir, { recursive: true });
11627
11758
  } catch {
11628
11759
  return;
11629
11760
  }
@@ -11636,7 +11767,7 @@ function showFirstRunMessage() {
11636
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");
11637
11768
  console.error("");
11638
11769
  try {
11639
- writeFileSync3(starShownFile, (/* @__PURE__ */ new Date()).toISOString());
11770
+ writeFileSync4(starShownFile, (/* @__PURE__ */ new Date()).toISOString());
11640
11771
  } catch {
11641
11772
  }
11642
11773
  }
@@ -11657,7 +11788,7 @@ Environment variables:
11657
11788
  CONTEXTSTREAM_JWT JWT for authentication (alternative to API key)
11658
11789
  CONTEXTSTREAM_WORKSPACE_ID Optional default workspace ID
11659
11790
  CONTEXTSTREAM_PROJECT_ID Optional default project ID
11660
- 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)
11661
11792
  CONTEXTSTREAM_TOOL_ALLOWLIST Optional comma-separated tool names to expose (overrides toolset)
11662
11793
  CONTEXTSTREAM_PRO_TOOLS Optional comma-separated PRO tool names (default: AI tools)
11663
11794
  CONTEXTSTREAM_UPGRADE_URL Optional upgrade URL shown for PRO tools on Free plan
@@ -11706,6 +11837,8 @@ async function main() {
11706
11837
  await server.connect(transport);
11707
11838
  console.error("ContextStream MCP server connected and ready");
11708
11839
  showFirstRunMessage();
11840
+ checkForUpdates().catch(() => {
11841
+ });
11709
11842
  }
11710
11843
  main().catch((err) => {
11711
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.47",
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",