@contextstream/mcp-server 0.3.42 → 0.3.44

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 +259 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7443,11 +7443,155 @@ ${options.workspaceId ? `# Workspace ID: ${options.workspaceId}` : ""}
7443
7443
  };
7444
7444
  }
7445
7445
 
7446
+ // src/tool-catalog.ts
7447
+ var TOOL_CATALOG = [
7448
+ {
7449
+ name: "Session",
7450
+ tools: [
7451
+ { name: "init", hint: "start-conv" },
7452
+ { name: "smart", hint: "each-msg" },
7453
+ { name: "capture", hint: "save" },
7454
+ { name: "recall", hint: "find" },
7455
+ { name: "remember", hint: "quick" },
7456
+ { name: "compress", hint: "end" },
7457
+ { name: "summary", hint: "brief" },
7458
+ { name: "delta", hint: "changes" },
7459
+ { name: "get_lessons", hint: "learn" },
7460
+ { name: "capture_lesson", hint: "mistake" },
7461
+ { name: "get_user_context", hint: "prefs" },
7462
+ { name: "smart_search", hint: "deep-find" }
7463
+ ]
7464
+ },
7465
+ {
7466
+ name: "Search",
7467
+ tools: [
7468
+ { name: "semantic", hint: "meaning" },
7469
+ { name: "hybrid", hint: "combo" },
7470
+ { name: "keyword", hint: "exact" },
7471
+ { name: "pattern", hint: "code" }
7472
+ ]
7473
+ },
7474
+ {
7475
+ name: "Memory",
7476
+ tools: [
7477
+ { name: "create_event", hint: "new" },
7478
+ { name: "list_events", hint: "list" },
7479
+ { name: "get_event", hint: "get" },
7480
+ { name: "update_event", hint: "edit" },
7481
+ { name: "delete_event", hint: "rm" },
7482
+ { name: "search", hint: "find" },
7483
+ { name: "decisions", hint: "choices" },
7484
+ { name: "timeline", hint: "history" },
7485
+ { name: "distill_event", hint: "extract" }
7486
+ ]
7487
+ },
7488
+ {
7489
+ name: "Knowledge",
7490
+ tools: [
7491
+ { name: "create_node", hint: "new" },
7492
+ { name: "list_nodes", hint: "list" },
7493
+ { name: "get_node", hint: "get" },
7494
+ { name: "update_node", hint: "edit" },
7495
+ { name: "delete_node", hint: "rm" },
7496
+ { name: "supersede_node", hint: "replace" }
7497
+ ]
7498
+ },
7499
+ {
7500
+ name: "Graph",
7501
+ tools: [
7502
+ { name: "related", hint: "links" },
7503
+ { name: "path", hint: "trace" },
7504
+ { name: "decisions", hint: "choices" },
7505
+ { name: "dependencies", hint: "deps" },
7506
+ { name: "impact", hint: "changes" },
7507
+ { name: "contradictions", hint: "conflicts" }
7508
+ ]
7509
+ },
7510
+ {
7511
+ name: "Workspace",
7512
+ tools: [
7513
+ { name: "list", hint: "" },
7514
+ { name: "get", hint: "" },
7515
+ { name: "create", hint: "" },
7516
+ { name: "associate", hint: "link-folder" },
7517
+ { name: "bootstrap", hint: "new-ws" }
7518
+ ]
7519
+ },
7520
+ {
7521
+ name: "Project",
7522
+ tools: [
7523
+ { name: "list", hint: "" },
7524
+ { name: "get", hint: "" },
7525
+ { name: "create", hint: "" },
7526
+ { name: "index", hint: "scan-code" },
7527
+ { name: "files", hint: "list-files" },
7528
+ { name: "overview", hint: "summary" }
7529
+ ]
7530
+ },
7531
+ {
7532
+ name: "AI",
7533
+ tools: [
7534
+ { name: "context", hint: "smart-ctx" },
7535
+ { name: "plan", hint: "generate" },
7536
+ { name: "tasks", hint: "breakdown" },
7537
+ { name: "embeddings", hint: "vectors" }
7538
+ ]
7539
+ }
7540
+ ];
7541
+ function generateToolCatalog(format = "grouped", category) {
7542
+ let categories = TOOL_CATALOG;
7543
+ if (category) {
7544
+ const filtered = TOOL_CATALOG.filter(
7545
+ (c) => c.name.toLowerCase() === category.toLowerCase()
7546
+ );
7547
+ if (filtered.length > 0) {
7548
+ categories = filtered;
7549
+ }
7550
+ }
7551
+ switch (format) {
7552
+ case "minimal":
7553
+ return generateMinimal(categories);
7554
+ case "full":
7555
+ return generateFull(categories);
7556
+ case "grouped":
7557
+ default:
7558
+ return generateGrouped(categories);
7559
+ }
7560
+ }
7561
+ function generateGrouped(categories) {
7562
+ return categories.map((cat) => {
7563
+ const tools = cat.tools.map((t) => t.hint ? `${t.name}(${t.hint})` : t.name).join(" ");
7564
+ return `${cat.name}: ${tools}`;
7565
+ }).join("\n");
7566
+ }
7567
+ function generateMinimal(categories) {
7568
+ return categories.map((cat) => {
7569
+ const tools = cat.tools.map((t) => t.name).join("|");
7570
+ return `${cat.name}:${tools}`;
7571
+ }).join("\n");
7572
+ }
7573
+ function generateFull(categories) {
7574
+ const lines = [];
7575
+ for (const cat of categories) {
7576
+ lines.push(`## ${cat.name}`);
7577
+ for (const tool of cat.tools) {
7578
+ const prefix = cat.name.toLowerCase().replace(/\s+/g, "_");
7579
+ const fullName = `${prefix}_${tool.name}`;
7580
+ lines.push(`- ${fullName}: ${tool.hint || "standard CRUD"}`);
7581
+ }
7582
+ }
7583
+ return lines.join("\n");
7584
+ }
7585
+ function getCoreToolsHint() {
7586
+ return `Session: init(start) smart(each-msg) capture(save) recall(find) remember(quick)`;
7587
+ }
7588
+
7446
7589
  // src/tools.ts
