@aloth/olcli 0.4.1 → 0.6.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 +228 -5
- package/dist/cli.js +120 -20
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +18 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +126 -21
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +25 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.d.ts +18 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +344 -0
- package/dist/mcp.js.map +1 -0
- package/package.json +16 -3
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* olcli MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Exposes OverleafClient methods as MCP tools so AI assistants
|
|
6
|
+
* (Claude Desktop, Cursor, Windsurf, …) can manage Overleaf projects.
|
|
7
|
+
*
|
|
8
|
+
* Transport: stdio (standard for Claude Desktop / Cursor / Windsurf)
|
|
9
|
+
*
|
|
10
|
+
* Auth: reads session cookie from OVERLEAF_SESSION env var or .olauth file in cwd.
|
|
11
|
+
*
|
|
12
|
+
* Start:
|
|
13
|
+
* npx @aloth/olcli-mcp
|
|
14
|
+
* node dist/mcp.js
|
|
15
|
+
* npm run mcp # (from repo root)
|
|
16
|
+
*/
|
|
17
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
18
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
19
|
+
import { z } from 'zod/v3';
|
|
20
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
21
|
+
import { readFile } from 'node:fs/promises';
|
|
22
|
+
import { join, resolve } from 'node:path';
|
|
23
|
+
import AdmZip from 'adm-zip';
|
|
24
|
+
import { OverleafClient } from './client.js';
|
|
25
|
+
import { getSessionCookie, getBaseUrl, getSessionCookieName, setSessionCookie, setSessionCookieName, getPasswordCredentials, } from './config.js';
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Auth helpers
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* Resolve session cookie: env var → .olauth file in cwd → stored config.
|
|
31
|
+
*/
|
|
32
|
+
function resolveSessionCookie() {
|
|
33
|
+
// 1. Explicit environment variable
|
|
34
|
+
if (process.env.OVERLEAF_SESSION) {
|
|
35
|
+
return process.env.OVERLEAF_SESSION.trim();
|
|
36
|
+
}
|
|
37
|
+
// 2. .olauth file in current working directory
|
|
38
|
+
const olauth = join(process.cwd(), '.olauth');
|
|
39
|
+
if (existsSync(olauth)) {
|
|
40
|
+
try {
|
|
41
|
+
const raw = readFileSync(olauth, 'utf-8').trim();
|
|
42
|
+
if (raw)
|
|
43
|
+
return raw;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// fall through
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// 3. Stored via `olcli auth` (Conf-based config)
|
|
50
|
+
const stored = getSessionCookie();
|
|
51
|
+
if (stored)
|
|
52
|
+
return stored;
|
|
53
|
+
throw new Error('No Overleaf session cookie found.\n' +
|
|
54
|
+
'Set OVERLEAF_SESSION=<cookie>, run `olcli auth`, or save password login credentials with `olcli auth --email <email> --password <password>`.');
|
|
55
|
+
}
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Lazy client factory — initialised once, reused across requests
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
let _client = null;
|
|
60
|
+
async function getClient() {
|
|
61
|
+
if (_client)
|
|
62
|
+
return _client;
|
|
63
|
+
const baseUrl = process.env.OVERLEAF_BASE_URL ?? getBaseUrl();
|
|
64
|
+
const cookieName = getSessionCookieName();
|
|
65
|
+
try {
|
|
66
|
+
const cookie = resolveSessionCookie();
|
|
67
|
+
_client = await OverleafClient.fromSessionCookie(cookie, baseUrl, cookieName);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
const credentials = getPasswordCredentials();
|
|
71
|
+
if (!credentials)
|
|
72
|
+
throw error;
|
|
73
|
+
_client = await OverleafClient.fromPasswordLogin(credentials.email, credentials.password, baseUrl);
|
|
74
|
+
const sessionCookie = _client.getSessionCookiePair(cookieName);
|
|
75
|
+
if (sessionCookie) {
|
|
76
|
+
setSessionCookieName(sessionCookie.name);
|
|
77
|
+
setSessionCookie(sessionCookie.value);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return _client;
|
|
81
|
+
}
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// MCP server setup
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
const server = new McpServer({
|
|
86
|
+
name: 'olcli',
|
|
87
|
+
version: '0.6.0',
|
|
88
|
+
}, {
|
|
89
|
+
capabilities: { tools: {} },
|
|
90
|
+
});
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Helper: wrap async tool handlers with consistent error formatting
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
function wrapTool(fn) {
|
|
95
|
+
return fn().then((result) => ({
|
|
96
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
97
|
+
}), (err) => ({
|
|
98
|
+
content: [{ type: 'text', text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
99
|
+
isError: true,
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
// Tool: list_projects
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
server.tool('list_projects', 'List all Overleaf projects in the account. Returns project IDs, names, and metadata.', async () => wrapTool(async () => {
|
|
106
|
+
const client = await getClient();
|
|
107
|
+
return client.listProjects();
|
|
108
|
+
}));
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
// Tool: get_project_info
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
server.tool('get_project_info', 'Get detailed information about an Overleaf project including its file tree (folders, docs, and files).', {
|
|
113
|
+
project_id: z.string().describe('The Overleaf project ID (24-char hex string)'),
|
|
114
|
+
}, async ({ project_id }) => wrapTool(async () => {
|
|
115
|
+
const client = await getClient();
|
|
116
|
+
return client.getProjectInfo(project_id);
|
|
117
|
+
}));
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Tool: pull_project
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
server.tool('pull_project', 'Download and extract an Overleaf project as a zip to a local directory. Creates the directory if it does not exist.', {
|
|
122
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
123
|
+
output_dir: z.string().describe('Local directory path to extract files into'),
|
|
124
|
+
overwrite: z
|
|
125
|
+
.boolean()
|
|
126
|
+
.optional()
|
|
127
|
+
.default(false)
|
|
128
|
+
.describe('Overwrite existing files (default: false)'),
|
|
129
|
+
}, async ({ project_id, output_dir, overwrite }) => wrapTool(async () => {
|
|
130
|
+
const client = await getClient();
|
|
131
|
+
const zipBuf = await client.downloadProject(project_id);
|
|
132
|
+
const outDir = resolve(output_dir);
|
|
133
|
+
mkdirSync(outDir, { recursive: true });
|
|
134
|
+
const zip = new AdmZip(zipBuf);
|
|
135
|
+
const entries = zip.getEntries();
|
|
136
|
+
const extracted = [];
|
|
137
|
+
const skipped = [];
|
|
138
|
+
for (const entry of entries) {
|
|
139
|
+
if (entry.isDirectory)
|
|
140
|
+
continue;
|
|
141
|
+
const destPath = join(outDir, entry.entryName);
|
|
142
|
+
if (!overwrite && existsSync(destPath)) {
|
|
143
|
+
skipped.push(entry.entryName);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
// Ensure parent dir exists
|
|
147
|
+
mkdirSync(join(outDir, entry.entryName.split('/').slice(0, -1).join('/')), { recursive: true });
|
|
148
|
+
writeFileSync(destPath, entry.getData());
|
|
149
|
+
extracted.push(entry.entryName);
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
output_dir: outDir,
|
|
153
|
+
extracted_count: extracted.length,
|
|
154
|
+
skipped_count: skipped.length,
|
|
155
|
+
extracted,
|
|
156
|
+
skipped,
|
|
157
|
+
};
|
|
158
|
+
}));
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// Tool: push_file
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
server.tool('push_file', 'Upload a local file to an Overleaf project. The remote path is inferred from the file_path argument.', {
|
|
163
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
164
|
+
local_path: z.string().describe('Absolute or relative path of the local file to upload'),
|
|
165
|
+
remote_path: z
|
|
166
|
+
.string()
|
|
167
|
+
.optional()
|
|
168
|
+
.describe('Target path within the project (default: basename of local_path)'),
|
|
169
|
+
}, async ({ project_id, local_path, remote_path }) => wrapTool(async () => {
|
|
170
|
+
const client = await getClient();
|
|
171
|
+
const absPath = resolve(local_path);
|
|
172
|
+
const content = await readFile(absPath);
|
|
173
|
+
const remoteName = remote_path ?? local_path.split('/').pop() ?? local_path;
|
|
174
|
+
return client.uploadFile(project_id, null, remoteName, content);
|
|
175
|
+
}));
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
// Tool: compile
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
server.tool('compile', 'Compile an Overleaf project using the remote LaTeX compiler. Returns the PDF URL and any log messages.', {
|
|
180
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
181
|
+
}, async ({ project_id }) => wrapTool(async () => {
|
|
182
|
+
const client = await getClient();
|
|
183
|
+
return client.compileProject(project_id);
|
|
184
|
+
}));
|
|
185
|
+
// ---------------------------------------------------------------------------
|
|
186
|
+
// Tool: download_pdf
|
|
187
|
+
// ---------------------------------------------------------------------------
|
|
188
|
+
server.tool('download_pdf', 'Compile an Overleaf project and download the resulting PDF to a local file.', {
|
|
189
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
190
|
+
output_path: z.string().describe('Local file path where the PDF should be saved (e.g. output.pdf)'),
|
|
191
|
+
}, async ({ project_id, output_path }) => wrapTool(async () => {
|
|
192
|
+
const client = await getClient();
|
|
193
|
+
const pdfBuf = await client.downloadPdf(project_id);
|
|
194
|
+
const absPath = resolve(output_path);
|
|
195
|
+
writeFileSync(absPath, pdfBuf);
|
|
196
|
+
return {
|
|
197
|
+
path: absPath,
|
|
198
|
+
bytes: pdfBuf.length,
|
|
199
|
+
};
|
|
200
|
+
}));
|
|
201
|
+
// ---------------------------------------------------------------------------
|
|
202
|
+
// Tool: list_comments
|
|
203
|
+
// ---------------------------------------------------------------------------
|
|
204
|
+
server.tool('list_comments', 'List review comments on an Overleaf project. Supports filtering by status (all, open, resolved).', {
|
|
205
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
206
|
+
status: z
|
|
207
|
+
.enum(['all', 'open', 'resolved'])
|
|
208
|
+
.optional()
|
|
209
|
+
.default('all')
|
|
210
|
+
.describe('Filter by comment status'),
|
|
211
|
+
include_context: z
|
|
212
|
+
.boolean()
|
|
213
|
+
.optional()
|
|
214
|
+
.default(false)
|
|
215
|
+
.describe('Include surrounding text context for each comment'),
|
|
216
|
+
}, async ({ project_id, status, include_context }) => wrapTool(async () => {
|
|
217
|
+
const client = await getClient();
|
|
218
|
+
return client.listComments(project_id, {
|
|
219
|
+
status,
|
|
220
|
+
contextLines: include_context ? 3 : 0,
|
|
221
|
+
});
|
|
222
|
+
}));
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
// Tool: get_entities
|
|
225
|
+
// ---------------------------------------------------------------------------
|
|
226
|
+
server.tool('get_entities', 'Get a flat list of all files and documents in an Overleaf project with their paths and types.', {
|
|
227
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
228
|
+
}, async ({ project_id }) => wrapTool(async () => {
|
|
229
|
+
const client = await getClient();
|
|
230
|
+
return client.getEntities(project_id);
|
|
231
|
+
}));
|
|
232
|
+
// ---------------------------------------------------------------------------
|
|
233
|
+
// Tool: download_file
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
server.tool('download_file', 'Download a single file from an Overleaf project by its path within the project.', {
|
|
236
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
237
|
+
remote_path: z.string().describe('Path of the file within the project (e.g. main.tex or figures/fig1.pdf)'),
|
|
238
|
+
output_path: z
|
|
239
|
+
.string()
|
|
240
|
+
.optional()
|
|
241
|
+
.describe('Local path to save the file (default: basename of remote_path in cwd)'),
|
|
242
|
+
}, async ({ project_id, remote_path, output_path }) => wrapTool(async () => {
|
|
243
|
+
const client = await getClient();
|
|
244
|
+
const fileBuf = await client.downloadByPath(project_id, remote_path);
|
|
245
|
+
const destPath = resolve(output_path ?? remote_path.split('/').pop() ?? remote_path);
|
|
246
|
+
writeFileSync(destPath, fileBuf);
|
|
247
|
+
return {
|
|
248
|
+
path: destPath,
|
|
249
|
+
bytes: fileBuf.length,
|
|
250
|
+
remote_path,
|
|
251
|
+
};
|
|
252
|
+
}));
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
// Tool: add_comment
|
|
255
|
+
// ---------------------------------------------------------------------------
|
|
256
|
+
server.tool('add_comment', 'Add a review comment to a specific location in an Overleaf project document.', {
|
|
257
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
258
|
+
doc_path: z.string().describe('Path of the document within the project (e.g. main.tex)'),
|
|
259
|
+
content: z.string().describe('The comment text'),
|
|
260
|
+
position: z.number().int().nonnegative().optional().describe('Character offset in the document where the comment is anchored'),
|
|
261
|
+
length: z.number().int().nonnegative().optional().describe('Length of the highlighted text span (0 for a point comment)'),
|
|
262
|
+
selected_text: z.string().optional().describe('The text being commented on (optional, used for context)'),
|
|
263
|
+
line: z.number().int().positive().optional().describe('Line number in the document (1-based, alternative to position)'),
|
|
264
|
+
column: z.number().int().nonnegative().optional().describe('Column number in the document (0-based, alternative to position)'),
|
|
265
|
+
}, async ({ project_id, doc_path, content, position, length, selected_text, line, column }) => wrapTool(async () => {
|
|
266
|
+
const client = await getClient();
|
|
267
|
+
return client.addComment(project_id, {
|
|
268
|
+
filePath: doc_path,
|
|
269
|
+
content,
|
|
270
|
+
position,
|
|
271
|
+
length,
|
|
272
|
+
selectedText: selected_text,
|
|
273
|
+
line,
|
|
274
|
+
column,
|
|
275
|
+
});
|
|
276
|
+
}));
|
|
277
|
+
// ---------------------------------------------------------------------------
|
|
278
|
+
// Tool: reply_to_comment
|
|
279
|
+
// ---------------------------------------------------------------------------
|
|
280
|
+
server.tool('reply_to_comment', 'Add a reply to an existing comment thread on an Overleaf project.', {
|
|
281
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
282
|
+
thread_id: z.string().describe('The comment thread ID (from list_comments)'),
|
|
283
|
+
content: z.string().describe('The reply message text'),
|
|
284
|
+
}, async ({ project_id, thread_id, content }) => wrapTool(async () => {
|
|
285
|
+
const client = await getClient();
|
|
286
|
+
const message = await client.postCommentMessage(project_id, thread_id, content);
|
|
287
|
+
return { replied: true, thread_id, message };
|
|
288
|
+
}));
|
|
289
|
+
// ---------------------------------------------------------------------------
|
|
290
|
+
// Tool: resolve_comment
|
|
291
|
+
// ---------------------------------------------------------------------------
|
|
292
|
+
server.tool('resolve_comment', 'Mark a review comment thread as resolved.', {
|
|
293
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
294
|
+
thread_id: z.string().describe('The comment thread ID (from list_comments)'),
|
|
295
|
+
}, async ({ project_id, thread_id }) => wrapTool(async () => {
|
|
296
|
+
const client = await getClient();
|
|
297
|
+
return client.resolveComment(project_id, thread_id);
|
|
298
|
+
}));
|
|
299
|
+
// ---------------------------------------------------------------------------
|
|
300
|
+
// Tool: delete_entity
|
|
301
|
+
// ---------------------------------------------------------------------------
|
|
302
|
+
server.tool('delete_entity', 'Delete a file or document from an Overleaf project by its remote path.', {
|
|
303
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
304
|
+
remote_path: z.string().describe('Path of the file/document to delete within the project'),
|
|
305
|
+
}, async ({ project_id, remote_path }) => wrapTool(async () => {
|
|
306
|
+
const client = await getClient();
|
|
307
|
+
await client.deleteByPath(project_id, remote_path);
|
|
308
|
+
return { deleted: remote_path };
|
|
309
|
+
}));
|
|
310
|
+
// ---------------------------------------------------------------------------
|
|
311
|
+
// Tool: rename_entity
|
|
312
|
+
// ---------------------------------------------------------------------------
|
|
313
|
+
server.tool('rename_entity', 'Rename a file or document within an Overleaf project.', {
|
|
314
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
315
|
+
remote_path: z.string().describe('Current path of the file/document within the project'),
|
|
316
|
+
new_name: z.string().describe('New filename (basename only, not a full path)'),
|
|
317
|
+
}, async ({ project_id, remote_path, new_name }) => wrapTool(async () => {
|
|
318
|
+
const client = await getClient();
|
|
319
|
+
await client.renameByPath(project_id, remote_path, new_name);
|
|
320
|
+
return { old_path: remote_path, new_name };
|
|
321
|
+
}));
|
|
322
|
+
// ---------------------------------------------------------------------------
|
|
323
|
+
// Tool: compile_with_outputs
|
|
324
|
+
// ---------------------------------------------------------------------------
|
|
325
|
+
server.tool('compile_with_outputs', 'Compile an Overleaf project and return all output file metadata (PDF, BBL, logs, etc.). Useful for arXiv submission workflows.', {
|
|
326
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
327
|
+
}, async ({ project_id }) => wrapTool(async () => {
|
|
328
|
+
const client = await getClient();
|
|
329
|
+
return client.compileWithOutputs(project_id);
|
|
330
|
+
}));
|
|
331
|
+
// ---------------------------------------------------------------------------
|
|
332
|
+
// Start
|
|
333
|
+
// ---------------------------------------------------------------------------
|
|
334
|
+
async function main() {
|
|
335
|
+
const transport = new StdioServerTransport();
|
|
336
|
+
await server.connect(transport);
|
|
337
|
+
// Log to stderr so it doesn't pollute the MCP stdio channel
|
|
338
|
+
process.stderr.write('olcli MCP server started (stdio)\n');
|
|
339
|
+
}
|
|
340
|
+
main().catch((err) => {
|
|
341
|
+
process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
342
|
+
process.exit(1);
|
|
343
|
+
});
|
|
344
|
+
//# sourceMappingURL=mcp.js.map
|
package/dist/mcp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aloth/olcli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Command-line interface for Overleaf — Sync, manage, and compile LaTeX projects from your terminal",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./cli": "./dist/cli.js"
|
|
14
|
+
},
|
|
6
15
|
"bin": {
|
|
7
|
-
"olcli": "dist/cli.js"
|
|
16
|
+
"olcli": "dist/cli.js",
|
|
17
|
+
"olcli-mcp": "dist/mcp.js"
|
|
8
18
|
},
|
|
9
19
|
"scripts": {
|
|
10
20
|
"build": "tsc",
|
|
21
|
+
"mcp": "node dist/mcp.js",
|
|
11
22
|
"dev": "tsx src/cli.ts",
|
|
12
23
|
"lint": "eslint src/",
|
|
13
24
|
"prepare": "npm run build"
|
|
@@ -44,6 +55,7 @@
|
|
|
44
55
|
},
|
|
45
56
|
"homepage": "https://github.com/aloth/olcli#readme",
|
|
46
57
|
"dependencies": {
|
|
58
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
47
59
|
"adm-zip": "^0.5.16",
|
|
48
60
|
"chalk": "^5.3.0",
|
|
49
61
|
"cheerio": "^1.0.0",
|
|
@@ -51,7 +63,8 @@
|
|
|
51
63
|
"conf": "^13.0.0",
|
|
52
64
|
"ignore": "^7.0.5",
|
|
53
65
|
"ora": "^8.0.1",
|
|
54
|
-
"tough-cookie": "^4.1.4"
|
|
66
|
+
"tough-cookie": "^4.1.4",
|
|
67
|
+
"zod": "^4.4.3"
|
|
55
68
|
},
|
|
56
69
|
"devDependencies": {
|
|
57
70
|
"@types/adm-zip": "^0.5.7",
|