@netique/overleaf-mcp 0.2.1 → 0.3.0
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 +1 -0
- package/dist/auth/browserLogin.js +18 -2
- package/dist/auth/browserLogin.js.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/tools/findAndReplace.js +192 -0
- package/dist/tools/findAndReplace.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@ Working end-to-end against `overleaf.com` — 16 tools, tracked-changes edits an
|
|
|
29
29
|
| `list_files` | Lists the file tree of the open project (cached, no network). Filter by `kind` and `path_contains`. |
|
|
30
30
|
| `read_file` | Reads a doc (returns text + OT version + a summary of tracked changes / comments) or a binary file (base64 + MIME). `path` is optional — defaults to the project's root doc. |
|
|
31
31
|
| `edit_file` | Replaces a doc's contents. Computes a minimal diff via `diff-match-patch`, submits it as an OT operation, and adds `meta.tc` so the edit lands as a pending suggestion in the Review panel by default. Pass `track: "off"` to write directly or `track: "auto"` to honor the project's track-changes setting. `path` is optional — defaults to the project's root doc. |
|
|
32
|
+
| `find_and_replace` | Surgical edit: replace one occurrence (or all, with `replace_all: true`) of `old_string` with `new_string` without re-emitting the rest of the doc. Cheaper in tokens than `edit_file` for targeted changes and avoids whitespace drift from re-emitting surrounding text. By default `old_string` must be unique; ambiguous matches return a list of line:col locations so you can extend the match. Same `track` defaults and OT path as `edit_file`, so it lands as a pending suggestion in the Review panel. |
|
|
32
33
|
| `list_tracked_changes` | Enumerates every pending tracked-change suggestion across the open project, with author name + email, doc path, op kind (insert/delete), position, op text, change_id. Filter by `author_email`, `author_id_endswith`, `path_contains`, `kind`, `text_contains`, `limit`. |
|
|
33
34
|
| `accept_changes` | Accepts one or more tracked changes by `change_id` (from `list_tracked_changes`). Multi-doc groups are batched automatically. Irreversible. |
|
|
34
35
|
| `reject_changes` | Rejects one or more tracked changes by `change_id`. Implemented as `applyOtUpdate` with the inverse op + `u:true` (same pathway Overleaf's web client uses). Irreversible. |
|
|
@@ -35,7 +35,9 @@ async function readDevToolsPort(profile, deadline) {
|
|
|
35
35
|
}
|
|
36
36
|
await new Promise((r) => setTimeout(r, 50));
|
|
37
37
|
}
|
|
38
|
-
throw new Error(
|
|
38
|
+
throw new Error(`Browser auth setup failed: Chrome was spawned but did not open its DevTools port within timeout. ` +
|
|
39
|
+
`This is a local environment problem — likely a broken Chrome install or a non-writable profile dir at ${profile}. ` +
|
|
40
|
+
`Do not retry the MCP call without user intervention; it will hit the same error. Ask the user to verify Chrome works manually.`);
|
|
39
41
|
}
|
|
40
42
|
function chromeFlags(profile, insecure) {
|
|
41
43
|
// Note: no URL argument here. We spawn Chrome with about:blank and then
|
|
@@ -87,6 +89,12 @@ export async function captureCookie(baseUrl, opts = {}) {
|
|
|
87
89
|
const chromePath = await findChrome(config.browserPath);
|
|
88
90
|
const profile = profileDir();
|
|
89
91
|
await fs.mkdir(profile, { recursive: true });
|
|
92
|
+
// Remove any DevToolsActivePort left behind by a previous Chrome — if we
|
|
93
|
+
// read a stale file, we'd try to connect to a port that nothing is bound
|
|
94
|
+
// to and surface as ECONNREFUSED to the caller. Deleting before spawn
|
|
95
|
+
// means the file's reappearance is a positive signal that the just-
|
|
96
|
+
// spawned Chrome is actually listening.
|
|
97
|
+
await fs.rm(path.join(profile, "DevToolsActivePort"), { force: true });
|
|
90
98
|
const args = chromeFlags(profile, config.insecure);
|
|
91
99
|
logger.info(`launching ${chromePath} (profile=${profile})`);
|
|
92
100
|
const child = spawn(chromePath, args, { stdio: "ignore", detached: false });
|
|
@@ -103,7 +111,15 @@ export async function captureCookie(baseUrl, opts = {}) {
|
|
|
103
111
|
if (earlyExitErr)
|
|
104
112
|
throw earlyExitErr;
|
|
105
113
|
const browserWsUrl = `ws://127.0.0.1:${port}${browserWsPath}`;
|
|
106
|
-
|
|
114
|
+
try {
|
|
115
|
+
cdp = await CdpClient.connect(browserWsUrl);
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
const msg = err.message ?? String(err);
|
|
119
|
+
throw new Error(`Browser auth setup failed: Chrome wrote a DevTools port (${port}) but the endpoint refused our connection (${msg}). ` +
|
|
120
|
+
`This is a local environment problem, NOT an Overleaf or network issue — retrying the same MCP call will hit the same error. ` +
|
|
121
|
+
`Ask the user to restart Claude (Desktop or Code) so the MCP server is respawned; if the failure persists, the Chrome profile at ${profile} may need to be removed.`);
|
|
122
|
+
}
|
|
107
123
|
// Reuse the about:blank tab Chrome opened on spawn. Creating a second
|
|
108
124
|
// target makes Overleaf see two concurrent /login requests, which it
|
|
109
125
|
// rejects with a generic "Session error" page.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserLogin.js","sourceRoot":"","sources":["../../src/auth/browserLogin.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,wEAAwE;AACxE,wEAAwE;AACxE,2BAA2B;AAE3B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAY/C,SAAS,UAAU;IACjB,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC;IACpG,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAC9G,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,OAAe,EAAE,QAAgB;IAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC5C,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9B,IAAI,IAAI,GAAG,CAAC,IAAI,QAAQ;gBAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,kBAAkB;QACpB,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,IAAI,KAAK,
|
|
1
|
+
{"version":3,"file":"browserLogin.js","sourceRoot":"","sources":["../../src/auth/browserLogin.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { registerOpenProject } from "./tools/openProject.js";
|
|
|
7
7
|
import { registerListFiles } from "./tools/listFiles.js";
|
|
8
8
|
import { registerReadFile } from "./tools/readFile.js";
|
|
9
9
|
import { registerEditFile } from "./tools/editFile.js";
|
|
10
|
+
import { registerFindAndReplace } from "./tools/findAndReplace.js";
|
|
10
11
|
import { registerCompile, registerReadLog } from "./tools/compile.js";
|
|
11
12
|
import { registerComments } from "./tools/comments.js";
|
|
12
13
|
import { registerTrackedChanges } from "./tools/trackedChanges.js";
|
|
@@ -27,6 +28,17 @@ const INSTRUCTIONS = [
|
|
|
27
28
|
" 2. open_project(id) -> joins the Socket.IO room, returns file tree + tc state",
|
|
28
29
|
" 3. read_file / edit_file by path (e.g. 'chapters/intro.tex')",
|
|
29
30
|
" 4. compile to verify edits build",
|
|
31
|
+
"",
|
|
32
|
+
"Auth UX (important for the user-facing message):",
|
|
33
|
+
"If no session cookie is stored yet, or the previous one has expired (Overleaf",
|
|
34
|
+
"cookies last ~5 days), the next tool call will spawn an isolated Chrome window",
|
|
35
|
+
"pointed at Overleaf so the user can log in. The window uses a dedicated profile",
|
|
36
|
+
"that does NOT share the user's main browser data, saved passwords, or any",
|
|
37
|
+
"password-manager extension — they must type their Overleaf credentials (or",
|
|
38
|
+
"click their SSO provider) manually. The window then closes automatically.",
|
|
39
|
+
"Before triggering an Overleaf tool call when you don't already know the user",
|
|
40
|
+
"is authenticated, briefly warn them: \"a Chrome window may pop up asking you",
|
|
41
|
+
"to log in — type your credentials there, it's a clean isolated profile.\"",
|
|
30
42
|
].join("\n");
|
|
31
43
|
async function main() {
|
|
32
44
|
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION }, { instructions: INSTRUCTIONS });
|
|
@@ -43,6 +55,7 @@ async function main() {
|
|
|
43
55
|
registerListFiles(server);
|
|
44
56
|
registerReadFile(server);
|
|
45
57
|
registerEditFile(server);
|
|
58
|
+
registerFindAndReplace(server);
|
|
46
59
|
registerCompile(server);
|
|
47
60
|
registerReadLog(server);
|
|
48
61
|
registerComments(server);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,KAAK,IAAI,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,WAAW,GAAG,cAAc,CAAC;AACnC,wEAAwE;AACxE,yEAAyE;AACzE,yEAAyE;AACzE,MAAM,cAAc,GAClB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAC7E,CAAC,OAAO,CAAC;AAEV,MAAM,YAAY,GAAG;IACnB,8EAA8E;IAC9E,oFAAoF;IACpF,EAAE;IACF,eAAe;IACf,kCAAkC;IAClC,iFAAiF;IACjF,gEAAgE;IAChE,oCAAoC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { applyOtUpdate, getActiveSocket } from "../api/socket.js";
|
|
3
|
+
import { getIdentity } from "../session/identity.js";
|
|
4
|
+
import { ensureDocLoaded, updateDoc } from "../session/docCache.js";
|
|
5
|
+
import { findByPath, getActiveProject } from "../session/activeProject.js";
|
|
6
|
+
import { textToOps } from "../ot/diff.js";
|
|
7
|
+
import { generateIdSeed } from "../ot/trackedChanges.js";
|
|
8
|
+
import { logger } from "../util/logger.js";
|
|
9
|
+
const Schema = z.object({
|
|
10
|
+
path: z
|
|
11
|
+
.string()
|
|
12
|
+
.min(1)
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Project-relative path of the doc to edit, e.g. 'main.tex'. If omitted, defaults to the project's root doc."),
|
|
15
|
+
old_string: z
|
|
16
|
+
.string()
|
|
17
|
+
.min(1)
|
|
18
|
+
.describe("Exact substring to find — must match byte-for-byte including whitespace. Must be unique in the doc unless `replace_all` is true."),
|
|
19
|
+
new_string: z
|
|
20
|
+
.string()
|
|
21
|
+
.describe("Replacement text. May be empty (effectively a delete)."),
|
|
22
|
+
replace_all: z
|
|
23
|
+
.boolean()
|
|
24
|
+
.default(false)
|
|
25
|
+
.describe("If true, replace every occurrence of `old_string`. If false (default), `old_string` must match exactly once — multi-match returns a list of locations so you can disambiguate with a longer `old_string`."),
|
|
26
|
+
expected_version: z
|
|
27
|
+
.number()
|
|
28
|
+
.int()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Optional safety check. If the doc's current version differs, the edit is rejected."),
|
|
31
|
+
track: z
|
|
32
|
+
.enum(["auto", "on", "off"])
|
|
33
|
+
.default("on")
|
|
34
|
+
.describe("Tracked-changes mode. Default 'on' lands the edit as a pending suggestion in the Review panel. 'off' writes directly; 'auto' tracks only when the project has track-changes enabled for this user."),
|
|
35
|
+
});
|
|
36
|
+
// Find every non-overlapping start index of `needle` in `haystack`.
|
|
37
|
+
export function findAllIndices(haystack, needle) {
|
|
38
|
+
if (!needle)
|
|
39
|
+
return [];
|
|
40
|
+
const out = [];
|
|
41
|
+
let i = 0;
|
|
42
|
+
while (i <= haystack.length - needle.length) {
|
|
43
|
+
const j = haystack.indexOf(needle, i);
|
|
44
|
+
if (j < 0)
|
|
45
|
+
break;
|
|
46
|
+
out.push(j);
|
|
47
|
+
i = j + needle.length;
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
// Map a char index into (1-based line, 1-based col, the full line text).
|
|
52
|
+
export function lineOf(text, idx) {
|
|
53
|
+
let line = 1;
|
|
54
|
+
let lineStart = 0;
|
|
55
|
+
for (let i = 0; i < idx; i++) {
|
|
56
|
+
if (text.charCodeAt(i) === 0x0a /* \n */) {
|
|
57
|
+
line++;
|
|
58
|
+
lineStart = i + 1;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const nextNl = text.indexOf("\n", lineStart);
|
|
62
|
+
const lineEnd = nextNl < 0 ? text.length : nextNl;
|
|
63
|
+
return { line, col: idx - lineStart + 1, lineText: text.slice(lineStart, lineEnd) };
|
|
64
|
+
}
|
|
65
|
+
export function registerFindAndReplace(server) {
|
|
66
|
+
server.registerTool("find_and_replace", {
|
|
67
|
+
title: "Surgical find-and-replace in an Overleaf doc",
|
|
68
|
+
description: "Replace one occurrence — or all, with `replace_all: true` — of `old_string` with `new_string` in a doc, without re-emitting the rest of the file. " +
|
|
69
|
+
"By default `old_string` must be unique; ambiguous matches are returned with line:column locations so you can extend the match. " +
|
|
70
|
+
"Submits the minimal OT operation through the same pathway as `edit_file`, so by default it lands as a pending suggestion in Overleaf's Review panel (track:'on'). " +
|
|
71
|
+
"If `path` is omitted, defaults to the project's root doc. " +
|
|
72
|
+
"Prefer this over `edit_file` for targeted edits — it's cheaper in tokens and avoids accidental whitespace drift from re-emitting the surrounding text.",
|
|
73
|
+
inputSchema: Schema.shape,
|
|
74
|
+
}, async (args) => {
|
|
75
|
+
const ap = getActiveProject();
|
|
76
|
+
if (!ap) {
|
|
77
|
+
return { content: [{ type: "text", text: "No project is open. Call open_project first." }], isError: true };
|
|
78
|
+
}
|
|
79
|
+
const resolvedPath = args.path ?? ap.rootDocPath;
|
|
80
|
+
if (!resolvedPath) {
|
|
81
|
+
return {
|
|
82
|
+
content: [{ type: "text", text: "No path provided and the project has no configured root doc. Pass a `path`." }],
|
|
83
|
+
isError: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const entity = findByPath(resolvedPath);
|
|
87
|
+
if (!entity) {
|
|
88
|
+
return {
|
|
89
|
+
content: [{ type: "text", text: `Path not found in project: '${resolvedPath}'. Use list_files to inspect available paths.` }],
|
|
90
|
+
isError: true,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (entity.kind !== "doc") {
|
|
94
|
+
return { content: [{ type: "text", text: `'${resolvedPath}' is a ${entity.kind}, not an editable doc.` }], isError: true };
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const cached = await ensureDocLoaded(entity.id);
|
|
98
|
+
if (args.expected_version !== undefined && cached.version !== args.expected_version) {
|
|
99
|
+
return {
|
|
100
|
+
content: [{ type: "text", text: `Version mismatch: cached version is ${cached.version}, you provided ${args.expected_version}. Re-read the file and retry.` }],
|
|
101
|
+
isError: true,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const indices = findAllIndices(cached.text, args.old_string);
|
|
105
|
+
if (indices.length === 0) {
|
|
106
|
+
return {
|
|
107
|
+
content: [{
|
|
108
|
+
type: "text",
|
|
109
|
+
text: `\`old_string\` not found in '${entity.path}' (doc has ${cached.text.length} chars at version ${cached.version}). ` +
|
|
110
|
+
`Check whitespace, line endings, and that you're reading the current text — re-call read_file if unsure.`,
|
|
111
|
+
}],
|
|
112
|
+
isError: true,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (indices.length > 1 && !args.replace_all) {
|
|
116
|
+
const sample = indices.slice(0, 10).map((i) => {
|
|
117
|
+
const { line, col, lineText } = lineOf(cached.text, i);
|
|
118
|
+
const trimmed = lineText.trim();
|
|
119
|
+
const preview = trimmed.length > 120 ? `${trimmed.slice(0, 117)}...` : trimmed;
|
|
120
|
+
return ` line ${line}:${col} ${preview}`;
|
|
121
|
+
}).join("\n");
|
|
122
|
+
const more = indices.length > 10 ? `\n ...and ${indices.length - 10} more` : "";
|
|
123
|
+
return {
|
|
124
|
+
content: [{
|
|
125
|
+
type: "text",
|
|
126
|
+
text: `\`old_string\` matched ${indices.length} times in '${entity.path}'. ` +
|
|
127
|
+
`Either extend \`old_string\` so it uniquely identifies one occurrence, or pass \`replace_all: true\` to replace every match.\nMatches:\n${sample}${more}`,
|
|
128
|
+
}],
|
|
129
|
+
isError: true,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
let newContent;
|
|
133
|
+
if (args.replace_all) {
|
|
134
|
+
newContent = cached.text.split(args.old_string).join(args.new_string);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
const idx = indices[0];
|
|
138
|
+
newContent = cached.text.slice(0, idx) + args.new_string + cached.text.slice(idx + args.old_string.length);
|
|
139
|
+
}
|
|
140
|
+
const ops = textToOps(cached.text, newContent);
|
|
141
|
+
if (ops.length === 0) {
|
|
142
|
+
return {
|
|
143
|
+
content: [{ type: "text", text: "No-op: old_string is identical to new_string at every match." }],
|
|
144
|
+
structuredContent: { path: entity.path, doc_id: entity.id, version: cached.version, ops_applied: 0 },
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const identity = await getIdentity();
|
|
148
|
+
const sock = getActiveSocket();
|
|
149
|
+
const shouldTrack = args.track === "on" ? true : args.track === "off" ? false : ap.trackChangesOnForMe;
|
|
150
|
+
const meta = {
|
|
151
|
+
source: sock?.publicId ?? "overleaf-mcp",
|
|
152
|
+
ts: Date.now(),
|
|
153
|
+
user_id: identity.userId,
|
|
154
|
+
};
|
|
155
|
+
if (shouldTrack)
|
|
156
|
+
meta.tc = generateIdSeed();
|
|
157
|
+
const update = { doc: entity.id, op: ops, v: cached.version, meta };
|
|
158
|
+
await applyOtUpdate(entity.id, update);
|
|
159
|
+
const newVersion = cached.version + 1;
|
|
160
|
+
updateDoc(entity.id, newContent, newVersion);
|
|
161
|
+
const replacements = args.replace_all ? indices.length : 1;
|
|
162
|
+
return {
|
|
163
|
+
content: [{
|
|
164
|
+
type: "text",
|
|
165
|
+
text: `Replaced ${replacements} occurrence(s) in '${entity.path}'. Doc version ${cached.version} -> ${newVersion}. ` +
|
|
166
|
+
(shouldTrack
|
|
167
|
+
? "Submitted as tracked changes — should appear as a pending suggestion in Overleaf's review panel."
|
|
168
|
+
: "Submitted as a direct edit (no tracking)."),
|
|
169
|
+
}],
|
|
170
|
+
structuredContent: {
|
|
171
|
+
path: entity.path,
|
|
172
|
+
doc_id: entity.id,
|
|
173
|
+
replacements,
|
|
174
|
+
ops_applied: ops.length,
|
|
175
|
+
version_before: cached.version,
|
|
176
|
+
version_after: newVersion,
|
|
177
|
+
tracked: shouldTrack,
|
|
178
|
+
track_mode: args.track,
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
184
|
+
logger.error("find_and_replace failed", msg);
|
|
185
|
+
return {
|
|
186
|
+
content: [{ type: "text", text: `Failed to find_and_replace in '${args.path ?? "(root doc)"}': ${msg}` }],
|
|
187
|
+
isError: true,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=findAndReplace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findAndReplace.js","sourceRoot":"","sources":["../../src/tools/findAndReplace.ts"],"names":[],"mappings":"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"}
|