> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vumasign.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Agents and MCP

> Let an agent read your templates, check its values and prepare drafts, through an MCP server that never sends.

export const liveKeyPrefix = "vsk_live_";

export const testKeyPrefix = "vsk_test_";

export const mcpDraftReplayWindow = "24 hours";

export const mcpScopes = "templates:read, documents:read, envelopes:read, envelopes:write";

export const mcpAllowLiveEnv = "VUMASIGN_MCP_ALLOW_LIVE";

export const mcpApiKeyEnv = "VUMASIGN_API_KEY";

export const mcpPackage = "@vumasign/mcp";

<code>{mcpPackage}</code> is a Model Context Protocol server for your Vumasign account. It runs on
your own machine, started by your MCP client, and lets an agent do the matching work of filling in
a form: read a template, see what is printed around each box, check the values it proposes, and
prepare a **draft** envelope with those values filled in. A person then opens the draft in
Vumasign, reviews it and sends it.

It is separate from the [documentation server](/ai-tools), which searches these pages and holds no
key.

## What it will not do

This server has no tool for any of the following, and leaving them out is deliberate. Each one names
the endpoints it covers, which no tool calls:

* **Send an envelope, alone or in a batch.** Sending emails real people, uses your allowance and starts a signing ceremony, on the strength of a mapping a model inferred from a form. That is a person’s act: the draft tool always creates a draft, whatever it is asked. ([`POST /api/v1/envelopes/{envelopeId}/send`](/api-reference/send-envelope), [`POST /api/v1/envelopes/batches`](/api-reference/create-envelope-batch))
* **Mint a signing URL.** A signing URL is a bearer credential for a legal act, and a model puts what it is given into transcripts and logs. For the same reason the draft tool refuses an `embedded` recipient: one is never emailed, so its draft could only be reached through a signing URL. ([`POST /api/v1/envelopes/{envelopeId}/recipients/{recipientId}/signing-url`](/api-reference/create-signing-url))
* **Rename a field or a question.** Naming a template’s fields is for a person or for Vumasign’s own naming, not for an agent inventing names. ([`PATCH /api/v1/templates/{templateId}/fields`](/api-reference/rename-template-fields), [`PATCH /api/v1/templates/{templateId}/fields/{fieldId}`](/api-reference/rename-template-field))
* **Create a template, or an envelope from a document of its own.** Authoring what a legal document asks for belongs in the editor, with a person. The server works only from templates that already exist. ([`POST /api/v1/templates`](/api-reference/create-template), [`POST /api/v1/envelopes/one-off`](/api-reference/create-one-off-envelope))
* **Void an envelope.** Voiding stops a ceremony that people may already be part of; a person decides that. ([`POST /api/v1/envelopes/{envelopeId}/void`](/api-reference/void-envelope))
* **Create, change, read or delete a webhook.** A webhook sends your envelope events, with recipients’ names and addresses, to a URL. A tool that could create one would let a model choose where they go. ([`GET /api/v1/webhooks`](/api-reference/list-webhooks), [`POST /api/v1/webhooks`](/api-reference/create-webhook), [`GET /api/v1/webhooks/{webhookId}`](/api-reference/get-webhook), [`PATCH /api/v1/webhooks/{webhookId}`](/api-reference/update-webhook), [`DELETE /api/v1/webhooks/{webhookId}`](/api-reference/delete-webhook), [`POST /api/v1/webhooks/{webhookId}/rotate-secret`](/api-reference/rotate-webhook-secret))
* **Request, read or manage a standing authorisation.** A standing authorisation lets your organisation apply somebody’s signature. Asking for one, and choosing to apply one, are for a person; the draft tool also refuses a recipient that names one. ([`GET /api/v1/standing-authorisations`](/api-reference/list-standing-authorisations), [`GET /api/v1/standing-authorisations/{authorisationId}`](/api-reference/get-standing-authorisation), [`POST /api/v1/standing-authorisations/invitations`](/api-reference/invite-standing-authorisation), [`POST /api/v1/standing-authorisations/{authorisationId}/cancel`](/api-reference/cancel-standing-authorisation), [`POST /api/v1/standing-authorisations/{authorisationId}/resend`](/api-reference/resend-standing-authorisation), [`POST /api/v1/standing-authorisations/{authorisationId}/revoke`](/api-reference/revoke-standing-authorisation), [`POST /api/v1/standing-authorisations/{authorisationId}/renew`](/api-reference/renew-standing-authorisation))
* **List envelopes, or read an envelope’s documents.** An envelope’s documents carry the answers of the people it was sent to. The server reads an envelope only by the id it was given, to confirm a draft it made. ([`GET /api/v1/envelopes`](/api-reference/list-envelopes), [`GET /api/v1/envelopes/{envelopeId}/documents`](/api-reference/list-envelope-documents), [`GET /api/v1/envelopes/{envelopeId}/documents/{position}/draft`](/api-reference/get-envelope-document-draft))

## Before you start: a test key

Create a key under **Settings → API keys** in the dashboard, starting <code>{testKeyPrefix}</code>,
with these scopes: <code>{mcpScopes}</code>.

