@contextstream/mcp-server 0.4.21 → 0.4.22

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 (3) hide show
  1. package/README.md +6 -4
  2. package/dist/index.js +41 -25
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -289,7 +289,7 @@ In consolidated mode, you call **domain tools** with `action` / `mode`:
289
289
  ### Examples
290
290
 
291
291
  ```
292
- search(mode="semantic", query="auth middleware")
292
+ search(mode="semantic", query="auth middleware", limit=3)
293
293
  memory(action="create_node", node_type="decision", title="Auth strategy", content="...")
294
294
  graph(action="impact", target="UserService")
295
295
  ```
@@ -327,9 +327,11 @@ Set **one** of:
327
327
  | `CONTEXTSTREAM_PROGRESSIVE_MODE` | Enables Router mode (~2 meta-tools) |
328
328
  | `CONTEXTSTREAM_CONTEXT_PACK` | Enable Context Pack for `context_smart` (code + graph + distill). Defaults to `true` |
329
329
  | `CONTEXTSTREAM_TOOLSET` | Legacy granular tool bundle: `light` / `standard` / `complete` (only when consolidated is off) |
330
- | `CONTEXTSTREAM_TOOL_ALLOWLIST` | Comma-separated tool names to expose (legacy granular mode) |
331
- | `CONTEXTSTREAM_SCHEMA_MODE` | Reduce schema verbosity; e.g., `compact` |
332
- | `CONTEXTSTREAM_OUTPUT_FORMAT` | Output formatting; e.g., `compact` / `pretty` |
330
+ | `CONTEXTSTREAM_TOOL_ALLOWLIST` | Comma-separated tool names to expose (legacy granular mode) |
331
+ | `CONTEXTSTREAM_SCHEMA_MODE` | Reduce schema verbosity; e.g., `compact` |
332
+ | `CONTEXTSTREAM_OUTPUT_FORMAT` | Output formatting; e.g., `compact` / `pretty` |
333
+ | `CONTEXTSTREAM_SEARCH_LIMIT` | Default MCP search limit (default: 3) |
334
+ | `CONTEXTSTREAM_SEARCH_MAX_CHARS` | Max chars per search result content (default: 400) |
333
335
 
334
336
  ### Optional Defaults
335
337
 
package/dist/index.js CHANGED
@@ -7548,7 +7548,7 @@ v0.4.x consolidates ~58 individual tools into ~11 domain tools with action/mode
7548
7548
 
7549
7549
  | Domain | Actions/Modes | Example |
7550
7550
  |--------|---------------|---------|
7551
- | **\`search\`** | mode: semantic, hybrid, keyword, pattern | \`search(mode="hybrid", query="auth implementation")\` |
7551
+ | **\`search\`** | mode: semantic, hybrid, keyword, pattern | \`search(mode="hybrid", query="auth implementation", limit=3)\` |
7552
7552
  | **\`session\`** | action: capture, capture_lesson, get_lessons, recall, remember, user_context, summary, compress, delta, smart_search, decision_trace | \`session(action="capture", event_type="decision", title="Use JWT", content="...")\` |
7553
7553
  | **\`memory\`** | action: create_event, get_event, update_event, delete_event, list_events, distill_event, create_node, get_node, update_node, delete_node, list_nodes, supersede_node, search, decisions, timeline, summary | \`memory(action="list_events", limit=10)\` |
7554
7554
  | **\`graph\`** | action: dependencies, impact, call_path, related, path, decisions, ingest, circular_dependencies, unused_code, contradictions | \`graph(action="impact", symbol_name="AuthService")\` |
@@ -7621,11 +7621,13 @@ Only after this preflight, proceed with search/analysis below.
7621
7621
 
7622
7622
  **Search order:**
7623
7623
  1. \`session(action="smart_search", query="...")\` - context-enriched
7624
- 2. \`search(mode="hybrid", query="...")\` or \`search(mode="keyword", query="<filename>")\`
7624
+ 2. \`search(mode="hybrid", query="...", limit=3)\` or \`search(mode="keyword", query="<filename>", limit=3)\`
7625
7625
  3. \`project(action="files")\` - file tree/list (only when needed)
7626
7626
  4. \`graph(action="dependencies", ...)\` - code structure
7627
7627
  5. Local repo scans (rg/ls/find) - only if ContextStream returns no results, errors, or the user explicitly asks
7628
7628
 
7629
+ **Search defaults:** \`search\` returns the top 3 results with compact snippets. Use \`limit\` + \`offset\` for pagination, and \`content_max_chars\` to expand snippets when needed.
7630
+
7629
7631
  If ContextStream returns results, stop and use them. Do NOT use local Search/Explore/Read unless you need exact code edits.
7630
7632
 
7631
7633
  **Code Analysis:**
@@ -7726,7 +7728,7 @@ Rules Version: ${RULES_VERSION}
7726
7728
 
7727
7729
  | Tool | Common Usage |
7728
7730
  |------|--------------|
7729
- | \`search\` | \`search(mode="semantic", query="...")\` \u2014 modes: semantic, hybrid, keyword, pattern |
7731
+ | \`search\` | \`search(mode="semantic", query="...", limit=3)\` \u2014 modes: semantic, hybrid, keyword, pattern |
7730
7732
  | \`session\` | \`session(action="capture", ...)\` \u2014 actions: capture, capture_lesson, get_lessons, recall, remember, user_context, summary, compress, delta, smart_search |
7731
7733
  | \`memory\` | \`memory(action="list_events", ...)\` \u2014 CRUD for events/nodes, search, decisions, timeline, summary |
7732
7734
  | \`graph\` | \`graph(action="dependencies", ...)\` \u2014 dependencies, impact, call_path, related, ingest |
@@ -9154,8 +9156,14 @@ function getOperationSchema(name) {
9154
9156
  };
9155
9157
  }
9156
9158
  }
9159
+ function parsePositiveInt(raw, fallback) {
9160
+ const parsed = Number.parseInt(raw ?? "", 10);
9161
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
9162
+ }
9157
9163
  var OUTPUT_FORMAT = process.env.CONTEXTSTREAM_OUTPUT_FORMAT || "compact";
9158
9164
  var COMPACT_OUTPUT = OUTPUT_FORMAT === "compact";
9165
+ var DEFAULT_SEARCH_LIMIT = parsePositiveInt(process.env.CONTEXTSTREAM_SEARCH_LIMIT, 3);
9166
+ var DEFAULT_SEARCH_CONTENT_MAX_CHARS = parsePositiveInt(process.env.CONTEXTSTREAM_SEARCH_MAX_CHARS, 400);
9159
9167
  var CONSOLIDATED_MODE = process.env.CONTEXTSTREAM_CONSOLIDATED !== "false";
9160
9168
  var CONSOLIDATED_TOOLS = /* @__PURE__ */ new Set([
9161
9169
  "session_init",
@@ -10303,13 +10311,28 @@ Access: Free`,
10303
10311
  query: external_exports.string(),
