Octree for agents

Compile LaTeX from any AI agentThe LaTeX compile API and MCP server

One API key, two ways in: a REST endpoint that turns LaTeX into a PDF, and an MCP server that gives Claude Code, Cursor and other agents a compile_latex tool. Send the source, get the PDF back in seconds, or a list of errors with file and line when it does not compile. It is the same compiler (TeX Live, latexmk) that runs the Octree editor, so there is nothing to install and every package is already there.

  • REST: POST https://app.useoctree.com/api/v1/compile
  • MCP: https://app.useoctree.com/api/mcp (Streamable HTTP)
  • Auth: Authorization: Bearer oct_live_…
  • Free: 30 compiles a day; Pro: 1,000 a day

Quickstart

Create a key under Settings → API keys in the Octree app. It starts with oct_live_ and is shown once, so copy it somewhere safe. Then pick your client:

Add Octree as a remote MCP server, then ask Claude to compile main.tex.

claude mcp add --transport http octree https://app.useoctree.com/api/mcp \
  --header "Authorization: Bearer oct_live_…"

# then, in Claude Code:
# > Write main.tex for a two-page lab report and compile it with Octree.

Cursor, Windsurf and any other MCP client

Clients that read an mcpServers config take a remote server with a URL and headers. In Cursor this goes in ~/.cursor/mcp.json (or .cursor/mcp.json in a project); Windsurf and other clients use the same shape in their own MCP config file, some under the name serverUrl instead of url.

mcp.json
{
  "mcpServers": {
    "octree": {
      "url": "https://app.useoctree.com/api/mcp",
      "headers": {
        "Authorization": "Bearer oct_live_…"
      }
    }
  }
}

Keep the key out of shared repositories: put it in your user-level config, or use your client’s environment-variable substitution if it has one.

REST API Reference

Base URL https://app.useoctree.com. Every request needs Authorization: Bearer oct_live_…. Request bodies are JSON.

POST /api/v1/compile

Compile LaTeX to PDF. Send either a single document or a set of files. There is no engine option: documents compile with pdfLaTeX, and the compiler switches to XeLaTeX or LuaLaTeX automatically when the document needs it (for example when it loads fontspec).

FieldTypeDescription
latexstringA complete single-file document (it must contain \documentclass), compiled as main.tex. Use this or files.
files{ path, content }[]Project files with relative, forward-slash paths, e.g. sections/intro.tex, refs.bib. Up to 50 files, text only in v1.
mainstringOptional, with files only: the .tex file to compile. Defaults to main.tex if present, else the first .tex file containing \documentclass. The main file must contain \documentclass, or the request is rejected with 400.
response"json" | "pdf"json (default) returns the object below; pdf returns the raw PDF. Accept: application/pdf does the same as pdf; an explicit response field wins over the header. Failures are JSON either way.
{
  "latex": "\\documentclass{article}\\begin{document}Hello\\end{document}",
  "response": "json"
}

A document that compiles returns ok: true with the PDF base64-encoded. A document with LaTeX errors is still a successful request: HTTP 200 with ok: false and the errors.

{
  "ok": true,
  "pdf_base64": "JVBERi0xLjUKJcfsj6IK…",
  "pages": 1,
  "duration_ms": 1840,
  "warnings": [],
  "log_tail": ""
}
FieldDescription
oktrue if a PDF was produced.
pdf_base64The PDF, base64-encoded (success only).
pagesPage count, when known.
duration_msCompile time in milliseconds.
warningsAlways [] on success in v1; warnings show up only in the log of a failed compile.
errors{ file, line, message, kind }[] when ok is false.
log_tailThe last lines of the LaTeX log when the compile fails; '' on success.
suggestionOptional hint for fixing the first error.

kind is one of missing_package, undefined_control_sequence, missing_dollar, missing_brace or latex_error, so an agent can branch on the error type without parsing the log. A compile that runs out of time is not a LaTeX error: it is HTTP 504 compile_timeout.

GET /api/v1/me

Your plan, today’s usage and resets_at, the next reset (midnight UTC, ISO 8601). Useful as a key check before a batch job.

request
curl https://app.useoctree.com/api/v1/me \
  -H "Authorization: Bearer $OCTREE_API_KEY"
200
{
  "user_id": "3f6c…",
  "plan": "free",
  "daily_limit": 30,
  "used_today": 4,
  "resets_at": "2026-11-09T00:00:00.000Z"
}

GET /api/v1/openapi.json

The OpenAPI description of the API, at https://app.useoctree.com/api/v1/openapi.json. Load it into Postman or an agent framework that builds tools from OpenAPI.

Errors and status codes

