Signable MCP server
Summary: This server gives MCP clients read-only access to a Signable e-signature account — you can look up envelopes, templates, contacts and users, but the sending/reminding/cancelling/expiring tools are not registered here (writes are disabled).
List envelopes — status, timestamps and party names, filtered by one status and/or a title keyword, paged by
offset/max_results.Get one envelope — every party with signing status and role, documents with fields and 24-hour download links, audit history, metadata.
List templates — templates with their parties and merge fields.
Get one template — the
party_ids andfield_ids/labels a send would need.Find contacts — search signers/recipients by part of a name or email (pages through the contact list 50 at a time, up to
max_pages).Get a contact's envelopes — their document history with status, timestamps and signed-PDF link; an empty list if they've never been sent one.
List users — team members with their role (User, Admin, Super-Admin).
Detail control — emails, mobile digits, passwords, audit IPs/user agents and upload-field links are withheld unless you set
include_contact_details; emails and phone-like text elsewhere are redacted by default.Cannot do (not enabled) — send an envelope from a template, remind, cancel or expire envelopes; all registered tools are read-only.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Signable MCP server Show me envelopes still awaiting signatures and who hasn't signed yet."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Signable MCP server
An MCP server that lets Claude, ChatGPT and other MCP clients work with a Signable e-signature account: envelopes, templates, contacts and users, and (when enabled) sending, reminding, cancelling and expiring envelopes. It is built from Signable's public API documentation and its published OpenAPI spec.
Once it's connected, someone on the account can ask things like:
"Which envelopes are still waiting for a signature, and who hasn't signed?"
"Show me the history of the 17 John Street tenancy contract."
"What does the Tenancy Contract template need before I can send it?"
"Find Sam Evans and list every document we've sent him."
With writes enabled: "Send the Mutual NDA template to Priya Shah at Acme, and remind the John Street signers."
Tools
Tool | What it does | API calls |
| Envelopes with status, timestamps and party names. Filters by one status and/or a title keyword, pages by offset. |
|
| One envelope: parties with signing status and role, documents with fields and 24-hour download links, audit history, metadata. |
|
| Templates with their parties and merge fields. |
|
| One template, so an assistant knows the |
|
| Search contacts by part of a name or email. The API has no search parameter, so this pages through the list (50 per call). Emails are hidden by default, but a query that matches an email fragment still confirms such an address exists on the account. |
|
| A contact's document history. The API answers 404 for a contact that exists but has never been sent an envelope (error code 10060); the tool fetches the contact first and turns that case into an empty list. |
|
| Team members with their role (User, Admin, Super-Admin). |
|
| Creates an envelope from one template and queues it for sending, or saves it as a draft. Fetches the template first and refuses locally if a template party has no signer, a signer's |
|
| Emails a reminder to every party that has not signed. Writes only. |
|
| Cancels a sent envelope (signers are emailed). Writes only. |
|
| Expires a sent envelope (no email). Writes only. |
|
Not covered on purpose: companies, usage, webhooks, branding, settings, embed sessions, party updates, and every delete endpoint.
Related MCP server: CanUSign MCP Server
Setup
Requires Node 18 or later.
npm install
npm run buildYou need an API key for your Signable account. The API authenticates with HTTP Basic: the key is the username; the password can be anything, Signable recommends x, and that is what this server sends.
Claude Desktop: add this to claude_desktop_config.json:
{
"mcpServers": {
"signable": {
"command": "node",
"args": ["/absolute/path/to/signable-mcp/dist/index.js"],
"env": { "SIGNABLE_API_KEY": "your-key" }
}
}
}Claude Code:
claude mcp add signable -e SIGNABLE_API_KEY=your-key -- node /absolute/path/to/signable-mcp/dist/index.jsVariable | Required | Meaning |
| yes | Your API key, sent as the HTTP Basic username with password |
| no |
|
| no | Defaults to |
Safety defaults
Read-only unless
SIGNABLE_ALLOW_WRITES=true. Read tools carry the MCPreadOnlyHintannotation;cancel_envelopeandexpire_envelopeare marked destructive.Email addresses of signers, contacts and users, the last four digits of signers' mobile numbers, envelope passwords, the IP addresses and user agents in the audit history, and the download link of a file a signer uploaded into an
uploadfield (the spec's example is a passport copy) are only returned when the assistant explicitly asks (include_contact_details). In free text (history lines, field values, field and merge-field labels, envelope and document titles, envelope metadata, redirect URLs, and signer, contact and user names) email addresses are replaced with[email redacted]and phone-number-like sequences with[phone redacted]by default. The phone match is a heuristic: it covers international numbers written with+or00(including the+44 (0)7700 …form), UK numbers written with a bracketed area code such as(020) 7946 0958, and UK-style0…numbers of 9 to 11 digits with spaces, dots or hyphens between groups. Other digit strings that happen to start with0(an order number, say) are redacted too, while hex fingerprints, numeric IDs, timestamps and hyphenated references such asPO-0001-000123are left alone; the raw text is available withinclude_contact_details. Envelope metadata nested more than 20 levels deep is replaced by a placeholder rather than returned unredacted. Template titles, template party labels and merge-field labels are always redacted (the template tools have noinclude_contact_detailsswitch); names are always returned, minus any email or phone typed into them. The same redaction is applied to Signable's own error messages before they are passed on.Document download links (
pdf_url,signed_pdf_urland the envelope's signed PDF) are returned by default: the spec documents them as direct links that give access to the whole document for 24 hours after generation. They are passed through as stored so they keep working; the redaction is not applied to them.IDs are checked before any call is made: contact IDs must be numeric (the spec types them as integers); fingerprints and party/field IDs must be short strings of letters, digits,
_and-(up to 64 characters, no slashes or spaces), because the spec does not document their format (all but one fingerprint example are 32 lowercase hex characters, one is 33; every party and field ID example is a number).send_envelope_from_templatecompares the request with the template before posting anything. Itsauto_expire_hoursandauto_remind_hourshave a minimum of 12: the spec documents that minimum for direct-document sends only, and it is assumed here for template sends.Signable does not document a rate limit. Requests are spaced 250 ms apart (about four per second). A 429 is retried at most twice for any method, including
POST /envelopes, on the assumption that a rate-limited request was not processed (see Status). The retry waits forRetry-After(whole or fractional seconds, or an HTTP-date; 2 s then 4 s when the header is absent or unreadable). Each wait is capped at 10 seconds, so one request waits at most 20 seconds in all; a tool call that makes several requests (pages, lookups) can still run past the MCP client's default 60-second request timeout. Past the cap: if Signable asks for a longer wait the call gives up at once and the message says how long to wait.502, 503 and 504 are retried the same way for
GETonly; when all three attempts fail the error says the service may be unavailable and to try again in a few minutes, without the gateway's HTML. APOST /envelopesor aPUT …/remind|cancel|expireis never retried after a gateway error, because the request may already have been processed and a retry could send an envelope or a reminder twice; the error tells the assistant to check withlist_envelopesorget_envelopebefore repeating it.A 200 whose body is not JSON (a proxy or a login page in the way) is reported as an error naming
SIGNABLE_BASE_URL, never as an empty list or an empty envelope.A rejected API key produces a message that says which variable to fix; a 400 from the API (for example cancelling an envelope that is not
sent) is passed on with Signable's own message and error code.
Tests
npm testThe test suite:
Validates every fixture record against the component schemas in Signable's published OpenAPI spec (
EnvelopeSignedSummary,EnvelopeDetailResponse,TemplateSummary,Contact,ContactEnvelopeSummary,User). The spec is downloaded fromdevelopers.signable.app/_bundle/openapi.yamltospec.yamlon the first run.Starts a local mock of the API under
/v1that serves those fixtures with the documented offset/limit pagination, returns Basic-auth 401s, 404s (including the spec's two contact cases: unknown contact, code 10053, and contact with no envelopes, code 10060) and 400s in the documented error shapes (thePOST /envelopes400 uses the spec's example code 10250), and answers the firstGET /templateswith a 429. The mock's list, detail, action and error responses are validated against the spec's response schemas, and the documented keys of each list and get response are asserted explicitly (see the note below).Starts the built server and drives it over stdio with the official MCP client: 29 checks covering every tool, tool annotations, offset pagination stopping at the documented total and continuing across pages that come back shorter than requested, the
envelope_statusandqfilters, redaction of emails and phone numbers by default (parties, contacts, users, history, fields and merge-field labels, template titles and party labels, metadata including a 24-level nested value, redirect URL, names; the+44 (0)…, bracketed,00-prefixed, extra-spaced and dot-separated phone forms), the upload-field link withheld by default, and their return on request, the 429 retry waiting forRetry-Afterin the seconds, fractional-seconds and HTTP-date forms, giving up after three attempts on a persistent 429 and at once on aRetry-Afterabove the cap, a 429 onPOST /envelopesretried once, a 502 retried forGETand never forPOST /envelopesor aPUTaction, aGETfailing three times with 503 reported with advice and without the gateway HTML, a 200 with a non-JSON body reported as an error, the write gate with the variable unset and set tofalse, thePOST /envelopesbody validated against the spec's "Send Template Request" schema, the local refusal of mismatched parties and fields and of acopyrecipient with a mobile number, the threePUTactions, the empty-list handling of the contact-with-no-envelopes 404 only on the first page at offset 0, ID validation before any call, the 401 and 404 messages, and that every request usedBasic base64(key:x)and a documented method and path.
Note that the spec marks no fields as required on TemplateSummary, Contact, ContactEnvelopeSummary, User, TemplateGetResponse, ContactGetResponse, TemplatesListResponse, ContactsListResponse, ContactEnvelopesListResponse and UsersListResponse, so schema validation of those only proves the types of fields that are present. Step 2 therefore also asserts that the documented keys are present in the mock's list and get responses; the fixture records themselves are only type-checked.
Status
This is a working prototype. It has not yet been run against the live API, because it was built without a Signable account. Everything below is taken from the published spec and should be confirmed on a real account:
The format of envelope and template fingerprints and of party and field IDs. The spec types them as strings; the validation here is deliberately loose.
The sort order of
GET /envelopes. The spec does not document one; its example lists newest first, and the server returns whatever order the API uses.GET /envelopes/{fingerprint}on adraftorprocessingenvelope, and whetherenvelope_historyanddocument_fieldsare present for every status.GET /contacts/{id}/envelopesfor a contact with no envelopes. The spec documents a 404 with code 10060 and the message "This contact hasn't been sent any envelopes.", but the example's summary says "Unknown or wrong-account contact", so the server fetches the contact first and only treats the 404 as "no envelopes" when that succeeded and the request was for the first page at offset 0. What the API answers for anoffsetpast the end of a list is not documented; the mock answers 200 with an empty list, and a 404 at a non-zero offset is passed on as an error rather than read as "no envelopes".The wording of Signable's error messages and whether any of them echo request data such as a party's email address; the texts here are the spec's examples, and the server redacts contact details from them regardless.
Whether the 12-hour minimum on
envelope_auto_expire_hoursandenvelope_auto_remind_hoursapplies to template sends; the spec documents it only for direct-document sends.The end of pagination. The server stops at an empty page or when
offset + returnedreaches the documentedtotal_*string; when no total is present a short page is taken as the end. A short page on its own is not, becauseLimitParamsays a request for more than 50 gets 10 back: the next page is then requested fromoffset + returned.ContactsListResponsealso documents anextURL, which is honoured when present. The list responses'limitfield is ambiguous in the spec (the schema describes it as the number of items returned, the examples echo the requested limit) and the server ignores it.A 429 on
POST /envelopesis retried on the assumption that a rate-limited request was not processed. The spec documents no 429 at all; confirm on a live account that Signable never creates the envelope before answering 429.The
POST /envelopesbody for a template send, in particular whatparty_idacopyrecipient should carry (the spec marksparty_idas required for every party, copy recipients included, without saying which ID a copy recipient should use) and whetherdocument_titlemay differ from the template title.Whether
PUT .../remind,.../canceland.../expireaccept an empty body, as documented (no request body is defined for them).The wording of the 400 returned when reminding, cancelling or expiring an envelope that is not
sent; the messages here are the spec's examples.role_idto role-name mapping (1User,2Admin,3Super-Admin) comes from the spec's user-creation schema.How many requests per second the API tolerates; the spec says nothing, so the throttle here is a guess on the polite side.
find_contacts pages through the contact list because GET /contacts has only offset and limit parameters. On large accounts, a search parameter on that endpoint would make this much cheaper.
Going to production
This version runs locally over stdio, with the account holder's own API key. For customers to connect from claude.ai or ChatGPT without handling keys, the next step is a remote server (Streamable HTTP) behind OAuth, hosted by Signable, and then a listing in the Claude and ChatGPT connector directories.
Licence
MIT. Built by Alexandru Dragoș (alexandru.dragos96@gmail.com) with an AI agent (Claude) working under his direction.
Available Tools
7 toolsfind_contactsFind contactsARead-only
Search contacts (signers and recipients) by part of their name or email. The API has no server-side search, so this pages through the contact list (50 per call) up to max_pages. Emails are only returned with include_contact_details; note that a match on an email fragment still confirms that such an address exists on the account.
Inputs: query (required), max_pages, max_results, include_contact_details.
get_contact_envelopesEnvelopes for a contactARead-only
A contact's document history: every envelope they are a recipient of, with status, timestamps and signed PDF link where available. A contact that exists but has never been sent an envelope gives an empty list.
Inputs: contact_id (required), offset, max_results, include_contact_details.
get_envelopeGet envelope detailsARead-only
Full detail for one envelope: each party with its signing status and role, the documents with their fields and download links (valid 24 hours), the audit history and any metadata.
Inputs: envelope_fingerprint (required), include_contact_details.
get_templateGet templateARead-only
One template with its parties (party_id, name) and the merge fields (field_id, label) each party can have pre-filled. Use this before send_envelope_from_template.
Inputs: template_fingerprint (required).
list_envelopesList envelopesARead-only
List envelopes on this Signable account in the order the API returns them (the spec does not document the sort order; its example lists newest first), with status, timestamps and the parties' names. Filter by one status and/or a keyword in the title.
Inputs: q, offset, status, max_results, +1 more.
list_templatesList templatesARead-only
Templates on this account with their parties and merge fields, so you know what a send from each template needs.
Inputs: offset, max_results.
list_usersList usersBRead-only
Team members on this Signable account with their role (User, Admin or Super-Admin). Emails are only returned with include_contact_details.
Inputs: max_results, include_contact_details.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 7 tools
Each tool targets a distinct resource and scope: contacts, contact envelope history, account envelopes, envelope details, template lists, template details, and users. There is no meaningful overlap that would cause an agent to select the wrong tool.
The naming mostly follows a predictable list_/get_ pattern, with list_ for collections and get_ for single items. The only minor deviation is find_contacts instead of list_contacts, but the convention is otherwise clear and consistent.
Seven tools is well-scoped for a Signable server focused on searching and retrieving account data. Each tool covers a meaningful part of the domain without unnecessary redundancy.
The server covers listing and retrieving contacts, envelopes, templates, and users, but entirely lacks write/send operations. This is especially notable since get_template mentions using it before send_envelope_from_template, yet no send tool exists, leaving a clear workflow dead-end.
Maintenance
Related MCP Connectors
Send PDFs for e-signature from Claude or ChatGPT: prepare, quote, send, track and get signed copies.
Create contacts, move deals, send proposals and invoices, read your inbox, from Claude or ChatGPT.
Read and send documents for signature — templates, recipients, fields and folders.
E-signatures: send, track, remind, void and download envelopes; templates and reports.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables users to create, manage, and track electronic signing requests and templates through Claude Desktop and other MCP-compatible clients. Provides multi-tenant authentication with customer API keys for secure document workflow operations.66 npm-
- AlicenseAqualityCmaintenanceEnables Claude to create and manage e-signature contracts, including generating PDFs, sending signing links, and checking contract status.60MIT
- AlicenseBqualityCmaintenanceEnables Claude, ChatGPT and other MCP clients to read practice-management data including organization, clinicians, diaries, availability, bookings, patients, invoices, payments, staff tasks, services, and locations, and optionally create staff tasks, create bookings, and cancel bookings.15MIT
- AlicenseNot gradedqualityBmaintenanceEnables ChatGPT and Claude to list, inspect, prepare and send Documenso envelopes for the caller's own team. Read-only tools stay team-scoped, drafts are prepared before any send, and every call uses the calling user's own team token rather than a shared credential.116 npmMIT