10304
10312
  workspace_id: external_exports.string().uuid().optional(),
10305
10313
  project_id: external_exports.string().uuid().optional(),
10306
- limit: external_exports.number().optional()
10314
+ limit: external_exports.number().optional().describe("Max results to return (default: 3)"),
10315
+ offset: external_exports.number().optional().describe("Offset for pagination"),
10316
+ content_max_chars: external_exports.number().optional().describe("Max chars per result content (default: 400)")
10307
10317
  });
10318
+ function normalizeSearchParams(input) {
10319
+ const limit = typeof input.limit === "number" && input.limit > 0 ? Math.min(Math.floor(input.limit), 100) : DEFAULT_SEARCH_LIMIT;
10320
+ const offset = typeof input.offset === "number" && input.offset > 0 ? Math.floor(input.offset) : void 0;
10321
+ const contentMax = typeof input.content_max_chars === "number" && input.content_max_chars > 0 ? Math.max(50, Math.min(Math.floor(input.content_max_chars), 1e4)) : DEFAULT_SEARCH_CONTENT_MAX_CHARS;
10322
+ return {
10323
+ query: input.query,
10324
+ workspace_id: resolveWorkspaceId(input.workspace_id),
10325
+ project_id: resolveProjectId(input.project_id),
10326
+ limit,
10327
+ offset,
10328
+ content_max_chars: contentMax
10329
+ };
10330
+ }
10308
10331
  registerTool(
10309
10332
  "search_semantic",
10310
10333
  { title: "Semantic search", description: "Semantic vector search", inputSchema: searchSchema },
10311
10334
  async (input) => {
10312
- const result = await client.searchSemantic(input);
10335
+ const result = await client.searchSemantic(normalizeSearchParams(input));
10313
10336
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
10314
10337
  }
10315
10338
  );
@@ -10317,7 +10340,7 @@ Access: Free`,
10317
10340
  "search_hybrid",
10318
10341
  { title: "Hybrid search", description: "Hybrid search (semantic + keyword)", inputSchema: searchSchema },
10319
10342
  async (input) => {
10320
- const result = await client.searchHybrid(input);
10343
+ const result = await client.searchHybrid(normalizeSearchParams(input));
10321
10344
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
10322
10345
  }
10323
10346
  );
@@ -10325,7 +10348,7 @@ Access: Free`,
10325
10348
  "search_keyword",
10326
10349
  { title: "Keyword search", description: "Keyword search", inputSchema: searchSchema },
10327
10350
  async (input) => {
10328
- const result = await client.searchKeyword(input);
10351
+ const result = await client.searchKeyword(normalizeSearchParams(input));
10329
10352
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
10330
10353
  }
10331
10354
  );
