Skip to content
contract.cli

MCP server

The agent drives. You approve.

The whole suite is designed for an agent-first workflow. sign-cli is the most concrete expression of that: every CLI command worth automating is exposed as an MCP tool over stdio, so any MCP-aware client (Claude Code, Cursor, Codex) can drive sending, tracking, detection, stamping, and verification — while the actual signing remains gated behind a per-signer human gesture.

The guardrail — Agents can send documents, detect signature fields, stamp previews, track status, and verify receipts — but they can't sign on a human's behalf. Every signature requires a per-signer token tied to that signer's email, with a TTL. The agent never sees the token. The human does. That asymmetry is the whole architecture.

Start the server

stdio MCP server
# Boots the MCP server on stdio. Wire it into any MCP-aware client.
sign mcp serve

# Or via npx, no install required:
npx sign-cli mcp serve

# Discover the catalog without spinning up the server:
sign mcp tools --format markdown

Wire it into Claude Code

Add to your ~/.config/claude-code/settings.json (or the project-level .claude/settings.json):

.claude/settings.json
{
  "mcpServers": {
    "sign-cli": {
      "command": "npx",
      "args": ["-y", "sign-cli", "mcp", "serve"]
    }
  }
}

After that, every sign-cli MCP tool shows up inside Claude Code. Ask the agent to "detect the signature field on contract.pdf and send it to alice@acme.com and bob@beta.com via SignWell" and it will call the right tools with the right arguments.

Wire it into Cursor

Cursor's MCP config lives at ~/.cursor/mcp.json:

~/.cursor/mcp.json
{
  "mcpServers": {
    "sign-cli": {
      "command": "npx",
      "args": ["-y", "sign-cli", "mcp", "serve"],
      "env": {}
    }
  }
}

Read-only mode for sandboxed agents

Run with --read-only true to block every mutating tool with a FORBIDDEN_READ_ONLY error. Useful for letting an agent inspect and track without any side effects. Pair with --tool to allow-list a specific subset, or --capability to disable resources/prompts.

sign mcp serve --read-only true \
  --tool request_show --tool audit_verify --tool pdf_detect_signature_field \
  --emit-events ./mcp-events.ndjson \
  --emit-events-redact true

Available tools — 19 in total

Every tool ships with an inputSchema and (where applicable) an outputSchema. request_watch also streams notifications/progress when the client supplies a progressToken. Don't hardcode this list — call sign mcp tools for the live catalog.

Read-only (safe to call without approval)

Tool What it does
signer_list List pending local-provider requests where the signer is a recipient.
signer_fetch_document Read (and optionally save) the unsigned PDF for a request. Requires the per-signer token.
request_show Enriched snapshot: approvals, signedBy[], declinedBy, and a nextSteps[] hint array.
request_status Poll the provider for the latest status of a request.
request_watch Poll until terminal (completed/declined/canceled/timeout). Streams progress notifications.
audit_verify Verify the hash-chained audit log for a request; reports any break.
audit_scan Cross-request audit search with filters (request id, event type, time window).
pdf_detect_signature_field Ranked signature-field candidates (AcroForm /Sig + anchor text). Read-only.
pdf_detect_date_field Date-anchor candidates with an alreadyFilled flag to avoid overwrites.
pdf_inspect_signatures Parse a signed PDF's PKCS#7: /ByteRange digest match, signer certs, trust label.
profile_list List named profiles (provider, dbPath, credentials bundle) and the active one.
profile_show Show resolved profile state. Credentials redacted by default; show_secrets: true to reveal.

Mutating (gated by --read-only true)

Tool What it does
sign Sign a local request as the holder of a per-signer token. Requires --provider local.
signer_decline Decline a local request as the token holder. Records a request.signer_declined event.
signer_reissue_token Mint a fresh token in place of an expired/lost one. Tied to the original signer email.
pdf_stamp_text Stamp plain text (dates, names) onto a PDF without producing a PAdES envelope.
preview Stamp a signature image or rendered name onto a PDF — no envelope, no audit mutation. Iterate before committing.
document One-shot DOCX|PDF → sealed PDF: convert, auto-place, stamp, PAdES-seal, verify chain.
request_receipt Export a cryptographically-signed receipt bundle (manifest + detached signature + cert chain).

HTTP API for non-MCP clients

Every MCP tool has a 1:1 HTTP equivalent under /v1/*, served by sign serve. Same input shape, same path-traversal guards, same read-only gating. Useful for agents and integrations that speak REST rather than MCP.

# Boot the HTTP API. Auth via SIGN_HTTP_BEARER_TOKEN.
sign serve --read-only true --rate-limit 5

# Discover the route catalog:
curl http://localhost:8787/v1/openapi.json

Profiles for credential isolation

Named profiles bundle provider, dbPath, strictProvider, and a credentials block (with {{env:VAR}} references that point at shell-managed secrets). The agent never holds API keys — it activates a profile by name; the credentials resolve from environment variables at call time.

# Create a profile that reads its API key from the shell environment
sign profile init --name prod \
  --provider signwell --db "~/.sign-cli/prod.db" \
  --strict-provider true
sign profile set --name prod \
  --key credentials.SIGNWELL_API_KEY --value "{{env:SIGNWELL_API_KEY}}"

# Activate per-call
sign --profile prod request show --request-id req_abc

# Or implicitly via a project-level sign-profile.json (git/npm-style discovery)

What the agent can't do

  • Sign on a human's behalf. The sign tool requires an explicit per-signer token. Tokens are scoped to one signer's email and expire after a configurable TTL.
  • Modify past audit events. The audit chain is hash-chained with append-only triggers; tampering breaks audit_verify.
  • Bypass the timestamp anchor. RFC 3161 anchors are external — the agent can't forge one.
  • Read or write paths outside the working directory. Every input/output path runs through validateDocumentPath / validateOutputPath. Opt out with SIGN_ALLOW_ABSOLUTE_DOCS=1.
  • Leak its credentials. Profile-injected secrets flow through the error-message redactor — even custom keys never show up in stack traces.

Why this matters

Most "agent-friendly" SaaS products are agent-friendly in the sense that they have an API. They aren't agent-safe. The MCP boundary here is designed so an agent can do all the operational work (detecting, sending, stamping previews, tracking, verifying, reporting) while the actual legal commitment — the signature — stays gated behind a human gesture.

That's a meaningful architectural choice for anyone deploying agents into ops workflows. You get the productivity wins of automation without the legal liability of a hallucinating model accidentally executing a contract.

Edit this page on GitHub