Typst Web MCP
Typst Web MCP is an MCP server that lets AI agents manage and edit typst.app cloud projects, sync Yjs CRDT text, search/replace, compile diagnostics, export PDFs, and capture previews.
Authenticate with Typst Web via email/password or session cookie, with browser fallback, and check auth status.
List, inspect, create, and delete Typst Web projects, including initial files and pinned compiler versions.
List, read, create, overwrite, and targeted-edit project text files using paged reads, content hashes, dry runs, and CRDT synchronization.
Search text or regex across project files and perform single or batch find-and-replace operations.
Upload or replace binary assets such as PNG, JPG, SVG, PDF, and fonts; rename, move, or delete files.
Retrieve compiler diagnostics via local Typst CLI, Typst Web cloud compiler, or automatic fallback.
Export projects to PDF and capture high-DPI PNG previews or live browser screenshots.
Preserve collaborator cursors and version history through native Yjs CRDT and Typst Web WebSocket/REST persistence.
Provides tools for interacting with typst.app cloud projects, enabling AI agents to manage projects and files, perform real-time Yjs CRDT document editing, upload binary assets, run Typst compiler diagnostics, export PDFs, and capture high-DPI preview screenshots.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Typst Web MCP check my typst project for errors"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Typst Web MCP
Model Context Protocol (MCP) server for https://typst.app — cloud projects, Yjs CRDT editing, and Typst compiler diagnostics
Installation
Add typst-mcp to your MCP client configuration (.pi/agent/mcp-adapter.json, claude_desktop_config.json, or .cursor/mcp.json).
Prerequisites
Node.js
>= 18Typst CLI (optional:
typstonPATHfor local CLI compilation speed; if not installed,typst_get_diagnosticsautomatically uses Typst Web cloud compiler diagnostics)
Option 1: Normal (Standard)
Runs the published typst-mcp package (npx -y typst-mcp):
{
"mcpServers": {
"typst-mcp": {
"command": "npx",
"args": ["-y", "typst-mcp"],
"env": {
"TYPST_EMAIL": "your-email@example.com",
"TYPST_PASSWORD": "your-password"
}
}
}
}Option 2: Always Latest
Bypasses local npx cache to automatically pull and run the newest release on launch (npx -y typst-mcp@latest):
{
"mcpServers": {
"typst-mcp": {
"command": "npx",
"args": ["-y", "typst-mcp@latest"],
"env": {
"TYPST_EMAIL": "your-email@example.com",
"TYPST_PASSWORD": "your-password"
}
}
}
}Related MCP server: Typleaf MCP Server
Overview
typst-web-mcp connects AI coding and writing agents directly to collaborative typst.app cloud projects. Instead of relying on brittle browser DOM scraping, it implements the native typst.app client protocol:
Native Yjs CRDT Text Sync: Decodes and mutates multiplayer
Y.Doc(doc.getText("text")) state vectors so surgical edits preserve collaborator cursors and version history.Binary
/editing/v3WebSocket Wire Protocol: Encodes and decodeslib0variable-length binary frames (Subscribe,TextUpdate,Pong,Refresh,Presence,Cursor,Leave) with REST/v1/files/:projectId/:fileId/yjspersistence.GraphQL & REST Project Management: Full project CRUD, file tree inspection, rename/move, delete, and binary figure/asset uploads (
PNG,JPG,SVG,PDF, fonts).Direct Authentication + Fallback: Authenticates via
GET /v1/to-signin+POST /v1/auth/signin(__Http-typst-session), with persistent session caching and automatic cookie/Playwright fallback on challenge.Compiler Diagnostics, Preview Screenshots & PDF Export: Synchronizes cloud Yjs text and binary assets into an isolated workspace and runs the Typst compiler to return structured line/column diagnostics, high-DPI PNG preview screenshots (
typst_capture_screenshot), and compiled PDFs (typst_export_pdf).
MCP Tools (18 Tools)
Category | Tool Name | Description |
Auth |
| Authenticate with |
Auth |
| Check active authentication state, login method, and stored session cookies. |
Projects |
| List all owned and shared/external projects in the user's |
Projects |
| Retrieve full project metadata, access permissions, pinned compiler version, and file tree ( |
Projects |
| Create a new |
Projects |
| Permanently delete a |
Files & CRDT |
| List all multiplayer Yjs text files and binary asset blobs in a project. |
Files & CRDT |
| Read bounded source pages (200 lines/16 KiB by default), with compact metadata, whole-file content hashes, separate continuation fields, and native image blocks. |
Files & CRDT |
| Create or overwrite a |
Files & CRDT |
| Apply validated, unique edits to one snapshot with optional stale-content protection, exact matching by default, compact receipts, opt-in fuzzy fallback, and bounded diff previews. |
Search & Replace |
| Search for text or regular expressions across project files, returning file paths, line numbers, and optional surrounding context lines. |
Search & Replace |
| Replace text or regex in one file or project-wide. Batch ordered replacement rules in one call with one save per changed file, compact summaries, optional diffs, and dry-run previews. |
Assets & Tree |
| Upload or replace binary assets ( |
Assets & Tree |
| Rename or move a file inside a |
Assets & Tree |
| Delete a file or binary asset from a project ( |
Compiler |
| Retrieve compiler diagnostics (errors, warnings, line/column numbers, and hints). Supports both local Typst CLI ( |
Compiler |
| Sync all cloud text & binary assets, compile the project to PDF, and save to |
Preview |
| Capture high-DPI PNG preview screenshots ( |
Read and edit efficiently
Use
typst_grep_projectto locate relevant text, then read just that range withtypst_read_file(offsetis 1-based,limitdefaults to 200 lines,maxBytesdefaults to 16 KiB and can be raised to 1 MiB).Keep the returned
contentHash. It is SHA-256 of the entire raw text file, including BOM and line endings, even when reading a range or displaying line numbers.Send all disjoint edits in one
typst_edit_filecall, withexpectedHashset to that hash. Prefer a short uniqueoldTextanchor over repeating a whole file.
{
"projectId": "your-project-id",
"filePath": "main.typ",
"expectedHash": "<contentHash from the read response>",
"edits": [
{ "oldText": "September 2025", "newText": "September 2026" }
]
}Text read responses include source only in content, with totalLines, startLine, endLine, truncated, and nextOffset when more source remains. They never repeat source in truncation metadata or append instructions to it. Complete lines and original line endings are retained, so unnumbered pages can be concatenated without losing bytes. A trailing newline does not create a phantom extra line. An empty file has totalLines: 0, startLine: 1, endLine: 0.
Read metadata defaults to {id, name}. Use output: "full" for full file metadata; this does not increase the source range. lineNumbers: true adds display prefixes: remove those prefixes when constructing oldText. Byte budgets include those prefixes. If one line cannot fit, the tool returns an actionable error rather than an empty page that cannot advance.
Edits match against the same original snapshot, not the result of previous edits. All entries must be valid, and each anchor must be unique, including overlapping occurrences. Invalid batches, overlapping ranges, and stale hashes fail before saving. matchMode: "exact" is the default and accepts LF/CRLF differences. Use matchMode: "fuzzy" to opt into Unicode quote/dash/space and NFKC fallback when no exact match exists. Fallback matching preserves characters outside the matched span. Edits retain the BOM and untouched line endings, including mixed LF/CRLF files.
Successful edits return a compact receipt with file ID/name, appliedCount, the resulting contentHash, and firstChangedLine. This avoids returning the same changes as both a diff and a patch. Optional controls:
output: "diff"adds a display diff;output: "full"also adds a patch and full metadata.Each diff/patch field is limited to 100 lines and
maxDiffBytesbytes (default 8192, maximum 1 MiB).diffTruncated/patchTruncatedexplicitly flag omissions; read the affected range for complete source.dryRun: truevalidates and previews without saving and defaults to diff output. ItsappliedCountdescribes proposed edits; itscontentHashstill identifies the unchanged cloud text.
expectedHash is checked on fresh text inside the shared file mutation queue, which serializes local edits, replacements, and whole-file writes to existing files. It detects changes made since the read; it is not a cloud compare-and-swap transaction and cannot prevent a collaborator from editing during the subsequent save. Yjs still merges concurrent cloud updates.
Changed defaults: reads previously allowed 2,000 lines/50 KiB and embedded continuation hints in content. Read callers should follow nextOffset now. MCP edits previously returned full diffs/patches and used fuzzy fallback automatically; request output: "full" or matchMode: "fuzzy" explicitly when needed. The low-level editYjsText helper retains its legacy fuzzy default; the client/MCP edit path defaults to exact matching.
Batch replacements for agents
Use one typst_find_and_replace call for related replacements. For example, expand abbreviated month names throughout all .typ files:
{
"projectId": "your-project-id",
"glob": "*.typ",
"replacements": [
{ "pattern": "\\bSep\\b", "replacement": "September", "regex": true },
{ "pattern": "\\bOct\\b", "replacement": "October", "regex": true }
]
}Each file is downloaded once, all rules run in order on the previous rule's result, and the file is saved once if its final text changed. All rules are validated before any files are written. File mutations remain serialized with other edits; a project-wide operation is not atomic across files if a network or save error occurs.
Batch calls default to output: "summary":
{
"filesModified": [
{
"file": "main.typ",
"replacementsCount": 3,
"replacementCounts": [2, 1],
"firstChangedLine": 4
}
],
"totalReplacements": 3,
"dryRun": false
}replacementCounts follows the input rule order and counts matches applied by each rule in that changed file. Unchanged files, including batches whose rules cancel each other out, are omitted and do not contribute to totals.
Set
dryRun: trueto preview without saving. Addoutput: "diff"to include a single combined display diff per file.Set
output: "full"to include both the display diff and unified patch.Set
regex,ignoreCase, andlimiton each batch rule.limitis a non-negative integer per rule per file;0disables that rule.Use either
replacementsor the existingpattern/replacementfields. Existing single-replacement calls still default tooutput: "full"; they can request"summary"too.Use
filePathto target one file by path or ID. A missing explicit file returns an error.
Development & Verification
From Source (Development)
Requires Bun >= 1.2:
git clone https://github.com/caphefalumi/typst-web-mcp.git
cd typst-web-mcp
bun install
bun run devBuild & Test
# Compile publishable output to dist/
bun run build
# Typecheck with strict TypeScript
bun run typecheck
# Full suite (includes test/smoke.test.ts: dist bin + npx -y typst-mcp)
bun test
# Smoke only (same as pi npx MCP config)
bun run test:smokePush/PR to main runs .github/workflows/ci.yml (bun ci, build, typecheck, bun test).
Publishing to npm
Same flow as Canvas-CLI:
Bump
versioninpackage.json(must not match a version already on npm).Commit, push, and create a GitHub Release for that tag — or run Actions → Publish → Run workflow (
workflow_dispatch).
.github/workflows/npm-publish.yml runs the same checks as CI (bun test, including smoke) in a test job; the publish job runs only if that passes, on the npm-publish environment: bun ci, bun run build, then npm publish --access public via npm trusted publishing (OIDC). The publish step clears NODE_AUTH_TOKEN so the CLI uses GitHub OIDC instead of a stale token from setup-node.
Trusted publisher (maintainers): package typst-mcp → Settings → Trusted publishing → GitHub Actions — user/org caphefalumi, repo typst-web-mcp, workflow file npm-publish.yml, environment npm-publish, allow npm publish.
License
Released under the MIT License. Copyright (c) 2026 Dang Duy Toan (caphefalumi).
Available Tools
18 toolstypst_auth_loginA
Authenticate with https://typst.app using direct email/password API login (POST /v1/auth/signin) or a session cookie (__Http-typst-session), with automatic cookie/browser fallback on challenge.
Inputs: email, password, sessionCookie, useBrowserFallback.
typst_auth_statusA
Check current https://typst.app authentication status, active session cookies, and login method.
Inputs: no named parameters.
typst_capture_screenshotA
Capture high-resolution PNG preview screenshots to verify the visual status of a https://typst.app project (mode='pages' renders compiled PNG pages via Typst; mode='browser' captures the live typst.app web editor & preview pane via Playwright).
Inputs: projectId (required), ppi, mode, pages, +3 more.
typst_create_projectC
Create a new project on https://typst.app with optional initial .typ/.bib files and pinned Typst compiler version.
Inputs: name (required), files, owner, folder, +1 more.
typst_delete_fileC
Delete a file or asset from a https://typst.app project via DeleteFilesMutation.
Inputs: filePath (required), projectId (required).
typst_delete_projectB
Permanently delete a project on https://typst.app by ID.
Inputs: projectId (required).
typst_edit_fileA
Apply all targeted edits against one original file snapshot, with one save. Prefer short unique oldText anchors and expectedHash from typst_read_file to reject stale edits. Exact matching by default (LF/CRLF resilient); matchMode='fuzzy' opts into Unicode/whitespace fallback. Malformed, ambiguous, or overlapping edits fail without saving. Summary output by default; dryRun previews a bounded diff. Unchanged characters and BOM are preserved.
Inputs: edits, dryRun, output, newText, +7 more.
typst_export_pdfB
Synchronize all text and binary files from a https://typst.app project, compile the document to PDF, and save it to outputPath.
Inputs: projectId (required), mainFile, outputPath.
typst_find_and_replaceA
Find and replace text or regex in one file or project-wide. Use replacements to batch mappings (e.g. Sep → September, Oct → October) in one call with one save per file. Rules run sequentially; later rules see earlier results. Batch output defaults to compact summary; request output='diff' or 'full' for previews. Supports dryRun and per-file mutation serialization. Project-wide changes are not atomic across files.
Inputs: projectId (required), glob, limit, regex, +8 more.
typst_get_diagnosticsA
Retrieve compiler diagnostics (errors, warnings, line/column numbers, and hints) for a https://typst.app project. Supports both local Typst CLI compilation (fastest) and Typst Web cloud diagnostics (zero-binary fallback using typst.app cloud compiler).
Inputs: projectId (required), mode, mainFile.
typst_get_projectA
Get detailed metadata, access permissions, pinned compiler version, and full file tree for a https://typst.app project.
Inputs: projectId (required).
typst_grep_projectA
Search for text or regular expressions across files in a https://typst.app project. Returns matching lines with file paths, line numbers, and optional surrounding context lines.
Inputs: pattern (required), projectId (required), glob, path, +4 more.
typst_list_filesB
List all files (multiplayer Yjs text files and binary asset blobs) inside a https://typst.app project.
Inputs: projectId (required).
typst_list_projectsA
List all owned and shared/external projects in the authenticated user's https://typst.app dashboard.
Inputs: no named parameters.
typst_read_fileA
Read project text in bounded pages (default 200 lines/16 KiB) or images as native image blocks. content contains source only; use nextOffset for continuation. contentHash covers the entire raw text file: pass it as expectedHash to typst_edit_file. Compact file metadata by default; output='full' adds metadata, not extra source lines. Use grep to locate relevant lines before reading large files.
Inputs: filePath (required), projectId (required), limit, offset, +3 more.
typst_rename_fileB
Rename or move a file inside a https://typst.app project via UpdatesFileMutation.
Inputs: newName (required), filePath (required), projectId (required).
typst_upload_assetA
Upload or replace a binary asset (PNG, JPG, SVG, PDF, font, etc.) in a https://typst.app project from a local file path or base64 data.
Inputs: fileName (required), projectId (required), convert, base64Data, +1 more.
typst_write_fileB
Create or overwrite a text file (.typ, .bib, .toml, etc.) in a https://typst.app project, synchronizing the Yjs CRDT update via WebSocket (/editing/v3) and REST (/v1/files/:projectId/:fileId/yjs).
Inputs: content (required), filePath (required), projectId (required), preferWebSocket.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 18 tools
Most tools have clearly distinct resource/action targets, and descriptions help separate rendering, searching, and file mutation operations. Some overlap remains between typst_write_file, typst_edit_file, and typst_find_and_replace, plus minor overlap between typst_list_files and typst_get_project.
All tools use a consistent typst_ prefix and snake_case, with mostly predictable action_resource names. Minor deviations include typst_auth_login/typst_auth_status using auth as a grouping prefix and typst_find_and_replace using a compound verb.
At 18 tools, the surface is slightly above the typical sweet spot but still reasonable for a project-management, file-editing, and rendering MCP. Each tool covers a meaningful operation, though the three content-mutation tools add some density.
Core project, file, auth, search, compile, export, and screenshot workflows are well covered, including binary asset handling. Minor gaps exist around project metadata updates, sharing/permissions management, and auth logout.
Maintenance
Related MCP Connectors
Write, compile and share Typst documents (papers, slides, drawings) from any AI agent.
Persistent cloud workspaces for AI agents: run commands, edit files, use git and a browser.
Project memory, documentation and controlled secret access for AI coding agents.
Shared project context for AI agents and teams: docs, tasks, and messages that stay current.
Related MCP Servers
- FlicenseBqualityDmaintenanceEnables AI agents to interact with Overleaf projects directly, including creating projects, managing files, and editing documents in real-time using Overleaf's native Operational Transformation protocol.101-
- AlicenseAqualityBmaintenanceEnables AI assistants to manage Typst and LaTeX projects on self-hosted Typleaf instances, including reading and editing documents, compiling to PDF, analyzing structure and page layout, checking citations, and reviewing git history.229MIT
- AlicenseAqualityCmaintenanceEnables local AI agents to discover projects and read, upload, update, and delete files in a self-hosted collaborative LaTeX/Markdown writing platform, plus maintain a local mirror with git-style pull, push, and status synchronization.14MIT
- AlicenseNot gradedqualityAmaintenanceGives AI agents access to a persistent document workspace, letting them search, read, and update notes, guides, and project documentation across a full catalog of tools, prompts, and resources. It connects either to the hosted Cloud endpoint over Streamable HTTP with OAuth or API-key auth, or to a self-hosted instance through a stdio bridge.MIT