@contextstream/mcp-server 0.3.18 → 0.3.19
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 +125 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5431,6 +5431,17 @@ var ContextStreamClient = class {
|
|
|
5431
5431
|
// ============================================
|
|
5432
5432
|
// Token-Saving Context Tools
|
|
5433
5433
|
// ============================================
|
|
5434
|
+
/**
|
|
5435
|
+
* Record a token savings event for user-facing dashboard analytics.
|
|
5436
|
+
* Best-effort: callers should not await this in latency-sensitive paths.
|
|
5437
|
+
*/
|
|
5438
|
+
trackTokenSavings(body) {
|
|
5439
|
+
const payload = this.withDefaults({
|
|
5440
|
+
source: "mcp",
|
|
5441
|
+
...body
|
|
5442
|
+
});
|
|
5443
|
+
return request(this.config, "/analytics/token-savings", { body: payload });
|
|
5444
|
+
}
|
|
5434
5445
|
/**
|
|
5435
5446
|
* Get a compact, token-efficient summary of workspace context.
|
|
5436
5447
|
* Designed to be included in every AI prompt without consuming many tokens.
|
|
@@ -5519,7 +5530,31 @@ var ContextStreamClient = class {
|
|
|
5519
5530
|
}
|
|
5520
5531
|
parts.push("");
|
|
5521
5532
|
parts.push('\u{1F4A1} Use session_recall("topic") for specific context');
|
|
5522
|
-
const
|
|
5533
|
+
const candidateSummary = parts.join("\n");
|
|
5534
|
+
const maxChars = maxTokens * 4;
|
|
5535
|
+
const candidateLines = candidateSummary.split("\n");
|
|
5536
|
+
const finalLines = [];
|
|
5537
|
+
let used = 0;
|
|
5538
|
+
for (const line of candidateLines) {
|
|
5539
|
+
const next = (finalLines.length ? "\n" : "") + line;
|
|
5540
|
+
if (used + next.length > maxChars) break;
|
|
5541
|
+
finalLines.push(line);
|
|
5542
|
+
used += next.length;
|
|
5543
|
+
}
|
|
5544
|
+
const summary = finalLines.join("\n");
|
|
5545
|
+
this.trackTokenSavings({
|
|
5546
|
+
tool: "session_summary",
|
|
5547
|
+
workspace_id: withDefaults.workspace_id,
|
|
5548
|
+
project_id: withDefaults.project_id,
|
|
5549
|
+
candidate_chars: candidateSummary.length,
|
|
5550
|
+
context_chars: summary.length,
|
|
5551
|
+
max_tokens: maxTokens,
|
|
5552
|
+
metadata: {
|
|
5553
|
+
decision_count: decisionCount,
|
|
5554
|
+
memory_count: memoryCount
|
|
5555
|
+
}
|
|
5556
|
+
}).catch(() => {
|
|
5557
|
+
});
|
|
5523
5558
|
return {
|
|
5524
5559
|
summary,
|
|
5525
5560
|
workspace_name: workspaceName,
|
|
@@ -5654,6 +5689,7 @@ var ContextStreamClient = class {
|
|
|
5654
5689
|
const charsPerToken = 4;
|
|
5655
5690
|
const maxChars = maxTokens * charsPerToken;
|
|
5656
5691
|
const parts = [];
|
|
5692
|
+
const candidateParts = [];
|
|
5657
5693
|
const sources = [];
|
|
5658
5694
|
let currentChars = 0;
|
|
5659
5695
|
if (params.include_decisions !== false && withDefaults.workspace_id) {
|
|
@@ -5665,14 +5701,22 @@ var ContextStreamClient = class {
|
|
|
5665
5701
|
});
|
|
5666
5702
|
if (decisions.items) {
|
|
5667
5703
|
parts.push("## Relevant Decisions\n");
|
|
5704
|
+
candidateParts.push("## Relevant Decisions\n");
|
|
5668
5705
|
currentChars += 25;
|
|
5669
|
-
|
|
5670
|
-
const
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5706
|
+
const decisionEntries = decisions.items.map((d) => {
|
|
5707
|
+
const title = d.title || "Decision";
|
|
5708
|
+
return { title, entry: `\u2022 ${title}
|
|
5709
|
+
` };
|
|
5710
|
+
});
|
|
5711
|
+
for (const d of decisionEntries) {
|
|
5712
|
+
candidateParts.push(d.entry);
|
|
5713
|
+
}
|
|
5714
|
+
candidateParts.push("\n");
|
|
5715
|
+
for (const d of decisionEntries) {
|
|
5716
|
+
if (currentChars + d.entry.length > maxChars * 0.4) break;
|
|
5717
|
+
parts.push(d.entry);
|
|
5718
|
+
currentChars += d.entry.length;
|
|
5719
|
+
sources.push({ type: "decision", title: d.title });
|
|
5676
5720
|
}
|
|
5677
5721
|
parts.push("\n");
|
|
5678
5722
|
}
|
|
@@ -5689,16 +5733,23 @@ var ContextStreamClient = class {
|
|
|
5689
5733
|
});
|
|
5690
5734
|
if (memory.results) {
|
|
5691
5735
|
parts.push("## Related Context\n");
|
|
5736
|
+
candidateParts.push("## Related Context\n");
|
|
5692
5737
|
currentChars += 20;
|
|
5693
|
-
|
|
5738
|
+
const memoryEntries = memory.results.map((m) => {
|
|
5694
5739
|
const title = m.title || "Context";
|
|
5695
5740
|
const content = m.content?.slice(0, 200) || "";
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5741
|
+
return { title, entry: `\u2022 ${title}: ${content}...
|
|
5742
|
+
` };
|
|
5743
|
+
});
|
|
5744
|
+
for (const m of memoryEntries) {
|
|
5745
|
+
candidateParts.push(m.entry);
|
|
5746
|
+
}
|
|
5747
|
+
candidateParts.push("\n");
|
|
5748
|
+
for (const m of memoryEntries) {
|
|
5749
|
+
if (currentChars + m.entry.length > maxChars * 0.7) break;
|
|
5750
|
+
parts.push(m.entry);
|
|
5751
|
+
currentChars += m.entry.length;
|
|
5752
|
+
sources.push({ type: "memory", title: m.title });
|
|
5702
5753
|
}
|
|
5703
5754
|
parts.push("\n");
|
|
5704
5755
|
}
|
|
@@ -5715,23 +5766,45 @@ var ContextStreamClient = class {
|
|
|
5715
5766
|
});
|
|
5716
5767
|
if (code.results) {
|
|
5717
5768
|
parts.push("## Relevant Code\n");
|
|
5769
|
+
candidateParts.push("## Relevant Code\n");
|
|
5718
5770
|
currentChars += 18;
|
|
5719
|
-
|
|
5771
|
+
const codeEntries = code.results.map((c) => {
|
|
5720
5772
|
const path3 = c.file_path || "file";
|
|
5721
5773
|
const content = c.content?.slice(0, 150) || "";
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5774
|
+
return { path: path3, entry: `\u2022 ${path3}: ${content}...
|
|
5775
|
+
` };
|
|
5776
|
+
});
|
|
5777
|
+
for (const c of codeEntries) {
|
|
5778
|
+
candidateParts.push(c.entry);
|
|
5779
|
+
}
|
|
5780
|
+
for (const c of codeEntries) {
|
|
5781
|
+
if (currentChars + c.entry.length > maxChars) break;
|
|
5782
|
+
parts.push(c.entry);
|
|
5783
|
+
currentChars += c.entry.length;
|
|
5784
|
+
sources.push({ type: "code", title: c.path });
|
|
5728
5785
|
}
|
|
5729
5786
|
}
|
|
5730
5787
|
} catch {
|
|
5731
5788
|
}
|
|
5732
5789
|
}
|
|
5733
5790
|
const context = parts.join("");
|
|
5791
|
+
const candidateContext = candidateParts.join("");
|
|
5734
5792
|
const tokenEstimate = Math.ceil(context.length / charsPerToken);
|
|
5793
|
+
this.trackTokenSavings({
|
|
5794
|
+
tool: "ai_context_budget",
|
|
5795
|
+
workspace_id: withDefaults.workspace_id,
|
|
5796
|
+
project_id: withDefaults.project_id,
|
|
5797
|
+
candidate_chars: candidateContext.length,
|
|
5798
|
+
context_chars: context.length,
|
|
5799
|
+
max_tokens: maxTokens,
|
|
5800
|
+
metadata: {
|
|
5801
|
+
include_decisions: params.include_decisions !== false,
|
|
5802
|
+
include_memory: params.include_memory !== false,
|
|
5803
|
+
include_code: !!params.include_code,
|
|
5804
|
+
sources: sources.length
|
|
5805
|
+
}
|
|
5806
|
+
}).catch(() => {
|
|
5807
|
+
});
|
|
5735
5808
|
return {
|
|
5736
5809
|
context,
|
|
5737
5810
|
token_estimate: tokenEstimate,
|
|
@@ -5908,6 +5981,7 @@ var ContextStreamClient = class {
|
|
|
5908
5981
|
let context;
|
|
5909
5982
|
let charsUsed = 0;
|
|
5910
5983
|
const maxChars = maxTokens * 4;
|
|
5984
|
+
let candidateContext;
|
|
5911
5985
|
if (format === "minified") {
|
|
5912
5986
|
const parts = [];
|
|
5913
5987
|
for (const item of items) {
|
|
@@ -5917,6 +5991,7 @@ var ContextStreamClient = class {
|
|
|
5917
5991
|
charsUsed += entry.length + 1;
|
|
5918
5992
|
}
|
|
5919
5993
|
context = parts.join("|");
|
|
5994
|
+
candidateContext = items.map((i) => `${i.type}:${i.value}`).join("|");
|
|
5920
5995
|
} else if (format === "structured") {
|
|
5921
5996
|
const grouped = {};
|
|
5922
5997
|
for (const item of items) {
|
|
@@ -5926,6 +6001,12 @@ var ContextStreamClient = class {
|
|
|
5926
6001
|
charsUsed += item.value.length + 5;
|
|
5927
6002
|
}
|
|
5928
6003
|
context = JSON.stringify(grouped);
|
|
6004
|
+
const candidateGrouped = {};
|
|
6005
|
+
for (const item of items) {
|
|
6006
|
+
if (!candidateGrouped[item.type]) candidateGrouped[item.type] = [];
|
|
6007
|
+
candidateGrouped[item.type].push(item.value);
|
|
6008
|
+
}
|
|
6009
|
+
candidateContext = JSON.stringify(candidateGrouped);
|
|
5929
6010
|
} else {
|
|
5930
6011
|
const lines = ["[CTX]"];
|
|
5931
6012
|
for (const item of items) {
|
|
@@ -5936,6 +6017,12 @@ var ContextStreamClient = class {
|
|
|
5936
6017
|
}
|
|
5937
6018
|
lines.push("[/CTX]");
|
|
5938
6019
|
context = lines.join("\n");
|
|
6020
|
+
const candidateLines = ["[CTX]"];
|
|
6021
|
+
for (const item of items) {
|
|
6022
|
+
candidateLines.push(`${item.type}:${item.value}`);
|
|
6023
|
+
}
|
|
6024
|
+
candidateLines.push("[/CTX]");
|
|
6025
|
+
candidateContext = candidateLines.join("\n");
|
|
5939
6026
|
}
|
|
5940
6027
|
if (context.length === 0 && withDefaults.workspace_id) {
|
|
5941
6028
|
const wsHint = items.find((i) => i.type === "W")?.value || withDefaults.workspace_id.slice(0, 8);
|
|
@@ -5943,7 +6030,23 @@ var ContextStreamClient = class {
|
|
|
5943
6030
|
W:${wsHint}
|
|
5944
6031
|
[NO_MATCHES]
|
|
5945
6032
|
[/CTX]`;
|
|
6033
|
+
candidateContext = context;
|
|
5946
6034
|
}
|
|
6035
|
+
this.trackTokenSavings({
|
|
6036
|
+
tool: "context_smart",
|
|
6037
|
+
workspace_id: withDefaults.workspace_id,
|
|
6038
|
+
project_id: withDefaults.project_id,
|
|
6039
|
+
candidate_chars: candidateContext.length,
|
|
6040
|
+
context_chars: context.length,
|
|
6041
|
+
max_tokens: maxTokens,
|
|
6042
|
+
metadata: {
|
|
6043
|
+
format,
|
|
6044
|
+
items: items.length,
|
|
6045
|
+
keywords: keywords.slice(0, 10),
|
|
6046
|
+
errors: errors.length
|
|
6047
|
+
}
|
|
6048
|
+
}).catch(() => {
|
|
6049
|
+
});
|
|
5947
6050
|
return {
|
|
5948
6051
|
context,
|
|
5949
6052
|
token_estimate: Math.ceil(context.length / 4),
|
package/package.json
CHANGED