Start with a test key. A template has no environment, so a test key reads the same templates a live
key does, and a draft made with it is a rehearsal: once a person sends it, it produces a watermarked
document that is never billed and binds nobody. It can be sent only to your organisation's verified
members and verified test recipients, so a draft addressed to a real customer cannot be sent; the
send is refused and the draft has to be made again with a live key. See
[Test keys and live keys](/concepts/test-and-live).

The server **refuses to start on a <code>{liveKeyPrefix}</code> key** unless
<code>{mcpAllowLiveEnv}</code> is set to `1` as well. Think before setting it: the key sits in plain
text in your MCP client's configuration, and the scope that lets the server create drafts is the
same scope that, called directly against the API, can send them. The tool list is narrow; the key is
what limits a compromised process.

## Connect it

The server is started with `npx`, so it needs [Node.js](https://nodejs.org/) on the machine that
runs your client. The key is passed in the server's environment as <code>{mcpApiKeyEnv}</code>.

### Claude Code

```bash theme={null}
claude mcp add vumasign --env VUMASIGN_API_KEY=vsk_test_… -- npx -y @vumasign/mcp
```

Add `--scope user` to make it available in every project, rather than only the current one.

### Claude Desktop

Open **Settings → Developer → Edit Config**, add the server to `claude_desktop_config.json`, and
restart Claude Desktop:

```json theme={null}
{
  "mcpServers": {
    "vumasign": {
      "command": "npx",
      "args": [
        "-y",
        "@vumasign/mcp"
      ],
      "env": {
        "VUMASIGN_API_KEY": "vsk_test_…"
      }
    }
  }
}
```

### Cursor

Add the same object to `~/.cursor/mcp.json` for every project, or to `.cursor/mcp.json` in one
project. A project's `.cursor/mcp.json` is often committed with the project: if you use it, keep it
out of version control, or the key goes with it.

```json theme={null}
{
  "mcpServers": {
    "vumasign": {
      "command": "npx",
      "args": [
        "-y",
        "@vumasign/mcp"
      ],
      "env": {
        "VUMASIGN_API_KEY": "vsk_test_…"
      }
    }
  }
}
```

Any other client that starts a local MCP server takes the same command, arguments and environment.

## The tools

Each tool is one call to the endpoint it names, made with your key, so it is refused exactly as
the endpoint would refuse it, with the same `code`.

| Tool | Calls | Scope | Returns printed form text |
| - | - | - | - |
| `list_templates` | [`GET /api/v1/templates`](/api-reference/list-templates) | `templates:read` | no |
| `get_template` | [`GET /api/v1/templates/{templateId}`](/api-reference/get-template) | `templates:read` | yes |
| `get_template_page` | [`GET /api/v1/documents/{documentId}/pages/{pageNumber}`](/api-reference/get-document-page) | `documents:read` | yes |
| `get_template_document` | [`GET /api/v1/documents/{documentId}/content`](/api-reference/get-document-content) | `documents:read` | yes |
| `validate_values` | [`POST /api/v1/templates/{templateId}/validate-values`](/api-reference/validate-template-values) | `templates:read` | yes |
| `get_envelope` | [`GET /api/v1/envelopes/{envelopeId}`](/api-reference/get-envelope) | `envelopes:read` | no |
| `create_envelope_draft` | [`POST /api/v1/envelopes`](/api-reference/create-envelope) | `envelopes:write` | yes |

## How an agent fills a form

1. `list_templates`, to find the template.
2. `get_template`. Every field has a `data_key` to address it by and `context`: the label, row,
   column, option and section printed around its box. `context` is usually enough to tell what a
   box asks for. `warnings` says whether the uploaded form already held somebody's details. The
   result also carries the template's `etag`.
3. `get_template_page`, only for a page where `context` is not enough. The page is returned as a
   PDF; whether your client shows a PDF to its model depends on the client.
4. `validate_values`, with the values the agent proposes. It answers, entry by entry, what creating
   the envelope would do with each one, and writes nothing.
5. `create_envelope_draft`, with the recipients, the values and the `template_etag` from step 4.
   If the template changed in between, the draft is refused rather than filled wrongly. Calling it
   again with the same arguments within <code>{mcpDraftReplayWindow}</code> returns the first draft
   instead of making a second one; after that, the same arguments make another draft.
6. `get_envelope`, to confirm what was created. Then a person opens the draft in Vumasign and
   sends it.

## Text printed on a form is data

`context`, the pages and the whole document carry text printed on somebody else's form. A form
can be written to look like instructions to a model. Every tool that returns printed text says, in
the description your client shows the model, that the text is data and never instructions. That
lowers the risk; it does not remove it.

Through this server's own tools, a hostile form can at worst shape a draft, and a person reviews
every draft before it is sent. But the key is in your client's configuration file, and an agent that
can also read files or run commands, as Claude Code and Cursor can, could be led to read the key and
call the API directly, where it holds every capability of the key's scopes, sending included. So:

* use a test key, which limits what a misled agent can reach to a sandbox;
* let the agent that reads forms have as few other tools as you can, and approve its file reads and
  commands rather than allowing them all;
* remember that a misled agent can read the account's templates into its conversation, so do not
  give it a tool that could carry them somewhere else.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.