MCP server

Let an AI agent send documents for signature and track them — Claude Code, Claude Desktop, Cursor, VS Code or your own agent, with your API key. The agent sends and tracks; every signer signs themselves.

wesign.now runs a remote Model Context Protocol server. Connect an AI agent to it and the agent can send a PDF or a template for signature, follow every signer, remind or withdraw, and fetch the links to the sealed PDF and its audit trail — on the same contract as the REST API: the same keys, monthly caps, rate limit, errors and API log.

https://www.wesign.now/api/mcp

Streamable HTTP, one endpoint, an API key on every request (Authorization: Bearer wsk_live_…). The same server also answers at https://api.wesign.now/mcp.

The agent sends; people sign. No tool signs anything. Each signer signs themselves from the personal link wesign.now emails them — a simple electronic signature (SES) — or with an SMS code to their phone as well, an advanced electronic signature (AES). The agent never receives a signing link unless you ask to deliver the links yourself (send_emails: false).

1 · Get your API key

  1. 1. Sign up free.
  2. 2. Settings → Company → Developer settings → Turn on (on a personal account: Settings → Profile).
  3. 3. Settings → Developers → Create API key.
  4. 4. Call GET /v1/me with the key. It sends nothing and shows the key works.

Create one key per agent and name it after the client ("Claude Code — Anna"): the API log then shows which agent made each call, and revoking one key stops one agent. Keep the key out of files you commit: the setups below read it from the environment variable WESIGN_API_KEY or ask for it (VS Code).

export WESIGN_API_KEY="wsk_live_…"   # paste the whole key here

2 · Connect your client

Claude Code

claude mcp add --transport http wesign https://www.wesign.now/api/mcp \
  --header "Authorization: Bearer $WESIGN_API_KEY"

Add --scope user to use it in every project. To share the setup with your team without sharing a key, put it in the project's .mcp.json, which reads each person's own variable:

{
  "mcpServers": {
    "wesign": {
      "type": "http",
      "url": "https://www.wesign.now/api/mcp",
      "headers": { "Authorization": "Bearer ${WESIGN_API_KEY}" }
    }
  }
}

Claude Desktop

Claude Desktop's own connector settings sign in with OAuth, which this server does not offer yet. Connect it through mcp-remote, a community bridge that passes your key as a header. In claude_desktop_config.json:

{
  "mcpServers": {
    "wesign": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://www.wesign.now/api/mcp",
        "--header",
        "Authorization:${WESIGN_AUTH_HEADER}"
      ],
      "env": { "WESIGN_AUTH_HEADER": "Bearer wsk_live_…" }
    }
  }
}

The header is written without a space after the colon on purpose: on Windows, Claude Desktop does not escape spaces inside args. Restart Claude Desktop after saving.

Cursor

In .cursor/mcp.json (one project) or ~/.cursor/mcp.json (every project):

{
  "mcpServers": {
    "wesign": {
      "url": "https://www.wesign.now/api/mcp",
      "headers": { "Authorization": "Bearer ${env:WESIGN_API_KEY}" }
    }
  }
}

VS Code

In .vscode/mcp.json. VS Code asks for the key when the server first starts, so it is not written into the file:

{
  "inputs": [
    { "type": "promptString", "id": "wesign-key", "description": "wesign.now API key", "password": true }
  ],
  "servers": {
    "wesign": {
      "type": "http",
      "url": "https://www.wesign.now/api/mcp",
      "headers": { "Authorization": "Bearer ${input:wesign-key}" }
    }
  }
}

Your own agent

Any MCP client that speaks Streamable HTTP and can send a header connects with the URL and Authorization: Bearer <key>. The server is stateless: no session id, every request stands alone, answers are JSON (no event stream). GET and DELETE answer 405.

Then ask the agent to call whoami: it sends nothing and shows the workspace, the plan and this month's API documents.

Tools

