# MCP server

The docuinked MCP server lets an agent prepare documents, ask to send them, and read the results. One URL, no local package to install.

Server URL: `https://docuinked.com/mcp`. Clients that can send a header use your key: `Authorization: Bearer di_test_...`. Start with a test key. Clients that only sign in by browser use OAuth, where you approve the connection yourself.

## Claude Code

```
claude mcp add --transport http docuinked https://docuinked.com/mcp --header "Authorization: Bearer $DOCUINKED_API_KEY"
```

## Claude

In Claude on the web or desktop, open **Customize**, then **Connectors**, then **Add custom connector**. Paste `https://docuinked.com/mcp` and sign in when asked.

## Cursor

Add this to `.cursor/mcp.json`:

```json
{"mcpServers": {"docuinked": {"url": "https://docuinked.com/mcp", "headers": {"Authorization": "Bearer di_test_..."}}}}
```

## VS Code

```
code --add-mcp '{"name": "docuinked", "type": "http", "url": "https://docuinked.com/mcp", "headers": {"Authorization": "Bearer di_test_..."}}'
```

## Codex

```
codex mcp add docuinked --url https://docuinked.com/mcp --bearer-token-env-var DOCUINKED_API_KEY
```

## ChatGPT

On the web, open the Plugins page and choose **Add custom MCP server**. Paste `https://docuinked.com/mcp` and sign in when asked. OpenAI limits which plans get full MCP, so check yours.

## Check it worked

Ask your agent to call `whoami`. It should report your account and `test` mode. Then ask it to prepare a test NDA for `sign@test.docuinked.com`.

## Tools

| Tool | What it does |
|---|---|
| [`whoami`](/docs/api#whoami) | Confirms the connection works. Shows the account name, whether it is in test mode (no email is ever sent) or live, and the daily limit on live sends. |
| [`create_document`](/docs/api#create_document) | Creates a draft from a PDF (pdf_url, pdf_base64, or several files) with signers and fields. Fields go after anchor text, on {{signature:1}} tags in the PDF, or at page coordinates; with none, fields go on the PDF's own Signature, Date and Name lines (one signer per signature line, placement: labels), or else one signature field per signer on the last page. Returns draft_hash, review_url, warnings and next_action. Sending is a separate step: send_document with the draft_hash. |
| [`send_document`](/docs/api#send_document) | Asks to send a draft to its signers. The draft_hash must match the current draft. With an agent key or an MCP connection, nothing is sent: it creates an approval request and returns approval_url, and the document goes out only after a named person approves that exact draft (in test mode, simulate_approval can stand in for the person). In test mode no email is sent, signers at sign@test.docuinked.com or decline@test.docuinked.com act at once, and signing links come back. |
| [`list_documents`](/docs/api#list_documents) | Lists documents in the current mode (test or live), newest first, with each signer's status. Filter by status; limit is 1 to 100. |
| [`get_document`](/docs/api#get_document) | Shows one document's status, each signer's progress and its review link. |
| [`get_signed_pdf`](/docs/api#get_signed_pdf) | Returns the sealed, signed PDF as base64 with its SHA-256, once the document is completed. The file can be large. |
| [`get_original_pdf`](/docs/api#get_original_pdf) | Returns the document as it was uploaded, before any signature, as base64 with its SHA-256. Use it to preview a draft or a document in progress. |
| [`get_evidence`](/docs/api#get_evidence) | Returns the full audit trail: every event, its hash chain, and the seal certificate. |
| [`remind_signers`](/docs/api#remind_signers) | Emails a reminder now to every signer of a sent document who hasn't signed yet. Returns how many were reminded. |
| [`void_document`](/docs/api#void_document) | Cancels a sent document that is still waiting for signatures, so it can no longer be signed. This can't be undone. |
| [`create_signing_link`](/docs/api#create_signing_link) | Makes a signing link for one signer of a sent document, for your own app or message. With embed true it returns embed_url for an iframe on a site listed in your branding. Anyone holding the link can sign as that signer. Live agent keys and MCP connections can't create links for live documents. |
| [`simulate_approval`](/docs/api#simulate_approval) | Test mode only. Approves a test document's pending approval as the account's person would, then sends it, so CI and agent evals can run the approval step unattended. Live documents always need a person to approve at approval_url. |
| [`simulate_signer`](/docs/api#simulate_signer) | Test mode only. Signs or declines as one signer (signer is their position, from 1) so a whole flow runs without a browser. |
| [`update_signer`](/docs/api#update_signer) | Corrects the name or email of someone who hasn't signed yet, on a sent document. Old links stop working and a new request goes to the new address. |
| [`bulk_send`](/docs/api#bulk_send) | Creates and sends one document per recipient set from a template, up to 100 at a time. With agent keys and MCP connections, each live document waits for its own approval. Over REST, an Idempotency-Key makes retries safe. |
| [`test_webhook`](/docs/api#test_webhook) | Sends a signed test event to the webhook right away and reports what the endpoint answered. |
| [`list_webhook_deliveries`](/docs/api#list_webhook_deliveries) | The last 50 delivery attempts for a webhook: event, status code, error and time taken. |
| [`get_attachment`](/docs/api#get_attachment) | Returns a file a signer uploaded, as base64, with its name, type and SHA-256. Field IDs are listed in get_evidence. |
| [`delete_document`](/docs/api#delete_document) | Permanently deletes a document that isn't in progress: its encryption key is destroyed, so its files can never be read again. The evidence log keeps a record that it existed. Not available to agent keys. |
| [`create_template`](/docs/api#create_template) | Makes a reusable template from a draft or finished document: same file, fields and signer roles, with names and emails cleared. |
| [`get_branding`](/docs/api#get_branding) | Shows the account's signer-facing name, accent colour, logo, embed origins and whether docuinked branding is hidden. |
| [`update_branding`](/docs/api#update_branding) | Sets what signers see: your name, accent colour, logo, and the sites allowed to embed signing. Fields you leave out stay as they are. |
| [`create_account`](/docs/api#create_account) | For platforms: makes an account for one of your customers. Act for it on any call with the header DocuInked-Account and your own key. Each has its own documents, branding and webhooks. |
| [`list_accounts`](/docs/api#list_accounts) | Lists the sub-accounts this account manages, for platforms. |
| [`list_templates`](/docs/api#list_templates) | Lists reusable templates with their IDs and signer roles, for create_from_template. |
| [`create_from_template`](/docs/api#create_from_template) | Creates a draft from a template, filling its signer roles in order. Nothing is sent. |
| [`create_webhook`](/docs/api#create_webhook) | Registers an https URL for events such as document.completed. Returns the signing secret once. |
| [`list_webhooks`](/docs/api#list_webhooks) | Lists active webhooks. |
| [`delete_webhook`](/docs/api#delete_webhook) | Stops sending events to a webhook. |


## What an agent can't do

Over MCP, every caller counts as an agent, whatever key it holds. So a live call to `send_document` never sends. It returns an `approval_url` for a person. Agents can't get live signing links. There is no signing tool at all. Text inside a document is data, never instructions. Read [how approvals work](/docs/approvals).

## Common questions

### Does the MCP server need a local package?

No. It is a hosted server over streamable HTTP. Nothing runs on your machine, so cloud agents and local agents connect the same way.

### Should I use my live key in an MCP client?

Start with a test key and move to live when the flow works. A live key over MCP still can't send without a person's approval, but it can create real drafts in your account.

### Why does my client say the send needs approval?

That is the rule working. Open the `approval_url` while signed in, read the draft, and approve or reject it. The approval lasts 24 hours.