@@ -10333,7 +10356,7 @@ Access: Free`,
10333
10356
  "search_pattern",
10334
10357
  { title: "Pattern search", description: "Pattern/regex search", inputSchema: searchSchema },
10335
10358
  async (input) => {
10336
- const result = await client.searchPattern(input);
10359
+ const result = await client.searchPattern(normalizeSearchParams(input));
10337
10360
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
10338
10361
  }
10339
10362
  );
@@ -13118,16 +13141,13 @@ Use this to remove a reminder that is no longer relevant.`,
13118
13141
  query: external_exports.string().describe("Search query"),
13119
13142
  workspace_id: external_exports.string().uuid().optional(),
13120
13143
  project_id: external_exports.string().uuid().optional(),
13121
- limit: external_exports.number().optional()
13144
+ limit: external_exports.number().optional().describe("Max results to return (default: 3)"),
13145
+ offset: external_exports.number().optional().describe("Offset for pagination"),
13146
+ content_max_chars: external_exports.number().optional().describe("Max chars per result content (default: 400)")
13122
13147
  })
13123
13148
  },
13124
13149
  async (input) => {
13125
- const params = {
13126
- query: input.query,
13127
- workspace_id: resolveWorkspaceId(input.workspace_id),
13128
- project_id: resolveProjectId(input.project_id),
13129
- limit: input.limit
13130
- };
13150
+ const params = normalizeSearchParams(input);
13131
13151
  let result;
13132
13152
  switch (input.mode) {
13133
13153
  case "semantic":
@@ -16739,10 +16759,7 @@ Code: ${device.user_code}`);
16739
16759
  }
16740
16760
  apiKey = createdKey.secret_key.trim();
16741
16761
  apiKeySource = "browser";
16742
- const maskedNewKey = maskApiKey(apiKey);
16743
- console.log(`
16744
- Created API key: ${maskedNewKey}
16745
- `);
16762
+ console.log("\nCreated API key\n");
16746
16763
  }
16747
16764
  }
16748
16765
  const client = new ContextStreamClient(buildClientConfig({ apiUrl, apiKey }));
@@ -16754,14 +16771,11 @@ Created API key: ${maskedNewKey}
16754
16771
  throw new Error(`Authentication failed. Check your API key. (${message})`);
16755
16772
  }
16756
16773
  const email = typeof me?.data?.email === "string" ? me.data.email : typeof me?.email === "string" ? me.email : void 0;
16757
- const maskedKey = maskApiKey(apiKey);
16758
- console.log(`Authenticated as: ${email || "unknown user"} (${maskedKey})
16759
- `);
16774
+ console.log("Authenticated\n");
16760
16775
  if (!dryRun && (apiKeySource === "browser" || apiKeySource === "paste")) {
16761
16776
  try {
16762
- const saved = await writeSavedCredentials({ apiUrl, apiKey, email });
16763
- console.log(`Saved API key for future runs: ${saved.path} (${maskedKey})
16764
- `);
16777
+ await writeSavedCredentials({ apiUrl, apiKey, email });
16778
+ console.log("Saved API key for future runs\n");
16765
16779
  } catch (err) {
16766
16780
  const msg = err instanceof Error ? err.message : String(err);
16767
16781
  console.log(`Warning: failed to save API key for future runs (${credentialsFilePath()}): ${msg}
@@ -17248,6 +17262,8 @@ Environment variables:
17248
17262
  CONTEXTSTREAM_PROGRESSIVE_MODE Progressive disclosure: true|false (default: false, starts with ~13 core tools)
17249
17263
  CONTEXTSTREAM_ROUTER_MODE Router pattern: true|false (default: false, exposes only 2 meta-tools)
17250
17264
  CONTEXTSTREAM_OUTPUT_FORMAT Output verbosity: compact|pretty (default: compact, ~30% fewer tokens)
17265
+ CONTEXTSTREAM_SEARCH_LIMIT Default MCP search limit (default: 3)
17266
+ CONTEXTSTREAM_SEARCH_MAX_CHARS Max chars per search result content (default: 400)
17251
17267
  CONTEXTSTREAM_CONSOLIDATED Consolidated domain tools: true|false (default: true in v0.4.x, ~75% token reduction)
17252
17268
  CONTEXTSTREAM_CONTEXT_PACK Enable Context Pack in context_smart: true|false (default: true)
17253
17269
  CONTEXTSTREAM_PRO_TOOLS Optional comma-separated PRO tool names (default: AI tools)
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.21",
4
+ "version": "0.4.22",
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",
@@ -22,7 +22,7 @@
22
22
  "typecheck": "tsc --noEmit"
23
23
  },
24
24
  "dependencies": {
25
- "@modelcontextprotocol/sdk": "^1.22.0",
25
+ "@modelcontextprotocol/sdk": "^1.25.1",
26
26
  "zod": "^3.23.8"
27
27
  },
28
28
  "devDependencies": {