Skip to main content
Glama
sheetrender

@sheetrender/mcp

Official

@sheetrender/mcp

MCP server for SheetRender. It lets your AI assistant render PDFs from HTML templates and spreadsheet data.

Setup

Get an API key from sheetrender.com under Settings → API keys, then add this to your MCP client config:

{
  "mcpServers": {
    "sheetrender": {
      "command": "npx",
      "args": ["-y", "@sheetrender/mcp"],
      "env": { "SHEETRENDER_API_KEY": "sr_live_..." }
    }
  }
}

SHEETRENDER_API_URL is also read, and defaults to https://sheetrender.com. Set it only if you're pointing at a self-hosted or staging instance.

Related MCP server: rendoc

Hosted endpoint

The same server runs at https://mcp.sheetrender.com/mcp over Streamable HTTP, so clients that can't spawn a local process can use it too. Nothing is installed; each request carries your API key:

Authorization: Bearer sr_live_...

Requests without that header get a 401. The key goes straight through to the SheetRender API for that one request and is never stored — the server keeps no sessions, so every request stands alone.

Where the key goes depends on the client:

  • Claude Code: claude mcp add --transport http sheetrender https://mcp.sheetrender.com/mcp --header "Authorization: Bearer sr_live_..."

  • Cursor, Windsurf, VS Code and other clients with an mcp.json:

    {
      "mcpServers": {
        "sheetrender": {
          "url": "https://mcp.sheetrender.com/mcp",
          "headers": { "Authorization": "Bearer sr_live_..." }
        }
      }
    }
  • Claude API (the Messages API's MCP connector): add {"type": "url", "url": "https://mcp.sheetrender.com/mcp", "name": "sheetrender", "authorization_token": "sr_live_..."} to mcp_servers.

  • claude.ai, Claude Desktop and ChatGPT custom connectors take a server URL and an OAuth client, not a static header. Until the endpoint speaks OAuth, use the stdio package above there — it's the same tools, with the key in env — or bridge with npx mcp-remote https://mcp.sheetrender.com/mcp --header "Authorization: Bearer sr_live_..." as the command.

Two differences from the stdio server follow from the process not running on your machine. Rendered PDFs come back inline as a base64 resource (up to 8 MB; larger ones are reported with their size and left for the web app) instead of as a temp-file path, and upload_dataset is not offered because there is no local file to read — send rows with create_dataset instead.

GET /healthz answers 200 without credentials. Request bodies are capped at 25 MB; anything larger is a 413.

Running it yourself

sheetrender-mcp-http is a second bin in the package. It reads PORT (default 8080), HOST (default 0.0.0.0), SHEETRENDER_API_URL, MAX_BODY_BYTES and IDLE_TIMEOUT_MS (default 60000), and logs one JSON line per request to stdout — method, path, status, duration, the JSON-RPC method and tool name, and a fingerprint of the key, never the key. The Dockerfile in this repo builds a non-root runtime image for it:

docker build -t sheetrender-mcp .
docker run --rm -p 8080:8080 sheetrender-mcp

Tools

render_pdf

Renders one PDF from HTML you supply.

Argument

Type

html

string

Required. A full HTML document. CSS has to be inline in a <style> tag; external stylesheets, fonts and scripts are not fetched.

data

object

Optional. Keys become Jinja variables, so {"total": "42.00"} makes {{ total }} available in the HTML.

page_settings

object

Optional, see below.

Returns the path of the saved PDF and its size. Under 512 KB it's also attached inline as a base64 resource, so clients that display attachments show the document itself.

Two server limits apply. HTML over 2 MB is rejected, and that's measured both on what you send and on the document after data is substituted in, so a template that expands a long dataset can cross the line even when the markup you wrote doesn't. The other is the free plan, where every rendered PDF carries a "Made with SheetRender" footer. That applies to render_pdf and render_template alike. Paid plans don't get it.

list_templates

No arguments. Returns each saved template's name, id and last-updated date. Call it to turn a template name the user mentioned into the id the other tools want.

render_template

Renders one PDF from a template already saved in the account.

Argument

Type

template_id

string

Required, from list_templates.

data

object

Required. One row's values, as Jinja variables.

page_settings

object

Optional. Omit it to keep the template's own saved page setup; passing it overrides that for this render.

Same return as render_pdf.

create_dataset

Turns JSON rows into a dataset a batch job can render. This is the usual way to start a batch: assemble the rows, send them, get back a dataset_id.

Argument

Type

template_id

string

Required, from list_templates. The dataset lands in that template's project.

rows

array of objects

Required. One flat object per document.

name

string

Optional label, used as the stored filename.

The header is the union of every row's keys in first-seen order, so rows don't have to agree on their keys — a missing one is a blank cell rather than a shifted row. Values have to be scalars: strings, numbers, booleans or null. Nested objects and arrays are rejected, and so are NaN, Infinity and whole numbers past 2^53 (send those as strings to keep them exact). The caps are 50,000 rows and 500,000 cells per call.

Returns the dataset id, row count and, for each column, the sanitized key. That key is what template placeholders, filename_template and group_by address, and it's often not the header verbatim — Invoice No becomes invoice_no. Read it off this result instead of guessing.

Creating a dataset is free; only rendering counts against the plan.

upload_dataset

The same thing from a file that already exists.

Argument

Type

template_id

string

Required, from list_templates.

file_path

string

Required. A .csv or .xlsx on the machine running this server — the user's machine, not SheetRender's. ~ is expanded.

The first row has to be the header. Files over 20 MB, the wrong extension and empty files are refused locally, before anything is uploaded. Same return as create_dataset.

list_datasets

Takes template_id and lists every dataset in that template's project, newest first, with ids, row counts and column keys. Use it to find data the user already loaded, or to read a dataset's column keys before writing a filename_template or picking group_by.

create_batch_job

Queues a background job that renders one PDF per row of a dataset. The whole loop runs from here — list_templatescreate_dataset or upload_datasetcreate_batch_jobget_jobget_document.

Argument

Type

template_id

string

Required, from list_templates.

dataset_id

string

Required, from create_dataset, upload_dataset or list_datasets. Must be in the same project as the template.

filename_template

string

Optional. Output naming pattern, e.g. invoice-{{ invoice_no }}.

group_by

string

Optional. Column key to group rows by, giving one multi-page PDF per distinct value.

Returns the job id to poll with get_job. Worth knowing: filename_template and group_by are persisted to the template and the project respectively, so they change the defaults for later runs too.

If the server predates the public batch endpoint, the tool reports that batch jobs are unavailable rather than failing obscurely. The three dataset tools do the same for a server that predates the dataset endpoints.

get_job

Takes job_id. Returns the status, rows done and failed, and the id and filename of every rendered document. That document list stays empty while the job is queued, retry_queued or running, and fills in once the job reaches succeeded, partial, failed or cancelled. Those document ids are what get_document takes.

get_document

Takes document_id and downloads that single rendered PDF. The ids come from get_job on a finished batch, and there's no other way to get one. Same return as render_pdf: path, size, and an inline blob under 512 KB.

If you want a whole batch, the merged PDF and ZIP in the web app beat fetching each document in turn.

page_settings

Shared by both render tools. Every field is optional:

{
  "page_size": "a4",
  "orientation": "portrait",
  "margins": { "top": 15, "right": 15, "bottom": 15, "left": 15 }
}

page_size is lowercase: a3, a4, a5, letter, legal or tabloid. Margins are plain numbers in millimetres, not CSS lengths.

Rendered PDFs are written to the system temp directory. API errors like a bad key, a missing template or a rate limit come back as tool errors carrying the server's own message.

The public API allows 120 requests per minute per API key. Past that it returns 429, and the tool reports that you're rate limited and should retry shortly. Batch job creation is metered separately and more tightly.

Development

You don't need node or npm on the host: scripts/dev.sh install, then scripts/dev.sh deno task build and scripts/dev.sh deno task test. scripts/dev.sh node dist/http.js runs the HTTP server on the host network.

MIT licensed.

Available Tools

6 tools
create_batch_jobStart a batch PDF jobAInspect

SheetRender turns HTML templates plus spreadsheet rows into rendered PDFs. This tool queues a batch job that renders one PDF per row of an uploaded dataset, and returns the job id.

Use it when the user wants many documents at once — "an invoice for every row", "one letter per employee". The dataset must already be uploaded to the SheetRender project; this tool cannot upload spreadsheets. Rendering happens in the background: poll get_job with the returned id to see progress and collect document ids.

filename_template and group_by are saved onto the template/project, so they change the defaults for later runs, not just this one. Only pass them when the user asked to change how output is named or grouped.

ParametersJSON Schema
NameRequiredDescriptionDefault
group_byNoColumn name to group rows by, producing one multi-page PDF per distinct value instead of one per row. Saved to the project.
dataset_idYesId of a dataset already uploaded to the same SheetRender project.
template_idYesTemplate id from list_templates.
filename_templateNoNaming pattern for output files, with column placeholders, e.g. "invoice-{{ invoice_no }}". Saved to the template.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully covers behavioral traits: it returns a job id, runs rendering in the background, and poll get_job is required. It also discloses the side-effect that filename_template and group_by are saved to the template/project, altering defaults for future runs—critical for an agent to know.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: it opens with a one-sentence system context, then the tool's specific action, followed by usage conditions, a behavioral note, and a parameter warning. Every sentence serves a purpose and the information is front-loaded with the core purpose. While not extremely short, it is efficient and free of fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description explains the return value (job id) and how to retrieve results via get_job. It covers prerequisites, background execution, and side-effects, making it fully self-contained for an agent to correctly invoke and interpret the results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides complete descriptions for all four parameters, including the persistence side-effect for group_by and filename_template. The description adds usage guidance ('Only pass them when...'), but does not introduce new semantic meaning about what each parameter does beyond the schema. Given 100% schema coverage, the description meets but does not exceed the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: it queues a batch job that renders one PDF per row of an uploaded dataset and returns a job id. It also distinguishes itself from siblings by mentioning the batch scenario ('many documents at once') versus single renders, making it specific and differentiating.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use it ('Use it when the user wants many documents at once'), provides a prerequisite (dataset must already be uploaded, cannot upload), and directs the agent to poll get_job for progress. This is clear guidance on when and how to use the tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_documentDownload a rendered documentAInspect

SheetRender turns HTML templates plus spreadsheet rows into rendered PDFs. This tool downloads one PDF produced by a batch job and returns the path to the saved file.

document_id comes from get_job on a finished batch — that is the only place these ids appear, so call get_job first and take an id from its document list. A document id is not a template id or a job id.

Use it to fetch a specific output the user asked about, or to spot-check a batch. Fetching every document of a large batch one at a time is slow; point the user at the SheetRender web app for the merged PDF or ZIP instead.

Returns the temp-file path and size; PDFs under 512 KB are also attached inline.

ParametersJSON Schema
NameRequiredDescriptionDefault
document_idYesDocument id from a finished job's document list in get_job.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the behavioral burden. It discloses that the return includes a temp-file path and size, that PDFs under 512 KB are attached inline, and warns about performance when fetching many documents. It also notes the provenance of document_id. While it doesn't mention error handling or permissions, it covers the essential behavior for a download tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: the first sentence states the core purpose, followed by id provenance, usage guidance, and return behavior. Every sentence adds value with no fluff, and the most critical information (spoiler: the id source) is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one parameter and no output schema, the description covers all necessary aspects: what it does, how to obtain the id, when to use it vs alternatives, and what the return includes. Nothing essential is missing for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already describes document_id with high coverage, but the description adds crucial disambiguation: it explains the id comes specifically from get_job's document list and clarifies it is not a template or job id. This goes beyond the schema's baseline, making parameter meaning clearer for the agent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the specific verb (download), resource (PDF from a batch job), and distinguishes it from siblings like render_pdf and get_job. It also clarifies that document_id comes from get_job, making the tool's role unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use the tool (fetch a specific document or spot-check a batch) and when to instead direct the user to the SheetRender web app for bulk downloads. It also references get_job for obtaining valid IDs, providing clear usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_jobCheck a batch PDF jobAInspect

SheetRender turns HTML templates plus spreadsheet rows into rendered PDFs. This tool reports the progress of a batch job started by create_batch_job.

Returns the status, rows done/failed, and — once the job reaches a finished state ("succeeded", "partial", "failed" or "cancelled") — the id and filename of every rendered document. The document list is empty while the job is still in "queued", "retry_queued" or "running", so poll again after a short wait rather than assuming zero documents.

Pass those document ids to get_document to download the individual PDFs.

ParametersJSON Schema
NameRequiredDescriptionDefault
job_idYesJob id returned by create_batch_job.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With zero annotations, the description carries the full behavioral burden and succeeds. It discloses the asynchronous polling nature, enumerates the complete state machine (queued, retry_queued, running, succeeded, partial, failed, cancelled), explains that the document list is empty during in-progress states, and specifies what becomes available once finished. This is exactly the behavioral context an agent needs to avoid misinterpreting empty results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short paragraphs, zero filler. The purpose and polling caveat are front-loaded; the SheetRender context sentence and the get_document routing both earn their place. The state enumeration is necessary, not redundant, given the target states versus document-list-availability states must be distinguished.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema and no annotations, the description fully compensates: it explains the returned fields (status, rows done/failed, document ids/filenames), the conditional availability of results, and the follow-up action. For a single-parameter polling tool, nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% — job_id is documented as 'Job id returned by create_batch_job.' The description reinforces but does not extend this: it references 'the id' of every rendered document but adds no new formatting or validation details beyond the schema. Baseline 3 is appropriate since the schema already carries the semantic weight.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource: 'reports the progress of a batch job started by create_batch_job' — it monitors a job rather than producing content. It distinguishes itself from siblings by explaining the workflow position (reports on create_batch_job output, feeds get_document). The title 'Check a batch PDF job' reinforces the purpose without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description names the prerequisite sibling (create_batch_job), the successor (get_document for downloading), and gives explicit call-timing guidance: poll again while status is in 'queued', 'retry_queued' or 'running' rather than treating an empty document list as zero results. This is concrete, actionable when-to-use guidance that maps the tool into a larger workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_templatesList SheetRender templatesAInspect

SheetRender turns HTML templates plus spreadsheet rows into rendered PDFs. This tool lists the templates saved in the user's account, with the id each one needs.

Call it first whenever the user refers to a template by name ("render the invoice template") so you can map that name to an id for render_template or create_batch_job. Takes no arguments.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the behavioral burden. It clearly states it is a listing operation that returns template ids, which is the core behavior. It adds context about being a prerequisite mapping step, which helps the agent understand its role. It does not explicitly state it is read-only or non-mutating, but that is strongly implied. It also does not mention return format or pagination, but for a simple list tool this is a minor omission. The description is transparent enough for correct invocation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the domain context and the tool's purpose, then immediately gives the when-to-use guidance and the arg note. Every sentence earns its place with no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter list tool with no output schema, the description covers the essential points: what it does, what it returns (ids), and when to call it. It does not describe the exact response structure or pagination, but those are often inferred and not critical for a simple list operation. The context about SheetRender and the mapping step adds completeness. Minor gap: it does not mention how many templates might be returned or any limits, but this is a minor omission given the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has zero properties, and the description explicitly says 'Takes no arguments.' This goes beyond the schema by removing any possible ambiguity about whether arguments might be accepted (an empty schema could be misread). The explicit statement adds value and fully clarifies parameter expectations.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb-resource pair ('lists the templates saved in the user's account') and clarifies the value it provides (the id each one needs). It also distinguishes itself from siblings by positioning it as the listing step against the rendering/job tools (render_template, create_batch_job). This is unambiguous and effectively differentiates the tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly instructs when to call it ('Call it first whenever the user refers to a template by name') and points to the follow-up tools (render_template, create_batch_job). It also notes the tool takes no arguments, which is a useful usage hint. No ambiguity about when or how to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