StatuserrorMeaning
200noneRequest handled. Check ok: the document compiled, or it has LaTeX errors listed in errors.
400invalid_requestMalformed body, e.g. invalid JSON, neither latex nor files, more than 50 files, a bad or duplicate path, or a main file without \documentclass.
401unauthorizedMissing, invalid or revoked API key.
413payload_too_largeSource over 2 MB, or a request body over 4 MB.
429quota_exceededDaily quota used up. Also returns limit, used, resets_at and upgrade_url.
429rate_limitedToo many failed key attempts from your IP address (10 a minute). Check the key and wait for Retry-After seconds.
503service_unavailableThe API key check is temporarily unavailable. Retry with backoff.
503compile_unavailableThe compiler is busy or temporarily unavailable. Retry after Retry-After seconds.
504compile_timeoutThe compile took too long. Simplify the document or split the work.

Every error response is JSON with an error code and a human-readable message.

Limits and keys

  • Free: 30 compiles per day. Pro: 1,000 compiles per day, reset at midnight UTC. REST and MCP share the same count, and check_latex counts like a compile.
  • Request size: up to 2 MB of source and 50 files.
  • Keys: oct_live_…, up to 5 per account, shown once, stored hashed, revocable at any time in Settings.

MCP Server Reference

The Octree LaTeX MCP server lives at https://app.useoctree.com/api/mcp. It speaks the Streamable HTTP transport and is stateless, so there is no session to set up or keep alive. Authenticate with the same API key in an Authorization: Bearer oct_live_… header.

ToolInputReturns
compile_latexlatex, or files + mainA short summary (pages and time, or the errors) and the PDF as a resource.
check_latexlatex, or files + mainErrors only, with file, line and kind. The fast loop for an agent fixing a document. Counts toward the daily quota.
get_quotanonePlan, daily limit, compiles used today and resets_at.

How an agent should use it

Write the .tex files first, with \documentclass in the main file. Call check_latex and fix what it reports, using the file, line and kind of each error, until it comes back clean. Then call compile_latex once to get the PDF. Every check counts toward the daily quota, so fix all reported errors before checking again. Each check returns only the errors, not a PDF, so the fix loop stays small, and the agent never has to read a raw LaTeX log. If you write instructions for your agent (a CLAUDE.md, Cursor rules or a system prompt), this one line is enough:

agent instructions
To build LaTeX, use the octree MCP tools: run check_latex until there are no errors, then compile_latex once to get the PDF.

Frequently Asked Questions

Is the Octree LaTeX compile API free?

Yes. Every Octree account can create API keys, and the free plan includes 30 compiles per day through the REST API and the MCP server. Octree Pro raises the limit to 1,000 compiles per day.

Which LaTeX packages are installed?

The API runs the same compiler as the Octree editor at app.useoctree.com: a full TeX Live installation driven by latexmk, so packages such as amsmath, TikZ, pgfplots, biblatex, beamer and the common thesis and resume classes are already there. Documents compile with pdfLaTeX by default; when a document needs XeLaTeX or LuaLaTeX (for example it loads fontspec), the compiler switches automatically. Shell escape is disabled, so packages that need it, such as minted, do not run.

Can I compile multi-file projects and images?

Multi-file projects, yes: send a files array of { path, content } objects plus the name of the main file, and \input, \include and .bib files resolve as they would on disk. In v1 every file is text; binary assets such as PNG or PDF images are coming. A request can carry up to 50 files and 2 MB of source.

What are the rate limits?

Limits are per account per day: 30 compiles on the free plan and 1,000 on Pro. When you run out, the API answers HTTP 429 with error quota_exceeded, the limit, how many you have used, when the count resets and a link to upgrade. GET /api/v1/me and the get_quota MCP tool show your current usage and when it resets (midnight UTC). check_latex counts toward the same limit.

Do you store the documents I compile through the API?

No. On the API and MCP path the LaTeX source and the PDF are not stored after the response is sent. Projects you create in the Octree editor are saved to your account as usual; that is separate from the API.

How are API keys secured?

Keys start with oct_live_ and are shown once, when you create them. Octree keeps only a hash of each key, so a key cannot be read back, only revoked. You can have up to 5 keys per account and revoke any of them in Settings.

Should my agent use the REST API or the MCP server?

Use the MCP server when the agent is an MCP client (Claude Code, Cursor, Windsurf and others): it gets compile_latex, check_latex and get_quota as tools with no glue code. Use the REST API from scripts, CI jobs, backends and agent frameworks that call HTTP directly. Both use the same API key and the same daily limit.

Learn More

  • Learn LaTeX – The basics your agent’s documents are built on
  • TikZ and PGFPlots – Diagrams and plots that compile through the API like any other package
  • Bibliography examples – Send a .bib file in files and cite as usual
  • Octree editor – The same compiler with an AI editor, PDF preview and saved projects

Give your agent a LaTeX compiler

Create a free API key, add one line to Claude Code or Cursor, and your agent can turn LaTeX into a PDF: 30 compiles a day free, 1,000 on Pro.

Get an API key →