mcp-signwell
Official# SignWell MCP Server
Model Context Protocol server that orchestrates SignWell's e-signature workflows.
## Prerequisites
- [Node.js](https://nodejs.org/) v18 or newer.
- A SignWell API key with document access (`SIGNWELL_API_KEY` environment variable).
- Optional overrides:
- `SIGNWELL_API_BASE_URL` for non-production endpoints.
- `SIGNWELL_API_TIMEOUT_MS` to tweak HTTP client timeouts (default 90000 ms; CLI flag `--timeout` on `setup` skips env prompts and writes this override).
## Setup
### Interactive Wizard (recommended)
1. Install dependencies if you have not already:
```bash
npm install
```
2. Bundle the CLI so MCP clients point at the build output:
```bash
npm run build
```
3. Run the wizard and follow the prompts:
```bash
node build/index.js setup
```
- Stores your SignWell secrets in `~/.config/signwell-mcp/env` on Linux, `~/Library/Application Support/SignWell/MCP/env` on macOS, or `%APPDATA%/SignWell/MCP/env` on Windows with `0700/0600` permissions.
- Automatically updates Claude Desktop, Claude Code, Cursor, and OpenCode configuration files (backups are captured before each write) so you do not have to hunt for platform paths.
- Client targets:
- Claude Code: `~/.claude.json` at `mcpServers.signwell`
- Claude Desktop: `claude_desktop_config.json` at `mcpServers.signwell`
- Cursor: `~/.cursor/mcp.json` at `mcpServers.signwell`
- OpenCode: `~/.config/opencode/opencode.json` at `mcp.signwell` (Windows: `%USERPROFILE%\.config\opencode\opencode.json`)
- Uses each client's documented JSON wrapper and STDIO/local server shape so the server is visible after the client restarts.
- If a previous Claude Code install wrote the stale `~/.claude/mcp.json` `servers.signwell` entry, rerunning setup backs up that legacy file and removes only the stale SignWell entry after writing the correct `~/.claude.json` config.
- Use `--print` (or `-p`) to preview outputs without writing to disk, and `--yes --api-key=...` for non-interactive runs (CI, devcontainers, etc.).
- Pass `--clients=claude-desktop,cursor` to limit which MCP clients the wizard configures; omit for "all". Use `--timeout=<ms>` only if you need a non-default HTTP timeout.
- After bundling (`npm run build`) and publishing the package, end users can invoke the same wizard with `npx @signwell/mcp setup`. Installing globally also enables invoking `signwell-mcp setup` directly.
### Manual exports
Prefer to manage env vars yourself? Export the required values before running the server:
```bash
export SIGNWELL_API_KEY="your_api_key"
# export SIGNWELL_API_BASE_URL="https://www.signwell.com/api/v1" # optional
```
## Installation (npm)
Once the package is published to npm (GitHub: `Bidsketch/signwell-mcp`):
- Run the setup wizard without installing anything globally:
```bash
npx @signwell/mcp setup
```
- Install globally if you prefer a persistent binary:
```bash
npm install -g @signwell/mcp
signwell-mcp setup
```
After configuration, start the MCP server via `signwell-mcp` (requires Node.js v18+).
The `signwell-mcp.mcpb` file is a separate Claude Desktop extension artifact. It uses the root `manifest.json` and should be rebuilt for releases after running `npm run build`.
## Local Development Workflow
1. Install dependencies: `npm install`
2. Bundle the CLI entrypoint (required for MCP client configs): `npm run build`
3. Configure credentials: `node build/index.js setup` (or `npx @signwell/mcp setup` once published)
4. Start the MCP server locally: `npm start` (runs `node build/index.js`)
5. Open another terminal to run tests and linters before committing:
```bash
npm test
npm run typecheck
npm run lint
```
6. When using MCP inspector or other clients, point them at `npm start` (stdio).
## Running the Server
- Development entrypoint (stdio transport):
```bash
SIGNWELL_API_KEY="$SIGNWELL_API_KEY" npm start
# or run directly:
SIGNWELL_API_KEY="$SIGNWELL_API_KEY" node build/index.js
```
- CLI helpers:
- `node build/index.js --help` prints usage and env expectations.
- `node build/index.js --version` prints the current build.
- `node build/index.js setup` launches the setup wizard described above when working from source.
- Once the package is bundled/published, `npx @signwell/mcp setup` runs the wizard and `SIGNWELL_API_KEY=... npx @signwell/mcp` starts the server via the packaged binary (global installs can call `signwell-mcp ...` directly).
### MCP Inspector
Use the MCP inspector to exercise tools locally:
```bash
npx @modelcontextprotocol/inspector node build/index.js
```
## Tests
Run the quality gates in order:
```bash
npm test
npm run typecheck
npm run lint
npm run format
```
## Demo
Sample MCP inspector session (sanitized IDs):
1. **Create Draft**
```json
Tool: document_create
Input: {
"name": "Sales Agreement",
"recipients": [{ "id": "1", "name": "Alice Example", "email": "alice@example.com" }],
"files": [{ "name": "agreement.pdf", "file_url": "https://files.example.com/agreement.pdf" }]
}
Output:
{
"ok": true,
"type": "document_create",
"message": "Document draft created.",
"data": {
"id": "doc_123",
"status": "draft"
}
}
```
2. **Send Draft**
```json
Tool: document_send_draft
Input: { "document_id": "doc_123", "confirm_send": true }
Output:
{
"ok": true,
"type": "document_send_draft",
"message": "Send request accepted.",
"data": { "id": "doc_123", "status": "Sent" },
"warnings": ["Status may update asynchronously. If this response still shows Draft, call document_get after a few seconds; do not send again. Recipient send_email is an embedded-signing setting, not an email-delivery receipt."]
}
```
3. **Check Status**
```json
Tool: document_get
Input: { "document_id": "doc_123" }
Output:
{
"ok": true,
"type": "document_get",
"message": "Fetched document status.",
"data": {
"id": "doc_123",
"status": "completed",
"recipients": [{ "email": "alice@example.com", "status": "signed" }]
}
}
```
4. **Completed PDF**
```json
Tool: document_completed_pdf
Input: { "document_id": "doc_123" }
Output:
{
"ok": true,
"type": "document_completed_pdf",
"data": {
"pdf_url": "https://signwell-downloads.example.com/doc_123.pdf"
}
}
```
## Privacy Policy
This section describes the data practices of the SignWell MCP Server.
### Data Collection
- The MCP server itself does **not** collect, transmit, or store any personal data or usage analytics.
- Your SignWell API key is stored locally on your machine with restrictive file permissions (`0600`) in platform-specific secure locations:
- **macOS:** `~/Library/Application Support/SignWell/MCP/env`
- **Linux:** `~/.config/signwell-mcp/env`
- **Windows:** `%APPDATA%/SignWell/MCP/env`
### Usage & Storage
- Files provided via `file_store` are held **temporarily in memory** with a 60-minute TTL and are cleared automatically.
- All in-memory file data is also cleared on server restart.
- No persistent data storage exists beyond the credential file created during setup.
### Third-Party Sharing
- The MCP server does **not** share data with any third parties.
- All API communication goes directly between your machine and SignWell's servers (`https://www.signwell.com/api/v1`).
### Telemetry & Analytics
- The server does **not** collect, transmit, or store usage analytics or telemetry of any kind.
### Data Retention
- In-memory file storage is cleared on server restart or after the 60-minute TTL expires.
- No persistent data is retained beyond the local credential configuration file.
### Contact
For privacy inquiries, contact [support@signwell.com](mailto:support@signwell.com) or open an issue at [github.com/Bidsketch/signwell-mcp/issues](https://github.com/Bidsketch/signwell-mcp/issues).
See also the hosted privacy policy at [https://www.signwell.com/privacy/](https://www.signwell.com/privacy/).
## Resources
- MCP resources: `document://{id}` and `template://{id}` expose read-only JSON snapshots that reuse the same normalization logic as the tools, so inspectors or other MCP clients can browse previously created assets quickly.
## Attaching Files & Draft Safety
- `document_create` and `template_create_document` always set `draft: true`, ensuring nothing is emailed until you intentionally call `document_send_draft`.
- Supply files via the `files` array using either `file_url` (public URL or the link your MCP client provides when you `@`-attach a file in UIs like Claude Desktop), `file_base64`, or `resource_uri`. When a `resource_uri` is provided the MCP server automatically calls `resources/read` to pull the attachment bytes and forwards them to SignWell's `/api/v1/documents/` endpoint.
## Document Corrections and Signing Dates
- **Recipient names:** pass `name` in each `document_create` recipient. Legacy `first_name` and `last_name` are combined when `name` is omitted. Set `test_mode: true` to create a non-binding test document without API billing.
- **Draft settings:** `document_send_draft` accepts optional updates such as `name`, `subject`, `message`, `expires_in`, and `reminders` alongside `confirm_send: true`. Omitted settings are preserved. It cannot edit recipients, files, or fields, or save changes without sending.
- **Sent recipients:** call `document_get` for recipient IDs, then `document_update_recipients` with `document_id`, `confirm_update: true`, and `recipients: [{ "id": "<returned recipient ID>", "name": "Correct Name", "email": "signer@example.com" }]`. Include both name and email, keeping the unchanged value. Only recipients who have not started signing on sent/viewed/pending/bounced documents can be changed. Non-embedded recipients receive a new notification email; embedded recipients follow their existing `send_email` setting.
- **Withdraw a document:** `document_delete` with `document_id` and `confirm_delete: true` deletes the document and cancels signing in progress. Delete an incorrect request before creating a replacement to avoid two live requests.
- **Send status:** a successful send returns “Send request accepted” and attempts one status refresh. If the refresh fails, the accepted send remains successful. Status may still lag; use `document_get` after a few seconds instead of resending. `send_email` is an embedded-signing option, not a delivery receipt.
For an automatically populated, locked signing date, use these existing SignWell text tags with `text_tags: true`:
```text
{{signature:1:y}} {{autofill_date_signed:1:y}}
{{signature:2:y}} {{date:2:y::::::y}}
```
Both date forms lock the signing date. Plain `{{date:1:y}}` remains editable for dates the signer should choose. Text-tag parsing is asynchronous: inspect fields with `document_get` after processing. See [SignWell's text-tag options](https://developers.signwell.com/reference/text-tag-options), [recipient updates](https://developers.signwell.com/reference/updaterecipients), and [update-and-send limitations](https://developers.signwell.com/reference/senddocument).
## Available Scripts
| Script | Purpose |
| --- | --- |
| `npm start` | Execute the MCP server entrypoint over stdio (after `npm run build`). |
| `npm test` | Run the test suite. |
| `npm run typecheck` | Type-check the project with `tsc --noEmit`. |
| `npm run lint` | Lint source and tests using Biome. |
| `npm run format` | Apply repository formatting conventions via Biome. |
| `npm run build` | Produce an ESM bundle at `build/index.js` using esbuild. |
## Directory Layout
```
.
├── src/ # MCP server source (entrypoint + domain modules)
│ └── setup/ # Interactive setup wizard for MCP client configuration
├── test/ # Test suites
├── build/ # Bundled output (ignored in releases)
├── biome.json # Biome lint/format configuration
└── tsconfig.json # TypeScript compiler configuration
```
TDQS
Scored across 14 tools
Each tool targets a distinct action: document creation vs. template creation, file validation vs. file storage, etc. There is no ambiguity; even similar tools like document_send_draft and document_send_reminder have clearly different purposes.
All tool names follow a consistent verb_noun pattern (e.g., document_create, template_list, file_store) using snake_case. No deviations or mixed conventions.
With 14 tools, the count is well within the 3-15 ideal range. Each tool addresses a specific step in the document signing workflow without being excessive or lacking.
The tool set covers core CRUD operations for documents and templates, file handling, validation, sending, reminders, and PDF retrieval. A minor gap is the absence of a document_delete tool, but deletion may be intentionally omitted as it's not a common part of the workflow.