7447
7590
  var LESSON_DEDUP_WINDOW_MS = 2 * 60 * 1e3;
7448
7591
  var recentLessonCaptures = /* @__PURE__ */ new Map();
7449
7592
  var CORE_TOOLSET = /* @__PURE__ */ new Set([
7450
7593
  "session_init",
7594
+ "session_tools",
7451
7595
  "context_smart",
7452
7596
  "session_summary",
7453
7597
  "session_capture",
@@ -7462,6 +7606,8 @@ var CORE_TOOLSET = /* @__PURE__ */ new Set([
7462
7606
  "generate_editor_rules",
7463
7607
  "workspace_associate",
7464
7608
  "workspace_bootstrap",
7609
+ "projects_create",
7610
+ "projects_list",
7465
7611
  "auth_me",
7466
7612
  "mcp_server_version"
7467
7613
  ]);
@@ -7812,16 +7958,82 @@ Upgrade: ${upgradeUrl}` : "";
7812
7958
  "projects_create",
7813
7959
  {
7814
7960
  title: "Create project",
7815
- description: "Create a project within a workspace (returns ApiResponse with created project in data).",
7961
+ description: `Create a new project within a workspace.
7962
+ Use this when you need to create a project for a specific folder/codebase.
7963
+ If workspace_id is not provided, uses the current session's workspace.
7964
+ Optionally associates a local folder and generates AI editor rules.
7965
+
7966
+ Access: Free`,
7816
7967
  inputSchema: external_exports.object({
7817
- name: external_exports.string(),
7818
- description: external_exports.string().optional(),
7819
- workspace_id: external_exports.string().uuid().optional()
7968
+ name: external_exports.string().describe("Project name"),
7969
+ description: external_exports.string().optional().describe("Project description"),
7970
+ workspace_id: external_exports.string().uuid().optional().describe("Workspace ID (uses current session workspace if not provided)"),
7971
+ folder_path: external_exports.string().optional().describe("Optional: Local folder path to associate with this project"),
7972
+ generate_editor_rules: external_exports.boolean().optional().describe("Generate AI editor rules in folder_path (requires folder_path)")
7820
7973
  })
7821
7974
  },
7822
7975
  async (input) => {
7823
- const result = await client.createProject(input);
7824
- return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
7976
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
7977
+ if (!workspaceId) {
7978
+ return errorResult("Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly.");
7979
+ }
7980
+ const result = await client.createProject({
7981
+ name: input.name,
7982
+ description: input.description,
7983
+ workspace_id: workspaceId
7984
+ });
7985
+ const projectData = result;
7986
+ let rulesGenerated = [];
7987
+ if (input.folder_path && projectData.id) {
7988
+ try {
7989
+ const configDir = path4.join(input.folder_path, ".contextstream");
7990
+ const configPath = path4.join(configDir, "config.json");
7991
+ if (!fs3.existsSync(configDir)) {
7992
+ fs3.mkdirSync(configDir, { recursive: true });
7993
+ }
7994
+ const config = {
7995
+ workspace_id: workspaceId,
7996
+ project_id: projectData.id,
7997
+ project_name: input.name
7998
+ };
7999
+ fs3.writeFileSync(configPath, JSON.stringify(config, null, 2));
8000
+ if (input.generate_editor_rules) {
8001
+ for (const editor of getAvailableEditors()) {
8002
+ const rule = generateRuleContent(editor, {
8003
+ workspaceId,
8004
+ projectName: input.name
8005
+ });
8006
+ if (rule) {
8007
+ const filePath = path4.join(input.folder_path, rule.filename);
8008
+ try {
8009
+ let existingContent = "";
8010
+ try {
8011
+ existingContent = fs3.readFileSync(filePath, "utf-8");
8012
+ } catch {
8013
+ }
8014
+ if (!existingContent) {
8015
+ fs3.writeFileSync(filePath, rule.content);
8016
+ rulesGenerated.push(rule.filename);
8017
+ } else if (!existingContent.includes("ContextStream")) {
8018
+ fs3.writeFileSync(filePath, existingContent + "\n\n" + rule.content);
8019
+ rulesGenerated.push(rule.filename + " (appended)");
8020
+ }
8021
+ } catch {
8022
+ }
8023
+ }
8024
+ }
8025
+ }
8026
+ } catch (err) {
8027
+ console.error("[ContextStream] Failed to write project config:", err);
8028
+ }
8029
+ }
8030
+ const response = {
8031
+ ...result,
8032
+ folder_path: input.folder_path,
8033
+ config_written: input.folder_path ? true : void 0,
8034
+ editor_rules_generated: rulesGenerated.length > 0 ? rulesGenerated : void 0
8035
+ };
8036
+ return { content: [{ type: "text", text: formatContent(response) }], structuredContent: toStructured(response) };
7825
8037
  }
7826
8038
  );
7827
8039
  registerTool(
@@ -8688,6 +8900,7 @@ This does semantic search on the first message. You only need context_smart on s
8688
8900
  ideRoots = [input.folder_path];
8689
8901
  }
8690
8902
  const result = await client.initSession(input, ideRoots);
8903
+ result.tools_hint = getCoreToolsHint();
8691
8904
  if (sessionManager) {
8692
8905
  sessionManager.markInitialized(result);
8693
8906
  }
@@ -8743,6 +8956,38 @@ This does semantic search on the first message. You only need context_smart on s
8743
8956
  return { content: [{ type: "text", text }], structuredContent: toStructured(result) };
8744
8957
  }
8745
8958
  );
8959
+ registerTool(
8960
+ "session_tools",
8961
+ {
8962
+ title: "Get available ContextStream tools",
8963
+ description: `Get an ultra-compact list of all available ContextStream MCP tools.
8964
+ Use this when you need to know what tools are available without reading full descriptions.
8965
+
8966
+ Returns a token-efficient tool catalog (~120 tokens) organized by category.
8967
+
8968
+ Format options:
8969
+ - 'grouped' (default): Category: tool(hint) tool(hint) - best for quick reference
8970
+ - 'minimal': Category:tool|tool|tool - most compact
8971
+ - 'full': Detailed list with descriptions
8972
+
8973
+ Example output (grouped):
8974
+ Session: init(start-conv) smart(each-msg) capture(save) recall(find) remember(quick)
8975
+ Search: semantic(meaning) hybrid(combo) keyword(exact)
8976
+ Memory: events(crud) nodes(knowledge) search(find) decisions(choices)`,
8977
+ inputSchema: external_exports.object({
8978
+ format: external_exports.enum(["grouped", "minimal", "full"]).optional().default("grouped").describe("Output format: grouped (default, ~120 tokens), minimal (~80 tokens), or full (~200 tokens)"),
8979
+ category: external_exports.string().optional().describe("Filter to specific category: Session, Search, Memory, Knowledge, Graph, Workspace, Project, AI")
8980
+ })
8981
+ },
8982
+ async (input) => {
8983
+ const format = input.format || "grouped";
8984
+ const catalog = generateToolCatalog(format, input.category);
8985
+ return {
8986
+ content: [{ type: "text", text: catalog }],
8987
+ structuredContent: { format, catalog }
8988
+ };
8989
+ }
8990
+ );
8746
8991
  registerTool(
8747
8992
  "session_get_user_context",
8748
8993
  {
@@ -10520,9 +10765,9 @@ var SessionManager = class {
10520
10765
  };
10521
10766
 
10522
10767
  // src/index.ts
10523
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
10768
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
10524
10769
  import { homedir as homedir3 } from "os";
10525
- import { join as join6 } from "path";
10770
+ import { join as join7 } from "path";
10526
10771
 
10527
10772
  // src/setup.ts
10528
10773
  import * as fs5 from "node:fs/promises";
@@ -11366,14 +11611,14 @@ Applying to ${projects.length} project(s)...`);
11366
11611
 
11367
11612
  // src/index.ts
11368
11613
  function showFirstRunMessage() {
11369
- const configDir = join6(homedir3(), ".contextstream");
11370
- const starShownFile = join6(configDir, ".star-shown");
11371
- if (existsSync2(starShownFile)) {
11614
+ const configDir = join7(homedir3(), ".contextstream");
11615
+ const starShownFile = join7(configDir, ".star-shown");
11616
+ if (existsSync3(starShownFile)) {
11372
11617
  return;
11373
11618
  }
11374
- if (!existsSync2(configDir)) {
11619
+ if (!existsSync3(configDir)) {
11375
11620
  try {
11376
- mkdirSync2(configDir, { recursive: true });
11621
+ mkdirSync3(configDir, { recursive: true });
11377
11622
  } catch {
11378
11623
  return;
11379
11624
  }
@@ -11386,7 +11631,7 @@ function showFirstRunMessage() {
11386
11631
  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");
11387
11632
  console.error("");
11388
11633
  try {
11389
- writeFileSync2(starShownFile, (/* @__PURE__ */ new Date()).toISOString());
11634
+ writeFileSync3(starShownFile, (/* @__PURE__ */ new Date()).toISOString());
11390
11635
  } catch {
11391
11636
  }
11392
11637
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contextstream/mcp-server",
3
- "version": "0.3.42",
3
+ "version": "0.3.44",
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",