@contextstream/mcp-server 0.2.7 → 0.3.0

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 +23 -33
  2. package/dist/index.js +269 -62
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -35,15 +35,14 @@ A powerful Model Context Protocol (MCP) server that provides persistent memory,
35
35
 
36
36
  ## Installation
37
37
 
38
- Add ContextStream to your AI tool's MCP configuration:
38
+ Add ContextStream to your AI tool's MCP configuration (works with **Cursor**, **VS Code**, **Claude Code**, **Windsurf**, and any MCP-compatible client):
39
39
 
40
- ### Cursor / VS Code
41
40
  ```json
42
41
  {
43
42
  "mcpServers": {
44
43
  "contextstream": {
45
44
  "command": "npx",
46
- "args": ["@contextstream/mcp-server"],
45
+ "args": ["-y", "@contextstream/mcp-server"],
47
46
  "env": {
48
47
  "CONTEXTSTREAM_API_URL": "https://api.contextstream.io",
49
48
  "CONTEXTSTREAM_API_KEY": "your_api_key"
@@ -53,39 +52,30 @@ Add ContextStream to your AI tool's MCP configuration:
53
52
  }
54
53
  ```
55
54
 
56
- ### Claude Code
57
- ```json
58
- {
59
- "mcpServers": {
60
- "contextstream": {
61
- "command": "npx",
62
- "args": ["@contextstream/mcp-server"],
63
- "env": {
64
- "CONTEXTSTREAM_API_URL": "https://api.contextstream.io",
65
- "CONTEXTSTREAM_API_KEY": "your_api_key"
66
- }
67
- }
68
- }
69
- }
70
- ```
55
+ Get your API key at [contextstream.io](https://contextstream.io)
71
56
 
72
- ### Windsurf
73
- ```json
74
- {
75
- "mcpServers": {
76
- "contextstream": {
77
- "command": "npx",
78
- "args": ["@contextstream/mcp-server"],
79
- "env": {
80
- "CONTEXTSTREAM_API_URL": "https://api.contextstream.io",
81
- "CONTEXTSTREAM_API_KEY": "your_api_key"
82
- }
83
- }
84
- }
85
- }
57
+ ## ✨ Auto-Context (v0.3.0+)
58
+
59
+ Context loads **automatically** on the first tool call of any conversation. No need to manually call `session_init` — your AI assistant gets workspace info, recent memory, and decisions immediately.
60
+
61
+ ```
62
+ ═══════════════════════════════════════════
63
+ 🧠 AUTO-CONTEXT LOADED (ContextStream)
64
+ ═══════════════════════════════════════════
65
+ 📁 Workspace: my-project
66
+ 📂 Project: backend-api
67
+
68
+ 📋 Recent Decisions:
69
+ • Use PostgreSQL for persistence
70
+ • JWT for authentication
71
+
72
+ 🧠 Recent Context:
73
+ • [decision] API design patterns
74
+ • [preference] TypeScript strict mode
75
+ ═══════════════════════════════════════════
86
76
  ```
87
77
 
88
- Get your API key at [contextstream.io](https://contextstream.io)
78
+ Works with **all MCP clients** — no client-side changes required.
89
79
 
90
80
  ## Environment Variables
91
81
 
package/dist/index.js CHANGED
@@ -5025,8 +5025,41 @@ function toStructured(data) {
5025
5025
  }
5026
5026
  return void 0;
5027
5027
  }
5028
- function registerTools(server, client) {
5029
- server.registerTool(
5028
+ function registerTools(server, client, sessionManager) {
5029
+ function wrapWithAutoContext(toolName, handler) {
5030
+ if (!sessionManager) {
5031
+ return handler;
5032
+ }
5033
+ return async (input) => {
5034
+ const skipAutoInit = toolName === "session_init";
5035
+ let contextPrefix = "";
5036
+ if (!skipAutoInit) {
5037
+ const autoInitResult = await sessionManager.autoInitialize();
5038
+ if (autoInitResult) {
5039
+ contextPrefix = autoInitResult.contextSummary + "\n\n";
5040
+ }
5041
+ }
5042
+ const result = await handler(input);
5043
+ if (contextPrefix && result && typeof result === "object") {
5044
+ const r = result;
5045
+ if (r.content && r.content.length > 0 && r.content[0].type === "text") {
5046
+ r.content[0] = {
5047
+ ...r.content[0],
5048
+ text: contextPrefix + "--- Tool Response ---\n\n" + r.content[0].text
5049
+ };
5050
+ }
5051
+ }
5052
+ return result;
5053
+ };
5054
+ }
5055
+ function registerTool(name, config, handler) {
5056
+ server.registerTool(
5057
+ name,
5058
+ config,
5059
+ wrapWithAutoContext(name, handler)
5060
+ );
5061
+ }
5062
+ registerTool(
5030
5063
  "auth_me",
5031
5064
  {
5032
5065
  title: "Get current user",
@@ -5038,7 +5071,7 @@ function registerTools(server, client) {
5038
5071
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5039
5072
  }
5040
5073
  );
5041
- server.registerTool(
5074
+ registerTool(
5042
5075
  "workspaces_list",
5043
5076
  {
5044
5077
  title: "List workspaces",
@@ -5050,7 +5083,7 @@ function registerTools(server, client) {
5050
5083
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5051
5084
  }
5052
5085
  );
5053
- server.registerTool(
5086
+ registerTool(
5054
5087
  "workspaces_create",
5055
5088
  {
5056
5089
  title: "Create workspace",
@@ -5066,7 +5099,7 @@ function registerTools(server, client) {
5066
5099
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5067
5100
  }
5068
5101
  );
5069
- server.registerTool(
5102
+ registerTool(
5070
5103
  "projects_list",
5071
5104
  {
5072
5105
  title: "List projects",
@@ -5078,7 +5111,7 @@ function registerTools(server, client) {
5078
5111
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5079
5112
  }
5080
5113
  );
5081
- server.registerTool(
5114
+ registerTool(
5082
5115
  "projects_create",
5083
5116
  {
5084
5117
  title: "Create project",
@@ -5094,7 +5127,7 @@ function registerTools(server, client) {
5094
5127
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5095
5128
  }
5096
5129
  );
5097
- server.registerTool(
5130
+ registerTool(
5098
5131
  "projects_index",
5099
5132
  {
5100
5133
  title: "Index project",
@@ -5112,7 +5145,7 @@ function registerTools(server, client) {
5112
5145
  project_id: external_exports.string().uuid().optional(),
5113
5146
  limit: external_exports.number().optional()
5114
5147
  });
5115
- server.registerTool(
5148
+ registerTool(
5116
5149
  "search_semantic",
5117
5150
  { title: "Semantic search", description: "Semantic vector search", inputSchema: searchSchema },
5118
5151
  async (input) => {
@@ -5120,7 +5153,7 @@ function registerTools(server, client) {
5120
5153
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5121
5154
  }
5122
5155
  );
5123
- server.registerTool(
5156
+ registerTool(
5124
5157
  "search_hybrid",
5125
5158
  { title: "Hybrid search", description: "Hybrid search (semantic + keyword)", inputSchema: searchSchema },
5126
5159
  async (input) => {
@@ -5128,7 +5161,7 @@ function registerTools(server, client) {
5128
5161
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5129
5162
  }
5130
5163
  );
5131
- server.registerTool(
5164
+ registerTool(
5132
5165
  "search_keyword",
5133
5166
  { title: "Keyword search", description: "Keyword search", inputSchema: searchSchema },
5134
5167
  async (input) => {
@@ -5136,7 +5169,7 @@ function registerTools(server, client) {
5136
5169
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5137
5170
  }
5138
5171
  );
5139
- server.registerTool(
5172
+ registerTool(
5140
5173
  "search_pattern",
5141
5174
  { title: "Pattern search", description: "Pattern/regex search", inputSchema: searchSchema },
5142
5175
  async (input) => {
@@ -5144,7 +5177,7 @@ function registerTools(server, client) {
5144
5177
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5145
5178
  }
5146
5179
  );
5147
- server.registerTool(
5180
+ registerTool(
5148
5181
  "memory_create_event",
5149
5182
  {
5150
5183
  title: "Create memory event",
@@ -5163,7 +5196,7 @@ function registerTools(server, client) {
5163
5196
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5164
5197
  }
5165
5198
  );
5166
- server.registerTool(
5199
+ registerTool(
5167
5200
  "memory_bulk_ingest",
5168
5201
  {
5169
5202
  title: "Bulk ingest events",
@@ -5179,7 +5212,7 @@ function registerTools(server, client) {
5179
5212
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5180
5213
  }
5181
5214
  );
5182
- server.registerTool(
5215
+ registerTool(
5183
5216
  "memory_list_events",
5184
5217
  {
5185
5218
  title: "List memory events",
@@ -5195,7 +5228,7 @@ function registerTools(server, client) {
5195
5228
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5196
5229
  }
5197
5230
  );
5198
- server.registerTool(
5231
+ registerTool(
5199
5232
  "memory_create_node",
5200
5233
  {
5201
5234
  title: "Create knowledge node",
@@ -5219,7 +5252,7 @@ function registerTools(server, client) {
5219
5252
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5220
5253
  }
5221
5254
  );
5222
- server.registerTool(
5255
+ registerTool(
5223
5256
  "memory_list_nodes",
5224
5257
  {
5225
5258
  title: "List knowledge nodes",
@@ -5235,7 +5268,7 @@ function registerTools(server, client) {
5235
5268
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5236
5269
  }
5237
5270
  );
5238
- server.registerTool(
5271
+ registerTool(
5239
5272
  "memory_search",
5240
5273
  {
5241
5274
  title: "Memory-aware search",
@@ -5252,7 +5285,7 @@ function registerTools(server, client) {
5252
5285
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5253
5286
  }
5254
5287
  );
5255
- server.registerTool(
5288
+ registerTool(
5256
5289
  "memory_decisions",
5257
5290
  {
5258
5291
  title: "Decision summaries",
@@ -5268,7 +5301,7 @@ function registerTools(server, client) {
5268
5301
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5269
5302
  }
5270
5303
  );
5271
- server.registerTool(
5304
+ registerTool(
5272
5305
  "graph_related",
5273
5306
  {
5274
5307
  title: "Related knowledge nodes",
@@ -5285,7 +5318,7 @@ function registerTools(server, client) {
5285
5318
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5286
5319
  }
5287
5320
  );
5288
- server.registerTool(
5321
+ registerTool(
5289
5322
  "graph_path",
5290
5323
  {
5291
5324
  title: "Knowledge path",
@@ -5302,7 +5335,7 @@ function registerTools(server, client) {
5302
5335
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5303
5336
  }
5304
5337
  );
5305
- server.registerTool(
5338
+ registerTool(
5306
5339
  "graph_decisions",
5307
5340
  {
5308
5341
  title: "Decision graph",
@@ -5318,7 +5351,7 @@ function registerTools(server, client) {
5318
5351
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5319
5352
  }
5320
5353
  );
5321
- server.registerTool(
5354
+ registerTool(
5322
5355
  "graph_dependencies",
5323
5356
  {
5324
5357
  title: "Code dependencies",
@@ -5334,7 +5367,7 @@ function registerTools(server, client) {
5334
5367
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5335
5368
  }
5336
5369
  );
5337
- server.registerTool(
5370
+ registerTool(
5338
5371
  "graph_call_path",
5339
5372
  {
5340
5373
  title: "Call path",
@@ -5350,7 +5383,7 @@ function registerTools(server, client) {
5350
5383
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5351
5384
  }
5352
5385
  );
5353
- server.registerTool(
5386
+ registerTool(
5354
5387
  "graph_impact",
5355
5388
  {
5356
5389
  title: "Impact analysis",
@@ -5362,7 +5395,7 @@ function registerTools(server, client) {
5362
5395
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5363
5396
  }
5364
5397
  );
5365
- server.registerTool(
5398
+ registerTool(
5366
5399
  "ai_context",
5367
5400
  {
5368
5401
  title: "Build AI context",
@@ -5382,7 +5415,7 @@ function registerTools(server, client) {
5382
5415
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5383
5416
  }
5384
5417
  );
5385
- server.registerTool(
5418
+ registerTool(
5386
5419
  "ai_embeddings",
5387
5420
  {
5388
5421
  title: "Generate embeddings",
@@ -5394,7 +5427,7 @@ function registerTools(server, client) {
5394
5427
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5395
5428
  }
5396
5429
  );
5397
- server.registerTool(
5430
+ registerTool(
5398
5431
  "ai_plan",
5399
5432
  {
5400
5433
  title: "Generate dev plan",
@@ -5410,7 +5443,7 @@ function registerTools(server, client) {
5410
5443
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5411
5444
  }
5412
5445
  );
5413
- server.registerTool(
5446
+ registerTool(
5414
5447
  "ai_tasks",
5415
5448
  {
5416
5449
  title: "Generate tasks",
@@ -5427,7 +5460,7 @@ function registerTools(server, client) {
5427
5460
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5428
5461
  }
5429
5462
  );
5430
- server.registerTool(
5463
+ registerTool(
5431
5464
  "ai_enhanced_context",
5432
5465
  {
5433
5466
  title: "Enhanced AI context",
@@ -5447,7 +5480,7 @@ function registerTools(server, client) {
5447
5480
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5448
5481
  }
5449
5482
  );
5450
- server.registerTool(
5483
+ registerTool(
5451
5484
  "projects_get",
5452
5485
  {
5453
5486
  title: "Get project",
@@ -5459,7 +5492,7 @@ function registerTools(server, client) {
5459
5492
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5460
5493
  }
5461
5494
  );
5462
- server.registerTool(
5495
+ registerTool(
5463
5496
  "projects_overview",
5464
5497
  {
5465
5498
  title: "Project overview",
@@ -5471,7 +5504,7 @@ function registerTools(server, client) {
5471
5504
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5472
5505
  }
5473
5506
  );
5474
- server.registerTool(
5507
+ registerTool(
5475
5508
  "projects_statistics",
5476
5509
  {
5477
5510
  title: "Project statistics",
@@ -5483,7 +5516,7 @@ function registerTools(server, client) {
5483
5516
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5484
5517
  }
5485
5518
  );
5486
- server.registerTool(
5519
+ registerTool(
5487
5520
  "projects_files",
5488
5521
  {
5489
5522
  title: "List project files",
@@ -5495,7 +5528,7 @@ function registerTools(server, client) {
5495
5528
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5496
5529
  }
5497
5530
  );
5498
- server.registerTool(
5531
+ registerTool(
5499
5532
  "projects_index_status",
5500
5533
  {
5501
5534
  title: "Index status",
@@ -5507,7 +5540,7 @@ function registerTools(server, client) {
5507
5540
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5508
5541
  }
5509
5542
  );
5510
- server.registerTool(
5543
+ registerTool(
5511
5544
  "projects_ingest_local",
5512
5545
  {
5513
5546
  title: "Ingest local files",
@@ -5551,7 +5584,7 @@ Automatically detects code files and skips ignored directories like node_modules
5551
5584
  };
5552
5585
  }
5553
5586
  );
5554
- server.registerTool(
5587
+ registerTool(
5555
5588
  "workspaces_get",
5556
5589
  {
5557
5590
  title: "Get workspace",
@@ -5563,7 +5596,7 @@ Automatically detects code files and skips ignored directories like node_modules
5563
5596
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5564
5597
  }
5565
5598
  );
5566
- server.registerTool(
5599
+ registerTool(
5567
5600
  "workspaces_overview",
5568
5601
  {
5569
5602
  title: "Workspace overview",
@@ -5575,7 +5608,7 @@ Automatically detects code files and skips ignored directories like node_modules
5575
5608
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5576
5609
  }
5577
5610
  );
5578
- server.registerTool(
5611
+ registerTool(
5579
5612
  "workspaces_analytics",
5580
5613
  {
5581
5614
  title: "Workspace analytics",
@@ -5587,7 +5620,7 @@ Automatically detects code files and skips ignored directories like node_modules
5587
5620
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5588
5621
  }
5589
5622
  );
5590
- server.registerTool(
5623
+ registerTool(
5591
5624
  "workspaces_content",
5592
5625
  {
5593
5626
  title: "Workspace content",
@@ -5599,7 +5632,7 @@ Automatically detects code files and skips ignored directories like node_modules
5599
5632
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5600
5633
  }
5601
5634
  );
5602
- server.registerTool(
5635
+ registerTool(
5603
5636
  "memory_get_event",
5604
5637
  {
5605
5638
  title: "Get memory event",
@@ -5611,7 +5644,7 @@ Automatically detects code files and skips ignored directories like node_modules
5611
5644
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5612
5645
  }
5613
5646
  );
5614
- server.registerTool(
5647
+ registerTool(
5615
5648
  "memory_update_event",
5616
5649
  {
5617
5650
  title: "Update memory event",
@@ -5629,7 +5662,7 @@ Automatically detects code files and skips ignored directories like node_modules
5629
5662
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5630
5663
  }
5631
5664
  );
5632
- server.registerTool(
5665
+ registerTool(
5633
5666
  "memory_delete_event",
5634
5667
  {
5635
5668
  title: "Delete memory event",
@@ -5641,7 +5674,7 @@ Automatically detects code files and skips ignored directories like node_modules
5641
5674
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5642
5675
  }
5643
5676
  );
5644
- server.registerTool(
5677
+ registerTool(
5645
5678
  "memory_distill_event",
5646
5679
  {
5647
5680
  title: "Distill memory event",
@@ -5653,7 +5686,7 @@ Automatically detects code files and skips ignored directories like node_modules
5653
5686
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5654
5687
  }
5655
5688
  );
5656
- server.registerTool(
5689
+ registerTool(
5657
5690
  "memory_get_node",
5658
5691
  {
5659
5692
  title: "Get knowledge node",
@@ -5665,7 +5698,7 @@ Automatically detects code files and skips ignored directories like node_modules
5665
5698
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5666
5699
  }
5667
5700
  );
5668
- server.registerTool(
5701
+ registerTool(
5669
5702
  "memory_update_node",
5670
5703
  {
5671
5704
  title: "Update knowledge node",
@@ -5683,7 +5716,7 @@ Automatically detects code files and skips ignored directories like node_modules
5683
5716
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5684
5717
  }
5685
5718
  );
5686
- server.registerTool(
5719
+ registerTool(
5687
5720
  "memory_delete_node",
5688
5721
  {
5689
5722
  title: "Delete knowledge node",
@@ -5695,7 +5728,7 @@ Automatically detects code files and skips ignored directories like node_modules
5695
5728
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5696
5729
  }
5697
5730
  );
5698
- server.registerTool(
5731
+ registerTool(
5699
5732
  "memory_supersede_node",
5700
5733
  {
5701
5734
  title: "Supersede knowledge node",
@@ -5712,7 +5745,7 @@ Automatically detects code files and skips ignored directories like node_modules
5712
5745
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5713
5746
  }
5714
5747
  );
5715
- server.registerTool(
5748
+ registerTool(
5716
5749
  "memory_timeline",
5717
5750
  {
5718
5751
  title: "Memory timeline",
@@ -5724,7 +5757,7 @@ Automatically detects code files and skips ignored directories like node_modules
5724
5757
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5725
5758
  }
5726
5759
  );
5727
- server.registerTool(
5760
+ registerTool(
5728
5761
  "memory_summary",
5729
5762
  {
5730
5763
  title: "Memory summary",
@@ -5736,7 +5769,7 @@ Automatically detects code files and skips ignored directories like node_modules
5736
5769
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5737
5770
  }
5738
5771
  );
5739
- server.registerTool(
5772
+ registerTool(
5740
5773
  "graph_circular_dependencies",
5741
5774
  {
5742
5775
  title: "Find circular dependencies",
@@ -5748,7 +5781,7 @@ Automatically detects code files and skips ignored directories like node_modules
5748
5781
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5749
5782
  }
5750
5783
  );
5751
- server.registerTool(
5784
+ registerTool(
5752
5785
  "graph_unused_code",
5753
5786
  {
5754
5787
  title: "Find unused code",
@@ -5760,7 +5793,7 @@ Automatically detects code files and skips ignored directories like node_modules
5760
5793
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5761
5794
  }
5762
5795
  );
5763
- server.registerTool(
5796
+ registerTool(
5764
5797
  "graph_contradictions",
5765
5798
  {
5766
5799
  title: "Find contradictions",
@@ -5772,7 +5805,7 @@ Automatically detects code files and skips ignored directories like node_modules
5772
5805
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5773
5806
  }
5774
5807
  );
5775
- server.registerTool(
5808
+ registerTool(
5776
5809
  "search_suggestions",
5777
5810
  {
5778
5811
  title: "Search suggestions",
@@ -5788,7 +5821,7 @@ Automatically detects code files and skips ignored directories like node_modules
5788
5821
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5789
5822
  }
5790
5823
  );
5791
- server.registerTool(
5824
+ registerTool(
5792
5825
  "session_init",
5793
5826
  {
5794
5827
  title: "Initialize conversation session",
@@ -5821,10 +5854,13 @@ IMPORTANT: If you know the current workspace folder path, pass it as folder_path
5821
5854
  ideRoots = [input.folder_path];
5822
5855
  }
5823
5856
  const result = await client.initSession(input, ideRoots);
5857
+ if (sessionManager) {
5858
+ sessionManager.markInitialized(result);
5859
+ }
5824
5860
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5825
5861
  }
5826
5862
  );
5827
- server.registerTool(
5863
+ registerTool(
5828
5864
  "session_get_user_context",
5829
5865
  {
5830
5866
  title: "Get user context and preferences",
@@ -5839,7 +5875,7 @@ Use this to understand how the user likes to work and adapt your responses accor
5839
5875
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5840
5876
  }
5841
5877
  );
5842
- server.registerTool(
5878
+ registerTool(
5843
5879
  "workspace_associate",
5844
5880
  {
5845
5881
  title: "Associate folder with workspace",
@@ -5859,7 +5895,7 @@ Optionally creates a parent folder mapping (e.g., all repos under /dev/company/*
5859
5895
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5860
5896
  }
5861
5897
  );
5862
- server.registerTool(
5898
+ registerTool(
5863
5899
  "session_capture",
5864
5900
  {
5865
5901
  title: "Capture context to memory",
@@ -5881,7 +5917,7 @@ Use this to persist decisions, insights, preferences, or important information.`
5881
5917
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5882
5918
  }
