@contextstream/mcp-server 0.4.20 → 0.4.21
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 +163 -13
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7482,6 +7482,7 @@ var CONTEXTSTREAM_TOOL_NAMES = [
|
|
|
7482
7482
|
"session_init",
|
|
7483
7483
|
"context_smart",
|
|
7484
7484
|
"context_feedback",
|
|
7485
|
+
"generate_rules",
|
|
7485
7486
|
// Consolidated domain tools (v0.4.x default)
|
|
7486
7487
|
"search",
|
|
7487
7488
|
// Modes: semantic, hybrid, keyword, pattern
|
|
@@ -7518,7 +7519,7 @@ Rules Version: ${RULES_VERSION}
|
|
|
7518
7519
|
|
|
7519
7520
|
| Message | What to Call |
|
|
7520
7521
|
|---------|--------------|
|
|
7521
|
-
| **1st message** | \`session_init(folder_path="...", context_hint="<user's message>")\` |
|
|
7522
|
+
| **1st message** | \`session_init(folder_path="...", context_hint="<user's message>")\`, then \`context_smart(user_message="<user's message>", format="minified", max_tokens=400)\` |
|
|
7522
7523
|
| **2nd+ messages** | \`context_smart(user_message="<user's message>", format="minified", max_tokens=400)\` |
|
|
7523
7524
|
| **Before risky/non-trivial work** | \`session(action="get_lessons", query="<topic>")\` |
|
|
7524
7525
|
| **After completing task** | \`session(action="capture", event_type="decision", ...)\` - MUST capture |
|
|
@@ -7527,6 +7528,8 @@ Rules Version: ${RULES_VERSION}
|
|
|
7527
7528
|
|
|
7528
7529
|
**NO EXCEPTIONS.** Do not skip even if you think you have enough context.
|
|
7529
7530
|
|
|
7531
|
+
**First message rule:** After \`session_init\`, always call \`context_smart\` before any other tool or response.
|
|
7532
|
+
|
|
7530
7533
|
**Context Pack (Pro+):** If enabled, use \`context_smart(..., mode="pack", distill=true)\` for code/file queries. If unavailable or disabled, omit \`mode\` and proceed with standard \`context_smart\` (the API will fall back).
|
|
7531
7534
|
|
|
7532
7535
|
**Tool naming:** Use the exact tool names exposed by your MCP client. Claude Code typically uses \`mcp__<server>__<tool>\` where \`<server>\` matches your MCP config (often \`contextstream\`). If a tool call fails with "No such tool available", refresh rules and match the tool list.
|
|
@@ -7539,7 +7542,7 @@ v0.4.x consolidates ~58 individual tools into ~11 domain tools with action/mode
|
|
|
7539
7542
|
|
|
7540
7543
|
### Standalone Tools (Always Call)
|
|
7541
7544
|
- **\`session_init\`** - Initialize session with workspace detection + context
|
|
7542
|
-
- **\`context_smart\`** - Semantic search for relevant context (CALL EVERY MESSAGE)
|
|
7545
|
+
- **\`context_smart\`** - Semantic search for relevant context (CALL EVERY MESSAGE, including immediately after \`session_init\`)
|
|
7543
7546
|
|
|
7544
7547
|
### Domain Tools (Use action/mode parameter)
|
|
7545
7548
|
|
|
@@ -7588,7 +7591,7 @@ If context still feels missing, use \`session(action="recall", query="...")\` fo
|
|
|
7588
7591
|
|
|
7589
7592
|
### Rules Update Notices
|
|
7590
7593
|
|
|
7591
|
-
- If you see **[RULES_NOTICE]**, update rules via \`
|
|
7594
|
+
- If you see **[RULES_NOTICE]**, update rules via \`generate_rules()\` (or rerun setup).
|
|
7592
7595
|
- If you see **[VERSION_NOTICE]**, tell the user to update MCP using the provided command.
|
|
7593
7596
|
|
|
7594
7597
|
---
|
|
@@ -7709,7 +7712,7 @@ Rules Version: ${RULES_VERSION}
|
|
|
7709
7712
|
|
|
7710
7713
|
| Message | What to Call |
|
|
7711
7714
|
|---------|--------------|
|
|
7712
|
-
| **1st message** | \`session_init(folder_path="<cwd>", context_hint="<user_message>")\` |
|
|
7715
|
+
| **1st message** | \`session_init(folder_path="<cwd>", context_hint="<user_message>")\`, then \`context_smart(user_message="<user_message>", format="minified", max_tokens=400)\` |
|
|
7713
7716
|
| **2nd+ messages** | \`context_smart(user_message="<user_message>", format="minified", max_tokens=400)\` |
|
|
7714
7717
|
| **Capture decisions** | \`session(action="capture", event_type="decision", title="...", content="...")\` |
|
|
7715
7718
|
| **Before risky work** | \`session(action="get_lessons", query="<topic>")\` |
|
|
@@ -7734,14 +7737,14 @@ Rules Version: ${RULES_VERSION}
|
|
|
7734
7737
|
|
|
7735
7738
|
### Behavior Rules
|
|
7736
7739
|
|
|
7737
|
-
- **First message**:
|
|
7740
|
+
- **First message**: Call \`session_init\` with context_hint, then call \`context_smart\` before any other tool or response
|
|
7738
7741
|
- **Every message after**: Always call \`context_smart\` BEFORE responding (semantic search for relevant context)
|
|
7739
7742
|
- **Before searching files/code**: Check \`project(action="index_status")\`; if missing/stale run \`project(action="ingest_local", path="<cwd>")\` or \`project(action="index")\`, and use \`graph(action="ingest")\` if needed
|
|
7740
7743
|
- **For discovery**: Use \`session(action="smart_search")\` or \`search(mode="hybrid")\` before any local repo scans
|
|
7741
7744
|
- **For file/function/config lookups**: Use \`search\`/\`graph\` first; only fall back to rg/ls/find if ContextStream returns no results
|
|
7742
7745
|
- **If ContextStream returns results**: Do NOT use local Search/Explore/Read; only open specific files when needed for exact edits
|
|
7743
7746
|
- **For code analysis**: Use \`graph(action="dependencies")\` or \`graph(action="impact")\` for call/dependency analysis
|
|
7744
|
-
- **On [RULES_NOTICE]**: Use \`
|
|
7747
|
+
- **On [RULES_NOTICE]**: Use \`generate_rules()\` to update rules
|
|
7745
7748
|
- **After completing work**: Always capture decisions/insights with \`session(action="capture")\`
|
|
7746
7749
|
- **On mistakes/corrections**: Immediately capture lessons with \`session(action="capture_lesson")\`
|
|
7747
7750
|
|
|
@@ -8174,12 +8177,12 @@ function getRulesNotice(folderPath, clientName) {
|
|
|
8174
8177
|
const candidates = resolveRulesCandidatePaths(folderPath, editorKey);
|
|
8175
8178
|
const existing = candidates.filter((filePath) => fs3.existsSync(filePath));
|
|
8176
8179
|
if (existing.length === 0) {
|
|
8177
|
-
const updateCommand2 =
|
|
8180
|
+
const updateCommand2 = "generate_rules()";
|
|
8178
8181
|
const notice2 = {
|
|
8179
8182
|
status: "missing",
|
|
8180
8183
|
latest: RULES_VERSION,
|
|
8181
8184
|
files_checked: candidates,
|
|
8182
|
-
update_tool: "
|
|
8185
|
+
update_tool: "generate_rules",
|
|
8183
8186
|
update_args: {
|
|
8184
8187
|
...folderPath ? { folder_path: folderPath } : {},
|
|
8185
8188
|
editors: editorKey ? [editorKey] : ["all"]
|
|
@@ -8213,7 +8216,7 @@ function getRulesNotice(folderPath, clientName) {
|
|
|
8213
8216
|
return null;
|
|
8214
8217
|
}
|
|
8215
8218
|
const current = versions.sort(compareVersions2).at(-1);
|
|
8216
|
-
const updateCommand =
|
|
8219
|
+
const updateCommand = "generate_rules()";
|
|
8217
8220
|
const notice = {
|
|
8218
8221
|
status: filesOutdated.length > 0 ? "behind" : "unknown",
|
|
8219
8222
|
current,
|
|
@@ -8221,7 +8224,7 @@ function getRulesNotice(folderPath, clientName) {
|
|
|
8221
8224
|
files_checked: existing,
|
|
8222
8225
|
...filesOutdated.length > 0 ? { files_outdated: filesOutdated } : {},
|
|
8223
8226
|
...filesMissingVersion.length > 0 ? { files_missing_version: filesMissingVersion } : {},
|
|
8224
|
-
update_tool: "
|
|
8227
|
+
update_tool: "generate_rules",
|
|
8225
8228
|
update_args: {
|
|
8226
8229
|
...folderPath ? { folder_path: folderPath } : {},
|
|
8227
8230
|
editors: editorKey ? [editorKey] : ["all"]
|
|
@@ -8444,6 +8447,55 @@ async function writeEditorRules(options) {
|
|
|
8444
8447
|
}
|
|
8445
8448
|
return results;
|
|
8446
8449
|
}
|
|
8450
|
+
function listGlobalRuleTargets(editors) {
|
|
8451
|
+
const targets = [];
|
|
8452
|
+
for (const editor of editors) {
|
|
8453
|
+
const globalPaths = RULES_GLOBAL_FILES[editor];
|
|
8454
|
+
if (!globalPaths || globalPaths.length === 0) {
|
|
8455
|
+
continue;
|
|
8456
|
+
}
|
|
8457
|
+
for (const filePath of globalPaths) {
|
|
8458
|
+
targets.push({ editor, filePath });
|
|
8459
|
+
}
|
|
8460
|
+
}
|
|
8461
|
+
return targets;
|
|
8462
|
+
}
|
|
8463
|
+
async function writeGlobalRules(options) {
|
|
8464
|
+
const results = [];
|
|
8465
|
+
for (const editor of options.editors) {
|
|
8466
|
+
const rule = generateRuleContent(editor, {
|
|
8467
|
+
mode: options.mode
|
|
8468
|
+
});
|
|
8469
|
+
if (!rule) {
|
|
8470
|
+
results.push({ editor, filename: "", status: "unknown editor", scope: "global" });
|
|
8471
|
+
continue;
|
|
8472
|
+
}
|
|
8473
|
+
const globalPaths = RULES_GLOBAL_FILES[editor] ?? [];
|
|
8474
|
+
if (globalPaths.length === 0) {
|
|
8475
|
+
results.push({ editor, filename: rule.filename, status: "skipped (no global path)", scope: "global" });
|
|
8476
|
+
continue;
|
|
8477
|
+
}
|
|
8478
|
+
for (const filePath of globalPaths) {
|
|
8479
|
+
if (fs3.existsSync(filePath) && !options.overwriteExisting) {
|
|
8480
|
+
results.push({ editor, filename: filePath, status: "skipped (exists)", scope: "global" });
|
|
8481
|
+
continue;
|
|
8482
|
+
}
|
|
8483
|
+
try {
|
|
8484
|
+
const status = await upsertRuleFile(filePath, rule.content);
|
|
8485
|
+
results.push({ editor, filename: filePath, status, scope: "global" });
|
|
8486
|
+
} catch (err) {
|
|
8487
|
+
results.push({
|
|
8488
|
+
editor,
|
|
8489
|
+
filename: filePath,
|
|
8490
|
+
status: `error: ${err.message}`,
|
|
8491
|
+
scope: "global"
|
|
8492
|
+
});
|
|
8493
|
+
}
|
|
8494
|
+
}
|
|
8495
|
+
}
|
|
8496
|
+
rulesNoticeCache.clear();
|
|
8497
|
+
return results;
|
|
8498
|
+
}
|
|
8447
8499
|
var WRITE_VERBS = /* @__PURE__ */ new Set([
|
|
8448
8500
|
"create",
|
|
8449
8501
|
"update",
|
|
@@ -8645,6 +8697,7 @@ var LIGHT_TOOLSET = /* @__PURE__ */ new Set([
|
|
|
8645
8697
|
"session_delta",
|
|
8646
8698
|
// Setup and configuration (3)
|
|
8647
8699
|
"generate_editor_rules",
|
|
8700
|
+
"generate_rules",
|
|
8648
8701
|
"workspace_associate",
|
|
8649
8702
|
"workspace_bootstrap",
|
|
8650
8703
|
// Project management (5)
|
|
@@ -8690,6 +8743,7 @@ var STANDARD_TOOLSET = /* @__PURE__ */ new Set([
|
|
|
8690
8743
|
"session_delta",
|
|
8691
8744
|
// Setup and configuration (3)
|
|
8692
8745
|
"generate_editor_rules",
|
|
8746
|
+
"generate_rules",
|
|
8693
8747
|
"workspace_associate",
|
|
8694
8748
|
"workspace_bootstrap",
|
|
8695
8749
|
// Workspace management (2)
|
|
@@ -8898,7 +8952,8 @@ var TOOL_BUNDLES = {
|
|
|
8898
8952
|
"session_compress",
|
|
8899
8953
|
"session_delta",
|
|
8900
8954
|
"decision_trace",
|
|
8901
|
-
"generate_editor_rules"
|
|
8955
|
+
"generate_editor_rules",
|
|
8956
|
+
"generate_rules"
|
|
8902
8957
|
]),
|
|
8903
8958
|
// Memory bundle (~12 tools) - full memory CRUD operations
|
|
8904
8959
|
memory: /* @__PURE__ */ new Set([
|
|
@@ -9033,7 +9088,7 @@ function inferOperationCategory(name) {
|
|
|
9033
9088
|
if (name.startsWith("reminder")) return "Reminders";
|
|
9034
9089
|
if (name.startsWith("slack_") || name.startsWith("github_") || name.startsWith("integration")) return "Integrations";
|
|
9035
9090
|
if (name.startsWith("ai_")) return "AI";
|
|
9036
|
-
if (name === "auth_me" || name === "mcp_server_version" || name === "generate_editor_rules") return "Utility";
|
|
9091
|
+
if (name === "auth_me" || name === "mcp_server_version" || name === "generate_editor_rules" || name === "generate_rules") return "Utility";
|
|
9037
9092
|
if (name === "tools_enable_bundle" || name === "contextstream" || name === "contextstream_help") return "Meta";
|
|
9038
9093
|
return "Other";
|
|
9039
9094
|
}
|
|
@@ -9107,6 +9162,8 @@ var CONSOLIDATED_TOOLS = /* @__PURE__ */ new Set([
|
|
|
9107
9162
|
// Standalone - complex initialization
|
|
9108
9163
|
"context_smart",
|
|
9109
9164
|
// Standalone - called every message
|
|
9165
|
+
"generate_rules",
|
|
9166
|
+
// Standalone - rule generation helper
|
|
9110
9167
|
"search",
|
|
9111
9168
|
// Consolidates search_semantic, search_hybrid, search_keyword, search_pattern
|
|
9112
9169
|
"session",
|
|
@@ -11819,6 +11876,98 @@ Example: "What were the auth decisions?" or "What are my TypeScript preferences?
|
|
|
11819
11876
|
return { content: [{ type: "text", text: formatContent(result) }], structuredContent: toStructured(result) };
|
|
11820
11877
|
}
|
|
11821
11878
|
);
|
|
11879
|
+
registerTool(
|
|
11880
|
+
"generate_rules",
|
|
11881
|
+
{
|
|
11882
|
+
title: "Generate ContextStream rules",
|
|
11883
|
+
description: `Generate AI rule files for editors (Windsurf, Cursor, Cline, Kilo Code, Roo Code, Claude Code, Aider).
|
|
11884
|
+
Defaults to the current project folder; no folder_path required when run from a project.
|
|
11885
|
+
Supported editors: ${getAvailableEditors().join(", ")}`,
|
|
11886
|
+
inputSchema: external_exports.object({
|
|
11887
|
+
folder_path: external_exports.string().optional().describe("Absolute path to the project folder (defaults to IDE root/cwd)"),
|
|
11888
|
+
editors: external_exports.array(external_exports.enum(["codex", "windsurf", "cursor", "cline", "kilo", "roo", "claude", "aider", "all"])).optional().describe("Which editors to generate rules for. Defaults to all."),
|
|
11889
|
+
workspace_name: external_exports.string().optional().describe("Workspace name to include in rules"),
|
|
11890
|
+
workspace_id: external_exports.string().uuid().optional().describe("Workspace ID to include in rules"),
|
|
11891
|
+
project_name: external_exports.string().optional().describe("Project name to include in rules"),
|
|
11892
|
+
additional_rules: external_exports.string().optional().describe("Additional project-specific rules to append"),
|
|
11893
|
+
mode: external_exports.enum(["minimal", "full"]).optional().describe("Rule verbosity mode (default: minimal)"),
|
|
11894
|
+
overwrite_existing: external_exports.boolean().optional().describe("Allow overwriting existing rule files (ContextStream block only)"),
|
|
11895
|
+
apply_global: external_exports.boolean().optional().describe("Also write global rule files for supported editors"),
|
|
11896
|
+
dry_run: external_exports.boolean().optional().describe("If true, return content without writing files")
|
|
11897
|
+
})
|
|
11898
|
+
},
|
|
11899
|
+
async (input) => {
|
|
11900
|
+
const folderPath = resolveFolderPath(input.folder_path, sessionManager);
|
|
11901
|
+
if (!folderPath) {
|
|
11902
|
+
return errorResult("Error: folder_path is required. Provide folder_path or run from a project directory.");
|
|
11903
|
+
}
|
|
11904
|
+
const editors = input.editors?.includes("all") || !input.editors ? getAvailableEditors() : input.editors.filter((e) => e !== "all");
|
|
11905
|
+
const results = [];
|
|
11906
|
+
if (input.dry_run) {
|
|
11907
|
+
for (const editor of editors) {
|
|
11908
|
+
const rule = generateRuleContent(editor, {
|
|
11909
|
+
workspaceName: input.workspace_name,
|
|
11910
|
+
workspaceId: input.workspace_id,
|
|
11911
|
+
projectName: input.project_name,
|
|
11912
|
+
additionalRules: input.additional_rules,
|
|
11913
|
+
mode: input.mode
|
|
11914
|
+
});
|
|
11915
|
+
if (!rule) {
|
|
11916
|
+
results.push({ editor, filename: "", status: "unknown editor" });
|
|
11917
|
+
continue;
|
|
11918
|
+
}
|
|
11919
|
+
results.push({
|
|
11920
|
+
editor,
|
|
11921
|
+
filename: rule.filename,
|
|
11922
|
+
status: "dry run - would update"
|
|
11923
|
+
});
|
|
11924
|
+
}
|
|
11925
|
+
} else {
|
|
11926
|
+
const writeResults = await writeEditorRules({
|
|
11927
|
+
folderPath,
|
|
11928
|
+
editors,
|
|
11929
|
+
workspaceName: input.workspace_name,
|
|
11930
|
+
workspaceId: input.workspace_id,
|
|
11931
|
+
projectName: input.project_name,
|
|
11932
|
+
additionalRules: input.additional_rules,
|
|
11933
|
+
mode: input.mode,
|
|
11934
|
+
overwriteExisting: input.overwrite_existing
|
|
11935
|
+
});
|
|
11936
|
+
results.push(...writeResults);
|
|
11937
|
+
}
|
|
11938
|
+
const globalTargets = listGlobalRuleTargets(editors);
|
|
11939
|
+
let globalResults;
|
|
11940
|
+
if (input.apply_global) {
|
|
11941
|
+
if (input.dry_run) {
|
|
11942
|
+
globalResults = globalTargets.map((target) => ({
|
|
11943
|
+
editor: target.editor,
|
|
11944
|
+
filename: target.filePath,
|
|
11945
|
+
status: "dry run - would update",
|
|
11946
|
+
scope: "global"
|
|
11947
|
+
}));
|
|
11948
|
+
} else {
|
|
11949
|
+
globalResults = await writeGlobalRules({
|
|
11950
|
+
editors,
|
|
11951
|
+
mode: input.mode,
|
|
11952
|
+
overwriteExisting: input.overwrite_existing
|
|
11953
|
+
});
|
|
11954
|
+
}
|
|
11955
|
+
}
|
|
11956
|
+
const createdCount = results.filter((r) => r.status === "created" || r.status === "updated" || r.status === "appended").length;
|
|
11957
|
+
const skippedCount = results.filter((r) => r.status.startsWith("skipped")).length;
|
|
11958
|
+
const baseMessage = input.dry_run ? "Dry run complete. Use dry_run: false to write files." : skippedCount > 0 ? `Generated ${createdCount} rule files. ${skippedCount} skipped (existing files). Re-run with overwrite_existing: true to replace ContextStream blocks.` : `Generated ${createdCount} rule files.`;
|
|
11959
|
+
const globalPrompt = input.apply_global ? "Global rule update complete." : globalTargets.length > 0 ? "Apply rules globally too? Re-run with apply_global: true." : "No global rule locations are known for these editors.";
|
|
11960
|
+
const summary = {
|
|
11961
|
+
folder: folderPath,
|
|
11962
|
+
results,
|
|
11963
|
+
...globalResults ? { global_results: globalResults } : {},
|
|
11964
|
+
...globalTargets.length > 0 ? { global_targets: globalTargets } : {},
|
|
11965
|
+
message: baseMessage,
|
|
11966
|
+
global_prompt: globalPrompt
|
|
11967
|
+
};
|
|
11968
|
+
return { content: [{ type: "text", text: formatContent(summary) }], structuredContent: toStructured(summary) };
|
|
11969
|
+
}
|
|
11970
|
+
);
|
|
11822
11971
|
registerTool(
|
|
11823
11972
|
"generate_editor_rules",
|
|
11824
11973
|
{
|
|
@@ -15169,7 +15318,8 @@ function registerPrompts(server) {
|
|
|
15169
15318
|
"- Otherwise ask me for an absolute folder path.",
|
|
15170
15319
|
"- Ask which editor(s) (windsurf,cursor,cline,kilo,roo,claude,aider) or default to all.",
|
|
15171
15320
|
"",
|
|
15172
|
-
"Then call `
|
|
15321
|
+
"Then call `generate_rules` and confirm which files were created/updated.",
|
|
15322
|
+
"Ask if the user also wants to apply rules globally (pass apply_global: true)."
|
|
15173
15323
|
].join("\n")
|
|
15174
15324
|
}
|
|
15175
15325
|
}
|
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.21",
|
|
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",
|