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 idsget_template— a template's data contract (itsvariablesandsample_data)create_template— AI-author a new template from a promptgenerate_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
- /llms.txt — condensed index; /llms-full.txt — full reference (endpoints, helpers, error codes)
- /openapi.json — OpenAPI 3.1 spec for client generation