@aloth/olcli 0.4.1 → 0.5.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 +186 -0
- 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 +318 -0
- package/dist/mcp.js.map +1 -0
- package/package.json +16 -3
package/README.md
CHANGED
|
@@ -438,6 +438,192 @@ olcli output bbl -o main.bbl
|
|
|
438
438
|
olcli zip -o arxiv-submission.zip
|
|
439
439
|
```
|
|
440
440
|
|
|
441
|
+
## Programmatic Usage (Library API)
|
|
442
|
+
|
|
443
|
+
`@aloth/olcli` exposes `OverleafClient` and all public interfaces as a proper library so you can use it in your own scripts, tools, and AI agents.
|
|
444
|
+
|
|
445
|
+
### Install
|
|
446
|
+
|
|
447
|
+
```bash
|
|
448
|
+
npm install @aloth/olcli
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Basic example
|
|
452
|
+
|
|
453
|
+
```ts
|
|
454
|
+
import { OverleafClient } from '@aloth/olcli';
|
|
455
|
+
|
|
456
|
+
// Create a client from an Overleaf session cookie
|
|
457
|
+
const client = await OverleafClient.fromSessionCookie(cookie);
|
|
458
|
+
|
|
459
|
+
// List all projects
|
|
460
|
+
const projects = await client.listProjects();
|
|
461
|
+
console.log(projects);
|
|
462
|
+
|
|
463
|
+
// Get detailed info (file tree) for a project
|
|
464
|
+
const info = await client.getProjectInfo(projectId);
|
|
465
|
+
|
|
466
|
+
// Download project as a zip buffer
|
|
467
|
+
const zipBuf = await client.downloadProject(projectId);
|
|
468
|
+
|
|
469
|
+
// Compile and download PDF
|
|
470
|
+
const pdfBuf = await client.downloadPdf(projectId);
|
|
471
|
+
|
|
472
|
+
// Upload a file
|
|
473
|
+
import { readFileSync } from 'node:fs';
|
|
474
|
+
await client.uploadFile(projectId, null, 'main.tex', readFileSync('main.tex'));
|
|
475
|
+
|
|
476
|
+
// List review comments
|
|
477
|
+
const comments = await client.listComments(projectId, { status: 'open' });
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Available exports
|
|
481
|
+
|
|
482
|
+
```ts
|
|
483
|
+
import {
|
|
484
|
+
// Core client
|
|
485
|
+
OverleafClient,
|
|
486
|
+
|
|
487
|
+
// Types / interfaces
|
|
488
|
+
Project, ProjectInfo, FolderEntry, DocEntry, FileEntry,
|
|
489
|
+
CommentMessage, ProjectComment, CommentContext, CommentStatus,
|
|
490
|
+
ListCommentsOptions, AddCommentOptions, Credentials,
|
|
491
|
+
|
|
492
|
+
// Configuration utilities
|
|
493
|
+
getBaseUrl, setBaseUrl, getSessionCookie, setSessionCookie,
|
|
494
|
+
getSessionCookieName, setSessionCookieName, getCsrf, setCsrf,
|
|
495
|
+
getLastProject, setLastProject, clearConfig, getConfigPath, saveOlAuth,
|
|
496
|
+
|
|
497
|
+
// Ignore utilities
|
|
498
|
+
DEFAULT_IGNORE_PATTERNS, loadIgnore, shouldIgnore, buildTexSiblingSet,
|
|
499
|
+
IgnoreContext, LoadIgnoreOptions,
|
|
500
|
+
} from '@aloth/olcli';
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
## MCP Server
|
|
506
|
+
|
|
507
|
+
`@aloth/olcli` ships an [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server so AI assistants like **Claude Desktop**, **Cursor**, and **Windsurf** can interact with your Overleaf projects directly.
|
|
508
|
+
|
|
509
|
+
### MCP tools
|
|
510
|
+
|
|
511
|
+
| Tool | Description |
|
|
512
|
+
|------|-------------|
|
|
513
|
+
| `list_projects` | List all Overleaf projects |
|
|
514
|
+
| `get_project_info` | Get file tree and metadata for a project |
|
|
515
|
+
| `pull_project` | Download and extract a project to a local directory |
|
|
516
|
+
| `push_file` | Upload a local file to a project |
|
|
517
|
+
| `compile` | Compile a project and get the PDF URL |
|
|
518
|
+
| `download_pdf` | Compile a project and save the PDF locally |
|
|
519
|
+
| `list_comments` | List review comments (filter: all / open / resolved) |
|
|
520
|
+
| `get_entities` | Get a flat list of all files in a project |
|
|
521
|
+
| `download_file` | Download a specific file by its remote path |
|
|
522
|
+
| `add_comment` | Add a review comment to a document |
|
|
523
|
+
| `resolve_comment` | Mark a comment thread as resolved |
|
|
524
|
+
| `delete_entity` | Delete a file or document by path |
|
|
525
|
+
| `rename_entity` | Rename a file or document |
|
|
526
|
+
| `compile_with_outputs` | Compile and return all output files (PDF, BBL, logs…) |
|
|
527
|
+
|
|
528
|
+
### Authentication
|
|
529
|
+
|
|
530
|
+
The MCP server reads your session cookie in this order:
|
|
531
|
+
|
|
532
|
+
1. **`OVERLEAF_SESSION` environment variable** — set in your MCP config (recommended)
|
|
533
|
+
2. **`.olauth` file in cwd** — written by `olcli auth`
|
|
534
|
+
3. **Stored config** — written by `olcli auth`
|
|
535
|
+
|
|
536
|
+
### Claude Desktop
|
|
537
|
+
|
|
538
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
539
|
+
|
|
540
|
+
```json
|
|
541
|
+
{
|
|
542
|
+
"mcpServers": {
|
|
543
|
+
"overleaf": {
|
|
544
|
+
"command": "npx",
|
|
545
|
+
"args": ["-y", "@aloth/olcli-mcp"],
|
|
546
|
+
"env": {
|
|
547
|
+
"OVERLEAF_SESSION": "<your-overleaf-session-cookie>"
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
Or if you have olcli installed globally (`npm install -g @aloth/olcli`):
|
|
555
|
+
|
|
556
|
+
```json
|
|
557
|
+
{
|
|
558
|
+
"mcpServers": {
|
|
559
|
+
"overleaf": {
|
|
560
|
+
"command": "olcli-mcp",
|
|
561
|
+
"env": {
|
|
562
|
+
"OVERLEAF_SESSION": "<your-overleaf-session-cookie>"
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
### Cursor
|
|
570
|
+
|
|
571
|
+
Add to your Cursor MCP settings (`~/.cursor/mcp.json` or project `.cursor/mcp.json`):
|
|
572
|
+
|
|
573
|
+
```json
|
|
574
|
+
{
|
|
575
|
+
"mcpServers": {
|
|
576
|
+
"overleaf": {
|
|
577
|
+
"command": "npx",
|
|
578
|
+
"args": ["-y", "@aloth/olcli-mcp"],
|
|
579
|
+
"env": {
|
|
580
|
+
"OVERLEAF_SESSION": "<your-overleaf-session-cookie>"
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### Windsurf
|
|
588
|
+
|
|
589
|
+
Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
590
|
+
|
|
591
|
+
```json
|
|
592
|
+
{
|
|
593
|
+
"mcpServers": {
|
|
594
|
+
"overleaf": {
|
|
595
|
+
"command": "npx",
|
|
596
|
+
"args": ["-y", "@aloth/olcli-mcp"],
|
|
597
|
+
"env": {
|
|
598
|
+
"OVERLEAF_SESSION": "<your-overleaf-session-cookie>"
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### Getting your session cookie
|
|
606
|
+
|
|
607
|
+
1. Open Overleaf in your browser and log in
|
|
608
|
+
2. Open DevTools → Application (Chrome) or Storage (Firefox) → Cookies
|
|
609
|
+
3. Find `overleaf_session2` (or `sharelatex.sid` for self-hosted)
|
|
610
|
+
4. Copy the value — that's your `OVERLEAF_SESSION`
|
|
611
|
+
|
|
612
|
+
Or run `olcli auth` and then the MCP server will pick it up automatically.
|
|
613
|
+
|
|
614
|
+
### Self-hosted Overleaf
|
|
615
|
+
|
|
616
|
+
Set `OVERLEAF_BASE_URL` in your MCP env:
|
|
617
|
+
|
|
618
|
+
```json
|
|
619
|
+
"env": {
|
|
620
|
+
"OVERLEAF_SESSION": "<cookie>",
|
|
621
|
+
"OVERLEAF_BASE_URL": "https://overleaf.yourcompany.com"
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
---
|
|
626
|
+
|
|
441
627
|
## Troubleshooting
|
|
442
628
|
|
|
443
629
|
### Session expired
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @aloth/olcli — Programmatic API
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the public surface of OverleafClient and all associated
|
|
5
|
+
* interfaces/types so consumers can import directly from the package root.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { OverleafClient } from '@aloth/olcli';
|
|
10
|
+
*
|
|
11
|
+
* const client = await OverleafClient.fromSessionCookie(cookie);
|
|
12
|
+
* const projects = await client.listProjects();
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export { OverleafClient, type Project, type ProjectInfo, type FolderEntry, type DocEntry, type FileEntry, type CommentMessage, type ProjectComment, type CommentContext, type ListCommentsOptions, type AddCommentOptions, type Credentials, type CommentStatus, } from './client.js';
|
|
16
|
+
export { getBaseUrl, setBaseUrl, getSessionCookieName, setSessionCookieName, getSessionCookie, setSessionCookie, getCsrf, setCsrf, getLastProject, setLastProject, clearConfig, getConfigPath, saveOlAuth, } from './config.js';
|
|
17
|
+
export { DEFAULT_IGNORE_PATTERNS, loadIgnore, shouldIgnore, buildTexSiblingSet, type IgnoreContext, type LoadIgnoreOptions, } from './ignore.js';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EACL,cAAc,EAEd,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAEhB,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,OAAO,EACP,OAAO,EACP,cAAc,EACd,cAAc,EACd,WAAW,EACX,aAAa,EACb,UAAU,GACX,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @aloth/olcli — Programmatic API
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the public surface of OverleafClient and all associated
|
|
5
|
+
* interfaces/types so consumers can import directly from the package root.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { OverleafClient } from '@aloth/olcli';
|
|
10
|
+
*
|
|
11
|
+
* const client = await OverleafClient.fromSessionCookie(cookie);
|
|
12
|
+
* const projects = await client.listProjects();
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
// Core client class + all public interfaces/types
|
|
16
|
+
export { OverleafClient, } from './client.js';
|
|
17
|
+
// Configuration utilities
|
|
18
|
+
export { getBaseUrl, setBaseUrl, getSessionCookieName, setSessionCookieName, getSessionCookie, setSessionCookie, getCsrf, setCsrf, getLastProject, setLastProject, clearConfig, getConfigPath, saveOlAuth, } from './config.js';
|
|
19
|
+
// Ignore subsystem
|
|
20
|
+
export { DEFAULT_IGNORE_PATTERNS, loadIgnore, shouldIgnore, buildTexSiblingSet, } from './ignore.js';
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,kDAAkD;AAClD,OAAO,EACL,cAAc,GAef,MAAM,aAAa,CAAC;AAErB,0BAA0B;AAC1B,OAAO,EACL,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,OAAO,EACP,OAAO,EACP,cAAc,EACd,cAAc,EACd,WAAW,EACX,aAAa,EACb,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,mBAAmB;AACnB,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,YAAY,EACZ,kBAAkB,GAGnB,MAAM,aAAa,CAAC"}
|
package/dist/mcp.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
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
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=mcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG"}
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
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, } 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> or run `olcli auth` first.');
|
|
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 cookie = resolveSessionCookie();
|
|
64
|
+
const baseUrl = process.env.OVERLEAF_BASE_URL ?? getBaseUrl();
|
|
65
|
+
_client = await OverleafClient.fromSessionCookie(cookie, baseUrl);
|
|
66
|
+
return _client;
|
|
67
|
+
}
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// MCP server setup
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
const server = new McpServer({
|
|
72
|
+
name: 'olcli',
|
|
73
|
+
version: '0.5.0',
|
|
74
|
+
}, {
|
|
75
|
+
capabilities: { tools: {} },
|
|
76
|
+
});
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// Helper: wrap async tool handlers with consistent error formatting
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
function wrapTool(fn) {
|
|
81
|
+
return fn().then((result) => ({
|
|
82
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
83
|
+
}), (err) => ({
|
|
84
|
+
content: [{ type: 'text', text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
|
|
85
|
+
isError: true,
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// Tool: list_projects
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
server.tool('list_projects', 'List all Overleaf projects in the account. Returns project IDs, names, and metadata.', async () => wrapTool(async () => {
|
|
92
|
+
const client = await getClient();
|
|
93
|
+
return client.listProjects();
|
|
94
|
+
}));
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// Tool: get_project_info
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
server.tool('get_project_info', 'Get detailed information about an Overleaf project including its file tree (folders, docs, and files).', {
|
|
99
|
+
project_id: z.string().describe('The Overleaf project ID (24-char hex string)'),
|
|
100
|
+
}, async ({ project_id }) => wrapTool(async () => {
|
|
101
|
+
const client = await getClient();
|
|
102
|
+
return client.getProjectInfo(project_id);
|
|
103
|
+
}));
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
// Tool: pull_project
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
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.', {
|
|
108
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
109
|
+
output_dir: z.string().describe('Local directory path to extract files into'),
|
|
110
|
+
overwrite: z
|
|
111
|
+
.boolean()
|
|
112
|
+
.optional()
|
|
113
|
+
.default(false)
|
|
114
|
+
.describe('Overwrite existing files (default: false)'),
|
|
115
|
+
}, async ({ project_id, output_dir, overwrite }) => wrapTool(async () => {
|
|
116
|
+
const client = await getClient();
|
|
117
|
+
const zipBuf = await client.downloadProject(project_id);
|
|
118
|
+
const outDir = resolve(output_dir);
|
|
119
|
+
mkdirSync(outDir, { recursive: true });
|
|
120
|
+
const zip = new AdmZip(zipBuf);
|
|
121
|
+
const entries = zip.getEntries();
|
|
122
|
+
const extracted = [];
|
|
123
|
+
const skipped = [];
|
|
124
|
+
for (const entry of entries) {
|
|
125
|
+
if (entry.isDirectory)
|
|
126
|
+
continue;
|
|
127
|
+
const destPath = join(outDir, entry.entryName);
|
|
128
|
+
if (!overwrite && existsSync(destPath)) {
|
|
129
|
+
skipped.push(entry.entryName);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
// Ensure parent dir exists
|
|
133
|
+
mkdirSync(join(outDir, entry.entryName.split('/').slice(0, -1).join('/')), { recursive: true });
|
|
134
|
+
writeFileSync(destPath, entry.getData());
|
|
135
|
+
extracted.push(entry.entryName);
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
output_dir: outDir,
|
|
139
|
+
extracted_count: extracted.length,
|
|
140
|
+
skipped_count: skipped.length,
|
|
141
|
+
extracted,
|
|
142
|
+
skipped,
|
|
143
|
+
};
|
|
144
|
+
}));
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
// Tool: push_file
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
server.tool('push_file', 'Upload a local file to an Overleaf project. The remote path is inferred from the file_path argument.', {
|
|
149
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
150
|
+
local_path: z.string().describe('Absolute or relative path of the local file to upload'),
|
|
151
|
+
remote_path: z
|
|
152
|
+
.string()
|
|
153
|
+
.optional()
|
|
154
|
+
.describe('Target path within the project (default: basename of local_path)'),
|
|
155
|
+
}, async ({ project_id, local_path, remote_path }) => wrapTool(async () => {
|
|
156
|
+
const client = await getClient();
|
|
157
|
+
const absPath = resolve(local_path);
|
|
158
|
+
const content = await readFile(absPath);
|
|
159
|
+
const remoteName = remote_path ?? local_path.split('/').pop() ?? local_path;
|
|
160
|
+
return client.uploadFile(project_id, null, remoteName, content);
|
|
161
|
+
}));
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
// Tool: compile
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
server.tool('compile', 'Compile an Overleaf project using the remote LaTeX compiler. Returns the PDF URL and any log messages.', {
|
|
166
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
167
|
+
}, async ({ project_id }) => wrapTool(async () => {
|
|
168
|
+
const client = await getClient();
|
|
169
|
+
return client.compileProject(project_id);
|
|
170
|
+
}));
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
// Tool: download_pdf
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
server.tool('download_pdf', 'Compile an Overleaf project and download the resulting PDF to a local file.', {
|
|
175
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
176
|
+
output_path: z.string().describe('Local file path where the PDF should be saved (e.g. output.pdf)'),
|
|
177
|
+
}, async ({ project_id, output_path }) => wrapTool(async () => {
|
|
178
|
+
const client = await getClient();
|
|
179
|
+
const pdfBuf = await client.downloadPdf(project_id);
|
|
180
|
+
const absPath = resolve(output_path);
|
|
181
|
+
writeFileSync(absPath, pdfBuf);
|
|
182
|
+
return {
|
|
183
|
+
path: absPath,
|
|
184
|
+
bytes: pdfBuf.length,
|
|
185
|
+
};
|
|
186
|
+
}));
|
|
187
|
+
// ---------------------------------------------------------------------------
|
|
188
|
+
// Tool: list_comments
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
server.tool('list_comments', 'List review comments on an Overleaf project. Supports filtering by status (all, open, resolved).', {
|
|
191
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
192
|
+
status: z
|
|
193
|
+
.enum(['all', 'open', 'resolved'])
|
|
194
|
+
.optional()
|
|
195
|
+
.default('all')
|
|
196
|
+
.describe('Filter by comment status'),
|
|
197
|
+
include_context: z
|
|
198
|
+
.boolean()
|
|
199
|
+
.optional()
|
|
200
|
+
.default(false)
|
|
201
|
+
.describe('Include surrounding text context for each comment'),
|
|
202
|
+
}, async ({ project_id, status, include_context }) => wrapTool(async () => {
|
|
203
|
+
const client = await getClient();
|
|
204
|
+
return client.listComments(project_id, {
|
|
205
|
+
status,
|
|
206
|
+
contextLines: include_context ? 3 : 0,
|
|
207
|
+
});
|
|
208
|
+
}));
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
// Tool: get_entities
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
server.tool('get_entities', 'Get a flat list of all files and documents in an Overleaf project with their paths and types.', {
|
|
213
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
214
|
+
}, async ({ project_id }) => wrapTool(async () => {
|
|
215
|
+
const client = await getClient();
|
|
216
|
+
return client.getEntities(project_id);
|
|
217
|
+
}));
|
|
218
|
+
// ---------------------------------------------------------------------------
|
|
219
|
+
// Tool: download_file
|
|
220
|
+
// ---------------------------------------------------------------------------
|
|
221
|
+
server.tool('download_file', 'Download a single file from an Overleaf project by its path within the project.', {
|
|
222
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
223
|
+
remote_path: z.string().describe('Path of the file within the project (e.g. main.tex or figures/fig1.pdf)'),
|
|
224
|
+
output_path: z
|
|
225
|
+
.string()
|
|
226
|
+
.optional()
|
|
227
|
+
.describe('Local path to save the file (default: basename of remote_path in cwd)'),
|
|
228
|
+
}, async ({ project_id, remote_path, output_path }) => wrapTool(async () => {
|
|
229
|
+
const client = await getClient();
|
|
230
|
+
const fileBuf = await client.downloadByPath(project_id, remote_path);
|
|
231
|
+
const destPath = resolve(output_path ?? remote_path.split('/').pop() ?? remote_path);
|
|
232
|
+
writeFileSync(destPath, fileBuf);
|
|
233
|
+
return {
|
|
234
|
+
path: destPath,
|
|
235
|
+
bytes: fileBuf.length,
|
|
236
|
+
remote_path,
|
|
237
|
+
};
|
|
238
|
+
}));
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
// Tool: add_comment
|
|
241
|
+
// ---------------------------------------------------------------------------
|
|
242
|
+
server.tool('add_comment', 'Add a review comment to a specific location in an Overleaf project document.', {
|
|
243
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
244
|
+
doc_path: z.string().describe('Path of the document within the project (e.g. main.tex)'),
|
|
245
|
+
content: z.string().describe('The comment text'),
|
|
246
|
+
position: z.number().int().nonnegative().optional().describe('Character offset in the document where the comment is anchored'),
|
|
247
|
+
length: z.number().int().nonnegative().optional().describe('Length of the highlighted text span (0 for a point comment)'),
|
|
248
|
+
selected_text: z.string().optional().describe('The text being commented on (optional, used for context)'),
|
|
249
|
+
line: z.number().int().positive().optional().describe('Line number in the document (1-based, alternative to position)'),
|
|
250
|
+
column: z.number().int().nonnegative().optional().describe('Column number in the document (0-based, alternative to position)'),
|
|
251
|
+
}, async ({ project_id, doc_path, content, position, length, selected_text, line, column }) => wrapTool(async () => {
|
|
252
|
+
const client = await getClient();
|
|
253
|
+
return client.addComment(project_id, {
|
|
254
|
+
filePath: doc_path,
|
|
255
|
+
content,
|
|
256
|
+
position,
|
|
257
|
+
length,
|
|
258
|
+
selectedText: selected_text,
|
|
259
|
+
line,
|
|
260
|
+
column,
|
|
261
|
+
});
|
|
262
|
+
}));
|
|
263
|
+
// ---------------------------------------------------------------------------
|
|
264
|
+
// Tool: resolve_comment
|
|
265
|
+
// ---------------------------------------------------------------------------
|
|
266
|
+
server.tool('resolve_comment', 'Mark a review comment thread as resolved.', {
|
|
267
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
268
|
+
thread_id: z.string().describe('The comment thread ID (from list_comments)'),
|
|
269
|
+
}, async ({ project_id, thread_id }) => wrapTool(async () => {
|
|
270
|
+
const client = await getClient();
|
|
271
|
+
return client.resolveComment(project_id, thread_id);
|
|
272
|
+
}));
|
|
273
|
+
// ---------------------------------------------------------------------------
|
|
274
|
+
// Tool: delete_entity
|
|
275
|
+
// ---------------------------------------------------------------------------
|
|
276
|
+
server.tool('delete_entity', 'Delete a file or document from an Overleaf project by its remote path.', {
|
|
277
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
278
|
+
remote_path: z.string().describe('Path of the file/document to delete within the project'),
|
|
279
|
+
}, async ({ project_id, remote_path }) => wrapTool(async () => {
|
|
280
|
+
const client = await getClient();
|
|
281
|
+
await client.deleteByPath(project_id, remote_path);
|
|
282
|
+
return { deleted: remote_path };
|
|
283
|
+
}));
|
|
284
|
+
// ---------------------------------------------------------------------------
|
|
285
|
+
// Tool: rename_entity
|
|
286
|
+
// ---------------------------------------------------------------------------
|
|
287
|
+
server.tool('rename_entity', 'Rename a file or document within an Overleaf project.', {
|
|
288
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
289
|
+
remote_path: z.string().describe('Current path of the file/document within the project'),
|
|
290
|
+
new_name: z.string().describe('New filename (basename only, not a full path)'),
|
|
291
|
+
}, async ({ project_id, remote_path, new_name }) => wrapTool(async () => {
|
|
292
|
+
const client = await getClient();
|
|
293
|
+
await client.renameByPath(project_id, remote_path, new_name);
|
|
294
|
+
return { old_path: remote_path, new_name };
|
|
295
|
+
}));
|
|
296
|
+
// ---------------------------------------------------------------------------
|
|
297
|
+
// Tool: compile_with_outputs
|
|
298
|
+
// ---------------------------------------------------------------------------
|
|
299
|
+
server.tool('compile_with_outputs', 'Compile an Overleaf project and return all output file metadata (PDF, BBL, logs, etc.). Useful for arXiv submission workflows.', {
|
|
300
|
+
project_id: z.string().describe('The Overleaf project ID'),
|
|
301
|
+
}, async ({ project_id }) => wrapTool(async () => {
|
|
302
|
+
const client = await getClient();
|
|
303
|
+
return client.compileWithOutputs(project_id);
|
|
304
|
+
}));
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
// Start
|
|
307
|
+
// ---------------------------------------------------------------------------
|
|
308
|
+
async function main() {
|
|
309
|
+
const transport = new StdioServerTransport();
|
|
310
|
+
await server.connect(transport);
|
|
311
|
+
// Log to stderr so it doesn't pollute the MCP stdio channel
|
|
312
|
+
process.stderr.write('olcli MCP server started (stdio)\n');
|
|
313
|
+
}
|
|
314
|
+
main().catch((err) => {
|
|
315
|
+
process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
316
|
+
process.exit(1);
|
|
317
|
+
});
|
|
318
|
+
//# 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.5.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",
|