ToolWhat it doesREST equivalent
whoamiThe key's workspace, plan, capabilities, SMS allowance and this month's API documents against the cap. Sends nothing, costs no rate-limit token.GET /v1/me
list_templatesThe workspace's templates; instantiable: true ones can be sent.GET /v1/templates
get_templateA template's input schema: recipient slots and field_values.GET /v1/templates/{id}
send_for_signatureSends a PDF (file_url or file_base64) to 1–20 signers. placement auto_append (default) adds a signature page; anchors uses markers in the PDF. A signer with phone_e164 also gets an SMS code (AES).POST /v1/signing-requests
send_from_templateFills a locked template and sends it; review: true stages it for a person to send from the app, validate_only: true only checks. Enterprise.POST /v1/templates/{id}/instantiate
list_signing_requestsOne row per signer, newest first, filtered by status, signer email, document or date.—
get_signing_requestA document's overall status and every signer's (document_id), or one signer with recent events (signing_request_id).GET /v1/documents/{id}, GET /v1/signing-requests/{id}
send_reminderEmails one signer their link again.POST /v1/signing-requests/{id}/remind
withdraw_signing_requestWithdraws one signer's request; their link stops working. Cannot be undone.POST /v1/signing-requests/{id}/withdraw
get_signed_documentOnce everyone has signed: signed_pdf_url and audit_trail_url, fetched with the same key. No file content.GET /v1/documents/{id}/signed, /audit-trail

A signing request is one signer: to remind or withdraw a whole document, the agent calls the tool once per signer (get_signing_request with the document_id lists them).

The send, withdraw and reminder tools carry MCP annotations that mark them as acting outside the conversation (destructiveHint / openWorldHint), so a client that honours them asks you before each call.

Limits and caps

  • Monthly cap. A document sent by an agent counts like one sent over REST, once per document whatever the number of signers:

    • Free: 10 documents a month, the plan's own cap
    • Branded: 100 documents a month through the API
    • Enterprise: no cap

    Past the cap, a send answers 402 api_monthly_limit (or tier_required, the plan's overall cap) with meta: { tier, cap, used }.

  • Rate limit. Every tool call except whoami takes one token from the key's 60 requests a minute, the same bucket as the key's REST calls. A refusal is 429 rate_limited with retry_after_sec. Connecting and listing the tools take no token.

  • Per address. Before any key is read, one IP address may send 120 requests a minute to the MCP server, every message counted (connecting and listing included). Over it, the HTTP answer is 429 rate_limited with a Retry-After; see Rate limits.

  • Templates. send_from_template needs the Enterprise plan and answers 402 enterprise-required on the others. list_templates and get_template work on every plan.

  • The PDF. file_url (https, a plain GET that answers the PDF itself) up to 25 MB, as on REST. file_base64 suits small files: the whole request is capped at 4.5 MB, so about 3 MB of PDF; send larger files by URL.

  • Retries. A send without idempotency_key gets one derived from its exact content, so an identical call within 24 hours answers the first result with replayed: true and sends nothing again (see Idempotency). To send the same content twice on purpose, pass a new idempotency_key.

Errors

A key that is missing, unknown, revoked or limited to the embedded scope is refused before any tool runs: HTTP 401 invalid_key with a WWW-Authenticate: Bearer challenge; a key used from an address its IP allowlist does not hold is 403 ip_not_allowed (Authentication).

Every other refusal is a tool result with isError: true whose content is the REST error plus its HTTP status and the request id:

{
  "error": "Monthly API limit reached (100 documents/month through the API on the branded tier). Upgrade to send more.",
  "code": "api_monthly_limit",
  "status": 402,
  "meta": { "tier": "branded", "cap": 100, "used": 100 },
  "request_id": "fra1::…"
}

Branch on code; the codes are the REST API's (Errors). Quote request_id to support with the time of the call.

Safety

  • No signing, no signing links. No tool signs, and results carry no signing link (a link is the signer's own credential). The one exception is the result of a send with send_emails: false, where you asked to deliver the links yourself: hand each link to its own signer.
  • Results are data. Document names, template names, signer names, metadata and audit events are written by other people. The server tells the agent to treat them as data, never as instructions, and returns them as JSON fields only.
  • One key per agent. A key can do over MCP exactly what it can do over REST. Revoke it in Settings → Developers and the agent is cut off at once.

The API log

Every tool call appears in Settings → Developers → API log, kept 30 days: POST /mcp/send_for_signature with its status, error code, key and request id, the same id the response's X-Request-Id header carries. A refused key appears as /mcp. No request or response body is stored.