AI assistants (MCP)
SignSealer is a remote MCP server at https://api.signsealer.com/mcp. Connect it
to Claude, ChatGPT, Codex, Claude Code, Cursor or VS Code, and ask: "send the
rental agreement to Ada Lovelace", "who still hasn't signed tomorrow's
waivers?", "remind them".
The Model Context Protocol is how
an assistant is given tools. Ours are the API: each tool makes the same
/v1 call a key would, with the same scopes, limits and answers, so an
assistant can do exactly what the person who connected it allowed and nothing
the API would refuse.
Connect it
Every client below signs in the same way: it opens SignSealer's sign-in, you choose the business, see what it is asking for, and press Connect. There is no key to copy. You need the permission to manage API keys in that business, which owners and admins have (Teams, roles and sign-in). You can disconnect it at any time under Integrations → Connected apps, and it stops that minute.
Claude (claude.ai and Claude Desktop)
Settings → Connectors → Add custom connector. Name it SignSealer,
give the URL https://api.signsealer.com/mcp, and press Connect.
ChatGPT
Settings → Apps & Connectors. With developer mode on, create a connector
with the URL https://api.signsealer.com/mcp and OAuth as its authentication.
Claude Code
claude mcp add --transport http signsealer https://api.signsealer.com/mcp
Then /mcp in a session to sign in.
Codex
In ~/.codex/config.toml:
[mcp_servers.signsealer]
url = "https://api.signsealer.com/mcp"
codex mcp login signsealer
Cursor
In ~/.cursor/mcp.json for every project, or .cursor/mcp.json
in one:
{
"mcpServers": {
"signsealer": { "url": "https://api.signsealer.com/mcp" }
}
}
Cursor signs in when it first connects. To add it in one step instead, open this link in a browser on the computer Cursor is on:
cursor://anysphere.cursor-deeplink/mcp/install?name=signsealer&config=eyJ1cmwiOiJodHRwczovL2FwaS5zaWduc2VhbGVyLmNvbS9tY3AifQ==
VS Code
In .vscode/mcp.json in a workspace, or in your own
mcp.json (the command MCP: Open User Configuration):
{
"servers": {
"signsealer": { "type": "http", "url": "https://api.signsealer.com/mcp" }
}
}
VS Code shows Start above the server, and signs in when it starts.
Anything else
A client that speaks MCP over HTTP finds the sign-in by itself from the URL:
{
"mcpServers": {
"signsealer": { "url": "https://api.signsealer.com/mcp" }
}
}
One that cannot sign in can send an API key instead, from
Integrations → API keys with signing:read and
signing:write, as a header:
{
"mcpServers": {
"signsealer": {
"url": "https://api.signsealer.com/mcp",
"headers": { "Authorization": "Bearer ${env:SIGNSEALER_KEY}" }
}
}
}
Keep the key in the environment, not in a file you commit. A key that holds
only signing:read gives an assistant that can look but not send.
What it can do
| Tool | What it does | Kind | Needs |
|---|---|---|---|
| signsealer_get_account | Who am I connected as. The SignSealer business this connection acts for: its name, what this connection may do (its scopes), whether it is a test sandbox where nothing reaches anybody, and whether the business can text people. Call it first, and tell the user which business they are connected to. | Reads | signing:read |
| signsealer_list_templates | List templates. The business's templates (the documents it sends), newest version first, with each one's code, title and whether it is published. Pass code for one template's versions. | Reads | signing:read |
| signsealer_get_template | Read a template. One template version: its text and the values it takes (the blanks a sender fills in), which signsealer_send_document's values answers. | Reads | signing:read |
| signsealer_list_documents | List documents. Documents sent for signature, newest first. Filter by status (draft, sent, completed, declined, expired, void, or open for draft and sent) or q (part of a title or a signer's name, email or number). Paged with limit and offset; the answer says total and has_more. | Reads | signing:read |
| signsealer_get_document | Read a document and who has signed. One document: its status and its signers, each with where they are (pending, signed, declined). Use it to answer "has everyone signed?". Personal detail is left out unless asked for: the text (include_text), the signers' answers to its questions (include_answers), and the event trail with addresses and devices (include_trail). | Reads | signing:read |
| signsealer_send_document | Send a document for signature. Prepares a document from a published template, fills in its values, and sends each signer their own link by email (or by text to a number that agreed to texts). This emails or texts real people: confirm the template, the values and every recipient with the user first. Answers with the document's id and each signer's link. If a send is refused after the document was prepared, the refusal names it: correct what it says and call this again with that document_id instead of template_code, so no second copy is made. | Changes something | signing:send |
| signsealer_remind_signer | Remind a signer. Sends one signer who has not signed a reminder with their link. Emails or texts a real person, at most as often as the business's reminder rules allow. | Changes something | signing:remind |
| signsealer_new_signing_link | Make a fresh signing link. A new signing link for one signer, to hand over yourself (in a chat, on a screen, as a QR code). The signer's previous link stops working. | Changes something | signing:links or signing:workflows |
| signsealer_void_document | Void a document. Cancels a document that is not finished: its links stop working and its signers are told. A completed document cannot be voided. Cannot be undone. | Changes something | signing:void |
| signsealer_get_certificate | Read a document's certificate. The certificate of completion of a signed document: who signed, when, from where, the fingerprint of what they signed, and the code anyone can check it with. | Reads | signing:read |
The four that change something are marked as such to the client, which asks you before it runs one. The server also tells the assistant to confirm the template, the values and every recipient with you before it sends anything, and never to send to an address you did not give it.
Sending takes an idempotency_key the assistant makes up for that one
send (reminding and voiding take one too, if given). An assistant whose
connection drops calls again with the same key and is answered with what the first
call did, so a retry never sends a document twice. Reading a document gives its
status and its signers; the text, the signers' answers and the event trail, with
its network addresses and devices, come only when asked for.
What you are asked to allow
An assistant asks for signing:read, signing:send, signing:remind, signing:links, signing:void. Reading
documents, templates and who has signed is given when you connect it. Each of the
four that reaches people or stops a link is a box on SignSealer's sign-in page, and
none is ticked until you tick it:
- Send documents for signature (
signing:send) - Remind a signer who has not signed (
signing:remind) - Make a fresh signing link (
signing:links) - Void a document that is not finished (
signing:void)
An assistant that only needs to tell you who has signed gets no box ticked. One asked to send a document is refused if Send documents for signature was left clear, and says so: nothing is sent. To change what it may do, connect it again and tick the boxes you want; what you tick replaces what it had, at once, even for the sign-in it already holds.
It is never given more than you hold yourself, and never the scopes that manage
templates, webhooks, workflows or keys. An API key with signing:write
holds all four.
The sign-in page says Not checked by SignSealer for an app that introduced itself, which every assistant does, and names where your browser goes back to afterwards: the assistant's own site, or an app on this computer for Codex and Claude Code. Connect it only when you started the connection yourself, just now.
For client builders
| What | Where, and how |
|---|---|
| Transport | Streamable HTTP, stateless: one JSON-RPC message per POST /mcp, answered with one JSON object; a notification is answered 202. No event stream (GET is 405) and no session. Protocol version 2026-07-28, with no handshake: each request names its version in _meta, and server/discover says which versions this server speaks. And, opened with initialize, 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05. |
| Without a token | 401 with WWW-Authenticate: Bearer resource_metadata= and the scopes. |
| Protected resource (RFC 9728) | https:// |
| Authorization server (RFC 8414) | https:// |
| Identifying your app | An OAuth Client ID Metadata Document: use its https address as client_id, and we read it, check its client_id is that address, and take its name and redirect_uris. Or register (RFC 7591) at POST https://. Redirects are https, or the loopback (http://127.0.0.1, http://[::1], http://localhost) with any port. |
| The grant | Authorization code with PKCE (S256 only). Refresh tokens only for an app that asks for them: name refresh_token in grant_types, in its registration or its metadata document; left out, the grant is the code alone, as RFC 7591 reads it. A resource (RFC 8707) must be this API, https:// or https://; anything else is invalid_target. |
| Limits | The API's, per token: see Limits and paging. A tool's refusal is the API's own status, message and hint. |
Building on the API directly instead? The quickstart and the Node client are the way in, and llms-full.txt is every page of these docs as one text file, for a coding assistant to read.
Ready to build? An API key takes a minute in the portal, and the free plan covers the first 10 agreements a month.
Get an API key