Atlas / MCP servers / sheetrender / sheetrender-mcp

sheetrender-mcpSAFE

mcp/sheetrender/sheetrender-mcp

MCP server for SheetRender: render PDFs from HTML templates and spreadsheet data via the SheetRender API

Verdict
SAFE
Grade
B
Trust score
89 /100
Exposed tools
16 12r · 4w · 0d
Transport
stdio · streamable-http
License
MIT
Stars
1
01

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
Read from source at commit b99daae22e63OBSERVED · 2026-10-12
02

Connect

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-code (npm)
claude mcp add mcp --env SHEETRENDER_API_KEY=${SHEETRENDER_API_KEY} -- npx -y @sheetrender/[email protected]
03

Exposed tools (16)

12 read · 4 write · 0 destructive.

ToolRiskDescription
InvoicereadNot offered.
Letterread
create_batch_jobwrite
create_continue_linkwrite
create_datasetwrite
design_templateread
get_designread
get_documentread
get_jobread
list_datasetsread
list_document_templatesread
list_templatesread
render_documentsread
render_pdfread
render_templateread
upload_datasetwrite
04

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.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codePASS
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
none-observed
Network
none-observed
Shell
none-observed
Dependencies
pinned
Secrets in source
none-found

Findings (15)

LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src-test/anon.test.ts:64
readFileSync(new URL("../../src-test/fixtures/builtin_catalogue.json", import.meta.url), "utf8"),
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src-test/http.test.ts:426
const CATALOGUE_JSON = readFileSync(new URL("../../src-test/fixtures/builtin_catalogue.json", import.meta.url), "utf8");
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src-test/widget.test.ts:109
const source = readFileSync(new URL("../../src/widget/documents.ts", import.meta.url), "utf8");
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src-test/widget.test.ts:199
assert.doesNotMatch(readFileSync(new URL("../../README.md", import.meta.url), "utf8"), BANNED_WORDS);
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src-test/widget.test.ts:203
const source = readFileSync(new URL(`../../src/${file}`, import.meta.url), "utf8");
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
src-test/http.test.ts:37
resolve(`http://127.0.0.1:${port}`);
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
src-test/http.test.ts:174
const { url } = await startMcp("http://127.0.0.1:1");
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
src-test/http.test.ts:183
const { url, logs } = await startMcp("http://127.0.0.1:1");
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
src-test/http.test.ts:196
const { url } = await startMcp("http://127.0.0.1:1");
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
src-test/http.test.ts:210
const { url, logs } = await startMcp("http://127.0.0.1:1");
LOWObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
src-test/anon.test.ts:443
assert.equal(pythonStrip(" x "), " x ");
LOWObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
src-test/anon.test.ts:445
assert.equal(pythonStrip("x"), "x");
LOWObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
src-test/anon.test.ts:452
assert.equal(pythonLength("👩💻"), 3);
LOWObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
src-test/anon.test.ts:478
assert.match(checkRows(three, [{ body: "abc" }]) ?? "", /limit of 3 characters/);
LOWObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
src-test/anon.test.ts:479
assert.match(checkRows(three, [{ body: "abc" }]) ?? "", /limit of 3 characters/);

Gates applied: no_behavioural_pass.

Audited 2026-10-12 · audit v0.4.1 · source sha b99daae22e63full audit observations/trust-audit/mcp-server/sheetrender__sheetrender-mcp.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-12b99daae22e63SAFEB89first audit
06

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.

Advertisement