@contextstream/mcp-server 0.2.8 → 0.3.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.
- package/README.md +22 -32
- package/dist/index.js +274 -62
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,9 +35,8 @@ 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": {
|
|
@@ -53,39 +52,30 @@ Add ContextStream to your AI tool's MCP configuration:
|
|
|
53
52
|
}
|
|
54
53
|
```
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"command": "npx",
|
|
62
|
-
"args": ["-y", "@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)
|
|
56
|
+
|
|
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.
|
|
71
60
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5973
|
+
registerTool(
|
|
5938
5974
|
"session_recall",
|
|
5939
5975
|
{
|
|
5940
5976
|
title: "Recall from memory",
|
|
@@ -6292,20 +6328,196 @@ 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
|
+
console.error("[ContextStream] listRoots response:", JSON.stringify(rootsResponse));
|
|
6384
|
+
if (rootsResponse?.roots) {
|
|
6385
|
+
this.ideRoots = rootsResponse.roots.map(
|
|
6386
|
+
(r) => r.uri.replace("file://", "")
|
|
6387
|
+
);
|
|
6388
|
+
console.error("[ContextStream] IDE roots detected:", this.ideRoots);
|
|
6389
|
+
}
|
|
6390
|
+
} catch (e) {
|
|
6391
|
+
console.error("[ContextStream] listRoots not available:", e?.message || e);
|
|
6392
|
+
}
|
|
6393
|
+
if (this.ideRoots.length === 0 && this.folderPath) {
|
|
6394
|
+
this.ideRoots = [this.folderPath];
|
|
6395
|
+
}
|
|
6396
|
+
this.initializationPromise = this._doInitialize();
|
|
6397
|
+
try {
|
|
6398
|
+
const result = await this.initializationPromise;
|
|
6399
|
+
return result;
|
|
6400
|
+
} finally {
|
|
6401
|
+
this.initializationPromise = null;
|
|
6402
|
+
}
|
|
6403
|
+
}
|
|
6404
|
+
async _doInitialize() {
|
|
6405
|
+
try {
|
|
6406
|
+
console.error("[ContextStream] Auto-initializing session context...");
|
|
6407
|
+
console.error("[ContextStream] Using IDE roots:", this.ideRoots.length > 0 ? this.ideRoots : "(none - will use fallback)");
|
|
6408
|
+
const context = await this.client.initSession(
|
|
6409
|
+
{
|
|
6410
|
+
auto_index: true,
|
|
6411
|
+
include_recent_memory: true,
|
|
6412
|
+
include_decisions: true
|
|
6413
|
+
},
|
|
6414
|
+
this.ideRoots
|
|
6415
|
+
);
|
|
6416
|
+
this.initialized = true;
|
|
6417
|
+
this.context = context;
|
|
6418
|
+
console.error("[ContextStream] Workspace resolved:", context.workspace_name, "(source:", context.workspace_source, ")");
|
|
6419
|
+
const summary = this.buildContextSummary(context);
|
|
6420
|
+
console.error("[ContextStream] Auto-initialization complete");
|
|
6421
|
+
console.error(`[ContextStream] Workspace: ${context.workspace_name || "unknown"}`);
|
|
6422
|
+
console.error(`[ContextStream] Project: ${context.project_id ? "loaded" : "none"}`);
|
|
6423
|
+
return { contextSummary: summary, context };
|
|
6424
|
+
} catch (error) {
|
|
6425
|
+
console.error("[ContextStream] Auto-initialization failed:", error);
|
|
6426
|
+
this.initialized = true;
|
|
6427
|
+
return null;
|
|
6428
|
+
}
|
|
6429
|
+
}
|
|
6430
|
+
/**
|
|
6431
|
+
* Build a concise context summary for prepending to tool responses
|
|
6432
|
+
*/
|
|
6433
|
+
buildContextSummary(context) {
|
|
6434
|
+
const parts = [];
|
|
6435
|
+
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");
|
|
6436
|
+
parts.push("\u{1F9E0} AUTO-CONTEXT LOADED (ContextStream)");
|
|
6437
|
+
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");
|
|
6438
|
+
if (context.status === "requires_workspace_selection") {
|
|
6439
|
+
parts.push("");
|
|
6440
|
+
parts.push("\u26A0\uFE0F NEW FOLDER DETECTED");
|
|
6441
|
+
parts.push(`Folder: ${context.folder_name || "unknown"}`);
|
|
6442
|
+
parts.push("");
|
|
6443
|
+
parts.push("Please ask the user which workspace this belongs to:");
|
|
6444
|
+
const candidates = context.workspace_candidates;
|
|
6445
|
+
if (candidates) {
|
|
6446
|
+
candidates.forEach((w, i) => {
|
|
6447
|
+
parts.push(` ${i + 1}. ${w.name}${w.description ? ` - ${w.description}` : ""}`);
|
|
6448
|
+
});
|
|
6449
|
+
}
|
|
6450
|
+
parts.push(" \u2022 Or create a new workspace");
|
|
6451
|
+
parts.push("");
|
|
6452
|
+
parts.push("Use workspace_associate tool after user selects.");
|
|
6453
|
+
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");
|
|
6454
|
+
return parts.join("\n");
|
|
6455
|
+
}
|
|
6456
|
+
if (context.workspace_name) {
|
|
6457
|
+
parts.push(`\u{1F4C1} Workspace: ${context.workspace_name}`);
|
|
6458
|
+
if (context.workspace_created) {
|
|
6459
|
+
parts.push(" (auto-created for this folder)");
|
|
6460
|
+
}
|
|
6461
|
+
}
|
|
6462
|
+
if (context.project_id) {
|
|
6463
|
+
const project = context.project;
|
|
6464
|
+
parts.push(`\u{1F4C2} Project: ${project?.name || "loaded"}`);
|
|
6465
|
+
if (context.project_created) {
|
|
6466
|
+
parts.push(" (auto-created, indexing in background)");
|
|
6467
|
+
}
|
|
6468
|
+
if (context.indexing_status === "started") {
|
|
6469
|
+
parts.push(" \u23F3 Code indexing in progress...");
|
|
6470
|
+
}
|
|
6471
|
+
}
|
|
6472
|
+
const decisions = context.recent_decisions;
|
|
6473
|
+
if (decisions?.items && decisions.items.length > 0) {
|
|
6474
|
+
parts.push("");
|
|
6475
|
+
parts.push("\u{1F4CB} Recent Decisions:");
|
|
6476
|
+
decisions.items.slice(0, 3).forEach((d) => {
|
|
6477
|
+
const title = d.title || d.content?.slice(0, 50) || "Untitled";
|
|
6478
|
+
parts.push(` \u2022 ${title}`);
|
|
6479
|
+
});
|
|
6480
|
+
}
|
|
6481
|
+
const memory = context.recent_memory;
|
|
6482
|
+
if (memory?.items && memory.items.length > 0) {
|
|
6483
|
+
parts.push("");
|
|
6484
|
+
parts.push("\u{1F9E0} Recent Context:");
|
|
6485
|
+
memory.items.slice(0, 3).forEach((m) => {
|
|
6486
|
+
const title = m.title || "Note";
|
|
6487
|
+
const type = m.event_type || "";
|
|
6488
|
+
parts.push(` \u2022 [${type}] ${title}`);
|
|
6489
|
+
});
|
|
6490
|
+
}
|
|
6491
|
+
if (context.ide_roots && context.ide_roots.length > 0) {
|
|
6492
|
+
const roots = context.ide_roots;
|
|
6493
|
+
parts.push("");
|
|
6494
|
+
parts.push(`\u{1F5A5}\uFE0F IDE Roots: ${roots.map((r) => r.split("/").pop()).join(", ")}`);
|
|
6495
|
+
}
|
|
6496
|
+
parts.push("");
|
|
6497
|
+
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");
|
|
6498
|
+
parts.push("Use session_remember to save important context.");
|
|
6499
|
+
parts.push("Use session_recall to retrieve past context.");
|
|
6500
|
+
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");
|
|
6501
|
+
return parts.join("\n");
|
|
6502
|
+
}
|
|
6503
|
+
};
|
|
6504
|
+
|
|
6295
6505
|
// src/index.ts
|
|
6296
6506
|
async function main() {
|
|
6297
6507
|
const config = loadConfig();
|
|
6298
6508
|
const client = new ContextStreamClient(config);
|
|
6299
6509
|
const server = new McpServer({
|
|
6300
6510
|
name: "contextstream-mcp",
|
|
6301
|
-
version: "0.
|
|
6511
|
+
version: "0.3.1"
|
|
6302
6512
|
});
|
|
6303
|
-
|
|
6513
|
+
const sessionManager = new SessionManager(server, client);
|
|
6514
|
+
registerTools(server, client, sessionManager);
|
|
6304
6515
|
registerResources(server, client, config.apiUrl);
|
|
6305
6516
|
registerPrompts(server);
|
|
6306
6517
|
console.error(`ContextStream MCP server starting...`);
|
|
6307
6518
|
console.error(`API URL: ${config.apiUrl}`);
|
|
6308
6519
|
console.error(`Auth: ${config.apiKey ? "API Key" : config.jwt ? "JWT" : "None"}`);
|
|
6520
|
+
console.error(`Auto-Context: ENABLED (context loads on first tool call)`);
|
|
6309
6521
|
const transport = new StdioServerTransport();
|
|
6310
6522
|
await server.connect(transport);
|
|
6311
6523
|
console.error("ContextStream MCP server connected and ready");
|
package/package.json
CHANGED