render_pdfRender HTML to PDFAInspect

SheetRender turns HTML templates plus spreadsheet rows into rendered PDFs. This tool renders a single PDF from HTML you supply and returns the path to the saved file.

Use it for one-off documents — an invoice, a report, a certificate — where you are writing the markup yourself. Use render_template instead when the user already has a saved template.

html must be a complete HTML document (, , ) with all CSS inline in a tag: external stylesheets, fonts and scripts are not fetched. Use @page and mm/cm units for print layout.

data keys become Jinja template variables, so passing {"total": "42.00"} lets the HTML say {{ total }}. Jinja loops and conditionals work too. Omit data if the HTML has no placeholders.

Two server limits to plan for: HTML over 2 MB is rejected, measured both on what you send and on the result after data is substituted in, so keep large tables paginated rather than emitting one enormous document; and accounts on the free plan get a "Made with SheetRender" footer added to every PDF, which is expected, not a bug — mention it if the user seems surprised.

Returns the temp-file path and size; PDFs under 512 KB are also attached inline.

ParametersJSON Schema
NameRequiredDescriptionDefault
dataNoTemplate variables as a flat JSON object. Each key becomes a Jinja variable, so {"customer": "Acme"} makes {{ customer }} available in the HTML.
htmlYesA complete HTML document with inline CSS. May contain Jinja placeholders filled from `data`.
page_settingsNoOptional page setup for the PDF.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It transparently discloses that external resources are not fetched, that HTML over 2MB is rejected (including after substitution), that free accounts get a footer, and that return includes path/size plus inline attachment for small PDFs. This exceeds expectations for behavioral disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear paragraphs. Each sentence earns its place: purpose, usage (with alternative), HTML requirements, data behavior, server limits, and return format. It is detailed but not repetitive; complexity is handled without bloat.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers all necessary aspects for correct use: input requirements, template variable mechanics, output behavior, error conditions (2MB limit), and an environmental quirk (free-plan footer). It is fully self-sufficient even without annotations or output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 100% schema coverage, the description adds substantial meaning beyond the schema: it explains Jinja variable substitution with a concrete example, confirms loops/conditionals work, clarifies that data can be omitted, and details page_settings usage in plain terms. This significantly aids correct invocation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: rendering a single PDF from user-supplied HTML and returning the saved file path. It also distinguishes itself from render_template by explicitly saying when to use which, making it easy for an agent to select correctly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool ('one-off documents... writing the markup yourself') and when to use the alternative (render_template when a saved template exists). It also warns about size limits and the free-plan footer, covering both usage context and potential pitfalls.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