5883
5919
  );
5884
- server.registerTool(
5920
+ registerTool(
5885
5921
  "session_smart_search",
5886
5922
  {
5887
5923
  title: "Smart context search",
@@ -5900,7 +5936,7 @@ Returns memory matches, relevant code, and related decisions in one call.`,
5900
5936
  return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
5901
5937
  }
5902
5938
  );
5903
- server.registerTool(
5939
+ registerTool(
5904
5940
  "session_remember",
5905
5941
  {
5906
5942
  title: "Remember this",
@@ -5934,7 +5970,7 @@ Example: "Remember that I prefer TypeScript strict mode" or "Remember we decided
5934
5970
  return { content: [{ type: "text", text: `Remembered: ${input.content.slice(0, 100)}...` }], structuredContent: toStructured(result) };
5935
5971
  }
5936
5972
  );
5937
- server.registerTool(
5973
+ registerTool(
5938
5974
  "session_recall",
5939
5975
  {
5940
5976
  title: "Recall from memory",
@@ -6292,20 +6328,191 @@ Then synthesize the retrieved context into a coherent briefing that will help wi
6292
6328
  );
6293
6329
  }
6294
6330
 
6331
+ // src/session-manager.ts
6332
+ var SessionManager = class {
6333
+ constructor(server, client) {
6334
+ this.server = server;
6335
+ this.client = client;
6336
+ this.initialized = false;
6337
+ this.initializationPromise = null;
6338
+ this.context = null;
6339
+ this.ideRoots = [];
6340
+ this.folderPath = null;
6341
+ }
6342
+ /**
6343
+ * Check if session has been auto-initialized
6344
+ */
6345
+ isInitialized() {
6346
+ return this.initialized;
6347
+ }
6348
+ /**
6349
+ * Get the auto-loaded context (if any)
6350
+ */
6351
+ getContext() {
6352
+ return this.context;
6353
+ }
6354
+ /**
6355
+ * Mark session as manually initialized (e.g., when session_init is called explicitly)
6356
+ */
6357
+ markInitialized(context) {
6358
+ this.initialized = true;
6359
+ this.context = context;
6360
+ }
6361
+ /**
6362
+ * Set the folder path hint (can be passed from tools that know the workspace path)
6363
+ */
6364
+ setFolderPath(path3) {
6365
+ this.folderPath = path3;
6366
+ }
6367
+ /**
6368
+ * Auto-initialize the session if not already done.
6369
+ * Returns context summary to prepend to tool response.
6370
+ *
6371
+ * This is the core of the auto-context feature.
6372
+ */
6373
+ async autoInitialize() {
6374
+ if (this.initialized) {
6375
+ return null;
6376
+ }
6377
+ if (this.initializationPromise) {
6378
+ await this.initializationPromise;
6379
+ return null;
6380
+ }
6381
+ try {
6382
+ const rootsResponse = await this.server.server.listRoots();
6383
+ if (rootsResponse?.roots) {
6384
+ this.ideRoots = rootsResponse.roots.map(
6385
+ (r) => r.uri.replace("file://", "")
6386
+ );
6387
+ }
6388
+ } catch {
6389
+ }
6390
+ if (this.ideRoots.length === 0 && this.folderPath) {
6391
+ this.ideRoots = [this.folderPath];
6392
+ }
6393
+ this.initializationPromise = this._doInitialize();
6394
+ try {
6395
+ const result = await this.initializationPromise;
6396
+ return result;
6397
+ } finally {
6398
+ this.initializationPromise = null;
6399
+ }
6400
+ }
6401
+ async _doInitialize() {
6402
+ try {
6403
+ console.error("[ContextStream] Auto-initializing session context...");
6404
+ const context = await this.client.initSession(
6405
+ {
6406
+ auto_index: true,
6407
+ include_recent_memory: true,
6408
+ include_decisions: true
6409
+ },
6410
+ this.ideRoots
6411
+ );
6412
+ this.initialized = true;
6413
+ this.context = context;
6414
+ const summary = this.buildContextSummary(context);
6415
+ console.error("[ContextStream] Auto-initialization complete");
6416
+ console.error(`[ContextStream] Workspace: ${context.workspace_name || "unknown"}`);
6417
+ console.error(`[ContextStream] Project: ${context.project_id ? "loaded" : "none"}`);
6418
+ return { contextSummary: summary, context };
6419
+ } catch (error) {
6420
+ console.error("[ContextStream] Auto-initialization failed:", error);
6421
+ this.initialized = true;
6422
+ return null;
6423
+ }
6424
+ }
6425
+ /**
6426
+ * Build a concise context summary for prepending to tool responses
6427
+ */
6428
+ buildContextSummary(context) {
6429
+ const parts = [];
6430
+ parts.push("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
6431
+ parts.push("\u{1F9E0} AUTO-CONTEXT LOADED (ContextStream)");
6432
+ parts.push("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
6433
+ if (context.status === "requires_workspace_selection") {
6434
+ parts.push("");
6435
+ parts.push("\u26A0\uFE0F NEW FOLDER DETECTED");
6436
+ parts.push(`Folder: ${context.folder_name || "unknown"}`);
6437
+ parts.push("");
6438
+ parts.push("Please ask the user which workspace this belongs to:");
6439
+ const candidates = context.workspace_candidates;
6440
+ if (candidates) {
6441
+ candidates.forEach((w, i) => {
6442
+ parts.push(` ${i + 1}. ${w.name}${w.description ? ` - ${w.description}` : ""}`);
6443
+ });
6444
+ }
6445
+ parts.push(" \u2022 Or create a new workspace");
6446
+ parts.push("");
6447
+ parts.push("Use workspace_associate tool after user selects.");
6448
+ parts.push("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
6449
+ return parts.join("\n");
6450
+ }
6451
+ if (context.workspace_name) {
6452
+ parts.push(`\u{1F4C1} Workspace: ${context.workspace_name}`);
6453
+ if (context.workspace_created) {
6454
+ parts.push(" (auto-created for this folder)");
6455
+ }
6456
+ }
6457
+ if (context.project_id) {
6458
+ const project = context.project;
6459
+ parts.push(`\u{1F4C2} Project: ${project?.name || "loaded"}`);
6460
+ if (context.project_created) {
6461
+ parts.push(" (auto-created, indexing in background)");
6462
+ }
6463
+ if (context.indexing_status === "started") {
6464
+ parts.push(" \u23F3 Code indexing in progress...");
6465
+ }
6466
+ }
6467
+ const decisions = context.recent_decisions;
6468
+ if (decisions?.items && decisions.items.length > 0) {
6469
+ parts.push("");
6470
+ parts.push("\u{1F4CB} Recent Decisions:");
6471
+ decisions.items.slice(0, 3).forEach((d) => {
6472
+ const title = d.title || d.content?.slice(0, 50) || "Untitled";
6473
+ parts.push(` \u2022 ${title}`);
6474
+ });
6475
+ }
6476
+ const memory = context.recent_memory;
6477
+ if (memory?.items && memory.items.length > 0) {
6478
+ parts.push("");
6479
+ parts.push("\u{1F9E0} Recent Context:");
6480
+ memory.items.slice(0, 3).forEach((m) => {
6481
+ const title = m.title || "Note";
6482
+ const type = m.event_type || "";
6483
+ parts.push(` \u2022 [${type}] ${title}`);
6484
+ });
6485
+ }
6486
+ if (context.ide_roots && context.ide_roots.length > 0) {
6487
+ const roots = context.ide_roots;
6488
+ parts.push("");
6489
+ parts.push(`\u{1F5A5}\uFE0F IDE Roots: ${roots.map((r) => r.split("/").pop()).join(", ")}`);
6490
+ }
6491
+ parts.push("");
6492
+ parts.push("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
6493
+ parts.push("Use session_remember to save important context.");
6494
+ parts.push("Use session_recall to retrieve past context.");
6495
+ parts.push("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
6496
+ return parts.join("\n");
6497
+ }
6498
+ };
6499
+
6295
6500
  // src/index.ts
6296
6501
  async function main() {
6297
6502
  const config = loadConfig();
6298
6503
  const client = new ContextStreamClient(config);
6299
6504
  const server = new McpServer({
6300
6505
  name: "contextstream-mcp",
6301
- version: "0.2.0"
6506
+ version: "0.3.0"
6302
6507
  });
6303
- registerTools(server, client);
6508
+ const sessionManager = new SessionManager(server, client);
6509
+ registerTools(server, client, sessionManager);
6304
6510
  registerResources(server, client, config.apiUrl);
6305
6511
  registerPrompts(server);
6306
6512
  console.error(`ContextStream MCP server starting...`);
6307
6513
  console.error(`API URL: ${config.apiUrl}`);
6308
6514
  console.error(`Auth: ${config.apiKey ? "API Key" : config.jwt ? "JWT" : "None"}`);
6515
+ console.error(`Auto-Context: ENABLED (context loads on first tool call)`);
6309
6516
  const transport = new StdioServerTransport();
6310
6517
  await server.connect(transport);
6311
6518
  console.error("ContextStream MCP server connected and ready");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contextstream/mcp-server",
3
- "version": "0.2.7",
3
+ "version": "0.3.0",
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",