@contextstream/mcp-server 0.4.35 → 0.4.36
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/dist/index.js +219 -134
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -4571,10 +4571,16 @@ var IGNORE_FILES = /* @__PURE__ */ new Set([
|
|
|
4571
4571
|
"composer.lock"
|
|
4572
4572
|
]);
|
|
4573
4573
|
var MAX_FILE_SIZE = 1024 * 1024;
|
|
4574
|
+
var MAX_BATCH_BYTES = 10 * 1024 * 1024;
|
|
4575
|
+
var LARGE_FILE_THRESHOLD = 2 * 1024 * 1024;
|
|
4576
|
+
var MAX_FILES_PER_BATCH = 200;
|
|
4574
4577
|
async function* readAllFilesInBatches(rootPath, options = {}) {
|
|
4575
|
-
const
|
|
4578
|
+
const maxBatchBytes = options.maxBatchBytes ?? MAX_BATCH_BYTES;
|
|
4579
|
+
const largeFileThreshold = options.largeFileThreshold ?? LARGE_FILE_THRESHOLD;
|
|
4580
|
+
const maxFilesPerBatch = options.maxFilesPerBatch ?? MAX_FILES_PER_BATCH;
|
|
4576
4581
|
const maxFileSize = options.maxFileSize ?? MAX_FILE_SIZE;
|
|
4577
4582
|
let batch = [];
|
|
4583
|
+
let currentBatchBytes = 0;
|
|
4578
4584
|
async function* walkDir(dir, relativePath = "") {
|
|
4579
4585
|
let entries;
|
|
4580
4586
|
try {
|
|
@@ -4596,28 +4602,46 @@ async function* readAllFilesInBatches(rootPath, options = {}) {
|
|
|
4596
4602
|
const stat2 = await fs.promises.stat(fullPath);
|
|
4597
4603
|
if (stat2.size > maxFileSize) continue;
|
|
4598
4604
|
const content = await fs.promises.readFile(fullPath, "utf-8");
|
|
4599
|
-
yield { path: relPath, content };
|
|
4605
|
+
yield { path: relPath, content, sizeBytes: stat2.size };
|
|
4600
4606
|
} catch {
|
|
4601
4607
|
}
|
|
4602
4608
|
}
|
|
4603
4609
|
}
|
|
4604
4610
|
}
|
|
4605
4611
|
for await (const file of walkDir(rootPath)) {
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4612
|
+
if (file.sizeBytes > largeFileThreshold) {
|
|
4613
|
+
if (batch.length > 0) {
|
|
4614
|
+
yield batch.map(({ sizeBytes, ...rest }) => rest);
|
|
4615
|
+
batch = [];
|
|
4616
|
+
currentBatchBytes = 0;
|
|
4617
|
+
}
|
|
4618
|
+
yield [{ path: file.path, content: file.content }];
|
|
4619
|
+
continue;
|
|
4610
4620
|
}
|
|
4621
|
+
const wouldExceedBytes = currentBatchBytes + file.sizeBytes > maxBatchBytes;
|
|
4622
|
+
const wouldExceedFiles = batch.length >= maxFilesPerBatch;
|
|
4623
|
+
if (wouldExceedBytes || wouldExceedFiles) {
|
|
4624
|
+
if (batch.length > 0) {
|
|
4625
|
+
yield batch.map(({ sizeBytes, ...rest }) => rest);
|
|
4626
|
+
batch = [];
|
|
4627
|
+
currentBatchBytes = 0;
|
|
4628
|
+
}
|
|
4629
|
+
}
|
|
4630
|
+
batch.push(file);
|
|
4631
|
+
currentBatchBytes += file.sizeBytes;
|
|
4611
4632
|
}
|
|
4612
4633
|
if (batch.length > 0) {
|
|
4613
|
-
yield batch;
|
|
4634
|
+
yield batch.map(({ sizeBytes, ...rest }) => rest);
|
|
4614
4635
|
}
|
|
4615
4636
|
}
|
|
4616
4637
|
async function* readChangedFilesInBatches(rootPath, sinceTimestamp, options = {}) {
|
|
4617
|
-
const
|
|
4638
|
+
const maxBatchBytes = options.maxBatchBytes ?? MAX_BATCH_BYTES;
|
|
4639
|
+
const largeFileThreshold = options.largeFileThreshold ?? LARGE_FILE_THRESHOLD;
|
|
4640
|
+
const maxFilesPerBatch = options.maxFilesPerBatch ?? MAX_FILES_PER_BATCH;
|
|
4618
4641
|
const maxFileSize = options.maxFileSize ?? MAX_FILE_SIZE;
|
|
4619
4642
|
const sinceMs = sinceTimestamp.getTime();
|
|
4620
4643
|
let batch = [];
|
|
4644
|
+
let currentBatchBytes = 0;
|
|
4621
4645
|
let filesScanned = 0;
|
|
4622
4646
|
let filesChanged = 0;
|
|
4623
4647
|
async function* walkDir(dir, relativePath = "") {
|
|
@@ -4644,21 +4668,36 @@ async function* readChangedFilesInBatches(rootPath, sinceTimestamp, options = {}
|
|
|
4644
4668
|
if (stat2.size > maxFileSize) continue;
|
|
4645
4669
|
const content = await fs.promises.readFile(fullPath, "utf-8");
|
|
4646
4670
|
filesChanged++;
|
|
4647
|
-
yield { path: relPath, content };
|
|
4671
|
+
yield { path: relPath, content, sizeBytes: stat2.size };
|
|
4648
4672
|
} catch {
|
|
4649
4673
|
}
|
|
4650
4674
|
}
|
|
4651
4675
|
}
|
|
4652
4676
|
}
|
|
4653
4677
|
for await (const file of walkDir(rootPath)) {
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4678
|
+
if (file.sizeBytes > largeFileThreshold) {
|
|
4679
|
+
if (batch.length > 0) {
|
|
4680
|
+
yield batch.map(({ sizeBytes, ...rest }) => rest);
|
|
4681
|
+
batch = [];
|
|
4682
|
+
currentBatchBytes = 0;
|
|
4683
|
+
}
|
|
4684
|
+
yield [{ path: file.path, content: file.content }];
|
|
4685
|
+
continue;
|
|
4686
|
+
}
|
|
4687
|
+
const wouldExceedBytes = currentBatchBytes + file.sizeBytes > maxBatchBytes;
|
|
4688
|
+
const wouldExceedFiles = batch.length >= maxFilesPerBatch;
|
|
4689
|
+
if (wouldExceedBytes || wouldExceedFiles) {
|
|
4690
|
+
if (batch.length > 0) {
|
|
4691
|
+
yield batch.map(({ sizeBytes, ...rest }) => rest);
|
|
4692
|
+
batch = [];
|
|
4693
|
+
currentBatchBytes = 0;
|
|
4694
|
+
}
|
|
4658
4695
|
}
|
|
4696
|
+
batch.push(file);
|
|
4697
|
+
currentBatchBytes += file.sizeBytes;
|
|
4659
4698
|
}
|
|
4660
4699
|
if (batch.length > 0) {
|
|
4661
|
-
yield batch;
|
|
4700
|
+
yield batch.map(({ sizeBytes, ...rest }) => rest);
|
|
4662
4701
|
}
|
|
4663
4702
|
console.error(
|
|
4664
4703
|
`[ContextStream] Incremental scan: ${filesChanged} changed files out of ${filesScanned} scanned (since ${sinceTimestamp.toISOString()})`
|
|
@@ -5078,7 +5117,7 @@ var ContextStreamClient = class {
|
|
|
5078
5117
|
return "full";
|
|
5079
5118
|
}
|
|
5080
5119
|
if (planName.includes("pro")) return "lite";
|
|
5081
|
-
if (planName.includes("free")) return "
|
|
5120
|
+
if (planName.includes("free")) return "lite";
|
|
5082
5121
|
return "lite";
|
|
5083
5122
|
} catch {
|
|
5084
5123
|
return "none";
|
|
@@ -6610,19 +6649,6 @@ var ContextStreamClient = class {
|
|
|
6610
6649
|
used += next.length;
|
|
6611
6650
|
}
|
|
6612
6651
|
const summary = finalLines.join("\n");
|
|
6613
|
-
this.trackTokenSavings({
|
|
6614
|
-
tool: "session_summary",
|
|
6615
|
-
workspace_id: withDefaults.workspace_id,
|
|
6616
|
-
project_id: withDefaults.project_id,
|
|
6617
|
-
candidate_chars: candidateSummary.length,
|
|
6618
|
-
context_chars: summary.length,
|
|
6619
|
-
max_tokens: maxTokens,
|
|
6620
|
-
metadata: {
|
|
6621
|
-
decision_count: decisionCount,
|
|
6622
|
-
memory_count: memoryCount
|
|
6623
|
-
}
|
|
6624
|
-
}).catch(() => {
|
|
6625
|
-
});
|
|
6626
6652
|
return {
|
|
6627
6653
|
summary,
|
|
6628
6654
|
workspace_name: workspaceName,
|
|
@@ -6864,21 +6890,6 @@ var ContextStreamClient = class {
|
|
|
6864
6890
|
const context = parts.join("");
|
|
6865
6891
|
const candidateContext = candidateParts.join("");
|
|
6866
6892
|
const tokenEstimate = Math.ceil(context.length / charsPerToken);
|
|
6867
|
-
this.trackTokenSavings({
|
|
6868
|
-
tool: "ai_context_budget",
|
|
6869
|
-
workspace_id: withDefaults.workspace_id,
|
|
6870
|
-
project_id: withDefaults.project_id,
|
|
6871
|
-
candidate_chars: candidateContext.length,
|
|
6872
|
-
context_chars: context.length,
|
|
6873
|
-
max_tokens: maxTokens,
|
|
6874
|
-
metadata: {
|
|
6875
|
-
include_decisions: params.include_decisions !== false,
|
|
6876
|
-
include_memory: params.include_memory !== false,
|
|
6877
|
-
include_code: !!params.include_code,
|
|
6878
|
-
sources: sources.length
|
|
6879
|
-
}
|
|
6880
|
-
}).catch(() => {
|
|
6881
|
-
});
|
|
6882
6893
|
return {
|
|
6883
6894
|
context,
|
|
6884
6895
|
token_estimate: tokenEstimate,
|
|
@@ -7222,21 +7233,6 @@ W:${wsHint}
|
|
|
7222
7233
|
versionNotice = await getUpdateNotice();
|
|
7223
7234
|
} catch {
|
|
7224
7235
|
}
|
|
7225
|
-
this.trackTokenSavings({
|
|
7226
|
-
tool: "context_smart",
|
|
7227
|
-
workspace_id: withDefaults.workspace_id,
|
|
7228
|
-
project_id: withDefaults.project_id,
|
|
7229
|
-
candidate_chars: candidateContext.length,
|
|
7230
|
-
context_chars: context.length,
|
|
7231
|
-
max_tokens: maxTokens,
|
|
7232
|
-
metadata: {
|
|
7233
|
-
format,
|
|
7234
|
-
items: items.length,
|
|
7235
|
-
keywords: keywords.slice(0, 10),
|
|
7236
|
-
errors: errors.length
|
|
7237
|
-
}
|
|
7238
|
-
}).catch(() => {
|
|
7239
|
-
});
|
|
7240
7236
|
return {
|
|
7241
7237
|
context,
|
|
7242
7238
|
token_estimate: Math.ceil(context.length / 4),
|
|
@@ -7885,6 +7881,29 @@ W:${wsHint}
|
|
|
7885
7881
|
{ method: "GET" }
|
|
7886
7882
|
);
|
|
7887
7883
|
}
|
|
7884
|
+
/**
|
|
7885
|
+
* Create a new Notion database
|
|
7886
|
+
*/
|
|
7887
|
+
async notionCreateDatabase(params) {
|
|
7888
|
+
const withDefaults = this.withDefaults(params || {});
|
|
7889
|
+
if (!withDefaults.workspace_id) {
|
|
7890
|
+
throw new Error("workspace_id is required for creating Notion database");
|
|
7891
|
+
}
|
|
7892
|
+
const query = new URLSearchParams();
|
|
7893
|
+
query.set("workspace_id", withDefaults.workspace_id);
|
|
7894
|
+
return request(
|
|
7895
|
+
this.config,
|
|
7896
|
+
`/integrations/notion/databases?${query.toString()}`,
|
|
7897
|
+
{
|
|
7898
|
+
method: "POST",
|
|
7899
|
+
body: {
|
|
7900
|
+
title: params.title,
|
|
7901
|
+
parent_page_id: params.parent_page_id,
|
|
7902
|
+
description: params.description
|
|
7903
|
+
}
|
|
7904
|
+
}
|
|
7905
|
+
);
|
|
7906
|
+
}
|
|
7888
7907
|
/**
|
|
7889
7908
|
* Search/list pages in Notion with smart type detection filtering
|
|
7890
7909
|
*/
|
|
@@ -9235,6 +9254,69 @@ async function markProjectIndexed(projectPath, options) {
|
|
|
9235
9254
|
await writeIndexStatus(status);
|
|
9236
9255
|
}
|
|
9237
9256
|
|
|
9257
|
+
// src/token-savings.ts
|
|
9258
|
+
var TOKEN_SAVINGS_FORMULA_VERSION = 1;
|
|
9259
|
+
var MAX_CHARS_PER_EVENT = 2e7;
|
|
9260
|
+
var BASE_OVERHEAD_CHARS = 500;
|
|
9261
|
+
var CANDIDATE_MULTIPLIERS = {
|
|
9262
|
+
// context_smart: Replaces reading multiple files to gather context
|
|
9263
|
+
context_smart: 5,
|
|
9264
|
+
ai_context_budget: 5,
|
|
9265
|
+
// search: Semantic search replaces iterative Glob/Grep/Read cycles
|
|
9266
|
+
search_semantic: 4.5,
|
|
9267
|
+
search_hybrid: 4,
|
|
9268
|
+
search_keyword: 2.5,
|
|
9269
|
+
search_pattern: 3,
|
|
9270
|
+
search_exhaustive: 3.5,
|
|
9271
|
+
search_refactor: 3,
|
|
9272
|
+
// session: Recall/search replaces reading through history
|
|
9273
|
+
session_recall: 5,
|
|
9274
|
+
session_smart_search: 4,
|
|
9275
|
+
session_user_context: 3,
|
|
9276
|
+
session_summary: 4,
|
|
9277
|
+
// graph: Would require extensive file traversal
|
|
9278
|
+
graph_dependencies: 8,
|
|
9279
|
+
graph_impact: 10,
|
|
9280
|
+
graph_call_path: 8,
|
|
9281
|
+
graph_related: 6,
|
|
9282
|
+
// memory: Context retrieval
|
|
9283
|
+
memory_search: 3.5,
|
|
9284
|
+
memory_decisions: 3,
|
|
9285
|
+
memory_timeline: 3,
|
|
9286
|
+
memory_summary: 4
|
|
9287
|
+
};
|
|
9288
|
+
function clampCharCount(value) {
|
|
9289
|
+
if (!Number.isFinite(value) || value <= 0) return 0;
|
|
9290
|
+
return Math.min(MAX_CHARS_PER_EVENT, Math.floor(value));
|
|
9291
|
+
}
|
|
9292
|
+
function trackToolTokenSavings(client, tool, contextText, params, extraMetadata) {
|
|
9293
|
+
try {
|
|
9294
|
+
const contextChars = clampCharCount(contextText.length);
|
|
9295
|
+
const multiplier = CANDIDATE_MULTIPLIERS[tool] ?? 3;
|
|
9296
|
+
const baseOverhead = contextChars > 0 ? BASE_OVERHEAD_CHARS : 0;
|
|
9297
|
+
const estimatedCandidate = Math.round(contextChars * multiplier + baseOverhead);
|
|
9298
|
+
const candidateChars = Math.max(contextChars, clampCharCount(estimatedCandidate));
|
|
9299
|
+
client.trackTokenSavings({
|
|
9300
|
+
tool,
|
|
9301
|
+
workspace_id: params?.workspace_id,
|
|
9302
|
+
project_id: params?.project_id,
|
|
9303
|
+
candidate_chars: candidateChars,
|
|
9304
|
+
context_chars: contextChars,
|
|
9305
|
+
max_tokens: params?.max_tokens,
|
|
9306
|
+
metadata: {
|
|
9307
|
+
method: "multiplier_estimate",
|
|
9308
|
+
formula_version: TOKEN_SAVINGS_FORMULA_VERSION,
|
|
9309
|
+
source: "mcp-server",
|
|
9310
|
+
multiplier,
|
|
9311
|
+
base_overhead_chars: baseOverhead,
|
|
9312
|
+
...extraMetadata ?? {}
|
|
9313
|
+
}
|
|
9314
|
+
}).catch(() => {
|
|
9315
|
+
});
|
|
9316
|
+
} catch {
|
|
9317
|
+
}
|
|
9318
|
+
}
|
|
9319
|
+
|
|
9238
9320
|
// src/tools.ts
|
|
9239
9321
|
var LESSON_DEDUP_WINDOW_MS = 2 * 60 * 1e3;
|
|
9240
9322
|
var recentLessonCaptures = /* @__PURE__ */ new Map();
|
|
@@ -10587,52 +10669,6 @@ function toStructured(data) {
|
|
|
10587
10669
|
}
|
|
10588
10670
|
return void 0;
|
|
10589
10671
|
}
|
|
10590
|
-
var CANDIDATE_MULTIPLIERS = {
|
|
10591
|
-
// context_smart: Replaces reading multiple files to gather context
|
|
10592
|
-
context_smart: 5,
|
|
10593
|
-
// search: Semantic search replaces iterative Glob/Grep/Read cycles
|
|
10594
|
-
search_semantic: 4.5,
|
|
10595
|
-
search_hybrid: 4,
|
|
10596
|
-
search_keyword: 2.5,
|
|
10597
|
-
search_pattern: 3,
|
|
10598
|
-
search_exhaustive: 3.5,
|
|
10599
|
-
search_refactor: 3,
|
|
10600
|
-
// session: Recall/search replaces reading through history
|
|
10601
|
-
session_recall: 5,
|
|
10602
|
-
session_smart_search: 4,
|
|
10603
|
-
session_user_context: 3,
|
|
10604
|
-
session_summary: 4,
|
|
10605
|
-
// graph: Would require extensive file traversal
|
|
10606
|
-
graph_dependencies: 8,
|
|
10607
|
-
graph_impact: 10,
|
|
10608
|
-
graph_call_path: 8,
|
|
10609
|
-
graph_related: 6,
|
|
10610
|
-
// memory: Context retrieval
|
|
10611
|
-
memory_search: 3.5,
|
|
10612
|
-
memory_decisions: 3,
|
|
10613
|
-
memory_timeline: 3,
|
|
10614
|
-
memory_summary: 4
|
|
10615
|
-
};
|
|
10616
|
-
function trackToolTokenSavings(client, tool, resultContent, params) {
|
|
10617
|
-
try {
|
|
10618
|
-
const contextStr = typeof resultContent === "string" ? resultContent : JSON.stringify(resultContent ?? {});
|
|
10619
|
-
const contextChars = contextStr.length;
|
|
10620
|
-
const multiplier = CANDIDATE_MULTIPLIERS[tool] ?? 3;
|
|
10621
|
-
const baseOverhead = 500;
|
|
10622
|
-
const candidateChars = Math.round(contextChars * multiplier + baseOverhead);
|
|
10623
|
-
client.trackTokenSavings({
|
|
10624
|
-
tool,
|
|
10625
|
-
workspace_id: params?.workspace_id,
|
|
10626
|
-
project_id: params?.project_id,
|
|
10627
|
-
candidate_chars: candidateChars,
|
|
10628
|
-
context_chars: contextChars,
|
|
10629
|
-
max_tokens: params?.max_tokens,
|
|
10630
|
-
metadata: { multiplier, source: "mcp-server" }
|
|
10631
|
-
}).catch(() => {
|
|
10632
|
-
});
|
|
10633
|
-
} catch {
|
|
10634
|
-
}
|
|
10635
|
-
}
|
|
10636
10672
|
function readStatNumber(payload, key) {
|
|
10637
10673
|
if (!payload || typeof payload !== "object") return void 0;
|
|
10638
10674
|
const direct = payload[key];
|
|
@@ -10876,7 +10912,8 @@ function registerTools(server, client, sessionManager) {
|
|
|
10876
10912
|
["graph_call_path", "full"],
|
|
10877
10913
|
["graph_circular_dependencies", "full"],
|
|
10878
10914
|
["graph_unused_code", "full"],
|
|
10879
|
-
["graph_ingest", "
|
|
10915
|
+
["graph_ingest", "lite"],
|
|
10916
|
+
// Pro can ingest (builds module-level graph), Elite gets full graph
|
|
10880
10917
|
["graph_contradictions", "full"]
|
|
10881
10918
|
]);
|
|
10882
10919
|
const graphLiteMaxDepth = 1;
|
|
@@ -15372,12 +15409,13 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
15372
15409
|
default:
|
|
15373
15410
|
toolType = "search_hybrid";
|
|
15374
15411
|
}
|
|
15375
|
-
|
|
15412
|
+
const outputText = formatContent(result);
|
|
15413
|
+
trackToolTokenSavings(client, toolType, outputText, {
|
|
15376
15414
|
workspace_id: params.workspace_id,
|
|
15377
15415
|
project_id: params.project_id
|
|
15378
15416
|
});
|
|
15379
15417
|
return {
|
|
15380
|
-
content: [{ type: "text", text:
|
|
15418
|
+
content: [{ type: "text", text: outputText }],
|
|
15381
15419
|
structuredContent: toStructured(result)
|
|
15382
15420
|
};
|
|
15383
15421
|
}
|
|
@@ -15588,12 +15626,13 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
15588
15626
|
include_related: input.include_related,
|
|
15589
15627
|
include_decisions: input.include_decisions
|
|
15590
15628
|
});
|
|
15591
|
-
|
|
15629
|
+
const outputText = formatContent(result);
|
|
15630
|
+
trackToolTokenSavings(client, "session_recall", outputText, {
|
|
15592
15631
|
workspace_id: workspaceId,
|
|
15593
15632
|
project_id: projectId
|
|
15594
15633
|
});
|
|
15595
15634
|
return {
|
|
15596
|
-
content: [{ type: "text", text:
|
|
15635
|
+
content: [{ type: "text", text: outputText }],
|
|
15597
15636
|
structuredContent: toStructured(result)
|
|
15598
15637
|
};
|
|
15599
15638
|
}
|
|
@@ -15615,11 +15654,12 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
15615
15654
|
}
|
|
15616
15655
|
case "user_context": {
|
|
15617
15656
|
const result = await client.getUserContext({ workspace_id: workspaceId });
|
|
15618
|
-
|
|
15657
|
+
const outputText = formatContent(result);
|
|
15658
|
+
trackToolTokenSavings(client, "session_user_context", outputText, {
|
|
15619
15659
|
workspace_id: workspaceId
|
|
15620
15660
|
});
|
|
15621
15661
|
return {
|
|
15622
|
-
content: [{ type: "text", text:
|
|
15662
|
+
content: [{ type: "text", text: outputText }],
|
|
15623
15663
|
structuredContent: toStructured(result)
|
|
15624
15664
|
};
|
|
15625
15665
|
}
|
|
@@ -15629,13 +15669,14 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
15629
15669
|
project_id: projectId,
|
|
15630
15670
|
max_tokens: input.max_tokens
|
|
15631
15671
|
});
|
|
15632
|
-
|
|
15672
|
+
const outputText = formatContent(result);
|
|
15673
|
+
trackToolTokenSavings(client, "session_summary", outputText, {
|
|
15633
15674
|
workspace_id: workspaceId,
|
|
15634
15675
|
project_id: projectId,
|
|
15635
15676
|
max_tokens: input.max_tokens
|
|
15636
15677
|
});
|
|
15637
15678
|
return {
|
|
15638
|
-
content: [{ type: "text", text:
|
|
15679
|
+
content: [{ type: "text", text: outputText }],
|
|
15639
15680
|
structuredContent: toStructured(result)
|
|
15640
15681
|
};
|
|
15641
15682
|
}
|
|
@@ -15679,12 +15720,13 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
15679
15720
|
include_decisions: input.include_decisions,
|
|
15680
15721
|
include_related: input.include_related
|
|
15681
15722
|
});
|
|
15682
|
-
|
|
15723
|
+
const outputText = formatContent(result);
|
|
15724
|
+
trackToolTokenSavings(client, "session_smart_search", outputText, {
|
|
15683
15725
|
workspace_id: workspaceId,
|
|
15684
15726
|
project_id: projectId
|
|
15685
15727
|
});
|
|
15686
15728
|
return {
|
|
15687
|
-
content: [{ type: "text", text:
|
|
15729
|
+
content: [{ type: "text", text: outputText }],
|
|
15688
15730
|
structuredContent: toStructured(result)
|
|
15689
15731
|
};
|
|
15690
15732
|
}
|
|
@@ -16031,12 +16073,13 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
16031
16073
|
query: input.query,
|
|
16032
16074
|
limit: input.limit
|
|
16033
16075
|
});
|
|
16034
|
-
|
|
16076
|
+
const outputText = formatContent(result);
|
|
16077
|
+
trackToolTokenSavings(client, "memory_search", outputText, {
|
|
16035
16078
|
workspace_id: workspaceId,
|
|
16036
16079
|
project_id: projectId
|
|
16037
16080
|
});
|
|
16038
16081
|
return {
|
|
16039
|
-
content: [{ type: "text", text:
|
|
16082
|
+
content: [{ type: "text", text: outputText }],
|
|
16040
16083
|
structuredContent: toStructured(result)
|
|
16041
16084
|
};
|
|
16042
16085
|
}
|
|
@@ -16047,12 +16090,13 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
16047
16090
|
category: input.category,
|
|
16048
16091
|
limit: input.limit
|
|
16049
16092
|
});
|
|
16050
|
-
|
|
16093
|
+
const outputText = formatContent(result);
|
|
16094
|
+
trackToolTokenSavings(client, "memory_decisions", outputText, {
|
|
16051
16095
|
workspace_id: workspaceId,
|
|
16052
16096
|
project_id: projectId
|
|
16053
16097
|
});
|
|
16054
16098
|
return {
|
|
16055
|
-
content: [{ type: "text", text:
|
|
16099
|
+
content: [{ type: "text", text: outputText }],
|
|
16056
16100
|
structuredContent: toStructured(result)
|
|
16057
16101
|
};
|
|
16058
16102
|
}
|
|
@@ -16061,11 +16105,12 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
16061
16105
|
return errorResult("timeline requires workspace_id. Call session_init first.");
|
|
16062
16106
|
}
|
|
16063
16107
|
const result = await client.memoryTimeline(workspaceId);
|
|
16064
|
-
|
|
16108
|
+
const outputText = formatContent(result);
|
|
16109
|
+
trackToolTokenSavings(client, "memory_timeline", outputText, {
|
|
16065
16110
|
workspace_id: workspaceId
|
|
16066
16111
|
});
|
|
16067
16112
|
return {
|
|
16068
|
-
content: [{ type: "text", text:
|
|
16113
|
+
content: [{ type: "text", text: outputText }],
|
|
16069
16114
|
structuredContent: toStructured(result)
|
|
16070
16115
|
};
|
|
16071
16116
|
}
|
|
@@ -16074,11 +16119,12 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
16074
16119
|
return errorResult("summary requires workspace_id. Call session_init first.");
|
|
16075
16120
|
}
|
|
16076
16121
|
const result = await client.memorySummary(workspaceId);
|
|
16077
|
-
|
|
16122
|
+
const outputText = formatContent(result);
|
|
16123
|
+
trackToolTokenSavings(client, "memory_summary", outputText, {
|
|
16078
16124
|
workspace_id: workspaceId
|
|
16079
16125
|
});
|
|
16080
16126
|
return {
|
|
16081
|
-
content: [{ type: "text", text:
|
|
16127
|
+
content: [{ type: "text", text: outputText }],
|
|
16082
16128
|
structuredContent: toStructured(result)
|
|
16083
16129
|
};
|
|
16084
16130
|
}
|
|
@@ -16263,12 +16309,13 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
16263
16309
|
max_depth: input.max_depth,
|
|
16264
16310
|
include_transitive: input.include_transitive
|
|
16265
16311
|
});
|
|
16266
|
-
|
|
16312
|
+
const outputText = formatContent(result);
|
|
16313
|
+
trackToolTokenSavings(client, "graph_dependencies", outputText, {
|
|
16267
16314
|
workspace_id: workspaceId,
|
|
16268
16315
|
project_id: projectId
|
|
16269
16316
|
});
|
|
16270
16317
|
return {
|
|
16271
|
-
content: [{ type: "text", text:
|
|
16318
|
+
content: [{ type: "text", text: outputText }],
|
|
16272
16319
|
structuredContent: toStructured(result)
|
|
16273
16320
|
};
|
|
16274
16321
|
}
|
|
@@ -16280,12 +16327,13 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
16280
16327
|
target: input.target,
|
|
16281
16328
|
max_depth: input.max_depth
|
|
16282
16329
|
});
|
|
16283
|
-
|
|
16330
|
+
const outputText = formatContent(result);
|
|
16331
|
+
trackToolTokenSavings(client, "graph_impact", outputText, {
|
|
16284
16332
|
workspace_id: workspaceId,
|
|
16285
16333
|
project_id: projectId
|
|
16286
16334
|
});
|
|
16287
16335
|
return {
|
|
16288
|
-
content: [{ type: "text", text:
|
|
16336
|
+
content: [{ type: "text", text: outputText }],
|
|
16289
16337
|
structuredContent: toStructured(result)
|
|
16290
16338
|
};
|
|
16291
16339
|
}
|
|
@@ -16298,12 +16346,13 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
16298
16346
|
target: input.target,
|
|
16299
16347
|
max_depth: input.max_depth
|
|
16300
16348
|
});
|
|
16301
|
-
|
|
16349
|
+
const outputText = formatContent(result);
|
|
16350
|
+
trackToolTokenSavings(client, "graph_call_path", outputText, {
|
|
16302
16351
|
workspace_id: workspaceId,
|
|
16303
16352
|
project_id: projectId
|
|
16304
16353
|
});
|
|
16305
16354
|
return {
|
|
16306
|
-
content: [{ type: "text", text:
|
|
16355
|
+
content: [{ type: "text", text: outputText }],
|
|
16307
16356
|
structuredContent: toStructured(result)
|
|
16308
16357
|
};
|
|
16309
16358
|
}
|
|
@@ -16317,12 +16366,13 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
16317
16366
|
project_id: projectId,
|
|
16318
16367
|
limit: input.limit
|
|
16319
16368
|
});
|
|
16320
|
-
|
|
16369
|
+
const outputText = formatContent(result);
|
|
16370
|
+
trackToolTokenSavings(client, "graph_related", outputText, {
|
|
16321
16371
|
workspace_id: workspaceId,
|
|
16322
16372
|
project_id: projectId
|
|
16323
16373
|
});
|
|
16324
16374
|
return {
|
|
16325
|
-
content: [{ type: "text", text:
|
|
16375
|
+
content: [{ type: "text", text: outputText }],
|
|
16326
16376
|
structuredContent: toStructured(result)
|
|
16327
16377
|
};
|
|
16328
16378
|
}
|
|
@@ -16786,7 +16836,7 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
16786
16836
|
"integration",
|
|
16787
16837
|
{
|
|
16788
16838
|
title: "Integration",
|
|
16789
|
-
description: `Integration operations for Slack, GitHub, and Notion. Provider: slack, github, notion, all. Actions: status, search, stats, activity, contributors, knowledge, summary, channels (slack), discussions (slack), repos (github), issues (github), create_page (notion), list_databases (notion), search_pages (notion with smart type detection - filter by event_type, status, priority, has_due_date, tags), get_page (notion), query_database (notion), update_page (notion).`,
|
|
16839
|
+
description: `Integration operations for Slack, GitHub, and Notion. Provider: slack, github, notion, all. Actions: status, search, stats, activity, contributors, knowledge, summary, channels (slack), discussions (slack), repos (github), issues (github), create_page (notion), create_database (notion), list_databases (notion), search_pages (notion with smart type detection - filter by event_type, status, priority, has_due_date, tags), get_page (notion), query_database (notion), update_page (notion).`,
|
|
16790
16840
|
inputSchema: external_exports.object({
|
|
16791
16841
|
provider: external_exports.enum(["slack", "github", "notion", "all"]).describe("Integration provider"),
|
|
16792
16842
|
action: external_exports.enum([
|
|
@@ -16804,6 +16854,7 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
16804
16854
|
"issues",
|
|
16805
16855
|
// Notion-specific actions
|
|
16806
16856
|
"create_page",
|
|
16857
|
+
"create_database",
|
|
16807
16858
|
"list_databases",
|
|
16808
16859
|
"search_pages",
|
|
16809
16860
|
"get_page",
|
|
@@ -16817,10 +16868,11 @@ Output formats: full (default, includes content), paths (file paths only - 80% t
|
|
|
16817
16868
|
since: external_exports.string().optional(),
|
|
16818
16869
|
until: external_exports.string().optional(),
|
|
16819
16870
|
// Notion-specific parameters
|
|
16820
|
-
title: external_exports.string().optional().describe("Page title (for Notion create_page/update_page)"),
|
|
16871
|
+
title: external_exports.string().optional().describe("Page/database title (for Notion create_page/update_page/create_database)"),
|
|
16821
16872
|
content: external_exports.string().optional().describe("Page content in Markdown (for Notion create_page/update_page)"),
|
|
16873
|
+
description: external_exports.string().optional().describe("Database description (for Notion create_database)"),
|
|
16822
16874
|
parent_database_id: external_exports.string().optional().describe("Parent database ID (for Notion create_page)"),
|
|
16823
|
-
parent_page_id: external_exports.string().optional().describe("Parent page ID (for Notion create_page)"),
|
|
16875
|
+
parent_page_id: external_exports.string().optional().describe("Parent page ID (for Notion create_page/create_database)"),
|
|
16824
16876
|
page_id: external_exports.string().optional().describe("Page ID (for Notion get_page/update_page)"),
|
|
16825
16877
|
database_id: external_exports.string().optional().describe("Database ID (for Notion query_database/search_pages/activity)"),
|
|
16826
16878
|
days: external_exports.number().optional().describe("Number of days for stats/summary (default: 7)"),
|
|
@@ -17112,6 +17164,39 @@ Created: ${result.created_time}`
|
|
|
17112
17164
|
structuredContent: toStructured(result)
|
|
17113
17165
|
};
|
|
17114
17166
|
}
|
|
17167
|
+
case "create_database": {
|
|
17168
|
+
if (input.provider !== "notion") {
|
|
17169
|
+
return errorResult("create_database is only available for notion provider");
|
|
17170
|
+
}
|
|
17171
|
+
if (!input.title) {
|
|
17172
|
+
return errorResult("title is required for create_database action");
|
|
17173
|
+
}
|
|
17174
|
+
if (!input.parent_page_id) {
|
|
17175
|
+
return errorResult("parent_page_id is required for create_database action");
|
|
17176
|
+
}
|
|
17177
|
+
if (!workspaceId) {
|
|
17178
|
+
return errorResult(
|
|
17179
|
+
"Error: workspace_id is required. Please call session_init first or provide workspace_id explicitly."
|
|
17180
|
+
);
|
|
17181
|
+
}
|
|
17182
|
+
const newDatabase = await client.notionCreateDatabase({
|
|
17183
|
+
workspace_id: workspaceId,
|
|
17184
|
+
title: input.title,
|
|
17185
|
+
parent_page_id: input.parent_page_id,
|
|
17186
|
+
description: input.description
|
|
17187
|
+
});
|
|
17188
|
+
return {
|
|
17189
|
+
content: [
|
|
17190
|
+
{
|
|
17191
|
+
type: "text",
|
|
17192
|
+
text: `Created database "${newDatabase.title}"
|
|
17193
|
+
ID: ${newDatabase.id}
|
|
17194
|
+
URL: ${newDatabase.url}`
|
|
17195
|
+
}
|
|
17196
|
+
],
|
|
17197
|
+
structuredContent: toStructured(newDatabase)
|
|
17198
|
+
};
|
|
17199
|
+
}
|
|
17115
17200
|
case "list_databases": {
|
|
17116
17201
|
if (input.provider !== "notion") {
|
|
17117
17202
|
return errorResult("list_databases is only available for notion provider");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contextstream/mcp-server",
|
|
3
3
|
"mcpName": "io.github.contextstreamio/mcp-server",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.36",
|
|
5
5
|
"description": "ContextStream MCP server - v0.4.x with consolidated domain tools (~11 tools, ~75% token reduction). Code context, memory, search, and AI tools.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"test-server": "tsx src/test-server.ts",
|
|
21
21
|
"test-server:start": "node dist/test-server.js",
|
|
22
22
|
"typecheck": "tsc --noEmit",
|
|
23
|
-
"test": "vitest run",
|
|
24
|
-
"test:watch": "vitest",
|
|
23
|
+
"test": "vitest run --config vitest.config.cjs",
|
|
24
|
+
"test:watch": "vitest --config vitest.config.cjs",
|
|
25
25
|
"lint": "eslint src/",
|
|
26
26
|
"lint:fix": "eslint src/ --fix",
|
|
27
27
|
"format": "prettier --write src/",
|