FormaTeX

\usepackage{mcp}

MCP Server for LaTeX

Connect Claude, Claude Code, Cursor, VS Code and other MCP-compatible agents to FormaTeX. Your assistant writes the LaTeX, compiles it, and hands back a link to the PDF in the same conversation.

\section{What is MCP}

What is the Model Context Protocol?

AI-native tool use

MCP is an open protocol, introduced by Anthropic, that lets AI clients discover and call external tools at run time, so an assistant can act without custom glue code.

A standard server interface

An MCP server publishes named tools with JSON Schema inputs. Any compatible client, such as Claude, Claude Code, Cursor, VS Code, Codex or your own agent, can call them.

FormaTeX as a toolset

The FormaTeX server exposes tools to compile LaTeX with an engine of your choice or with automatic fixes, validate syntax, run async jobs and compile saved templates, plus resources and a fix_latex prompt.

End to end in one turn

Ask for a report. The assistant writes the LaTeX, calls a compile tool, and returns a download link for the finished PDF.

\section{Setup}

Setup guide

There are two ways to connect. The hosted server needs nothing installed; the local binary runs on your machine. Both use the same FormaTeX API key and work on every plan, including Free. Compilations made through MCP count toward the same monthly API quota as REST calls.

Step 1. Create an API key

Create a key on the API Keys page of your dashboard. FormaTeX keys start with fex_. Keep the key in an environment variable such as FORMATEX_API_KEYrather than committing it to a repo.

Step 2, option 1. Hosted server (recommended)

The server athttps://mcp.formatex.io/mcpspeaks Streamable HTTP. There is nothing to install, and every request carries your API key.

Claude (claude.ai and Claude Desktop)

  1. Open Customize, then Connectors, and choose Add custom connector.
  2. Enter the server URL below.
  3. Sign in when prompted. The authorization page asks for your FormaTeX API key. If your client exposes request headers instead, set Authorization: Bearer <your key>.
Server URL
https://mcp.formatex.io/mcp

claude_desktop_config.jsonis only for local servers that Claude Desktop starts itself. Add the hosted server through Connectors, not through that file.

Claude Code

Register the server from the CLI, or commit a .mcp.jsonat the project root.${VAR} expansion works in that file, so the key stays in your environment.

terminal
export FORMATEX_API_KEY="fex_your_api_key"

claude mcp add --transport http formatex https://mcp.formatex.io/mcp \
  --header "Authorization: Bearer $FORMATEX_API_KEY"
.mcp.json
{
  "mcpServers": {
    "formatex": {
      "type": "http",
      "url": "https://mcp.formatex.io/mcp",
      "headers": {
        "Authorization": "Bearer ${FORMATEX_API_KEY}"
      }
    }
  }
}

Cursor

Add the server to.cursor/mcp.jsonin your project, or to~/.cursor/mcp.jsonfor every project.

.cursor/mcp.json
{
  "mcpServers": {
    "formatex": {
      "url": "https://mcp.formatex.io/mcp",
      "headers": {
        "Authorization": "Bearer ${env:FORMATEX_API_KEY}"
      }
    }
  }
}

VS Code

VS Code reads.vscode/mcp.json. Its top-level key is servers, notmcpServers, and remote entries need "type": "http".

.vscode/mcp.json
{
  "inputs": [
    {
      "type": "promptString",
      "id": "formatex-api-key",
      "description": "FormaTeX API key",
      "password": true
    }
  ],
  "servers": {
    "formatex": {
      "type": "http",
      "url": "https://mcp.formatex.io/mcp",
      "headers": {
        "Authorization": "Bearer ${input:formatex-api-key}"
      }
    }
  }
}

Codex

Add a server table to~/.codex/config.toml. bearer_token_env_varnames the environment variable that holds the key.

~/.codex/config.toml
[mcp_servers.formatex]
url = "https://mcp.formatex.io/mcp"
bearer_token_env_var = "FORMATEX_API_KEY"

Step 2, option 2. Local binary (stdio)

Runformatex-mcpon your machine. The client starts it as a child process and the binary reads your key from the FORMATEX_API_KEYenvironment variable. Choose this route if your client only supports stdio.

Install the binary

terminal
# Requires Go 1.23 or newer
go install github.com/formatexio/mcp/cmd/formatex-mcp@latest

# The binary lands in $(go env GOPATH)/bin as formatex-mcp.
# Prebuilt binaries: https://github.com/formatexio/mcp/releases

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json on macOS or%APPDATA%\Claude\claude_desktop_config.json on Windows, then restart Claude Desktop.

claude_desktop_config.json
{
  "mcpServers": {
    "formatex": {
      "command": "/full/path/to/formatex-mcp",
      "env": {
        "FORMATEX_API_KEY": "fex_your_api_key"
      }
    }
  }
}

Claude Code

terminal
claude mcp add --env FORMATEX_API_KEY=fex_your_api_key \
  --transport stdio formatex -- /full/path/to/formatex-mcp

Codex

~/.codex/config.toml
[mcp_servers.formatex]
command = "formatex-mcp"

[mcp_servers.formatex.env]
FORMATEX_API_KEY = "fex_your_api_key"

