Kamy
Document API for AI-native software: render PDFs, e-sign, PAdES-seal, and verify.
Connect it
Settings → Connectors → Add custom connector
URL: https://mcp.kamy.dev/mcpSettings → Apps & Connectors → Advanced → Developer mode
Create connector with URL: https://mcp.kamy.dev/mcp{
"mcpServers": {
"kamy": {
"url": "https://mcp.kamy.dev/mcp"
}
}
}claude mcp add --transport http kamy https://mcp.kamy.dev/mcp{
"servers": {
"kamy": {
"type": "http",
"url": "https://mcp.kamy.dev/mcp"
}
}
}59 tools, verified live
list_templatesread-onlyList Kamy's public system PDF templates. No authentication required.
get_template_schemaread-onlyFetch the JSON Schema (exact data shape) and a copy-pasteable sample payload for a Kamy system template by slug. Call this before render_pdf so you fill the right fields with the right types instead of guessing. No authentication required.
create_templateCreate a new custom PDF template owned by this account: a name, a unique slug, a Handlebars/HTML body, and optional CSS and JSON Schema. The slug is what render_pdf then takes as `template`. Custom templates are a paid feature â on the Free plan this returns 403 FORBIDDEN before anything is created. The slug must be unique within the account and must not collide with a built-in system slug (invo
update_templateEdit an existing custom template's DRAFT â name, html, css, schema, tags, visibility â addressed by UUID or slug. Only the fields you pass are changed. Crucially, this does not change what renders once the template has been published even once: while published_version is set, render_pdf serves that frozen snapshot and your edits stay invisible until publish_template moves the pointer, so an ed
publish_templateMake a template version live for rendering. Called with no `version`, it snapshots the current draft into a new version and points published_version at it â this is how you ship an edit made with update_template. Called with an existing `version`, it republishes that earlier snapshot and leaves the draft alone. Reach for rollback_template instead when you are reverting a bad release: only that t
rollback_templatecan modifyRevert a template after a bad release: repoints published_version at the version you name, so every subsequent render immediately serves that snapshot again. Prefer this over publish_template's `version` argument whenever you are reverting, because only this tool takes expectedPublishedVersion â an optimistic fence that rejects with 409 VERSION_CONFLICT if someone moved the pointer since you rea
list_template_versionsread-onlyList a template's immutable version snapshots, newest first, as { id, version, createdAt }. This is where the version number that publish_template and rollback_template take comes from. Bodies are deliberately not included â call get_template_version when you need one snapshot's html, css and schema. Works on system and public templates as well as your own, by UUID or slug. Read-only and spends
get_template_versionread-onlyFetch one template version snapshot in full â html, css, schema, createdBy, createdAt â exactly as it was frozen when that version was cut. Use list_template_versions first to find the number. Use this to inspect what a released version actually contained, or to recover content a later draft edit overwrote; it changes nothing on its own, so pair it with rollback_template when you want that ver
render_pdfRender a PDF from a Kamy template and data, and wait for it. This is the default document tool: it blocks until the file exists and hands back { id, url, bytes, durationMs, templateId, createdAt } in one call, where url is a signed download link valid for one hour and id is the render id every later tool takes. Reach for render_async instead when waiting is not acceptable, and render_batch when se
render_docxRender an editable Word (.docx) document from a Kamy template and data. Takes the same { template, data } payload as render_pdf but produces a different container â reach for it when the recipient has to EDIT the document (legal redlines, Word-based intake, corporate templates) rather than receive a fixed artifact. Only five slugs have a Word implementation â invoice, receipt, quote, contract,
render_pptxBuild a PowerPoint (.pptx) deck from a slide spec: an ordered array of slides, each tagged with one of five fixed layouts (title, bullets, two-column, table, quote). This is NOT a template renderer like render_pdf / render_docx â there is no template slug and no free-form layout, so content has to be shaped into those five. It also converts nothing; use convert_document to turn a file you alread
render_xlsxBuild an Excel (.xlsx) workbook from a sheet spec: columns with keys, row objects keyed to those columns, optional Excel number formats and a formula-aware total row (bare 'SUM' / 'AVG' / 'COUNT' / 'MIN' / 'MAX' expands into a real formula over the column's data range). Choose this over render_pdf when the recipient will sort, filter or recompute the numbers, and over render_docx when the content
render_htmlCompile a Kamy template â or raw Handlebars source you pass inline â against a data payload and get the rendered HTML string back. No browser runs, no PDF is produced and no file is stored, so this is the tool for piping a template into a transactional email provider, or for inspecting the markup before committing to render_pdf. Use render_pdf instead whenever the output has to be a paginated,
convert_documentConvert a file you already hold â .docx, .xlsx or .csv â into a PDF, preserving its existing content. Pass the bytes base64-encoded together with the original filename, which is what the API uses to detect the input type. This is the inbound direction: it consumes an existing document, whereas render_docx / render_xlsx / render_pptx GENERATE new documents from structured data, and render_pdf b
merge_pdfsConcatenate 2â20 existing renders into a single new PDF, in exactly the order the ids are given. Both the inputs and the output are Kamy render ids, so this is the composition step after several render_pdf / convert_document / edit_pdf calls â it cannot merge arbitrary URLs or raw bytes, and every id must belong to this account and point at a completed render or the whole call fails. The sourc
split_pdfExtract page ranges from one existing render into separate new PDFs â the inverse of merge_pdfs. Each range you pass produces its own render, returned in the same order, so one call can both halve a contract and peel off single pages. Omit a range's `to` to run to the end of the document; a range starting past the last page fails the entire call. The source render is left untouched. Returns { re
edit_pdfModify an existing PDF: fill AcroForm fields by name, stamp text at absolute coordinates, or paint opaque boxes over regions. Operations apply in the order given, to either a render you own (renderId) or a PDF Kamy downloads from a public URL (pdfUrl) â supply exactly one. Use this when a document already exists and needs values or marks; use render_pdf when the document should be generated from
upload_fileStore an image, font or PDF in the account's asset bucket and get back a `kamy://asset/<id>` reference you can drop anywhere inside a render_pdf / render_html data payload â Kamy swaps it for a fresh signed URL at render time. That reference is the point of this tool: it is how a logo, signature image or custom font gets into a template without hosting it yourself. Pass contentBase64 and this se
get_uploadread-onlyLook up a stored asset by its upload id: filename, contentType, sizeBytes, status, its `kamy://asset/<id>` reference, and a freshly signed downloadUrl valid for one hour once the bytes exist. Its main use is confirming an out-of-band transfer landed â upload_file returns uploaded:false when the file was too large to pass inline and you PUT it yourself â because this read reconciles a still-'pe
validate_payloadread-onlyDry-run a render payload against a template's schema WITHOUT producing a PDF or using quota. Returns per-field self-healing errors (expected type, value received, allowed values, an example) so you can fix the data before render_pdf. Requires a Kamy API key.
extract_documentExtract structured data from a PDF (invoice, receipt, contract, ID document, or any form). Returns the parsed JSON plus a public verify URL that proves the extraction matches the source. Use this when an agent needs to read an inbound document and act on it.
ask_kamyread-onlyAsk Kamy Brain a question about Kamy usage, templates, plans, or errors. Sends the question to Kamy's public assistant endpoint and returns a paragraph answer.
create_signature_requestSend a previously rendered PDF to a signer for e-signature when a Kamy API key is configured. Without a key, returns dashboard setup instructions.
create_envelopeSend a single PDF to 2â10 signers as one envelope. This is the multi-signer counterpart to create_signature_request, which handles exactly one signer â the API rejects an envelope with fewer than two recipients, so pick the tool by signer count. routing 'parallel' (default) emails everyone at once and each signs independently; routing 'sequential' emails only the lowest-order recipient and act
list_signature_requestsread-onlyList signature requests created by the configured Kamy account, newest first. Without a key, returns dashboard setup instructions.
get_signature_certificateread-onlyReturns the authenticated download URL for a signature request's Certificate of Completion PDF â the process audit trail (invite â opened â consent â signed, with IP / user-agent) that legal teams expect. Only available after the request reaches a terminal state. Without a key, returns dashboard setup instructions.
get_signature_requestread-onlyFetch one signature request by id, with the detail list_signature_requests leaves out: the placed_fields layout, signed_at plus signed_ip and signed_user_agent, last_reminded_at, cc_emails, and envelope_id + recipient_order when it is part of an envelope. Use list_signature_requests to find an id and this to inspect it; use get_signature_certificate when what you actually want is the legal audit-t
get_enveloperead-onlyFetch one multi-signer envelope with every recipient in signing order â each with a live sign_url, status, recipient_order, expires_at and last_reminded_at â plus the envelope's own status and routing. This is the tool for 'who still has not signed?' after a create_envelope send; get_signature_request answers that for a single standalone request and returns no recipient list. Under sequential
remind_signatureResend the signature invitation email. Pass signatureRequestId to nudge one signer, or envelopeId to nudge every currently-pending recipient of an envelope â supply exactly one; there is no separate envelope-reminder tool. This sends real email to third parties. Each recipient is capped at one reminder per hour: the single-request form returns 429 REMIND_TOO_SOON with a Retry-After header, while
bulk_signature_requestsFan one already-rendered PDF out to up to 100 independent signers in a single call â the 'send this NDA to everyone on the list' path. Each signer gets their own request, their own sign link and their own invitation email, but they all share one source render, so only one document is produced and stored. Choose create_envelope instead when the recipients are signing the SAME document together an
preview_field_placementread-onlyCheck a placedFields layout against a real render's page geometry before anything is sent: no signature request is created, no email goes out, and no signature quota is spent. It accepts exactly what create_signature_request accepts â all seven field types, `options`, and anchor-positioned fields â so anything that previews clean will send. Returns each page's true width and height, so a sende
list_signature_templatesread-onlyList this account's reusable e-signature presets â saved field placements, default invite message, default link lifetime and CC list â newest first. These are signing presets, NOT the document catalog: list_templates is what render_pdf draws from. Rows here carry only id, name, description, expires_in and cc_emails; call get_signature_template for the placed_fields and position. Pass an id as
get_signature_templateread-onlyFetch one e-signature preset in full, including the placed_fields array and position that list_signature_templates omits. Use it to inspect or copy an existing field layout before applying it through create_signature_request's signatureTemplateId, or as the starting point for a preview_field_placement check against a new render. Read-only and spends no quota. Requires a Kamy API key with the `sign
pki_sign_pdfCryptographically sign an existing render with PAdES when a Kamy API key is configured. Without a key, returns dashboard setup instructions.
verify_pdf_signatureread-onlyTurn PDF bytes you are holding into their SHA-256 digest and the matching kamy.dev/verify/{sha256} page URL. Purely local: the MCP Worker hashes the base64 in memory, makes no Kamy API call, stores nothing and forwards nothing, so it works with no key and never leaves a trace. Note it returns no verdict â it does not tell you whether the document is genuine, signed, or on record anywhere. It is
attest_artifactCryptographically sign an output your agent produced â a PDF, report, code patch, dataset, email â so a third party can later confirm those exact bytes are the ones that were recorded, unmodified. Pass content_text or content_base64 and Kamy hashes the bytes for you; pass content_sha256 alone when the content itself must never leave your environment. Returns { attestation_id, content_sha256, s
verify_attestationread-onlyAsk Kamy whether a SHA-256 digest has an attestation on record â the tool that actually returns a verdict. Takes a digest, not a file: if what you hold is a PDF, run verify_pdf_signature over the bytes first and pass the sha256 it gives you. A match returns { verified: true, artifact_type, recorded_at, signature, public_key }. A false result means no attestation exists for those exact bytes, whi
record_agent_actionAppend one signed tool_call -> tool_result pair to a tamper-evident ledger. Call it after any consequential tool invocation â a payment, an outbound email, a write into a customer system â so there is a hash-chained record of what the agent asked for and what came back, signed at write time. Pass a stable run_id to keep an entire agent run in one chain, and parent_sha256 to link records explic
get_provenance_chainread-onlyReplay everything recorded under one run_id â artifacts from attest_artifact and calls from record_agent_action â in order, with each record's link to its parent hash. Use it to answer 'what did this agent actually do, and in what sequence?' during an incident review, a handover, or an audit. Returns { run_id, chain_intact, records: [...] }, where chain_intact is the server's verdict on whethe
trace_recordRecord one LLM call â prompt, output, provider, model, tokens, latency â into Kamy Trace, a signed retention ledger. Each record is hashed and signed at write time, so it can be produced later without the 'you could have edited this' objection. Reach for it when model calls need a reviewable history: regulated workflows, customer-facing generations, anything you may have to explain months late
trace_record_batchWrite up to 100 Kamy Trace records in one call. Reach for this over trace_record whenever you have more than a couple of buffered LLM calls to persist â it is one auth, one quota check and one round trip instead of N. Each element takes exactly the shape trace_record takes. The whole batch is counted against the monthly Trace quota up front, so a batch that would cross the plan cap is rejected i
trace_searchread-onlyQuery this account's Kamy Trace records, newest first, filtered by feature, status, provider, tag, or time window. Returns record metadata â model, tokens, latency, status, content hash, recorded_at â plus next_cursor for paging; it does not return the stored prompt and output bodies. Use it to answer questions like 'how many flagged calls last week?' or to locate a specific record's id before
verify_mcp_serverDetect when an MCP server changes its tool manifest after you adopted it â the 'rug pull' case, where a server you already trusted silently rewrites a tool's description or input schema. Pass server_url and Kamy fetches that third-party server's manifest itself, or pass manifest when you already hold it (local or private servers). Returns status 'new' (first fingerprint for this account â noth
scan_tool_descriptionread-onlyHeuristic pattern scan of MCP tool description text for prompt-injection tells â instructions addressed at the reading model, data-exfiltration hints, attempts to override your system prompt or hide content. Run it on descriptions from third-party MCP servers before you act on what they say. Returns risk 'low' | 'medium' | 'high' and the matched findings with excerpts. This is a heuristic aid, N
get_startedread-onlyEverything needed to go from nothing to a rendered document in one call: the steps to create an API key in the dashboard, and â when you name a `framework` â the install command for the Kamy SDK, the environment variable it reads, and the client-setup snippet for that stack. Add a `template` slug and it also returns a ready-to-paste route handler that renders it. Every argument is optional and
get_accountread-onlyRead everything about the authenticated Kamy account in one call: profile, plan and plan status, the plan's limits (renders per month, API keys, seats, custom templates, overage pricing, priority queue), month-to-date render usage, and whether documents rendered on this plan carry Kamy's own watermark. This is the only tool that answers any of those questions â there is no separate quota tool. C
list_rendersread-onlyList the documents this account has already produced, newest first. This is how you find a PDF made earlier â in a previous turn, by a schedule, or by another process â when you no longer hold its URL. Download URLs returned by the render tools are signed and expire after an hour, so a link from earlier in the conversation is probably dead; find the render here, then call get_render with its i
get_renderread-onlyFetch one previously produced document by its render id, with a freshly signed download URL valid for the next hour. This is the recovery path for an expired link: the URL is minted at read time, so calling this again on an old render always yields a working download. Use list_renders first if you do not have the id. Returns { id, name, templateId, templateName, status, bytes, durationMs, url, cre
get_render_pagesread-onlyRasterise every page of an existing render to a PNG image and return one signed 1-hour URL per page, with pixel width and height. Use this when a page has to be looked at rather than read â thumbnails, previews, visual QA of a layout, or an image attachment â and use extract_from_render when you want the text. The render must already have status 'success'; a queued or failed one comes back as
extract_from_renderread-onlyRead the text or the form fields back out of a document this account already rendered, without uploading anything. Pass type='text' (the default) for per-page text plus a joined fullText string, or type='fields' for the PDF's AcroForm field names, types and current values â the latter is how you discover what edit_pdf can fill in. Choose extract_document instead when the PDF came from outside Ka
render_asyncQueue one PDF render and return immediately with { jobId, status: 'queued' } instead of waiting for the document. Choose this over render_pdf when blocking is not acceptable â a heavy template, a large data set, or a turn where you have other work to do â and poll get_job with the returned jobId until status is 'completed' (the finished render, including its download URL, arrives on the job) o
get_jobread-onlyPoll an asynchronous render job started by render_async. Returns { jobId, status } where status is 'queued', 'processing', 'completed' or 'failed'; on 'completed' the response also carries `render` with the finished document's id, signed URL, size and duration, and on 'failed' it carries `error` with the reason. Poll every few seconds rather than in a tight loop â a typical render finishes in se
render_batchRender up to 100 documents in a single blocking call, each from its own template, HTML or URL, and get every result back in one response. Choose this over calling render_pdf in a loop whenever you have more than a couple of documents â it is one round trip, one quota reservation and one rate-limit charge. It does block: items render sequentially inside a 300-second budget, so expect to wait, and
create_scheduleSet up a recurring render: a cron expression, a template, and where each document goes. Use this instead of render_pdf when the user wants a document produced repeatedly on a calendar â a weekly report, a monthly invoice run â so nothing has to stay running. Delivery channel is 'email' or 'whatsapp' (recipients required) or 'download' (stored only; retrieve later with list_renders). The cron i
list_schedulesread-onlyList this account's recurring render schedules, newest first, with the id needed to delete one. Use it to answer what is already automated before creating a duplicate, and to diagnose a schedule that is not producing documents: each row carries enabled, schedule, timezone, next_run_at, and last_run_at / last_run_status / last_run_error from the most recent firing â last_run_error is where a deli
delete_schedulecan modifyPermanently delete a recurring schedule so it stops firing. There is no undo and no trash â recreate it with create_schedule if it is deleted by mistake, so confirm with the user before calling this on a schedule you did not just create. If the intent is only to pause it, do not use this tool: a schedule can be switched off and back on again via its `enabled` flag on the REST endpoint (PATCH /v1
create_webhookRegister an HTTPS endpoint that Kamy POSTs to when work finishes, so a long render or an e-signature does not have to be polled. Use this when the caller owns a server that can receive callbacks; use get_job or list_renders when it cannot. The response includes a one-time signing secret used to verify delivery signatures â it is shown here and never again, so surface it to the user immediately a
list_webhooksread-onlyList the webhook endpoints registered on this account, with the id needed to test one. Each row carries url, events, enabled, and lastDeliveryAt / lastStatus from the most recent delivery â lastStatus is the HTTP code the caller's own server returned, so this is where a silently broken endpoint shows up as a 4xx or 5xx. Signing secrets are never returned here; they are shown only once, by create
test_webhookSend a real test.ping event to a registered webhook endpoint â an actual outbound HTTP POST to whatever URL the user configured, signed like a genuine delivery. Use it to prove an endpoint is reachable and that signature verification works before relying on it. Delivery is dispatched in the background, so the { message: 'Test ping dispatched' } you get back means accepted for sending, not that t
Alternatives in Developer Tools
Compare →QRQR RápidoA
Generate QR codes for URLs, PIX, Wi-Fi, vCards, WhatsApp and more. For AI agents.
ZTZoom Team ChatOfficialA
Zoom Chat server for channels, messages, contacts, files, and chat collaboration.
ZTZoom TasksOfficialA
Zoom Tasks server for creating, updating, assigning, and synchronizing task workflows.
ZDZoom DocsOfficialA
Zoom Docs server for creating and retrieving Zoom documents and notes in Markdown.
ZWZoom WhiteboardOfficialA
Zoom Whiteboard server for creating boards and diagrams and locating existing boards.
ZWZoom WorkspaceOfficialA
Zoom workspace server for meetings, chat, docs, recordings, and AI-generated collaboration content.