render_templateRender a saved template to PDFAInspect

SheetRender turns HTML templates plus spreadsheet rows into rendered PDFs. This tool renders one PDF from a template already saved in the user's account and returns the path to the saved file.

Use it when the user wants a document in their existing design. Get template_id from list_templates. Use render_pdf instead when you are writing the HTML yourself.

data supplies one row's worth of values: each key becomes a Jinja variable in the template's HTML. To render a PDF for every row of a spreadsheet, use create_batch_job rather than calling this repeatedly.

Omit page_settings to keep the template's own saved page setup — passing it overrides that for this render only.

Free-plan accounts get a "Made with SheetRender" footer on the PDF, same as render_pdf — expected, not a bug.

Returns the temp-file path and size; PDFs under 512 KB are also attached inline.

ParametersJSON Schema
NameRequiredDescriptionDefault
dataYesTemplate variables as a flat JSON object. Each key becomes a Jinja variable, so {"customer": "Acme"} makes {{ customer }} available in the HTML.
template_idYesTemplate id from list_templates.
page_settingsNoOptional page setup for the PDF.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must carry behavioral disclosure. It covers the output (temp-file path, size, inline attachment under 512 KB), the page_settings override behavior, and the free-plan footer. It does not mention error cases or side effects, but the core mutating behavior (creating a PDF) is transparently described.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized and front-loaded with purpose. It conveys all necessary context in a compact flow: what the tool does, when to use it, how data works, page_settings caveat, free-plan note, and output details. No superfluous sentences; every line earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the nested page_settings object and no output schema, the description covers everything needed to call the tool correctly: how to obtain template_id, the data shape, optional page_settings behavior, return value specifics, and the free-plan footer. It also routes to alternatives, making it complete for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with detailed property descriptions, so baseline is 3. The description adds value by explaining that omitting page_settings keeps the template's saved setup and that data supplies one row of variables. It also clarifies the 'overrides for this render only' nuance not present in the schema, pushing it above baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool renders one PDF from a saved template and returns the file path. It distinguishes from siblings by naming render_pdf (for custom HTML) and create_batch_job (for multiple rows), and directs to list_templates for the ID. The verb+resource+scope is specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit guidance is given for when to use this vs alternatives: use it for existing designs, render_pdf when writing HTML yourself, and create_batch_job for rendering many rows. It also instructs to get template_id from list_templates. This leaves no ambiguity about selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 6 tool updatesv0.1.2
    • First observedcreate_batch_job
    • First observedget_document
    • First observedget_job
    • First observedlist_templates
    • First observedrender_pdf
    • First observedrender_template

