@contextstream/mcp-server 0.3.73 → 0.4.1

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 +1221 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7662,6 +7662,13 @@ ${options.workspaceId ? `# Workspace ID: ${options.workspaceId}` : ""}
7662
7662
  content: content.trim() + "\n"
7663
7663
  };
7664
7664
  }
7665
+ function generateAllRuleFiles(options) {
7666
+ return getAvailableEditors().map((editor) => {
7667
+ const result = generateRuleContent(editor, options);
7668
+ if (!result) return null;
7669
+ return { editor, ...result };
7670
+ }).filter((r) => r !== null);
7671
+ }
7665
7672
 
7666
7673
  // src/tool-catalog.ts
7667
7674
  var TOOL_CATALOG = [
@@ -8511,6 +8518,31 @@ function getOperationSchema(name) {
8511
8518
  }
8512
8519
  var OUTPUT_FORMAT = process.env.CONTEXTSTREAM_OUTPUT_FORMAT || "compact";
8513
8520
  var COMPACT_OUTPUT = OUTPUT_FORMAT === "compact";
8521
+ var CONSOLIDATED_MODE = process.env.CONTEXTSTREAM_CONSOLIDATED !== "false";
8522
+ var CONSOLIDATED_TOOLS = /* @__PURE__ */ new Set([
8523
+ "session_init",
8524
+ // Standalone - complex initialization
8525
+ "context_smart",
8526
+ // Standalone - called every message
8527
+ "search",
8528
+ // Consolidates search_semantic, search_hybrid, search_keyword, search_pattern
8529
+ "session",
8530
+ // Consolidates session_capture, session_recall, etc.
8531
+ "memory",
8532
+ // Consolidates memory_create_event, memory_get_event, etc.
8533
+ "graph",
8534
+ // Consolidates graph_dependencies, graph_impact, etc.
8535
+ "project",
8536
+ // Consolidates projects_list, projects_create, etc.
8537
+ "workspace",
8538
+ // Consolidates workspaces_list, workspace_associate, etc.
8539
+ "reminder",
8540
+ // Consolidates reminders_list, reminders_create, etc.
8541
+ "integration",
8542
+ // Consolidates slack_*, github_*, integrations_*
8543
+ "help"
8544
+ // Consolidates session_tools, auth_me, mcp_server_version, etc.
8545
+ ]);
8514
8546
  var TOOLSET_ALIASES = {
8515
8547
  // Light mode - minimal, fastest
8516
8548
  light: LIGHT_TOOLSET,
@@ -8722,6 +8754,12 @@ function registerTools(server, client, sessionManager) {
8722
8754
  } else {
8723
8755
  console.error("[ContextStream] Output format: pretty (set CONTEXTSTREAM_OUTPUT_FORMAT=compact for fewer tokens)");
8724
8756
  }
8757
+ if (CONSOLIDATED_MODE) {
8758
+ console.error(`[ContextStream] Consolidated mode: ENABLED (~${CONSOLIDATED_TOOLS.size} domain tools, ~75% token reduction)`);
8759
+ console.error("[ContextStream] Set CONTEXTSTREAM_CONSOLIDATED=false to use individual tools.");
8760
+ } else {
8761
+ console.error("[ContextStream] Consolidated mode: disabled (using individual tools)");
8762
+ }
8725
8763
  let serverRef = server;
8726
8764
  const defaultProTools = /* @__PURE__ */ new Set([
8727
8765
  // AI endpoints (typically paid/credit-metered)
@@ -9107,7 +9145,18 @@ Upgrade: ${upgradeUrl2}` : "";
9107
9145
  }
9108
9146
  const ROUTER_DIRECT_TOOLS = /* @__PURE__ */ new Set(["contextstream", "contextstream_help"]);
9109
9147
  function registerTool(name, config, handler) {
9110
- if (toolAllowlist && !toolAllowlist.has(name)) {
9148
+ if (CONSOLIDATED_MODE && !CONSOLIDATED_TOOLS.has(name)) {
9149
+ operationsRegistry.set(name, {
9150
+ name,
9151
+ title: config.title,
9152
+ description: config.description,
9153
+ inputSchema: config.inputSchema,
9154
+ handler,
9155
+ category: inferOperationCategory(name)
9156
+ });
9157
+ return;
9158
+ }
9159
+ if (!CONSOLIDATED_MODE && toolAllowlist && !toolAllowlist.has(name)) {
9111
9160
  if (ROUTER_MODE && !ROUTER_DIRECT_TOOLS.has(name)) {
9112
9161
  operationsRegistry.set(name, {
9113
9162
  name,
@@ -9120,7 +9169,7 @@ Upgrade: ${upgradeUrl2}` : "";
9120
9169
  }
9121
9170
  return;
9122
9171
  }
9123
- if (!shouldRegisterIntegrationTool(name)) {
9172
+ if (!CONSOLIDATED_MODE && !shouldRegisterIntegrationTool(name)) {
9124
9173
  return;
9125
9174
  }
9126
9175
  if (ROUTER_MODE && !ROUTER_DIRECT_TOOLS.has(name)) {
@@ -12296,6 +12345,1175 @@ Use this to remove a reminder that is no longer relevant.`,
12296
12345
  };
12297
12346
  }
12298
12347
  );
12348
+ if (CONSOLIDATED_MODE) {
12349
+ registerTool(
12350
+ "search",
12351
+ {
12352
+ title: "Search",
12353
+ description: `Search workspace memory and knowledge. Modes: semantic (meaning-based), hybrid (semantic + keyword), keyword (exact match), pattern (regex).`,
12354
+ inputSchema: external_exports.object({
12355
+ mode: external_exports.enum(["semantic", "hybrid", "keyword", "pattern"]).describe("Search mode"),
12356
+ query: external_exports.string().describe("Search query"),
12357
+ workspace_id: external_exports.string().uuid().optional(),
12358
+ project_id: external_exports.string().uuid().optional(),
12359
+ limit: external_exports.number().optional()
12360
+ })
12361
+ },
12362
+ async (input) => {
12363
+ const params = {
12364
+ query: input.query,
12365
+ workspace_id: resolveWorkspaceId(input.workspace_id),
12366
+ project_id: resolveProjectId(input.project_id),
12367
+ limit: input.limit
12368
+ };
12369
+ let result;
12370
+ switch (input.mode) {
12371
+ case "semantic":
12372
+ result = await client.searchSemantic(params);
12373
+ break;
12374
+ case "hybrid":
12375
+ result = await client.searchHybrid(params);
12376
+ break;
12377
+ case "keyword":
12378
+ result = await client.searchKeyword(params);
12379
+ break;
12380
+ case "pattern":
12381
+ result = await client.searchPattern(params);
12382
+ break;
12383
+ }
12384
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12385
+ }
12386
+ );
12387
+ registerTool(
12388
+ "session",
12389
+ {
12390
+ title: "Session",
12391
+ description: `Session management operations. Actions: capture (save decision/insight), capture_lesson (save lesson from mistake), get_lessons (retrieve lessons), recall (natural language recall), remember (quick save), user_context (get preferences), summary (workspace summary), compress (compress chat), delta (changes since timestamp), smart_search (context-enriched search), decision_trace (trace decision provenance).`,
12392
+ inputSchema: external_exports.object({
12393
+ action: external_exports.enum([
12394
+ "capture",
12395
+ "capture_lesson",
12396
+ "get_lessons",
12397
+ "recall",
12398
+ "remember",
12399
+ "user_context",
12400
+ "summary",
12401
+ "compress",
12402
+ "delta",
12403
+ "smart_search",
12404
+ "decision_trace"
12405
+ ]).describe("Action to perform"),
12406
+ workspace_id: external_exports.string().uuid().optional(),
12407
+ project_id: external_exports.string().uuid().optional(),
12408
+ // Content params
12409
+ query: external_exports.string().optional().describe("Query for recall/search/lessons/decision_trace"),
12410
+ content: external_exports.string().optional().describe("Content for capture/remember/compress"),
12411
+ title: external_exports.string().optional().describe("Title for capture/capture_lesson"),
12412
+ event_type: external_exports.enum(["decision", "preference", "insight", "task", "bug", "feature", "correction", "lesson", "warning", "frustration", "conversation"]).optional().describe("Event type for capture"),
12413
+ importance: external_exports.enum(["low", "medium", "high", "critical"]).optional(),
12414
+ tags: external_exports.array(external_exports.string()).optional(),
12415
+ // Lesson-specific
12416
+ category: external_exports.enum(["workflow", "code_quality", "verification", "communication", "project_specific"]).optional(),
12417
+ trigger: external_exports.string().optional().describe("What caused the problem"),
12418
+ impact: external_exports.string().optional().describe("What went wrong"),
12419
+ prevention: external_exports.string().optional().describe("How to prevent in future"),
12420
+ severity: external_exports.enum(["low", "medium", "high", "critical"]).optional(),
12421
+ keywords: external_exports.array(external_exports.string()).optional(),
12422
+ // Other params
12423
+ since: external_exports.string().optional().describe("ISO timestamp for delta"),
12424
+ limit: external_exports.number().optional(),
12425
+ max_tokens: external_exports.number().optional().describe("Max tokens for summary"),
12426
+ include_decisions: external_exports.boolean().optional(),
12427
+ include_related: external_exports.boolean().optional(),
12428
+ include_impact: external_exports.boolean().optional(),
12429
+ session_id: external_exports.string().optional(),
12430
+ code_refs: external_exports.array(external_exports.object({
12431
+ file_path: external_exports.string(),
12432
+ symbol_id: external_exports.string().optional(),
12433
+ symbol_name: external_exports.string().optional()
12434
+ })).optional(),
12435
+ provenance: external_exports.object({
12436
+ repo: external_exports.string().optional(),
12437
+ branch: external_exports.string().optional(),
12438
+ commit_sha: external_exports.string().optional(),
12439
+ pr_url: external_exports.string().url().optional(),
12440
+ issue_url: external_exports.string().url().optional(),
12441
+ slack_thread_url: external_exports.string().url().optional()
12442
+ }).optional()
12443
+ })
12444
+ },
12445
+ async (input) => {
12446
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
12447
+ const projectId = resolveProjectId(input.project_id);
12448
+ switch (input.action) {
12449
+ case "capture": {
12450
+ if (!input.event_type || !input.title || !input.content) {
12451
+ return errorResult("capture requires: event_type, title, content");
12452
+ }
12453
+ const result = await client.captureContext({
12454
+ workspace_id: workspaceId,
12455
+ project_id: projectId,
12456
+ event_type: input.event_type,
12457
+ title: input.title,
12458
+ content: input.content,
12459
+ importance: input.importance,
12460
+ tags: input.tags,
12461
+ session_id: input.session_id,
12462
+ code_refs: input.code_refs,
12463
+ provenance: input.provenance
12464
+ });
12465
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12466
+ }
12467
+ case "capture_lesson": {
12468
+ if (!input.title || !input.category || !input.trigger || !input.impact || !input.prevention) {
12469
+ return errorResult("capture_lesson requires: title, category, trigger, impact, prevention");
12470
+ }
12471
+ const lessonInput = {
12472
+ title: input.title,
12473
+ category: input.category,
12474
+ trigger: input.trigger,
12475
+ impact: input.impact,
12476
+ prevention: input.prevention,
12477
+ severity: input.severity || "medium",
12478
+ keywords: input.keywords,
12479
+ workspace_id: workspaceId,
12480
+ project_id: projectId
12481
+ };
12482
+ const signature = buildLessonSignature(lessonInput, workspaceId || "global", projectId);
12483
+ if (isDuplicateLessonCapture(signature)) {
12484
+ return { content: [{ type: "text", text: formatContent({ deduplicated: true, message: "Lesson already captured recently" }) }] };
12485
+ }
12486
+ const result = await client.captureLesson(lessonInput);
12487
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12488
+ }
12489
+ case "get_lessons": {
12490
+ const result = await client.getLessons({
12491
+ workspace_id: workspaceId,
12492
+ project_id: projectId,
12493
+ query: input.query,
12494
+ category: input.category,
12495
+ severity: input.severity,
12496
+ limit: input.limit
12497
+ });
12498
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12499
+ }
12500
+ case "recall": {
12501
+ if (!input.query) {
12502
+ return errorResult("recall requires: query");
12503
+ }
12504
+ const result = await client.recallContext({
12505
+ workspace_id: workspaceId,
12506
+ project_id: projectId,
12507
+ query: input.query
12508
+ });
12509
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12510
+ }
12511
+ case "remember": {
12512
+ if (!input.content) {
12513
+ return errorResult("remember requires: content");
12514
+ }
12515
+ const result = await client.rememberContext({
12516
+ workspace_id: workspaceId,
12517
+ project_id: projectId,
12518
+ content: input.content,
12519
+ importance: input.importance
12520
+ });
12521
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12522
+ }
12523
+ case "user_context": {
12524
+ const result = await client.getUserContext({ workspace_id: workspaceId });
12525
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12526
+ }
12527
+ case "summary": {
12528
+ const result = await client.getSessionSummary({
12529
+ workspace_id: workspaceId,
12530
+ project_id: projectId,
12531
+ max_tokens: input.max_tokens
12532
+ });
12533
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12534
+ }
12535
+ case "compress": {
12536
+ if (!input.content) {
12537
+ return errorResult("compress requires: content (the chat history to compress)");
12538
+ }
12539
+ const result = await client.compressSession({
12540
+ workspace_id: workspaceId,
12541
+ project_id: projectId,
12542
+ chat_history: input.content
12543
+ });
12544
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12545
+ }
12546
+ case "delta": {
12547
+ if (!input.since) {
12548
+ return errorResult("delta requires: since (ISO timestamp)");
12549
+ }
12550
+ const result = await client.getSessionDelta({
12551
+ workspace_id: workspaceId,
12552
+ project_id: projectId,
12553
+ since: input.since,
12554
+ limit: input.limit
12555
+ });
12556
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12557
+ }
12558
+ case "smart_search": {
12559
+ if (!input.query) {
12560
+ return errorResult("smart_search requires: query");
12561
+ }
12562
+ const result = await client.smartSearch({
12563
+ workspace_id: workspaceId,
12564
+ project_id: projectId,
12565
+ query: input.query,
12566
+ include_decisions: input.include_decisions,
12567
+ include_related: input.include_related
12568
+ });
12569
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12570
+ }
12571
+ case "decision_trace": {
12572
+ if (!input.query) {
12573
+ return errorResult("decision_trace requires: query");
12574
+ }
12575
+ const result = await client.decisionTrace({
12576
+ workspace_id: workspaceId,
12577
+ project_id: projectId,
12578
+ query: input.query,
12579
+ include_impact: input.include_impact,
12580
+ limit: input.limit
12581
+ });
12582
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12583
+ }
12584
+ default:
12585
+ return errorResult(`Unknown action: ${input.action}`);
12586
+ }
12587
+ }
12588
+ );
12589
+ registerTool(
12590
+ "memory",
12591
+ {
12592
+ title: "Memory",
12593
+ description: `Memory operations for events and nodes. Event actions: create_event, get_event, update_event, delete_event, list_events, distill_event. Node actions: create_node, get_node, update_node, delete_node, list_nodes, supersede_node. Query actions: search, decisions, timeline, summary.`,
12594
+ inputSchema: external_exports.object({
12595
+ action: external_exports.enum([
12596
+ "create_event",
12597
+ "get_event",
12598
+ "update_event",
12599
+ "delete_event",
12600
+ "list_events",
12601
+ "distill_event",
12602
+ "create_node",
12603
+ "get_node",
12604
+ "update_node",
12605
+ "delete_node",
12606
+ "list_nodes",
12607
+ "supersede_node",
12608
+ "search",
12609
+ "decisions",
12610
+ "timeline",
12611
+ "summary"
12612
+ ]).describe("Action to perform"),
12613
+ workspace_id: external_exports.string().uuid().optional(),
12614
+ project_id: external_exports.string().uuid().optional(),
12615
+ // ID params
12616
+ event_id: external_exports.string().uuid().optional(),
12617
+ node_id: external_exports.string().uuid().optional(),
12618
+ // Content params
12619
+ title: external_exports.string().optional(),
12620
+ content: external_exports.string().optional(),
12621
+ event_type: external_exports.string().optional(),
12622
+ node_type: external_exports.string().optional(),
12623
+ metadata: external_exports.record(external_exports.any()).optional(),
12624
+ // Query params
12625
+ query: external_exports.string().optional(),
12626
+ category: external_exports.string().optional(),
12627
+ limit: external_exports.number().optional(),
12628
+ // Node relations
12629
+ relations: external_exports.array(external_exports.object({
12630
+ type: external_exports.string(),
12631
+ target_id: external_exports.string().uuid()
12632
+ })).optional(),
12633
+ new_node_id: external_exports.string().uuid().optional().describe("For supersede: the new node ID"),
12634
+ // Provenance
12635
+ provenance: external_exports.object({
12636
+ repo: external_exports.string().optional(),
12637
+ branch: external_exports.string().optional(),
12638
+ commit_sha: external_exports.string().optional(),
12639
+ pr_url: external_exports.string().url().optional(),
12640
+ issue_url: external_exports.string().url().optional(),
12641
+ slack_thread_url: external_exports.string().url().optional()
12642
+ }).optional(),
12643
+ code_refs: external_exports.array(external_exports.object({
12644
+ file_path: external_exports.string(),
12645
+ symbol_id: external_exports.string().optional(),
12646
+ symbol_name: external_exports.string().optional()
12647
+ })).optional()
12648
+ })
12649
+ },
12650
+ async (input) => {
12651
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
12652
+ const projectId = resolveProjectId(input.project_id);
12653
+ switch (input.action) {
12654
+ case "create_event": {
12655
+ if (!input.event_type || !input.title || !input.content) {
12656
+ return errorResult("create_event requires: event_type, title, content");
12657
+ }
12658
+ const result = await client.createMemoryEvent({
12659
+ workspace_id: workspaceId,
12660
+ project_id: projectId,
12661
+ event_type: input.event_type,
12662
+ title: input.title,
12663
+ content: input.content,
12664
+ metadata: input.metadata,
12665
+ provenance: input.provenance,
12666
+ code_refs: input.code_refs
12667
+ });
12668
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12669
+ }
12670
+ case "get_event": {
12671
+ if (!input.event_id) {
12672
+ return errorResult("get_event requires: event_id");
12673
+ }
12674
+ const result = await client.getMemoryEvent(input.event_id);
12675
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12676
+ }
12677
+ case "update_event": {
12678
+ if (!input.event_id) {
12679
+ return errorResult("update_event requires: event_id");
12680
+ }
12681
+ const result = await client.updateMemoryEvent({
12682
+ event_id: input.event_id,
12683
+ title: input.title,
12684
+ content: input.content,
12685
+ metadata: input.metadata
12686
+ });
12687
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12688
+ }
12689
+ case "delete_event": {
12690
+ if (!input.event_id) {
12691
+ return errorResult("delete_event requires: event_id");
12692
+ }
12693
+ const result = await client.deleteMemoryEvent(input.event_id);
12694
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12695
+ }
12696
+ case "list_events": {
12697
+ const result = await client.listMemoryEvents({
12698
+ workspace_id: workspaceId,
12699
+ project_id: projectId,
12700
+ limit: input.limit
12701
+ });
12702
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12703
+ }
12704
+ case "distill_event": {
12705
+ if (!input.event_id) {
12706
+ return errorResult("distill_event requires: event_id");
12707
+ }
12708
+ const result = await client.distillEvent(input.event_id);
12709
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12710
+ }
12711
+ case "create_node": {
12712
+ if (!input.node_type || !input.title || !input.content) {
12713
+ return errorResult("create_node requires: node_type, title, content");
12714
+ }
12715
+ const result = await client.createKnowledgeNode({
12716
+ workspace_id: workspaceId,
12717
+ project_id: projectId,
12718
+ node_type: input.node_type,
12719
+ title: input.title,
12720
+ content: input.content,
12721
+ relations: input.relations
12722
+ });
12723
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12724
+ }
12725
+ case "get_node": {
12726
+ if (!input.node_id) {
12727
+ return errorResult("get_node requires: node_id");
12728
+ }
12729
+ const result = await client.getKnowledgeNode(input.node_id);
12730
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12731
+ }
12732
+ case "update_node": {
12733
+ if (!input.node_id) {
12734
+ return errorResult("update_node requires: node_id");
12735
+ }
12736
+ const result = await client.updateKnowledgeNode({
12737
+ node_id: input.node_id,
12738
+ title: input.title,
12739
+ content: input.content
12740
+ });
12741
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12742
+ }
12743
+ case "delete_node": {
12744
+ if (!input.node_id) {
12745
+ return errorResult("delete_node requires: node_id");
12746
+ }
12747
+ const result = await client.deleteKnowledgeNode(input.node_id);
12748
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12749
+ }
12750
+ case "list_nodes": {
12751
+ const result = await client.listKnowledgeNodes({
12752
+ workspace_id: workspaceId,
12753
+ project_id: projectId,
12754
+ limit: input.limit
12755
+ });
12756
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12757
+ }
12758
+ case "supersede_node": {
12759
+ if (!input.node_id || !input.new_node_id) {
12760
+ return errorResult("supersede_node requires: node_id, new_node_id");
12761
+ }
12762
+ const result = await client.supersedeKnowledgeNode({
12763
+ node_id: input.node_id,
12764
+ new_node_id: input.new_node_id
12765
+ });
12766
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12767
+ }
12768
+ case "search": {
12769
+ if (!input.query) {
12770
+ return errorResult("search requires: query");
12771
+ }
12772
+ const result = await client.searchMemory({
12773
+ workspace_id: workspaceId,
12774
+ project_id: projectId,
12775
+ query: input.query,
12776
+ limit: input.limit
12777
+ });
12778
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12779
+ }
12780
+ case "decisions": {
12781
+ const result = await client.memoryDecisions({
12782
+ workspace_id: workspaceId,
12783
+ project_id: projectId,
12784
+ category: input.category,
12785
+ limit: input.limit
12786
+ });
12787
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12788
+ }
12789
+ case "timeline": {
12790
+ const result = await client.memoryTimeline({
12791
+ workspace_id: workspaceId
12792
+ });
12793
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12794
+ }
12795
+ case "summary": {
12796
+ const result = await client.memorySummary({
12797
+ workspace_id: workspaceId
12798
+ });
12799
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12800
+ }
12801
+ default:
12802
+ return errorResult(`Unknown action: ${input.action}`);
12803
+ }
12804
+ }
12805
+ );
12806
+ registerTool(
12807
+ "graph",
12808
+ {
12809
+ title: "Graph",
12810
+ description: `Code graph analysis. Actions: dependencies (module deps), impact (change impact), call_path (function call path), related (related nodes), path (path between nodes), decisions (decision history), ingest (build graph), circular_dependencies, unused_code, contradictions.`,
12811
+ inputSchema: external_exports.object({
12812
+ action: external_exports.enum([
12813
+ "dependencies",
12814
+ "impact",
12815
+ "call_path",
12816
+ "related",
12817
+ "path",
12818
+ "decisions",
12819
+ "ingest",
12820
+ "circular_dependencies",
12821
+ "unused_code",
12822
+ "contradictions"
12823
+ ]).describe("Action to perform"),
12824
+ workspace_id: external_exports.string().uuid().optional(),
12825
+ project_id: external_exports.string().uuid().optional(),
12826
+ // ID params
12827
+ node_id: external_exports.string().uuid().optional().describe("For related/contradictions"),
12828
+ source_id: external_exports.string().uuid().optional().describe("For path"),
12829
+ target_id: external_exports.string().uuid().optional().describe("For path"),
12830
+ // Target specification
12831
+ target: external_exports.object({
12832
+ type: external_exports.string().describe("module|function|type|variable"),
12833
+ id: external_exports.string().describe("Element identifier")
12834
+ }).optional().describe("For dependencies/impact"),
12835
+ source: external_exports.object({
12836
+ type: external_exports.string().describe("function"),
12837
+ id: external_exports.string().describe("Function identifier")
12838
+ }).optional().describe("For call_path"),
12839
+ // Options
12840
+ max_depth: external_exports.number().optional(),
12841
+ include_transitive: external_exports.boolean().optional(),
12842
+ limit: external_exports.number().optional(),
12843
+ wait: external_exports.boolean().optional().describe("For ingest: wait for completion")
12844
+ })
12845
+ },
12846
+ async (input) => {
12847
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
12848
+ const projectId = resolveProjectId(input.project_id);
12849
+ const gatedActions = ["related", "path", "decisions", "call_path", "circular_dependencies", "unused_code", "ingest", "contradictions"];
12850
+ if (gatedActions.includes(input.action)) {
12851
+ const gate = await gateIfGraphTool(`graph_${input.action}`, input);
12852
+ if (gate) return gate;
12853
+ }
12854
+ switch (input.action) {
12855
+ case "dependencies": {
12856
+ if (!input.target) {
12857
+ return errorResult("dependencies requires: target { type, id }");
12858
+ }
12859
+ const result = await client.graphDependencies({
12860
+ target: input.target,
12861
+ max_depth: input.max_depth,
12862
+ include_transitive: input.include_transitive
12863
+ });
12864
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12865
+ }
12866
+ case "impact": {
12867
+ if (!input.target) {
12868
+ return errorResult("impact requires: target { type, id }");
12869
+ }
12870
+ const result = await client.graphImpact({
12871
+ target: input.target,
12872
+ max_depth: input.max_depth
12873
+ });
12874
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12875
+ }
12876
+ case "call_path": {
12877
+ if (!input.source || !input.target) {
12878
+ return errorResult("call_path requires: source { type, id }, target { type, id }");
12879
+ }
12880
+ const result = await client.graphCallPath({
12881
+ source: input.source,
12882
+ target: input.target,
12883
+ max_depth: input.max_depth
12884
+ });
12885
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12886
+ }
12887
+ case "related": {
12888
+ if (!input.node_id) {
12889
+ return errorResult("related requires: node_id");
12890
+ }
12891
+ const result = await client.graphRelated({
12892
+ node_id: input.node_id,
12893
+ workspace_id: workspaceId,
12894
+ project_id: projectId,
12895
+ limit: input.limit
12896
+ });
12897
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12898
+ }
12899
+ case "path": {
12900
+ if (!input.source_id || !input.target_id) {
12901
+ return errorResult("path requires: source_id, target_id");
12902
+ }
12903
+ const result = await client.graphPath({
12904
+ source_id: input.source_id,
12905
+ target_id: input.target_id,
12906
+ workspace_id: workspaceId,
12907
+ project_id: projectId
12908
+ });
12909
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12910
+ }
12911
+ case "decisions": {
12912
+ const result = await client.graphDecisions({
12913
+ workspace_id: workspaceId,
12914
+ project_id: projectId,
12915
+ limit: input.limit
12916
+ });
12917
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12918
+ }
12919
+ case "ingest": {
12920
+ if (!projectId) {
12921
+ return errorResult("ingest requires: project_id");
12922
+ }
12923
+ const result = await client.graphIngest({
12924
+ project_id: projectId,
12925
+ wait: input.wait
12926
+ });
12927
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12928
+ }
12929
+ case "circular_dependencies": {
12930
+ if (!projectId) {
12931
+ return errorResult("circular_dependencies requires: project_id");
12932
+ }
12933
+ const result = await client.findCircularDependencies(projectId);
12934
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12935
+ }
12936
+ case "unused_code": {
12937
+ if (!projectId) {
12938
+ return errorResult("unused_code requires: project_id");
12939
+ }
12940
+ const result = await client.findUnusedCode(projectId);
12941
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12942
+ }
12943
+ case "contradictions": {
12944
+ if (!input.node_id) {
12945
+ return errorResult("contradictions requires: node_id");
12946
+ }
12947
+ const result = await client.findContradictions(input.node_id);
12948
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
12949
+ }
12950
+ default:
12951
+ return errorResult(`Unknown action: ${input.action}`);
12952
+ }
12953
+ }
12954
+ );
12955
+ registerTool(
12956
+ "project",
12957
+ {
12958
+ title: "Project",
12959
+ description: `Project management. Actions: list, get, create, update, index (trigger indexing), overview, statistics, files, index_status, ingest_local (index local folder).`,
12960
+ inputSchema: external_exports.object({
12961
+ action: external_exports.enum([
12962
+ "list",
12963
+ "get",
12964
+ "create",
12965
+ "update",
12966
+ "index",
12967
+ "overview",
12968
+ "statistics",
12969
+ "files",
12970
+ "index_status",
12971
+ "ingest_local"
12972
+ ]).describe("Action to perform"),
12973
+ workspace_id: external_exports.string().uuid().optional(),
12974
+ project_id: external_exports.string().uuid().optional(),
12975
+ // Create/update params
12976
+ name: external_exports.string().optional(),
12977
+ description: external_exports.string().optional(),
12978
+ folder_path: external_exports.string().optional(),
12979
+ generate_editor_rules: external_exports.boolean().optional(),
12980
+ // Ingest params
12981
+ path: external_exports.string().optional().describe("Local path to ingest"),
12982
+ overwrite: external_exports.boolean().optional(),
12983
+ write_to_disk: external_exports.boolean().optional(),
12984
+ // Pagination
12985
+ page: external_exports.number().optional(),
12986
+ page_size: external_exports.number().optional()
12987
+ })
12988
+ },
12989
+ async (input) => {
12990
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
12991
+ const projectId = resolveProjectId(input.project_id);
12992
+ switch (input.action) {
12993
+ case "list": {
12994
+ const result = await client.listProjects({
12995
+ workspace_id: workspaceId,
12996
+ page: input.page,
12997
+ page_size: input.page_size
12998
+ });
12999
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13000
+ }
13001
+ case "get": {
13002
+ if (!projectId) {
13003
+ return errorResult("get requires: project_id");
13004
+ }
13005
+ const result = await client.getProject(projectId);
13006
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13007
+ }
13008
+ case "create": {
13009
+ if (!input.name) {
13010
+ return errorResult("create requires: name");
13011
+ }
13012
+ const result = await client.createProject({
13013
+ workspace_id: workspaceId,
13014
+ name: input.name,
13015
+ description: input.description,
13016
+ folder_path: input.folder_path,
13017
+ generate_editor_rules: input.generate_editor_rules
13018
+ });
13019
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13020
+ }
13021
+ case "update": {
13022
+ if (!projectId) {
13023
+ return errorResult("update requires: project_id");
13024
+ }
13025
+ const result = await client.updateProject({
13026
+ project_id: projectId,
13027
+ name: input.name,
13028
+ description: input.description
13029
+ });
13030
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13031
+ }
13032
+ case "index": {
13033
+ if (!projectId) {
13034
+ return errorResult("index requires: project_id");
13035
+ }
13036
+ const result = await client.indexProject(projectId);
13037
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13038
+ }
13039
+ case "overview": {
13040
+ if (!projectId) {
13041
+ return errorResult("overview requires: project_id");
13042
+ }
13043
+ const result = await client.projectOverview(projectId);
13044
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13045
+ }
13046
+ case "statistics": {
13047
+ if (!projectId) {
13048
+ return errorResult("statistics requires: project_id");
13049
+ }
13050
+ const result = await client.projectStatistics(projectId);
13051
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13052
+ }
13053
+ case "files": {
13054
+ if (!projectId) {
13055
+ return errorResult("files requires: project_id");
13056
+ }
13057
+ const result = await client.projectFiles(projectId);
13058
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13059
+ }
13060
+ case "index_status": {
13061
+ if (!projectId) {
13062
+ return errorResult("index_status requires: project_id");
13063
+ }
13064
+ const result = await client.projectIndexStatus(projectId);
13065
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13066
+ }
13067
+ case "ingest_local": {
13068
+ if (!input.path) {
13069
+ return errorResult("ingest_local requires: path");
13070
+ }
13071
+ const validPath = await validateReadableDirectory(input.path);
13072
+ if (!validPath.ok) {
13073
+ return errorResult(validPath.error);
13074
+ }
13075
+ const files = await readAllFilesInBatches(validPath.resolvedPath, async (batch) => {
13076
+ await client.ingestLocalFiles({
13077
+ project_id: projectId,
13078
+ files: batch,
13079
+ overwrite: input.overwrite,
13080
+ write_to_disk: input.write_to_disk
13081
+ });
13082
+ });
13083
+ const result = { files_ingested: files, project_id: projectId };
13084
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13085
+ }
13086
+ default:
13087
+ return errorResult(`Unknown action: ${input.action}`);
13088
+ }
13089
+ }
13090
+ );
13091
+ registerTool(
13092
+ "workspace",
13093
+ {
13094
+ title: "Workspace",
13095
+ description: `Workspace management. Actions: list, get, associate (link folder to workspace), bootstrap (create workspace and initialize).`,
13096
+ inputSchema: external_exports.object({
13097
+ action: external_exports.enum(["list", "get", "associate", "bootstrap"]).describe("Action to perform"),
13098
+ workspace_id: external_exports.string().uuid().optional(),
13099
+ // Associate/bootstrap params
13100
+ folder_path: external_exports.string().optional(),
13101
+ workspace_name: external_exports.string().optional(),
13102
+ create_parent_mapping: external_exports.boolean().optional(),
13103
+ generate_editor_rules: external_exports.boolean().optional(),
13104
+ // Bootstrap-specific
13105
+ description: external_exports.string().optional(),
13106
+ visibility: external_exports.enum(["private", "public"]).optional(),
13107
+ auto_index: external_exports.boolean().optional(),
13108
+ context_hint: external_exports.string().optional(),
13109
+ // Pagination
13110
+ page: external_exports.number().optional(),
13111
+ page_size: external_exports.number().optional()
13112
+ })
13113
+ },
13114
+ async (input) => {
13115
+ switch (input.action) {
13116
+ case "list": {
13117
+ const result = await client.listWorkspaces({
13118
+ page: input.page,
13119
+ page_size: input.page_size
13120
+ });
13121
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13122
+ }
13123
+ case "get": {
13124
+ if (!input.workspace_id) {
13125
+ return errorResult("get requires: workspace_id");
13126
+ }
13127
+ const result = await client.getWorkspace(input.workspace_id);
13128
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13129
+ }
13130
+ case "associate": {
13131
+ if (!input.folder_path || !input.workspace_id) {
13132
+ return errorResult("associate requires: folder_path, workspace_id");
13133
+ }
13134
+ const result = await client.associateWorkspace({
13135
+ folder_path: input.folder_path,
13136
+ workspace_id: input.workspace_id,
13137
+ workspace_name: input.workspace_name,
13138
+ create_parent_mapping: input.create_parent_mapping,
13139
+ generate_editor_rules: input.generate_editor_rules
13140
+ });
13141
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13142
+ }
13143
+ case "bootstrap": {
13144
+ if (!input.workspace_name) {
13145
+ return errorResult("bootstrap requires: workspace_name");
13146
+ }
13147
+ const result = await client.bootstrapWorkspace({
13148
+ workspace_name: input.workspace_name,
13149
+ folder_path: input.folder_path,
13150
+ description: input.description,
13151
+ visibility: input.visibility,
13152
+ create_parent_mapping: input.create_parent_mapping,
13153
+ generate_editor_rules: input.generate_editor_rules,
13154
+ auto_index: input.auto_index,
13155
+ context_hint: input.context_hint
13156
+ });
13157
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13158
+ }
13159
+ default:
13160
+ return errorResult(`Unknown action: ${input.action}`);
13161
+ }
13162
+ }
13163
+ );
13164
+ registerTool(
13165
+ "reminder",
13166
+ {
13167
+ title: "Reminder",
13168
+ description: `Reminder management. Actions: list, active (pending/overdue), create, snooze, complete, dismiss.`,
13169
+ inputSchema: external_exports.object({
13170
+ action: external_exports.enum(["list", "active", "create", "snooze", "complete", "dismiss"]).describe("Action to perform"),
13171
+ workspace_id: external_exports.string().uuid().optional(),
13172
+ project_id: external_exports.string().uuid().optional(),
13173
+ reminder_id: external_exports.string().uuid().optional(),
13174
+ // Create params
13175
+ title: external_exports.string().optional(),
13176
+ content: external_exports.string().optional(),
13177
+ remind_at: external_exports.string().optional().describe("ISO 8601 datetime"),
13178
+ priority: external_exports.enum(["low", "normal", "high", "urgent"]).optional(),
13179
+ recurrence: external_exports.enum(["daily", "weekly", "monthly"]).optional(),
13180
+ keywords: external_exports.array(external_exports.string()).optional(),
13181
+ // Snooze params
13182
+ until: external_exports.string().optional().describe("ISO 8601 datetime"),
13183
+ // Filter params
13184
+ status: external_exports.enum(["pending", "completed", "dismissed", "snoozed"]).optional(),
13185
+ context: external_exports.string().optional(),
13186
+ limit: external_exports.number().optional()
13187
+ })
13188
+ },
13189
+ async (input) => {
13190
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
13191
+ const projectId = resolveProjectId(input.project_id);
13192
+ switch (input.action) {
13193
+ case "list": {
13194
+ const result = await client.remindersList({
13195
+ workspace_id: workspaceId,
13196
+ project_id: projectId,
13197
+ status: input.status,
13198
+ priority: input.priority,
13199
+ limit: input.limit
13200
+ });
13201
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13202
+ }
13203
+ case "active": {
13204
+ const result = await client.remindersActive({
13205
+ workspace_id: workspaceId,
13206
+ project_id: projectId,
13207
+ context: input.context,
13208
+ limit: input.limit
13209
+ });
13210
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13211
+ }
13212
+ case "create": {
13213
+ if (!input.title || !input.content || !input.remind_at) {
13214
+ return errorResult("create requires: title, content, remind_at");
13215
+ }
13216
+ const result = await client.remindersCreate({
13217
+ workspace_id: workspaceId,
13218
+ project_id: projectId,
13219
+ title: input.title,
13220
+ content: input.content,
13221
+ remind_at: input.remind_at,
13222
+ priority: input.priority,
13223
+ recurrence: input.recurrence,
13224
+ keywords: input.keywords
13225
+ });
13226
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13227
+ }
13228
+ case "snooze": {
13229
+ if (!input.reminder_id || !input.until) {
13230
+ return errorResult("snooze requires: reminder_id, until");
13231
+ }
13232
+ const result = await client.remindersSnooze({
13233
+ reminder_id: input.reminder_id,
13234
+ until: input.until
13235
+ });
13236
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13237
+ }
13238
+ case "complete": {
13239
+ if (!input.reminder_id) {
13240
+ return errorResult("complete requires: reminder_id");
13241
+ }
13242
+ const result = await client.remindersComplete({
13243
+ reminder_id: input.reminder_id
13244
+ });
13245
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13246
+ }
13247
+ case "dismiss": {
13248
+ if (!input.reminder_id) {
13249
+ return errorResult("dismiss requires: reminder_id");
13250
+ }
13251
+ const result = await client.remindersDismiss({
13252
+ reminder_id: input.reminder_id
13253
+ });
13254
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13255
+ }
13256
+ default:
13257
+ return errorResult(`Unknown action: ${input.action}`);
13258
+ }
13259
+ }
13260
+ );
13261
+ registerTool(
13262
+ "integration",
13263
+ {
13264
+ title: "Integration",
13265
+ description: `Integration operations for Slack and GitHub. Provider: slack, github, all. Actions: status, search, stats, activity, contributors, knowledge, summary, channels (slack), discussions (slack), repos (github), issues (github).`,
13266
+ inputSchema: external_exports.object({
13267
+ provider: external_exports.enum(["slack", "github", "all"]).describe("Integration provider"),
13268
+ action: external_exports.enum([
13269
+ "status",
13270
+ "search",
13271
+ "stats",
13272
+ "activity",
13273
+ "contributors",
13274
+ "knowledge",
13275
+ "summary",
13276
+ "channels",
13277
+ "discussions",
13278
+ "sync_users",
13279
+ "repos",
13280
+ "issues"
13281
+ ]).describe("Action to perform"),
13282
+ workspace_id: external_exports.string().uuid().optional(),
13283
+ project_id: external_exports.string().uuid().optional(),
13284
+ query: external_exports.string().optional(),
13285
+ limit: external_exports.number().optional(),
13286
+ since: external_exports.string().optional(),
13287
+ until: external_exports.string().optional()
13288
+ })
13289
+ },
13290
+ async (input) => {
13291
+ const workspaceId = resolveWorkspaceId(input.workspace_id);
13292
+ const projectId = resolveProjectId(input.project_id);
13293
+ const integrationGated = await gateIfIntegrationTool(
13294
+ input.provider === "slack" ? "slack_search" : input.provider === "github" ? "github_search" : "integrations_status"
13295
+ );
13296
+ if (integrationGated) return integrationGated;
13297
+ const params = {
13298
+ workspace_id: workspaceId,
13299
+ project_id: projectId,
13300
+ query: input.query,
13301
+ limit: input.limit,
13302
+ since: input.since,
13303
+ until: input.until
13304
+ };
13305
+ switch (input.action) {
13306
+ case "status": {
13307
+ const result = await client.integrationsStatus(params);
13308
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13309
+ }
13310
+ case "search": {
13311
+ if (input.provider === "slack") {
13312
+ const result = await client.slackSearch(params);
13313
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13314
+ } else if (input.provider === "github") {
13315
+ const result = await client.githubSearch(params);
13316
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13317
+ } else {
13318
+ const result = await client.integrationsSearch(params);
13319
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13320
+ }
13321
+ }
13322
+ case "stats": {
13323
+ if (input.provider === "slack") {
13324
+ const result = await client.slackStats(params);
13325
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13326
+ } else if (input.provider === "github") {
13327
+ const result = await client.githubStats(params);
13328
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13329
+ }
13330
+ return errorResult("stats requires provider: slack or github");
13331
+ }
13332
+ case "activity": {
13333
+ if (input.provider === "slack") {
13334
+ const result = await client.slackActivity(params);
13335
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13336
+ } else if (input.provider === "github") {
13337
+ const result = await client.githubActivity(params);
13338
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13339
+ }
13340
+ return errorResult("activity requires provider: slack or github");
13341
+ }
13342
+ case "contributors": {
13343
+ if (input.provider === "slack") {
13344
+ const result = await client.slackContributors(params);
13345
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13346
+ } else if (input.provider === "github") {
13347
+ const result = await client.githubContributors(params);
13348
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13349
+ }
13350
+ return errorResult("contributors requires provider: slack or github");
13351
+ }
13352
+ case "knowledge": {
13353
+ if (input.provider === "slack") {
13354
+ const result = await client.slackKnowledge(params);
13355
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13356
+ } else if (input.provider === "github") {
13357
+ const result = await client.githubKnowledge(params);
13358
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13359
+ } else {
13360
+ const result = await client.integrationsKnowledge(params);
13361
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13362
+ }
13363
+ }
13364
+ case "summary": {
13365
+ if (input.provider === "slack") {
13366
+ const result = await client.slackSummary(params);
13367
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13368
+ } else if (input.provider === "github") {
13369
+ const result = await client.githubSummary(params);
13370
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13371
+ } else {
13372
+ const result = await client.integrationsSummary(params);
13373
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13374
+ }
13375
+ }
13376
+ case "channels": {
13377
+ if (input.provider !== "slack") {
13378
+ return errorResult("channels is only available for slack provider");
13379
+ }
13380
+ const result = await client.slackChannels(params);
13381
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13382
+ }
13383
+ case "discussions": {
13384
+ if (input.provider !== "slack") {
13385
+ return errorResult("discussions is only available for slack provider");
13386
+ }
13387
+ const result = await client.slackDiscussions(params);
13388
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13389
+ }
13390
+ case "sync_users": {
13391
+ if (input.provider !== "slack") {
13392
+ return errorResult("sync_users is only available for slack provider");
13393
+ }
13394
+ const result = await client.slackSyncUsers(params);
13395
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13396
+ }
13397
+ case "repos": {
13398
+ if (input.provider !== "github") {
13399
+ return errorResult("repos is only available for github provider");
13400
+ }
13401
+ const result = await client.githubRepos(params);
13402
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13403
+ }
13404
+ case "issues": {
13405
+ if (input.provider !== "github") {
13406
+ return errorResult("issues is only available for github provider");
13407
+ }
13408
+ const result = await client.githubIssues(params);
13409
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13410
+ }
13411
+ default:
13412
+ return errorResult(`Unknown action: ${input.action}`);
13413
+ }
13414
+ }
13415
+ );
13416
+ registerTool(
13417
+ "help",
13418
+ {
13419
+ title: "Help",
13420
+ description: `Utility and help. Actions: tools (list available tools), auth (current user), version (server version), editor_rules (generate AI editor rules), enable_bundle (enable tool bundle in progressive mode).`,
13421
+ inputSchema: external_exports.object({
13422
+ action: external_exports.enum(["tools", "auth", "version", "editor_rules", "enable_bundle"]).describe("Action to perform"),
13423
+ // For tools
13424
+ format: external_exports.enum(["grouped", "minimal", "full"]).optional(),
13425
+ category: external_exports.string().optional(),
13426
+ // For editor_rules
13427
+ folder_path: external_exports.string().optional(),
13428
+ editors: external_exports.array(external_exports.string()).optional(),
13429
+ mode: external_exports.enum(["minimal", "full"]).optional(),
13430
+ dry_run: external_exports.boolean().optional(),
13431
+ workspace_id: external_exports.string().uuid().optional(),
13432
+ workspace_name: external_exports.string().optional(),
13433
+ project_name: external_exports.string().optional(),
13434
+ additional_rules: external_exports.string().optional(),
13435
+ // For enable_bundle
13436
+ bundle: external_exports.enum(["session", "memory", "search", "graph", "workspace", "project", "reminders", "integrations"]).optional(),
13437
+ list_bundles: external_exports.boolean().optional()
13438
+ })
13439
+ },
13440
+ async (input) => {
13441
+ switch (input.action) {
13442
+ case "tools": {
13443
+ const format = input.format || "grouped";
13444
+ const catalog = generateToolCatalog(format, input.category);
13445
+ const consolidatedInfo = CONSOLIDATED_MODE ? `
13446
+
13447
+ [Consolidated Mode]
13448
+ Domain tools: ${Array.from(CONSOLIDATED_TOOLS).join(", ")}
13449
+ Each domain tool has an 'action' parameter for specific operations.` : "";
13450
+ return {
13451
+ content: [{ type: "text", text: catalog + consolidatedInfo }],
13452
+ structuredContent: {
13453
+ format,
13454
+ catalog,
13455
+ consolidated_mode: CONSOLIDATED_MODE,
13456
+ domain_tools: CONSOLIDATED_MODE ? Array.from(CONSOLIDATED_TOOLS) : void 0
13457
+ }
13458
+ };
13459
+ }
13460
+ case "auth": {
13461
+ const result = await client.me();
13462
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13463
+ }
13464
+ case "version": {
13465
+ const result = { name: "contextstream-mcp", version: VERSION };
13466
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13467
+ }
13468
+ case "editor_rules": {
13469
+ if (!input.folder_path) {
13470
+ return errorResult("editor_rules requires: folder_path");
13471
+ }
13472
+ const result = await generateAllRuleFiles(input.folder_path, {
13473
+ editors: input.editors,
13474
+ mode: input.mode,
13475
+ dryRun: input.dry_run,
13476
+ workspaceId: input.workspace_id,
13477
+ workspaceName: input.workspace_name,
13478
+ projectName: input.project_name,
13479
+ additionalRules: input.additional_rules
13480
+ });
13481
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13482
+ }
13483
+ case "enable_bundle": {
13484
+ if (input.list_bundles) {
13485
+ const bundles = getBundleInfo();
13486
+ const result2 = {
13487
+ progressive_mode: PROGRESSIVE_MODE,
13488
+ consolidated_mode: CONSOLIDATED_MODE,
13489
+ bundles,
13490
+ hint: CONSOLIDATED_MODE ? "Consolidated mode is enabled. All operations are available via domain tools." : PROGRESSIVE_MODE ? "Progressive mode is enabled. Use enable_bundle to unlock additional tools." : "Neither progressive nor consolidated mode is enabled."
13491
+ };
13492
+ return { content: [{ type: "text", text: formatContent(result2) }], structuredContent: toStructured(result2) };
13493
+ }
13494
+ if (!input.bundle) {
13495
+ return errorResult("enable_bundle requires: bundle (or use list_bundles: true)");
13496
+ }
13497
+ if (CONSOLIDATED_MODE) {
13498
+ return {
13499
+ content: [{ type: "text", text: "Consolidated mode is enabled. All operations are available via domain tools (search, session, memory, graph, project, workspace, reminder, integration, help)." }]
13500
+ };
13501
+ }
13502
+ if (!PROGRESSIVE_MODE) {
13503
+ return {
13504
+ content: [{ type: "text", text: "Progressive mode is not enabled. All tools from your toolset are already available." }]
13505
+ };
13506
+ }
13507
+ const result = enableBundle(input.bundle);
13508
+ return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
13509
+ }
13510
+ default:
13511
+ return errorResult(`Unknown action: ${input.action}`);
13512
+ }
13513
+ }
13514
+ );
13515
+ console.error(`[ContextStream] Consolidated mode: Registered ${CONSOLIDATED_TOOLS.size} domain tools.`);
13516
+ }
12299
13517
  }
12300
13518
 
12301
13519
  // src/resources.ts
@@ -14779,6 +15997,7 @@ Environment variables:
14779
15997
  CONTEXTSTREAM_PROGRESSIVE_MODE Progressive disclosure: true|false (default: false, starts with ~13 core tools)
14780
15998
  CONTEXTSTREAM_ROUTER_MODE Router pattern: true|false (default: false, exposes only 2 meta-tools)
14781
15999
  CONTEXTSTREAM_OUTPUT_FORMAT Output verbosity: compact|pretty (default: compact, ~30% fewer tokens)
16000
+ CONTEXTSTREAM_CONSOLIDATED Consolidated domain tools: true|false (default: true in v0.4.x, ~75% token reduction)
14782
16001
  CONTEXTSTREAM_PRO_TOOLS Optional comma-separated PRO tool names (default: AI tools)
14783
16002
  CONTEXTSTREAM_UPGRADE_URL Optional upgrade URL shown for PRO tools on Free plan
14784
16003
  CONTEXTSTREAM_ENABLE_PROMPTS Enable MCP prompts list (default: true)
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.3.73",
4
+ "version": "0.4.1",
5
5
  "description": "MCP server exposing ContextStream public API - code context, memory, search, and AI tools for developers",
6
6
  "type": "module",
7
7
  "license": "MIT",