eContract Developers

MCP server

Connect Claude, ChatGPT, Cursor, VS Code or your own agent to eContract with the Model Context Protocol

eContract runs a remote Model Context Protocol server. AI clients that speak MCP can send contracts for e-signature, follow signing, hand out signing links and fetch signed PDFs and audit trails, without custom code.

https://api.econtract.online/mcp
  • Transport: Streamable HTTP, stateless, POST /mcp (protocol 2026-07-28; clients that still start with initialize are served too). GET and DELETE /mcp answer 405 (after authentication).
  • Signing is always human. No tool signs or declines; the agent gives each signer their own link and the person signs.

Authentication

Every request needs Authorization: Bearer <token>, either:

  • OAuth 2.1 (recommended for apps people connect): the client discovers everything from the server's 401 answer and runs the OAuth flow in the browser. The user signs in, picks a workspace and approves the scopes. Tokens are eco_at_… and must be issued for the resource https://api.econtract.online/mcp.
  • An API key cl_live_… (headless agents, CI, CLI configs with a fixed header), created under Dashboard → API Keys.

A request without a valid token gets:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://api.econtract.online/.well-known/oauth-protected-resource/mcp", scope="contracts:read contracts:write templates:read files:read files:write ai:use"

error="invalid_token" is added when a token was sent but is not valid. The protected resource metadata points to the authorization server https://api.econtract.online.

The MCP server checks every token with eContract and never forwards it; tool calls reach the contract API with the same identity, scopes and role cap as REST calls.

Tools

ToolScopeWhat it does
list_templatestemplates:readList workspace templates (search, category, type, page, limit)
get_templatetemplates:readA template and the variables to fill
list_contractscontracts:readList contracts (status, search, fromDate, toDate, page, limit)
get_contractcontracts:readStatus, processing status, signers and a nextStep hint. Accepts the id or the code (CTR-…)
send_contractcontracts:writeCreate and send in one step: one of file (base64 PDF/DOCX), fileUrl (https) or templateId + templateValues; signers, signingOrder, expiresInDays, delivery (email, link, both)
get_signing_linkscontracts:writeA fresh signing link for every signer who still has to sign. Sends no email
send_remindercontracts:writeEmail pending signers again (all, or one signerId)
void_contractcontracts:writeCancel a contract (destructive)
download_signed_documentcontracts:readThe PDF as an embedded application/pdf resource (version: signed or original)
get_audit_trailcontracts:readEvents, signers, hash-chain check and document SHA-256
verify_pdfnoneCheck the digital signatures of any PDF (base64)
analyze_contractai:use (+ contracts:read with contractId)AI summary: type, parties, value, duration, suggested titles and signers, from text, contentBase64 or contractId

Also a resource template econtract://contracts/{contractId}/document/{version} (contracts:read).

  • Write tools take an optional idempotencyKey. Without it the server generates one and returns it, so the model can repeat a call safely (see Idempotency).
  • Documents passing through the connector (uploads and downloads) are limited to 10 MB; larger files must be uploaded with fileUrl or downloaded in the eContract app.
  • API errors come back as tool results with isError: true, the error code, message, requestId and a hint for the model.

Typical workflow

  1. list_templates / get_template, or take the user's PDF or DOCX.
  2. send_contract, after confirming title, document and signers with the user. It returns processingStatus: "processing".
  3. Poll get_contract until processingStatus is ready.
  4. With delivery: "link" or "both": get_signing_links, and give each signer only their own link.
  5. While waiting: get_contract, send_reminder; void_contract to cancel.
  6. When status is completed: download_signed_document and get_audit_trail.

Connect your client

Server URL: https://api.econtract.online/mcp. OAuth clients only need the URL; they find the rest themselves.

Claude.ai and Claude Desktop

Settings → Connectors → Add custom connector, URL https://api.econtract.online/mcp, then Connect and approve the consent screen. (Menu names: verify against the current Claude UI.)

Claude Code

# OAuth (opens the browser on first use; or run /mcp inside Claude Code)
claude mcp add --transport http econtract https://api.econtract.online/mcp

# API key
claude mcp add --transport http econtract https://api.econtract.online/mcp \
  --header "Authorization: Bearer cl_live_..."

Project-scoped .mcp.json:

{
  "mcpServers": {
    "econtract": {
      "type": "http",
      "url": "https://api.econtract.online/mcp",
      "headers": { "Authorization": "Bearer ${ECONTRACT_API_KEY}" }
    }
  }
}

ChatGPT

Enable Developer mode (Settings → Apps & Connectors → Advanced), then Create a connector with URL https://api.econtract.online/mcp and authentication OAuth. (Menu names: verify against the current ChatGPT UI.)

Cursor

~/.cursor/mcp.json (or .cursor/mcp.json in a project):

{
  "mcpServers": {
    "econtract": { "url": "https://api.econtract.online/mcp" }
  }
}

Add "headers": { "Authorization": "Bearer cl_live_..." } to use an API key instead of OAuth. (Verify against the current Cursor docs.)

VS Code (GitHub Copilot agent mode)

.vscode/mcp.json:

{
  "servers": {
    "econtract": { "type": "http", "url": "https://api.econtract.online/mcp" }
  }
}

VS Code runs the OAuth flow when the server answers 401. For an API key add "headers": { "Authorization": "Bearer ${input:econtract-key}" } with a matching inputs entry. (Verify against the current VS Code docs.)

Your own agent or the MCP Inspector

Any MCP client with Streamable HTTP works. To try the tools by hand: npx @modelcontextprotocol/inspector, transport Streamable HTTP, URL https://api.econtract.online/mcp, header Authorization: Bearer cl_live_….

Troubleshooting

SymptomCauseFix
401 with WWW-Authenticate: Bearer resource_metadata=…No token, or the client did not run OAuthReconnect; the client should follow resource_metadata. With an API key check the Authorization header
401 with error="invalid_token"Token expired or revoked, key revoked, user left the workspace, or an OAuth token issued only for the REST APILet the client refresh or reconnect; OAuth clients must ask for resource=https://api.econtract.online/mcp
400 invalid_requestToken sent in the URL (?access_token=)Send it in the Authorization header only
403 with WWW-Authenticate: Bearer error="insufficient_scope", scope="…"The tool needs a scope the connection lacksOAuth clients can re-authorize with the listed scope; for an API key add the scope under Dashboard → API Keys
403 Forbidden: invalid Origin headerA browser client sent an Origin that is not allowedBrowser clients must run on an https origin (or http on localhost)
429 with Retry-After (JSON-RPC error, data.code: "RATE_LIMITED")More than 60 requests per minute for this key or connectionWait Retry-After seconds
503 with Retry-After: 5eContract could not check the tokenRetry shortly
Tool result isError: true, code HUMAN_ACTION_REQUIREDThe model tried to sign or declineGive the signer their link from get_signing_links
Tool result isError: true, code INSUFFICIENT_SCOPE or FORBIDDENScope missing, or the user's workspace role does not allow itReconnect with the scope, or use an account with a suitable role
download_signed_document fails with DOCUMENT_NOT_SIGNEDNot everyone has signed yetWait for status: "completed"
The client shows no eContract toolsConnection failed silentlyCheck the client's MCP log; test with the MCP Inspector and an API key

On this page