TDQS

A4.8/5.0
Disambiguation5/5

Each tool has a distinct purpose: listing templates, rendering from raw HTML, rendering from a saved template, creating a batch job, checking job progress, and downloading a specific document. The descriptions explicitly clarify when to use render_pdf vs render_template and how get_job and get_document relate, leaving no ambiguity.

Naming Consistency5/5

All tool names follow the consistent verb_noun pattern in snake_case (list_templates, render_pdf, render_template, create_batch_job, get_job, get_document). The verbs are clear and the pattern is uniform, making it easy to predict tool behavior from the name.

Tool Count5/5

Six tools is well-scoped for a PDF rendering MCP server. It covers the essential operations without bloat: listing templates, two rendering modes, batch job management, and document retrieval. Each tool earns its place in the workflow.

Completeness4/5

The core rendering lifecycle is covered: list templates, render single or batch, check job status, and download outputs. Minor gaps exist, such as no tool for uploading templates or datasets (stated as handled outside the MCP), and no cancellation or template management, but these are reasonable omissions for an integration-focused server.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    B
    maintenance
    Provides PDF.co API functionality through the Model Context Protocol, enabling AI assistants to perform various PDF processing tasks like conversion, editing, searching, and security operations.
    38
    9
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Generate professional PDFs from Claude, Cursor, and other AI tools. Create invoices, contracts, reports, and certificates from templates or inline HTML markup.
    7
    59
    1
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sheetrender/sheetrender-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server