Using doclinth from an AI agent

doclinth is built to be called by software and by the agents that software runs. There are two ways in: connect over MCP (the agent discovers and calls typed tools), or wire POST /v1/generate directly as a tool. Both authenticate with your normal API key, and both hit the same deterministic render path.

Create once, generate forever

The durable pattern: an agent (or a human) authors a template once, then every document after is a plain data call. The render path never touches an LLM, so the same published template and data produce the same document, render after render — no drift between runs, no model bill per PDF, and a signed URL you can hand straight to a user. Let the model decide what to put in the document; let doclinth decide how it looks, the same way every time.

Connect over MCP

The remote MCP server speaks streamable HTTP at https://doclinth.com/mcp. Authenticate with your API key as the bearer token. It exposes four tools:

  • list_templates — your templates and their ids
  • get_template — a template's data contract (its variables and sample_data)
  • create_template — AI-author a new template from a prompt
  • generate_pdf — render a template with data → a 24-hour signed URL

The intended flow is get_template first (to learn the exact data shape), then generate_pdf. Each tool's description carries a worked example the agent reads at call time.

Claude Code

claude mcp add --transport http doclinth https://doclinth.com/mcp \
  --header "Authorization: Bearer dl_live_YOUR_KEY"

Claude Desktop (and other stdio-only clients)

Bridge the remote server through mcp-remote in your claude_desktop_config.json:

{
  "mcpServers": {
    "doclinth": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote", "https://doclinth.com/mcp",
        "--header", "Authorization: Bearer dl_live_YOUR_KEY"
      ]
    }
  }
}

Any streamable-HTTP MCP client

{
  "mcpServers": {
    "doclinth": {
      "type": "http",
      "url": "https://doclinth.com/mcp",
      "headers": { "Authorization": "Bearer dl_live_YOUR_KEY" }
    }
  }
}

Or wire /v1/generate as a tool directly

If you're building your own agent loop, skip MCP and expose generate_pdf as a tool whose handler calls the REST API. This works with any tool-calling model. Tool schema:

{
  "name": "generate_pdf",
  "description": "Render a doclinth template with data into a PDF. Returns a 24h signed URL.",
  "input_schema": {
    "type": "object",
    "properties": {
      "template_id": { "type": "string", "description": "A template id you own." },
      "data": { "type": "object", "description": "Values merged into the template." }
    },
    "required": ["template_id"]
  }
}

The handler is a single request:

async function generatePdf({ template_id, data }) {
  const res = await fetch("https://doclinth.com/v1/generate", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.DOCLINTH_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ template_id, data, options: { output: "url" } }),
  });
  if (!res.ok) {
    const { error } = await res.json();
    throw new Error(`${error.code}: ${error.message}`);
  }
  return res.json(); // { url, expires_at }
}

Give the model list_templates and get_templateas tools too, so it can discover ids and learn each template's variables before it renders.

Machine-readable references