@pressa/mcp
MCP (Model Context Protocol) server for Pressa - a LaTeX-to-PDF compilation service. This server lets AI assistants compile LaTeX documents and check API usage through a standardized interface.
Setup
Add this to your MCP client configuration (e.g. Claude Desktop, Cursor):
{
"mcpServers": {
"pressa": {
"command": "npx",
"args": ["-y", "@pressa/mcp"],
"env": {
"PRESSA_API_KEY": "pressa_your_key_here"
}
}
}
}
Environment Variables
PRESSA_API_KEY | Yes | - | Your Pressa API key (starts with pressa_) |
PRESSA_API_URL | No | https://api.pressa.dev | API base URL |
Tools
compile
Compile LaTeX source code into a PDF.
Input:
latex | string | Yes | Complete LaTeX source code. Must contain \documentclass, \begin{document}, \input{}, or \include{}. Plain text, markdown, or raw notes are rejected with not_latex_source (422). The AI agent should generate LaTeX itself, not bounce back to the user. |
compiler | string | No | "pdflatex" (default), "xelatex", or "lualatex" (Pro and Business plans only) |
Each plan has limits on pages per document, LaTeX source size, PDF output size, and compile timeout. If a compile exceeds your plan's page limit, the document does not count against your monthly quota and the MCP response includes the limit and an upgrade URL. Non-LaTeX input is rejected with a structured requirements list and an example_template so the LLM can self-correct without user intervention.
Output (success):
{
"job_id": "ffc2bd62-3b67-45d6-be14-b529c4b9489f",
"pdf_url": "https://api.pressa.dev/api/v1/pdfs/ffc2bd62...?sig=xxx&exp=xxx",
"expires_at": "2026-04-09T20:44:55Z",
"pages": 1,
"compilation_time_ms": 359,
"usage": {
"plan": "free",
"compilations_this_month": 9,
"monthly_limit": 50
}
}
Output (error): Compilation log and error line number.
usage
Get current API usage statistics.
Input: None.
Output:
{
"user": {
"email": "user@example.com",
"username": "user",
"plan": "free"
},
"usage": {
"compilations_this_month": 9,
"monthly_limit": 50,
"remaining": 41,
"resets_at": "2026-04-30T23:59:59Z"
},
"api_key": {
"prefix": "pressa_a",
"name": "my-key",
"total_requests": 15,
"last_used_at": "2026-04-08T20:44:55Z"
}
}
save_template
Save or update a LaTeX template by name. Paid plans only. Upserts: a second call with the same name overwrites the first.
name | string | Yes | Template name (max 100 chars). Unique per user. |
latex_content | string | Yes | Full LaTeX source for the template body. |
description | string | No | Short human-readable summary (max 500 chars). Shown in list_templates. |
instructions | string | No | Agent playbook (prose markdown, max 50000 chars). Describes how to fill the template - defaults, workflow rules, edge cases, conditional logic. Optional but recommended for templates with dynamic parts. See note below. |
description vs instructions: description is the one-line UI summary ("Standard Toptal monthly invoice"). instructions is the longer playbook your AI agent reads alongside the LaTeX when filling the template ("Ask the user only for total amount; date is today; invoice number format YYYYMMDD-N where N is sequential count for the calendar year; for EU clients add VAT line"). They are different fields.
list_templates
List the user's saved templates. Does not include latex_content or instructions to keep the response small.
Input: None.
Each item in the returned array carries id, name, description, updated_at, latex_size_bytes, and has_instructions (boolean). Use the has_instructions flag to decide whether a follow-up get_template call will return a useful playbook.
get_template
Fetch a single template by ID or name. Returns the full latex_content plus instructions (if any) in one round trip - your agent gets the layout and the playbook together.
id_or_name | string | Yes | Numeric ID or URL-safe template name. |
delete_template
Delete a template by ID or name.
id_or_name | string | Yes | Numeric ID or URL-safe template name. |
Development
npm install
npm run build
npm start
License
MIT