sheetrender-mcpSAFE
MCP server for SheetRender: render PDFs from HTML templates and spreadsheet data via the SheetRender API
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
MCP server for SheetRender: turn rows of a spreadsheet into one PDF each, such as certificates, letters, donation receipts and offer letters.
The quickest start needs no account and no install. Add the hosted server `https://mcp.sheetrender.com/mcp` as a connector in ChatGPT, Claude or any client that takes a Streamable HTTP URL, then paste or describe your rows. It fills SheetRender's built-in templates and returns a preview and a PDF per row (details).
With a SheetRender API key you get the full tool set: your own saved templates, HTML templates, datasets and batch jobs, either through the npm package below or the same hosted URL.
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.
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 the smaller no-key tool set described below. 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 Cod
b99daae22e63OBSERVED · 2026-10-12Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add mcp --env SHEETRENDER_API_KEY=${SHEETRENDER_API_KEY} -- npx -y @sheetrender/[email protected]Exposed tools (16)
12 read · 4 write · 0 destructive.
| Tool | Risk | Description |
|---|---|---|
Invoice | read | Not offered. |
Letter | read | |
create_batch_job | write | |
create_continue_link | write | |
create_dataset | write | |
design_template | read | |
get_design | read | |
get_document | read | |
get_job | read | |
list_datasets | read | |
list_document_templates | read | |
list_templates | read | |
render_documents | read | |
render_pdf | read | |
render_template | read | |
upload_dataset | write |
Trust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (15)
readFileSync(new URL("../../src-test/fixtures/builtin_catalogue.json", import.meta.url), "utf8"),const CATALOGUE_JSON = readFileSync(new URL("../../src-test/fixtures/builtin_catalogue.json", import.meta.url), "utf8");const source = readFileSync(new URL("../../src/widget/documents.ts", import.meta.url), "utf8");assert.doesNotMatch(readFileSync(new URL("../../README.md", import.meta.url), "utf8"), BANNED_WORDS);const source = readFileSync(new URL(`../../src/${file}`, import.meta.url), "utf8");resolve(`http://127.0.0.1:${port}`);const { url } = await startMcp("http://127.0.0.1:1");const { url, logs } = await startMcp("http://127.0.0.1:1");const { url } = await startMcp("http://127.0.0.1:1");const { url, logs } = await startMcp("http://127.0.0.1:1");assert.equal(pythonStrip(" x "), " x ");assert.equal(pythonStrip("x"), "x");assert.equal(pythonLength("👩💻"), 3);assert.match(checkRows(three, [{ body: "abc" }]) ?? "", /limit of 3 characters/);assert.match(checkRows(three, [{ body: "abc" }]) ?? "", /limit of 3 characters/);Gates applied: no_behavioural_pass.
b99daae22e63full audit observations/trust-audit/mcp-server/sheetrender__sheetrender-mcp.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-12 | b99daae22e63 | SAFE | B | 89 | first audit |
Questions
What is the sheetrender-mcp MCP server?
MCP server for SheetRender: render PDFs from HTML templates and spreadsheet data via the SheetRender API
What tools does sheetrender-mcp expose?
16 in total: 12 read-only, 4 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.
Is sheetrender-mcp safe to connect to an agent?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean server reads B.
What credentials does sheetrender-mcp need?
It reads SHEETRENDER_API_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does sheetrender-mcp run?
It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as @sheetrender/mcp at 0.5.3.
How current is this page?
The grade is for one exact copy of the source (b99daae22e63), read on 2026-10-12. The repository is watched and re-audited when it changes.