Authentication and checks

  • Hosted server: send the key as Authorization: Bearer <key>or X-API-Key: <key>. A request without a key gets a 401.
  • Claude custom connectors sign in with OAuth. The authorization page asks for your API key.
  • The hosted server is Streamable HTTP only. It has no /sseendpoint, so a client that supports only the older SSE transport should use the local binary.
  • Free plans compile with pdflatex and xelatex. lualatex, latexmk and saved templates need Pro or above.

To confirm the hosted server is up, call its health endpoint. Then ask your assistant to “List the available LaTeX engines”; it should calllist_engines.

terminal
curl https://mcp.formatex.io/health
# {"status":"ok","service":"formatex-mcp","version":"1.0.0"}

\section{Tools}

Tools, resources and prompt

ToolWhat it does
compile_smartCompiles with automatic engine detection and error fixing, retrying with fallback engines. The recommended default. Returns a PDF download link.
compile_latexCompiles with the engine you name: pdflatex, xelatex, lualatex or latexmk. Returns a PDF download link.
check_syntaxValidates source for syntax errors, forbidden commands and structural issues without compiling. Does not count against the monthly compilation quota.
compile_asyncSubmits a compilation job and returns a job ID immediately. Suited to large documents and batch workflows.
get_jobReturns the status of an async job: a PDF download link when it completed, the error log when it failed.
fetch_pdf_bytesReturns a compiled PDF as base64 bytes, for when you need the file itself rather than a link.
list_enginesLists the available LaTeX engines and when to use each one.
get_usageShows this month's compilation statistics and plan limits for the API key.
list_templatesLists your saved templates with IDs, names, descriptions and variables. Pro plan and above.
get_templateReturns one saved template with its full LaTeX source and variable definitions. Pro plan and above.
create_templateSaves a new template with variable placeholders, checking the variable schema first. Pro plan and above, up to the plan's template limit.
update_templateChanges only the fields it is given on a saved template. The previous version is replaced. Pro plan and above.
compile_templateCompiles a saved template by ID with optional variable substitutions. Pro plan and above.

Two resources,formatex://enginesand formatex://usage, expose the engine list and your current usage. Thefix_latexprompt takes your LaTeX source and the error log and returns structured instructions for fixing the errors.

\section{Tool Definition}

Tool definition

This is thecompile_latexentry exactly as the hosted server returns it fromtools/list. runsand timeoutare integers; send0 to leave them to the API, which then chooses the number of passes and applies the default timeout for your plan. compile_smarttakes latex, runsandtimeoutand picks the engine itself, andcompile_asyncrequires onlylatex.

tools/list entry: compile_latex
{
  "name": "compile_latex",
  "description": "Compile LaTeX source code to a PDF using the FormaTeX API. Returns a download URL for the PDF. Specify the engine explicitly (pdflatex for standard documents, xelatex/lualatex for Unicode/modern fonts, latexmk for complex documents).",
  "inputSchema": {
    "type": "object",
    "properties": {
      "latex": { "type": "string" },
      "engine": { "type": "string" },
      "runs": { "type": "integer" },
      "timeout": { "type": "integer" }
    },
    "required": ["latex", "engine", "runs", "timeout"],
    "additionalProperties": false
  }
}

A successful compile returns plain text: job metadata and a Download PDFlink. The PDF itself is not inlined, which keeps the conversation small.fetch_pdf_bytesis the only tool that returns the file as base64; call it with the job ID when you need the bytes.

tool result text
Compilation successful. Engine: pdflatex, Duration: <ms> ms, Job ID: <job id>, PDF size: <bytes> bytes
Download PDF: <url>

\section{Python Example}

Use the server from the Messages API

The Messages API MCP connector lets Claude call the hosted server without you running an MCP client. It is a beta feature: send the mcp-client-2025-11-20beta header, list the server under mcp_servers, and enable its tools with an mcp_toolsetentry intools. The example asks Claude to write and compile a one-page note in a single request.

mcp_example.py
import os

import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY

response = client.beta.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=2048,
    betas=["mcp-client-2025-11-20"],
    mcp_servers=[
        {
            "type": "url",
            "url": "https://mcp.formatex.io/mcp",
            "name": "formatex",
            # Your FormaTeX API key, sent to the server as a bearer token.
            "authorization_token": os.environ["FORMATEX_API_KEY"],
        }
    ],
    tools=[{"type": "mcp_toolset", "mcp_server_name": "formatex"}],
    messages=[
        {
            "role": "user",
            "content": (
                "Write a one-page LaTeX note on gradient descent with the "
                "update rule as a display equation, compile it, and give me "
                "the PDF link."
            ),
        }
    ],
)

for block in response.content:
    if block.type == "mcp_tool_use":
        print("Tool call:", block.name)
    elif block.type == "text":
        print(block.text)

The connector supports tool calls only, so resources and the fix_latexprompt are available in MCP clients rather than through the API.

\section{Use Cases}

Use cases

Research reports

Ask your assistant to summarise a paper and compile a formatted PDF with equations, figures and a bibliography from one prompt.

Automated documentation

Let an agent in your pipeline generate release notes or reference documents as LaTeX and compile them to PDF.

On-demand certificates

Generate personalised certificates or invoices. The agent fills the variables of a saved template (Pro and above) and FormaTeX renders the PDF.

\end{mcp}

Let Claude compile your LaTeX

Create a FormaTeX API key, add the hosted server to your client, and start generating PDFs from your AI chat.