@contextstream/mcp-server 0.4.56 → 0.4.57
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 +264 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -312,8 +312,8 @@ function detectUpdateMethod() {
|
|
|
312
312
|
if (execPath.includes("node_modules") || execPath.includes("npm")) {
|
|
313
313
|
return "npm";
|
|
314
314
|
}
|
|
315
|
-
const
|
|
316
|
-
if (
|
|
315
|
+
const os2 = platform();
|
|
316
|
+
if (os2 === "win32") {
|
|
317
317
|
return "powershell";
|
|
318
318
|
}
|
|
319
319
|
return "curl";
|
|
@@ -10373,6 +10373,10 @@ function rewriteNotFoundMessage(input) {
|
|
|
10373
10373
|
// src/files.ts
|
|
10374
10374
|
import * as fs2 from "fs";
|
|
10375
10375
|
import * as path2 from "path";
|
|
10376
|
+
import { exec } from "child_process";
|
|
10377
|
+
import { promisify } from "util";
|
|
10378
|
+
import * as os from "os";
|
|
10379
|
+
import * as crypto from "crypto";
|
|
10376
10380
|
|
|
10377
10381
|
// src/ignore.ts
|
|
10378
10382
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
@@ -10446,6 +10450,7 @@ async function loadIgnorePatterns(projectRoot) {
|
|
|
10446
10450
|
}
|
|
10447
10451
|
|
|
10448
10452
|
// src/files.ts
|
|
10453
|
+
var execAsync = promisify(exec);
|
|
10449
10454
|
var CODE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
10450
10455
|
// Rust
|
|
10451
10456
|
"rs",
|
|
@@ -10553,12 +10558,116 @@ var MAX_FILE_SIZE = 1024 * 1024;
|
|
|
10553
10558
|
var MAX_BATCH_BYTES = 10 * 1024 * 1024;
|
|
10554
10559
|
var LARGE_FILE_THRESHOLD = 2 * 1024 * 1024;
|
|
10555
10560
|
var MAX_FILES_PER_BATCH = 200;
|
|
10561
|
+
var gitContextCache = /* @__PURE__ */ new Map();
|
|
10562
|
+
function getMachineId() {
|
|
10563
|
+
const hostname2 = os.hostname();
|
|
10564
|
+
const hash = crypto.createHash("sha256").update(hostname2).digest("hex");
|
|
10565
|
+
return hash.substring(0, 12);
|
|
10566
|
+
}
|
|
10567
|
+
async function isGitRepo(rootPath) {
|
|
10568
|
+
try {
|
|
10569
|
+
await execAsync("git rev-parse --is-inside-work-tree", {
|
|
10570
|
+
cwd: rootPath,
|
|
10571
|
+
timeout: 5e3
|
|
10572
|
+
});
|
|
10573
|
+
return true;
|
|
10574
|
+
} catch {
|
|
10575
|
+
return false;
|
|
10576
|
+
}
|
|
10577
|
+
}
|
|
10578
|
+
async function getGitBranch(rootPath) {
|
|
10579
|
+
try {
|
|
10580
|
+
const { stdout: stdout2 } = await execAsync("git branch --show-current", {
|
|
10581
|
+
cwd: rootPath,
|
|
10582
|
+
timeout: 5e3
|
|
10583
|
+
});
|
|
10584
|
+
const branch = stdout2.trim();
|
|
10585
|
+
return branch || void 0;
|
|
10586
|
+
} catch {
|
|
10587
|
+
return void 0;
|
|
10588
|
+
}
|
|
10589
|
+
}
|
|
10590
|
+
async function getGitDefaultBranch(rootPath) {
|
|
10591
|
+
try {
|
|
10592
|
+
const { stdout: stdout2 } = await execAsync(
|
|
10593
|
+
"git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null",
|
|
10594
|
+
{ cwd: rootPath, timeout: 5e3 }
|
|
10595
|
+
);
|
|
10596
|
+
const match = stdout2.trim().match(/refs\/remotes\/origin\/(.+)/);
|
|
10597
|
+
if (match) return match[1];
|
|
10598
|
+
} catch {
|
|
10599
|
+
}
|
|
10600
|
+
try {
|
|
10601
|
+
const { stdout: stdout2 } = await execAsync(
|
|
10602
|
+
"git config --get init.defaultBranch 2>/dev/null",
|
|
10603
|
+
{ cwd: rootPath, timeout: 5e3 }
|
|
10604
|
+
);
|
|
10605
|
+
const branch = stdout2.trim();
|
|
10606
|
+
if (branch) return branch;
|
|
10607
|
+
} catch {
|
|
10608
|
+
}
|
|
10609
|
+
try {
|
|
10610
|
+
const { stdout: stdout2 } = await execAsync("git branch --list main master", {
|
|
10611
|
+
cwd: rootPath,
|
|
10612
|
+
timeout: 5e3
|
|
10613
|
+
});
|
|
10614
|
+
const branches = stdout2.trim().split("\n").map((b) => b.replace(/^\*?\s*/, "").trim()).filter(Boolean);
|
|
10615
|
+
if (branches.includes("main")) return "main";
|
|
10616
|
+
if (branches.includes("master")) return "master";
|
|
10617
|
+
} catch {
|
|
10618
|
+
}
|
|
10619
|
+
return void 0;
|
|
10620
|
+
}
|
|
10621
|
+
async function getFileGitInfo(rootPath, relativePath) {
|
|
10622
|
+
try {
|
|
10623
|
+
const { stdout: stdout2 } = await execAsync(
|
|
10624
|
+
`git log -1 --format="%H %ct" -- "${relativePath}"`,
|
|
10625
|
+
{ cwd: rootPath, timeout: 5e3 }
|
|
10626
|
+
);
|
|
10627
|
+
const parts = stdout2.trim().split(" ");
|
|
10628
|
+
if (parts.length >= 2) {
|
|
10629
|
+
const sha = parts[0];
|
|
10630
|
+
const unixTimestamp = parseInt(parts[1], 10);
|
|
10631
|
+
if (sha && !isNaN(unixTimestamp)) {
|
|
10632
|
+
const timestamp = new Date(unixTimestamp * 1e3).toISOString();
|
|
10633
|
+
return { sha, timestamp };
|
|
10634
|
+
}
|
|
10635
|
+
}
|
|
10636
|
+
} catch {
|
|
10637
|
+
}
|
|
10638
|
+
return void 0;
|
|
10639
|
+
}
|
|
10640
|
+
async function getGitContext(rootPath) {
|
|
10641
|
+
const cached = gitContextCache.get(rootPath);
|
|
10642
|
+
if (cached) return cached;
|
|
10643
|
+
const machineId = getMachineId();
|
|
10644
|
+
const isRepo = await isGitRepo(rootPath);
|
|
10645
|
+
if (!isRepo) {
|
|
10646
|
+
const context2 = { isGitRepo: false, machineId };
|
|
10647
|
+
gitContextCache.set(rootPath, context2);
|
|
10648
|
+
return context2;
|
|
10649
|
+
}
|
|
10650
|
+
const [branch, defaultBranch] = await Promise.all([
|
|
10651
|
+
getGitBranch(rootPath),
|
|
10652
|
+
getGitDefaultBranch(rootPath)
|
|
10653
|
+
]);
|
|
10654
|
+
const context = {
|
|
10655
|
+
isGitRepo: true,
|
|
10656
|
+
branch,
|
|
10657
|
+
defaultBranch,
|
|
10658
|
+
isDefaultBranch: branch !== void 0 && branch === defaultBranch,
|
|
10659
|
+
machineId
|
|
10660
|
+
};
|
|
10661
|
+
gitContextCache.set(rootPath, context);
|
|
10662
|
+
return context;
|
|
10663
|
+
}
|
|
10556
10664
|
async function* readAllFilesInBatches(rootPath, options = {}) {
|
|
10557
10665
|
const maxBatchBytes = options.maxBatchBytes ?? MAX_BATCH_BYTES;
|
|
10558
10666
|
const largeFileThreshold = options.largeFileThreshold ?? LARGE_FILE_THRESHOLD;
|
|
10559
10667
|
const maxFilesPerBatch = options.maxFilesPerBatch ?? options.batchSize ?? MAX_FILES_PER_BATCH;
|
|
10560
10668
|
const maxFileSize = options.maxFileSize ?? MAX_FILE_SIZE;
|
|
10561
10669
|
const ig = options.ignoreInstance ?? await loadIgnorePatterns(rootPath);
|
|
10670
|
+
const gitCtx = await getGitContext(rootPath);
|
|
10562
10671
|
let batch = [];
|
|
10563
10672
|
let currentBatchBytes = 0;
|
|
10564
10673
|
async function* walkDir(dir, relativePath = "") {
|
|
@@ -10584,7 +10693,25 @@ async function* readAllFilesInBatches(rootPath, options = {}) {
|
|
|
10584
10693
|
const stat2 = await fs2.promises.stat(fullPath);
|
|
10585
10694
|
if (stat2.size > maxFileSize) continue;
|
|
10586
10695
|
const content = await fs2.promises.readFile(fullPath, "utf-8");
|
|
10587
|
-
|
|
10696
|
+
const file = {
|
|
10697
|
+
path: relPath,
|
|
10698
|
+
content,
|
|
10699
|
+
sizeBytes: stat2.size,
|
|
10700
|
+
// Always include machine_id and source_modified_at
|
|
10701
|
+
machine_id: gitCtx.machineId,
|
|
10702
|
+
source_modified_at: stat2.mtime.toISOString()
|
|
10703
|
+
};
|
|
10704
|
+
if (gitCtx.isGitRepo) {
|
|
10705
|
+
file.git_branch = gitCtx.branch;
|
|
10706
|
+
file.git_default_branch = gitCtx.defaultBranch;
|
|
10707
|
+
file.is_default_branch = gitCtx.isDefaultBranch;
|
|
10708
|
+
const gitInfo = await getFileGitInfo(rootPath, relPath);
|
|
10709
|
+
if (gitInfo) {
|
|
10710
|
+
file.git_commit_sha = gitInfo.sha;
|
|
10711
|
+
file.git_commit_timestamp = gitInfo.timestamp;
|
|
10712
|
+
}
|
|
10713
|
+
}
|
|
10714
|
+
yield file;
|
|
10588
10715
|
} catch {
|
|
10589
10716
|
}
|
|
10590
10717
|
}
|
|
@@ -10593,11 +10720,12 @@ async function* readAllFilesInBatches(rootPath, options = {}) {
|
|
|
10593
10720
|
for await (const file of walkDir(rootPath)) {
|
|
10594
10721
|
if (file.sizeBytes > largeFileThreshold) {
|
|
10595
10722
|
if (batch.length > 0) {
|
|
10596
|
-
yield batch.map(({ sizeBytes, ...rest }) => rest);
|
|
10723
|
+
yield batch.map(({ sizeBytes: sizeBytes2, ...rest }) => rest);
|
|
10597
10724
|
batch = [];
|
|
10598
10725
|
currentBatchBytes = 0;
|
|
10599
10726
|
}
|
|
10600
|
-
|
|
10727
|
+
const { sizeBytes, ...fileData } = file;
|
|
10728
|
+
yield [fileData];
|
|
10601
10729
|
continue;
|
|
10602
10730
|
}
|
|
10603
10731
|
const wouldExceedBytes = currentBatchBytes + file.sizeBytes > maxBatchBytes;
|
|
@@ -10623,6 +10751,7 @@ async function* readChangedFilesInBatches(rootPath, sinceTimestamp, options = {}
|
|
|
10623
10751
|
const maxFileSize = options.maxFileSize ?? MAX_FILE_SIZE;
|
|
10624
10752
|
const sinceMs = sinceTimestamp.getTime();
|
|
10625
10753
|
const ig = options.ignoreInstance ?? await loadIgnorePatterns(rootPath);
|
|
10754
|
+
const gitCtx = await getGitContext(rootPath);
|
|
10626
10755
|
let batch = [];
|
|
10627
10756
|
let currentBatchBytes = 0;
|
|
10628
10757
|
let filesScanned = 0;
|
|
@@ -10653,7 +10782,25 @@ async function* readChangedFilesInBatches(rootPath, sinceTimestamp, options = {}
|
|
|
10653
10782
|
if (stat2.size > maxFileSize) continue;
|
|
10654
10783
|
const content = await fs2.promises.readFile(fullPath, "utf-8");
|
|
10655
10784
|
filesChanged++;
|
|
10656
|
-
|
|
10785
|
+
const file = {
|
|
10786
|
+
path: relPath,
|
|
10787
|
+
content,
|
|
10788
|
+
sizeBytes: stat2.size,
|
|
10789
|
+
// Always include machine_id and source_modified_at
|
|
10790
|
+
machine_id: gitCtx.machineId,
|
|
10791
|
+
source_modified_at: stat2.mtime.toISOString()
|
|
10792
|
+
};
|
|
10793
|
+
if (gitCtx.isGitRepo) {
|
|
10794
|
+
file.git_branch = gitCtx.branch;
|
|
10795
|
+
file.git_default_branch = gitCtx.defaultBranch;
|
|
10796
|
+
file.is_default_branch = gitCtx.isDefaultBranch;
|
|
10797
|
+
const gitInfo = await getFileGitInfo(rootPath, relPath);
|
|
10798
|
+
if (gitInfo) {
|
|
10799
|
+
file.git_commit_sha = gitInfo.sha;
|
|
10800
|
+
file.git_commit_timestamp = gitInfo.timestamp;
|
|
10801
|
+
}
|
|
10802
|
+
}
|
|
10803
|
+
yield file;
|
|
10657
10804
|
} catch {
|
|
10658
10805
|
}
|
|
10659
10806
|
}
|
|
@@ -10662,11 +10809,12 @@ async function* readChangedFilesInBatches(rootPath, sinceTimestamp, options = {}
|
|
|
10662
10809
|
for await (const file of walkDir(rootPath)) {
|
|
10663
10810
|
if (file.sizeBytes > largeFileThreshold) {
|
|
10664
10811
|
if (batch.length > 0) {
|
|
10665
|
-
yield batch.map(({ sizeBytes, ...rest }) => rest);
|
|
10812
|
+
yield batch.map(({ sizeBytes: sizeBytes2, ...rest }) => rest);
|
|
10666
10813
|
batch = [];
|
|
10667
10814
|
currentBatchBytes = 0;
|
|
10668
10815
|
}
|
|
10669
|
-
|
|
10816
|
+
const { sizeBytes, ...fileData } = file;
|
|
10817
|
+
yield [fileData];
|
|
10670
10818
|
continue;
|
|
10671
10819
|
}
|
|
10672
10820
|
const wouldExceedBytes = currentBatchBytes + file.sizeBytes > maxBatchBytes;
|
|
@@ -11763,6 +11911,26 @@ var ContextStreamClient = class {
|
|
|
11763
11911
|
uuidSchema.parse(projectId);
|
|
11764
11912
|
return request(this.config, `/projects/${projectId}/index/status`, { method: "GET" });
|
|
11765
11913
|
}
|
|
11914
|
+
/**
|
|
11915
|
+
* Get index history for audit trail
|
|
11916
|
+
* Shows which files were indexed, when, by which machine, and from which branch
|
|
11917
|
+
*/
|
|
11918
|
+
projectIndexHistory(projectId, params) {
|
|
11919
|
+
uuidSchema.parse(projectId);
|
|
11920
|
+
const queryParams = new URLSearchParams();
|
|
11921
|
+
if (params?.machine_id) queryParams.set("machine_id", params.machine_id);
|
|
11922
|
+
if (params?.branch) queryParams.set("branch", params.branch);
|
|
11923
|
+
if (params?.since) queryParams.set("since", params.since);
|
|
11924
|
+
if (params?.until) queryParams.set("until", params.until);
|
|
11925
|
+
if (params?.path_pattern) queryParams.set("path_pattern", params.path_pattern);
|
|
11926
|
+
if (params?.sort_by) queryParams.set("sort_by", params.sort_by);
|
|
11927
|
+
if (params?.sort_order) queryParams.set("sort_order", params.sort_order);
|
|
11928
|
+
if (params?.page) queryParams.set("page", params.page.toString());
|
|
11929
|
+
if (params?.limit) queryParams.set("limit", params.limit.toString());
|
|
11930
|
+
const queryString = queryParams.toString();
|
|
11931
|
+
const url = `/projects/${projectId}/index/history${queryString ? `?${queryString}` : ""}`;
|
|
11932
|
+
return request(this.config, url, { method: "GET" });
|
|
11933
|
+
}
|
|
11766
11934
|
/**
|
|
11767
11935
|
* Check if project ingestion is recommended and return a recommendation.
|
|
11768
11936
|
* This is used by session_init to inform the AI about the project's index status.
|
|
@@ -11837,10 +12005,11 @@ var ContextStreamClient = class {
|
|
|
11837
12005
|
* Ingest files for indexing
|
|
11838
12006
|
* This uploads files to the API for indexing
|
|
11839
12007
|
* @param projectId - Project UUID
|
|
11840
|
-
* @param files - Array of files to ingest
|
|
12008
|
+
* @param files - Array of files to ingest (with optional version metadata)
|
|
11841
12009
|
* @param options - Optional ingest options
|
|
11842
12010
|
* @param options.write_to_disk - When true, write files to disk under QA_FILE_WRITE_ROOT before indexing
|
|
11843
12011
|
* @param options.overwrite - Allow overwriting existing files when write_to_disk is enabled
|
|
12012
|
+
* @param options.force - When true, bypass version checking and force re-index all files
|
|
11844
12013
|
*/
|
|
11845
12014
|
ingestFiles(projectId, files, options) {
|
|
11846
12015
|
uuidSchema.parse(projectId);
|
|
@@ -11848,7 +12017,8 @@ var ContextStreamClient = class {
|
|
|
11848
12017
|
body: {
|
|
11849
12018
|
files,
|
|
11850
12019
|
...options?.write_to_disk !== void 0 && { write_to_disk: options.write_to_disk },
|
|
11851
|
-
...options?.overwrite !== void 0 && { overwrite: options.overwrite }
|
|
12020
|
+
...options?.overwrite !== void 0 && { overwrite: options.overwrite },
|
|
12021
|
+
...options?.force !== void 0 && { force: options.force }
|
|
11852
12022
|
}
|
|
11853
12023
|
});
|
|
11854
12024
|
}
|
|
@@ -11946,6 +12116,23 @@ var ContextStreamClient = class {
|
|
|
11946
12116
|
uuidSchema.parse(workspaceId);
|
|
11947
12117
|
return request(this.config, `/workspaces/${workspaceId}/content`, { method: "GET" });
|
|
11948
12118
|
}
|
|
12119
|
+
/**
|
|
12120
|
+
* Get workspace index settings for multi-machine sync configuration
|
|
12121
|
+
*/
|
|
12122
|
+
getWorkspaceIndexSettings(workspaceId) {
|
|
12123
|
+
uuidSchema.parse(workspaceId);
|
|
12124
|
+
return request(this.config, `/workspaces/${workspaceId}/index-settings`, { method: "GET" });
|
|
12125
|
+
}
|
|
12126
|
+
/**
|
|
12127
|
+
* Update workspace index settings (admin only)
|
|
12128
|
+
*/
|
|
12129
|
+
updateWorkspaceIndexSettings(workspaceId, settings) {
|
|
12130
|
+
uuidSchema.parse(workspaceId);
|
|
12131
|
+
return request(this.config, `/workspaces/${workspaceId}/index-settings`, {
|
|
12132
|
+
method: "PUT",
|
|
12133
|
+
body: settings
|
|
12134
|
+
});
|
|
12135
|
+
}
|
|
11949
12136
|
// Memory extended operations
|
|
11950
12137
|
getMemoryEvent(eventId) {
|
|
11951
12138
|
uuidSchema.parse(eventId);
|
|
@@ -24991,7 +25178,7 @@ ${formatContent(result)}`
|
|
|
24991
25178
|
"project",
|
|
24992
25179
|
{
|
|
24993
25180
|
title: "Project",
|
|
24994
|
-
description: `Project management. Actions: list, get, create, update, index (trigger indexing), overview, statistics, files, index_status, ingest_local (index local folder), team_projects (list all team projects - team plans only).`,
|
|
25181
|
+
description: `Project management. Actions: list, get, create, update, index (trigger indexing), overview, statistics, files, index_status, index_history (audit trail of indexed files), ingest_local (index local folder), team_projects (list all team projects - team plans only).`,
|
|
24995
25182
|
inputSchema: external_exports.object({
|
|
24996
25183
|
action: external_exports.enum([
|
|
24997
25184
|
"list",
|
|
@@ -25003,6 +25190,7 @@ ${formatContent(result)}`
|
|
|
25003
25190
|
"statistics",
|
|
25004
25191
|
"files",
|
|
25005
25192
|
"index_status",
|
|
25193
|
+
"index_history",
|
|
25006
25194
|
"ingest_local",
|
|
25007
25195
|
"team_projects"
|
|
25008
25196
|
]).describe("Action to perform"),
|
|
@@ -25017,6 +25205,15 @@ ${formatContent(result)}`
|
|
|
25017
25205
|
path: external_exports.string().optional().describe("Local path to ingest"),
|
|
25018
25206
|
overwrite: external_exports.boolean().optional(),
|
|
25019
25207
|
write_to_disk: external_exports.boolean().optional(),
|
|
25208
|
+
force: external_exports.boolean().optional().describe("Force re-index all files, bypassing version check logic"),
|
|
25209
|
+
// Index history filters
|
|
25210
|
+
machine_id: external_exports.string().optional().describe("Filter by machine ID that indexed the files"),
|
|
25211
|
+
branch: external_exports.string().optional().describe("Filter by git branch"),
|
|
25212
|
+
since: external_exports.string().optional().describe("Filter files indexed after this timestamp (ISO 8601)"),
|
|
25213
|
+
until: external_exports.string().optional().describe("Filter files indexed before this timestamp (ISO 8601)"),
|
|
25214
|
+
path_pattern: external_exports.string().optional().describe("Filter by file path pattern (partial match)"),
|
|
25215
|
+
sort_by: external_exports.enum(["path", "indexed", "size"]).optional().describe("Sort field (default: indexed)"),
|
|
25216
|
+
sort_order: external_exports.enum(["asc", "desc"]).optional().describe("Sort order (default: desc)"),
|
|
25020
25217
|
// Pagination
|
|
25021
25218
|
page: external_exports.number().optional(),
|
|
25022
25219
|
page_size: external_exports.number().optional()
|
|
@@ -25115,6 +25312,25 @@ ${formatContent(result)}`
|
|
|
25115
25312
|
content: [{ type: "text", text: formatContent(result) }]
|
|
25116
25313
|
};
|
|
25117
25314
|
}
|
|
25315
|
+
case "index_history": {
|
|
25316
|
+
if (!projectId) {
|
|
25317
|
+
return errorResult("index_history requires: project_id");
|
|
25318
|
+
}
|
|
25319
|
+
const result = await client.projectIndexHistory(projectId, {
|
|
25320
|
+
machine_id: input.machine_id,
|
|
25321
|
+
branch: input.branch,
|
|
25322
|
+
since: input.since,
|
|
25323
|
+
until: input.until,
|
|
25324
|
+
path_pattern: input.path_pattern,
|
|
25325
|
+
sort_by: input.sort_by,
|
|
25326
|
+
sort_order: input.sort_order,
|
|
25327
|
+
page: input.page,
|
|
25328
|
+
limit: input.page_size
|
|
25329
|
+
});
|
|
25330
|
+
return {
|
|
25331
|
+
content: [{ type: "text", text: formatContent(result) }]
|
|
25332
|
+
};
|
|
25333
|
+
}
|
|
25118
25334
|
case "ingest_local": {
|
|
25119
25335
|
if (!input.path) {
|
|
25120
25336
|
return errorResult("ingest_local requires: path");
|
|
@@ -25128,23 +25344,26 @@ ${formatContent(result)}`
|
|
|
25128
25344
|
}
|
|
25129
25345
|
const ingestOptions = {
|
|
25130
25346
|
...input.write_to_disk !== void 0 && { write_to_disk: input.write_to_disk },
|
|
25131
|
-
...input.overwrite !== void 0 && { overwrite: input.overwrite }
|
|
25347
|
+
...input.overwrite !== void 0 && { overwrite: input.overwrite },
|
|
25348
|
+
...input.force !== void 0 && { force: input.force }
|
|
25132
25349
|
};
|
|
25133
25350
|
startBackgroundIngest(projectId, validPath.resolvedPath, ingestOptions);
|
|
25351
|
+
const forceNote = input.force ? " (force mode - version checks bypassed)" : "";
|
|
25134
25352
|
const result = {
|
|
25135
25353
|
status: "started",
|
|
25136
|
-
message:
|
|
25354
|
+
message: `Ingestion running in background${forceNote}`,
|
|
25137
25355
|
project_id: projectId,
|
|
25138
25356
|
path: validPath.resolvedPath,
|
|
25139
25357
|
...input.write_to_disk !== void 0 && { write_to_disk: input.write_to_disk },
|
|
25140
25358
|
...input.overwrite !== void 0 && { overwrite: input.overwrite },
|
|
25359
|
+
...input.force !== void 0 && { force: input.force },
|
|
25141
25360
|
note: "Use 'project' with action 'index_status' to monitor progress."
|
|
25142
25361
|
};
|
|
25143
25362
|
return {
|
|
25144
25363
|
content: [
|
|
25145
25364
|
{
|
|
25146
25365
|
type: "text",
|
|
25147
|
-
text: `Ingestion started in background for directory: ${validPath.resolvedPath}. Use 'project' with action 'index_status' to monitor progress.`
|
|
25366
|
+
text: `Ingestion started in background${forceNote} for directory: ${validPath.resolvedPath}. Use 'project' with action 'index_status' to monitor progress.`
|
|
25148
25367
|
}
|
|
25149
25368
|
]
|
|
25150
25369
|
};
|
|
@@ -25178,9 +25397,9 @@ ${formatContent(result)}`
|
|
|
25178
25397
|
"workspace",
|
|
25179
25398
|
{
|
|
25180
25399
|
title: "Workspace",
|
|
25181
|
-
description: `Workspace management. Actions: list, get, associate (link folder to workspace), bootstrap (create workspace and initialize), team_members (list members with access - team plans only).`,
|
|
25400
|
+
description: `Workspace management. Actions: list, get, associate (link folder to workspace), bootstrap (create workspace and initialize), team_members (list members with access - team plans only), index_settings (get/update multi-machine sync settings - admin only).`,
|
|
25182
25401
|
inputSchema: external_exports.object({
|
|
25183
|
-
action: external_exports.enum(["list", "get", "associate", "bootstrap", "team_members"]).describe("Action to perform"),
|
|
25402
|
+
action: external_exports.enum(["list", "get", "associate", "bootstrap", "team_members", "index_settings"]).describe("Action to perform"),
|
|
25184
25403
|
workspace_id: external_exports.string().uuid().optional(),
|
|
25185
25404
|
// Associate/bootstrap params
|
|
25186
25405
|
folder_path: external_exports.string().optional(),
|
|
@@ -25192,6 +25411,12 @@ ${formatContent(result)}`
|
|
|
25192
25411
|
visibility: external_exports.enum(["private", "public"]).optional(),
|
|
25193
25412
|
auto_index: external_exports.boolean().optional(),
|
|
25194
25413
|
context_hint: external_exports.string().optional(),
|
|
25414
|
+
// Index settings params (for update)
|
|
25415
|
+
branch_policy: external_exports.enum(["default_branch_wins", "newest_wins", "feature_branch_wins"]).optional().describe("Which branch takes priority: default_branch_wins (default), newest_wins, feature_branch_wins"),
|
|
25416
|
+
conflict_resolution: external_exports.enum(["newest_timestamp", "default_branch", "manual"]).optional().describe("How to resolve conflicts: newest_timestamp (default), default_branch, manual"),
|
|
25417
|
+
allowed_machines: external_exports.array(external_exports.string()).optional().describe("List of allowed machine IDs (empty = all allowed)"),
|
|
25418
|
+
auto_sync_enabled: external_exports.boolean().optional().describe("Whether to auto-sync from all machines (default: true)"),
|
|
25419
|
+
max_machines: external_exports.number().optional().describe("Maximum machines allowed to index (0 = unlimited)"),
|
|
25195
25420
|
// Pagination
|
|
25196
25421
|
page: external_exports.number().optional(),
|
|
25197
25422
|
page_size: external_exports.number().optional()
|
|
@@ -25295,6 +25520,29 @@ ${formatContent(result)}`
|
|
|
25295
25520
|
content: [{ type: "text", text: formatContent(teamMembers) }]
|
|
25296
25521
|
};
|
|
25297
25522
|
}
|
|
25523
|
+
case "index_settings": {
|
|
25524
|
+
if (!input.workspace_id) {
|
|
25525
|
+
return errorResult("index_settings requires: workspace_id");
|
|
25526
|
+
}
|
|
25527
|
+
const hasUpdateParams = input.branch_policy !== void 0 || input.conflict_resolution !== void 0 || input.allowed_machines !== void 0 || input.auto_sync_enabled !== void 0 || input.max_machines !== void 0;
|
|
25528
|
+
if (hasUpdateParams) {
|
|
25529
|
+
const result = await client.updateWorkspaceIndexSettings(input.workspace_id, {
|
|
25530
|
+
branch_policy: input.branch_policy,
|
|
25531
|
+
conflict_resolution: input.conflict_resolution,
|
|
25532
|
+
allowed_machines: input.allowed_machines,
|
|
25533
|
+
auto_sync_enabled: input.auto_sync_enabled,
|
|
25534
|
+
max_machines: input.max_machines
|
|
25535
|
+
});
|
|
25536
|
+
return {
|
|
25537
|
+
content: [{ type: "text", text: formatContent(result) }]
|
|
25538
|
+
};
|
|
25539
|
+
} else {
|
|
25540
|
+
const result = await client.getWorkspaceIndexSettings(input.workspace_id);
|
|
25541
|
+
return {
|
|
25542
|
+
content: [{ type: "text", text: formatContent(result) }]
|
|
25543
|
+
};
|
|
25544
|
+
}
|
|
25545
|
+
}
|
|
25298
25546
|
default:
|
|
25299
25547
|
return errorResult(`Unknown action: ${input.action}`);
|
|
25300
25548
|
}
|
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.57",
|
|
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",
|