@contextstream/mcp-server 0.3.52 → 0.3.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +92 -21
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4701,6 +4701,8 @@ import { createRequire } from "module";
4701
4701
  import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
4702
4702
  import { homedir } from "os";
4703
4703
  import { join as join3 } from "path";
4704
+ var UPGRADE_COMMAND = "npm update -g @contextstream/mcp-server";
4705
+ var NPM_LATEST_URL = "https://registry.npmjs.org/@contextstream/mcp-server/latest";
4704
4706
  function getVersion() {
4705
4707
  try {
4706
4708
  const require2 = createRequire(import.meta.url);
@@ -4724,6 +4726,7 @@ function compareVersions(v1, v2) {
4724
4726
  return 0;
4725
4727
  }
4726
4728
  var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
4729
+ var latestVersionPromise = null;
4727
4730
  function getCacheFilePath() {
4728
4731
  return join3(homedir(), ".contextstream", "version-cache.json");
4729
4732
  }
@@ -4752,33 +4755,40 @@ function writeCache(latestVersion) {
4752
4755
  } catch {
4753
4756
  }
4754
4757
  }
4755
- async function checkForUpdates() {
4756
- const currentVersion = VERSION;
4757
- if (currentVersion === "unknown") return;
4758
+ async function fetchLatestVersion() {
4758
4759
  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
4760
  const controller = new AbortController();
4767
4761
  const timeout = setTimeout(() => controller.abort(), 5e3);
4768
- const response = await fetch("https://registry.npmjs.org/@contextstream/mcp-server/latest", {
4762
+ const response = await fetch(NPM_LATEST_URL, {
4769
4763
  signal: controller.signal,
4770
4764
  headers: { "Accept": "application/json" }
4771
4765
  });
4772
4766
  clearTimeout(timeout);
4773
- if (!response.ok) return;
4767
+ if (!response.ok) return null;
4774
4768
  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
- }
4769
+ return typeof data.version === "string" ? data.version : null;
4781
4770
  } catch {
4771
+ return null;
4772
+ }
4773
+ }
4774
+ async function resolveLatestVersion() {
4775
+ const cached = readCache();
4776
+ if (cached) return cached.latestVersion;
4777
+ if (!latestVersionPromise) {
4778
+ latestVersionPromise = fetchLatestVersion().finally(() => {
4779
+ latestVersionPromise = null;
4780
+ });
4781
+ }
4782
+ const latestVersion = await latestVersionPromise;
4783
+ if (latestVersion) {
4784
+ writeCache(latestVersion);
4785
+ }
4786
+ return latestVersion;
4787
+ }
4788
+ async function checkForUpdates() {
4789
+ const notice = await getUpdateNotice();
4790
+ if (notice?.behind) {
4791
+ showUpdateWarning(notice.current, notice.latest);
4782
4792
  }
4783
4793
  }
4784
4794
  function showUpdateWarning(currentVersion, latestVersion) {
@@ -4786,12 +4796,30 @@ function showUpdateWarning(currentVersion, latestVersion) {
4786
4796
  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
4797
  console.error(`\u26A0\uFE0F Update available: v${currentVersion} \u2192 v${latestVersion}`);
4788
4798
  console.error("");
4789
- console.error(" Run: npm update -g @contextstream/mcp-server");
4799
+ console.error(` Run: ${UPGRADE_COMMAND}`);
4790
4800
  console.error("");
4791
4801
  console.error(" Then restart your AI tool to use the new version.");
4792
4802
  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
4803
  console.error("");
4794
4804
  }
4805
+ async function getUpdateNotice() {
4806
+ const currentVersion = VERSION;
4807
+ if (currentVersion === "unknown") return null;
4808
+ try {
4809
+ const latestVersion = await resolveLatestVersion();
4810
+ if (!latestVersion) return null;
4811
+ if (compareVersions(currentVersion, latestVersion) < 0) {
4812
+ return {
4813
+ current: currentVersion,
4814
+ latest: latestVersion,
4815
+ behind: true,
4816
+ upgrade_command: UPGRADE_COMMAND
4817
+ };
4818
+ }
4819
+ } catch {
4820
+ }
4821
+ return null;
4822
+ }
4795
4823
 
4796
4824
  // src/client.ts
4797
4825
  var uuidSchema = external_exports.string().uuid();
@@ -5174,6 +5202,19 @@ var ContextStreamClient = class {
5174
5202
  };
5175
5203
  return request(this.config, "/graph/impact-analysis", { body: apiBody });
5176
5204
  }
5205
+ graphIngest(body) {
5206
+ const withDefaults = this.withDefaults(body);
5207
+ const projectId = withDefaults.project_id;
5208
+ if (!projectId) {
5209
+ throw new Error("project_id is required to ingest the graph.");
5210
+ }
5211
+ uuidSchema.parse(projectId);
5212
+ const apiBody = {};
5213
+ if (body.wait !== void 0) {
5214
+ apiBody.wait = body.wait;
5215
+ }
5216
+ return request(this.config, `/graph/ingest/${projectId}`, { body: apiBody });
5217
+ }
5177
5218
  // AI
5178
5219
  buildAiContextRequest(input) {
5179
5220
  const payload = {
@@ -6598,6 +6639,11 @@ W:${wsHint}
6598
6639
  [/CTX]`;
6599
6640
  candidateContext = context;
6600
6641
  }
6642
+ let versionNotice = null;
6643
+ try {
6644
+ versionNotice = await getUpdateNotice();
6645
+ } catch {
6646
+ }
6601
6647
  this.trackTokenSavings({
6602
6648
  tool: "context_smart",
6603
6649
  workspace_id: withDefaults.workspace_id,
@@ -6618,6 +6664,7 @@ W:${wsHint}
6618
6664
  token_estimate: Math.ceil(context.length / 4),
6619
6665
  format,
6620
6666
  sources_used: items.filter((i) => context.includes(i.value.slice(0, 20))).length,
6667
+ ...versionNotice ? { version_notice: versionNotice } : {},
6621
6668
  ...errors.length > 0 && { errors }
6622
6669
  // Include errors for debugging
6623
6670
  };
@@ -7244,6 +7291,7 @@ var CONTEXTSTREAM_TOOL_NAMES = [
7244
7291
  "graph_impact",
7245
7292
  "graph_circular_dependencies",
7246
7293
  "graph_unused_code",
7294
+ "graph_ingest",
7247
7295
  "graph_contradictions",
7248
7296
  // AI (PRO)
7249
7297
  "ai_context",
@@ -7474,7 +7522,7 @@ To expose all tools below, set \`CONTEXTSTREAM_TOOLSET=full\` in your MCP config
7474
7522
  \`memory_create_event\`, \`memory_bulk_ingest\`, \`memory_list_events\`, \`memory_create_node\`, \`memory_list_nodes\`, \`memory_search\`, \`memory_decisions\`, \`memory_get_event\`, \`memory_update_event\`, \`memory_delete_event\`, \`memory_distill_event\`, \`memory_get_node\`, \`memory_update_node\`, \`memory_delete_node\`, \`memory_supersede_node\`, \`memory_timeline\`, \`memory_summary\`
7475
7523
 
7476
7524
  **Graph** (code analysis):
7477
- \`graph_related\`, \`graph_path\`, \`graph_decisions\`, \`graph_dependencies\`, \`graph_call_path\`, \`graph_impact\`, \`graph_circular_dependencies\`, \`graph_unused_code\`, \`graph_contradictions\`
7525
+ \`graph_related\`, \`graph_path\`, \`graph_decisions\`, \`graph_dependencies\`, \`graph_call_path\`, \`graph_impact\`, \`graph_circular_dependencies\`, \`graph_unused_code\`, \`graph_ingest\`, \`graph_contradictions\`
7478
7526
 
7479
7527
  **AI** (PRO):
7480
7528
  \`ai_context\`, \`ai_enhanced_context\`, \`ai_context_budget\`, \`ai_embeddings\`, \`ai_plan\`, \`ai_tasks\`
@@ -7670,6 +7718,7 @@ var TOOL_CATALOG = [
7670
7718
  { name: "path", hint: "trace" },
7671
7719
  { name: "decisions", hint: "choices" },
7672
7720
  { name: "dependencies", hint: "deps" },
7721
+ { name: "ingest", hint: "build" },
7673
7722
  { name: "impact", hint: "changes" },
7674
7723
  { name: "contradictions", hint: "conflicts" }
7675
7724
  ]
@@ -7856,6 +7905,7 @@ var STANDARD_TOOLSET = /* @__PURE__ */ new Set([
7856
7905
  "graph_impact",
7857
7906
  "graph_circular_dependencies",
7858
7907
  "graph_unused_code",
7908
+ "graph_ingest",
7859
7909
  // Search (3)
7860
7910
  "search_semantic",
7861
7911
  "search_hybrid",
@@ -8631,6 +8681,25 @@ Access: Free`,
8631
8681
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8632
8682
  }
8633
8683
  );
8684
+ registerTool(
8685
+ "graph_ingest",
8686
+ {
8687
+ title: "Ingest code graph",
8688
+ description: "Build and persist the dependency graph for a project",
8689
+ inputSchema: external_exports.object({
8690
+ project_id: external_exports.string().uuid().optional(),
8691
+ wait: external_exports.boolean().optional().describe("If true, wait for ingestion to finish before returning.")
8692
+ })
8693
+ },
8694
+ async (input) => {
8695
+ const projectId = resolveProjectId(input.project_id);
8696
+ if (!projectId) {
8697
+ return errorResult("Error: project_id is required. Please call session_init first or provide project_id explicitly.");
8698
+ }
8699
+ const result = await client.graphIngest({ project_id: projectId, wait: input.wait });
8700
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
8701
+ }
8702
+ );
8634
8703
  registerTool(
8635
8704
  "ai_context",
8636
8705
  {
@@ -10145,8 +10214,10 @@ This saves ~80% tokens compared to including full chat history.`,
10145
10214
  const footer = `
10146
10215
  ---
10147
10216
  \u{1F3AF} ${result.sources_used} sources | ~${result.token_estimate} tokens | format: ${result.format}`;
10217
+ const versionNoticeLine = result.version_notice?.behind ? `
10218
+ [VERSION_NOTICE] current=${result.version_notice.current} latest=${result.version_notice.latest} upgrade="${result.version_notice.upgrade_command}"` : "";
10148
10219
  return {
10149
- content: [{ type: "text", text: result.context + footer }],
10220
+ content: [{ type: "text", text: result.context + footer + versionNoticeLine }],
10150
10221
  structuredContent: toStructured(result)
10151
10222
  };
10152
10223
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contextstream/mcp-server",
3
- "version": "0.3.52",
3
+ "version": "0.3.54",
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",