spotdraft-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@spotdraft-mcp List all contracts pending signature from Acme Corp"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
SpotDraft MCP Server
Give Claude direct, safety-gated access to your SpotDraft contracts.
This is a locally-hosted MCP (Model Context Protocol) server that wraps the SpotDraft Public API so you can query and drive your SpotDraft workspace -- contracts, templates, counterparties, obligations, analytics -- conversationally from Claude, instead of clicking through the UI or writing one-off scripts.
It ships as two separate servers built from one codebase:
spotdraft-read-- every read-only operation. Safe to blanket-allow; nothing here has side effects.spotdraft-write-- every mutating operation (create/send/void/invite/etc.). Every single tool requires your explicit approval on every call -- it cannot be pre-approved or run unattended.
That split exists so you can tell your MCP client "always allow reads, always ask before writes" in one line each, instead of trusting a single server's internal judgment about what's safe.
What can you do with this?
Once connected, ask Claude things like:
"List all contracts pending signature from Acme Corp"
"What's the status of contract T-4821?"
"Show me the obligations tracked on H-102"
"Draft a new NDA from the Standard NDA template for this counterparty" (write -- will prompt for approval)
"Void contract T-991, it was created by mistake" (write + destructive -- will prompt for approval)
"Run an analytics query for all contracts executed last quarter by contract type"
Claude figures out which SpotDraft API call(s) to make; you approve anything that changes data.
Related MCP server: cfr-compliance-mcp
Coverage
This server covers the v2.1 SpotDraft API family (the current/latest version) plus the small
set of v1-only endpoints that have no v2.1 successor (legal intake, native integrations,
obligation types, view-email, webhook-sample) -- 114 operations total. Superseded v2 and
old-v1 endpoints with a v2.1 replacement are intentionally excluded.
Coverage is delivered two ways:
Curated tools (~15 read + ~13 write) for the most common contract-lifecycle workflows -- listing/searching contracts, checking status, downloading, creating from a template, sending to counterparties, voiding, managing counterparties and users, etc. Tight, well-described input schemas.
A search + execute fallback, so nothing is out of reach even if it doesn't have a curated tool:
search_actions(intent, access?)-- keyword-search the full 114-operation catalog.execute_read_request(operationId, ...)-- call any read-classified operation by ID.execute_write_request(operationId, ...)-- call any write-classified operation by ID (write server only; force-gated like every other write tool).
Re-vendoring a newer OpenAPI spec and re-running npm run gen:catalog keeps this catalog current
without hand-editing generated code.
Quick start
What you'll need
Node.js 20+ and git.
A SpotDraft API credential (Client ID + Client Secret): in SpotDraft, go to Settings -> Developer Settings -> Generate API Credential. If you don't have access to that page, ask whoever administers your SpotDraft workspace to generate one for you.
An MCP-capable client (e.g. Claude Code).
1. Clone and build
git clone <this-repo-url> spotdraft-mcp
cd spotdraft-mcp
npm install
npm run buildThis produces dist/index.js, which both server modes run.
2. Configure your MCP client
Add two server entries -- one per mode -- pointing at the same built file, with
SPOTDRAFT_MODE as the only thing that differs:
{
"mcpServers": {
"spotdraft-read": {
"command": "node",
"args": ["/absolute/path/to/spotdraft-mcp/dist/index.js"],
"env": {
"SPOTDRAFT_MODE": "read",
"SPOTDRAFT_CLIENT_ID": "your-client-id",
"SPOTDRAFT_CLIENT_SECRET": "your-client-secret",
"SPOTDRAFT_REGION": "us"
}
},
"spotdraft-write": {
"command": "node",
"args": ["/absolute/path/to/spotdraft-mcp/dist/index.js"],
"env": {
"SPOTDRAFT_MODE": "write",
"SPOTDRAFT_CLIENT_ID": "your-client-id",
"SPOTDRAFT_CLIENT_SECRET": "your-client-secret",
"SPOTDRAFT_REGION": "us"
}
}
}
}On Windows, double the backslashes in the path (C:\\Users\\you\\...).
If you only ever need read access, register just spotdraft-read.
3. Set your approval rules
In your MCP client's permission settings, add:
{
"permissions": {
"allow": ["mcp__spotdraft-read__*"],
"ask": ["mcp__spotdraft-write__*"]
}
}This blanket-allows every read tool and requires per-call approval for every write tool. Every
write tool also sets _meta["anthropic/requiresUserInteraction"] = true, which forces approval on
supporting clients even if a broader "don't ask again" rule is in effect.
4. Verify
Ask Claude to "list SpotDraft users" (calls list_users, a good connectivity check) and confirm it
returns your workspace roster without any approval prompt. Then ask it to do something mutating
(e.g. draft a contract note) and confirm it does prompt for approval.
Configuration reference
Env var | Required | Purpose |
| yes |
|
| yes | SpotDraft API |
| yes | SpotDraft API |
| no (default |
|
| no | Optional |
| no | Escape hatch to override the computed base URL entirely. |
Region -> base URL mapping: us -> api.us.spotdraft.com, eu -> api.eu.spotdraft.com,
in -> api.in.spotdraft.com, me -> api.me.spotdraft.com.
Curated tools
Read (spotdraft-read) -- always safe, never prompts
Tool | What it does |
| Paginated contract search/list with common filters. |
| Display status + name for one contract by composite ID. |
| The contract's text (as plain text, structured segments, or HTML). |
| A temporary signed download URL (PDF/DOCX) -- not the file bytes. |
| Notes/comments on a contract's activity log. |
| Obligations (renewal, payment, deliverable reminders) tracked on a contract. |
| Structured metadata fields recorded on a contract. |
| Contract templates available in the workspace. |
| A template's field definitions (for building |
| Configured contract types and their IDs. |
| Counterparty organizations/individuals, paginated. |
| Full detail for one counterparty. |
| Workspace users (also the recommended connectivity self-test). |
| Tables/columns available to |
| Runs a read-only GoogleSQL query against SpotDraft's analytics tables. |
| Keyword-search the full 114-op catalog (on both servers). |
| Call any read-classified operation by ID (full-coverage fallback). |
Write (spotdraft-write) -- every call requires approval
Tool | What it does |
| Creates a contract from a template + contract_data + counterparties. |
| Emails a contract to its counterparties. |
| Uploads an existing document as a new contract headed for signature. |
| Uploads an existing document as a new contract headed for review/redlining. |
| Advances a contract to the execution/signature stage. |
| Destructive. Permanently voids a contract. |
| Invites a role/user/new-email to a contract with a specific permission level. |
| Adds a note/comment to a contract's activity log. |
| Creates/updates structured metadata fields on a contract, in bulk. |
| Creates a new counterparty (organization or individual). |
| Adds a contact person to an existing counterparty. |
| Registers a webhook subscription for contract/counterparty activity. |
| Invites a new user to the workspace. |
| Call any write-classified operation by ID (full-coverage fallback). |
Security model
Two servers, not one with internal flags. Approval tooling in MCP clients keys off the tool name
mcp__<server-name>__<tool-name>, so splitting read/write into two server names is what makes "always allow reads, always ask on writes" expressible as two simple rules.Every write tool force-gates. In addition to the two-server split, every write tool sets
_meta["anthropic/requiresUserInteraction"] = trueandreadOnlyHint: false;void_contractadditionally setsdestructiveHint: true. Read tools setreadOnlyHint: trueand never force-gate. This is belt-and-suspenders: the server split is the primary control, the tool annotations are a second, client-enforced layer that can't be bypassed by a broad allow rule. Any operation reachable throughexecute_read_request/execute_write_requestis checked against the same catalogaccessflag server-side, so the fallback path can't be used to sneak a write through the read server or vice versa.Semantic, not just HTTP-method-based, classification. A handful of
POSTendpoints with no side effects (analytics query, contract preview, sidebar query, clickwrap agreement preview, contract-download-link generation) are classified as read. Everything else that isn't aGETis write.Credentials never leave your machine and are never logged.
SPOTDRAFT_CLIENT_SECRET/SPOTDRAFT_CLIENT_IDare read from environment variables supplied by your MCP client, and are redacted from any error message or log line before it can be printed or returned to the model.Composite IDs are never mutated. SpotDraft composite contract IDs (
T-123,H-45) are sent to the API exactly as given -- never re-prefixed, re-cased, or reformatted.
How it works
You -> Claude -> spotdraft-read / spotdraft-write (this server, on your machine) -> SpotDraft API -> Your workspaceBoth server modes are built from the same dist/index.js; SPOTDRAFT_MODE decides which tool set
gets registered at startup (see src/server.ts). The operation catalog
(src/generated/catalog.ts) is generated from a vendored copy of SpotDraft's own OpenAPI spec
(openapi/spotdraft-openapi.json) by scripts/gen-catalog.ts -- re-run npm run gen:catalog after
re-vendoring a newer spec to pick up new operations.
Project structure
spotdraft-mcp/
├── package.json # bin: spotdraft-mcp-read / spotdraft-mcp-write; scripts: build/dev/gen:catalog/test
├── tsconfig.json
├── openapi/
│ ├── spotdraft-openapi.json # vendored OpenAPI spec (source of truth for coverage)
│ └── FETCHED.md # provenance / fetch date for the vendored spec
├── scripts/
│ ├── gen-catalog.ts # parses the vendored spec -> src/generated/catalog.ts
│ └── run-tests.mjs # cross-shell test runner (see "Development" below)
├── src/
│ ├── index.ts # entry point for both bin commands
│ ├── server.ts # builds the McpServer per SPOTDRAFT_MODE
│ ├── config.ts # env parsing, region resolution, validation
│ ├── http.ts # SpotDraft HTTP client: auth, retries, redaction
│ ├── generated/catalog.ts # generated operation catalog (do not hand-edit)
│ ├── tools/
│ │ ├── read/ # curated read tool modules
│ │ ├── write/ # curated write tool modules
│ │ ├── shared.ts # registration helper (annotations, error handling, pagination)
│ │ └── fallback.ts # search_actions + execute_read_request + execute_write_request
│ └── util/ (ids.ts, format.ts, errors.ts)
└── test/ # unit tests (node:test)Development
npm install # install dependencies
npm run gen:catalog # regenerate src/generated/catalog.ts from openapi/spotdraft-openapi.json
npm run build # compile TypeScript -> dist/
npm test # run the unit test suite
npm run dev # run src/index.ts directly via tsx (no build step)npm test runs scripts/run-tests.mjs, which enumerates test/*.test.ts and passes them
explicitly to Node's built-in test runner -- letting the test runner glob-scan the test/
directory itself conflicts with the tsx ESM loader hook on some Node versions.
License
MIT.
Available Tools
19 toolsexecute_read_requestExecute a SpotDraft read operationARead-only
Calls any SpotDraft catalog operation classified as 'read' (GET endpoints, plus the handful of side-effect-free POST endpoints like analytics query, contract preview, and download-link generation) by operationId. Look up the operationId and its parameter shape with search_actions first. Refuses to run any operation whose catalog access is 'write' -- use execute_write_request (on the spotdraft-write server) for those instead.
Inputs: operationId (required), body, query, path_params.
find_contracts_by_external_metadataFind contracts by external record IDARead-only
Reverse lookup: given an external record ID (for Rad AI, a HubSpot deal ID), returns the SpotDraft contracts linked to it (up to 50). Use to answer 'which SpotDraft contracts are linked to deal X'. Pairs with get_contract_external_metadata (forward lookup by contract).
Inputs: external_metadata_id (required).
get_analytics_catalogGet analytics catalogARead-only
Returns the catalog of tables/views/columns available to query via run_analytics_query. Call this first if you don't already know the schema.
Inputs: no named parameters.
get_contract_contentGet contract contentARead-only
Retrieves the text content of a contract in the requested format ('text' for a single string, 'segments' for a structured breakdown, or 'html'). Use this to read what a contract actually says. Does NOT return a downloadable file -- use get_contract_download_link for that.
Inputs: composite_id (required), format.
get_contract_download_linkGet contract download linkARead-only
Generates a temporary, signed download URL for a contract's file (PDF or DOCX). Returns the link -- does NOT stream the file's bytes into the conversation. This is a POST endpoint with no persisted side effect (it only mints a short-lived URL), so it is classified as a read operation.
Inputs: composite_id (required), format.
get_contract_external_metadataGet contract external metadataARead-only
Reads the external-system link recorded on a contract -- for Rad AI this is the linked HubSpot deal (id, integration_name, record_type). Returns an empty/null shape if the contract isn't linked. Pairs with set_contract_external_metadata (write) and find_contracts_by_external_metadata (reverse lookup).
Inputs: contract_id (required).
get_contract_key_pointersGet contract key pointersARead-only
Lists the key pointers (extracted/structured metadata fields, e.g. effective date, term length, renewal terms) recorded against a contract. Pairs with set_contract_key_pointers (write).
Inputs: composite_id (required).
get_contract_obligationsGet contract obligationsARead-only
Lists the obligations (e.g. renewal, payment, deliverable reminders) tracked against a contract.
Inputs: contract_id (required).
get_contract_statusGet contract statusARead-only
Returns the display status and contract name for one contract, looked up by composite ID. This is the same lookup the Rad AI HubSpot integration uses. Does NOT return full contract details -- use get_contract_content or list_contracts for that.
Inputs: composite_id (required).
get_counterpartyGet counterpartyARead-only
Returns full details for a single counterparty by ID, including addresses and contacts summary.
Inputs: counterparty_id (required).
get_template_metadataGet template metadataARead-only
Returns the field definitions (contract_data keys, types, and options) for a specific contract template. Use this before calling create_contract to know which contract_data keys the template expects.
Inputs: template_id (required).
list_contract_notesList contract notesARead-only
Lists the comments/notes left on a contract's activity log, in SpotDraft's UI these appear as 'notes'. Pairs with create_contract_note (write) for adding a new one.
Inputs: contract_id (required).
list_contractsList contractsARead-only
Lists contracts in the SpotDraft workspace, paginated. Supports free-text search and a small set of common filters. Returns each contract's id, name, display status, contract type, and key dates. For filters not exposed here (there are dozens of filter__[$op] variants in the full API), use search_actions to find v2.1_public_contracts_retrieve and call it via execute_read_request.
Inputs: page, limit, query, extra_filters, +2 more.
list_contract_typesList contract typesARead-only
Lists all contract types configured in the workspace (e.g. NDA, MSA, SOW), with their numeric IDs. Use the returned ids with list_contracts' contract_type_id filter or upload_contract_for_signing's contract_type_id field.
Inputs: no named parameters.
list_counterpartiesList counterpartiesARead-only
Lists counterparty organizations/individuals in the workspace, paginated, with optional email and status filters.
Inputs: page, limit, status, client_email_address.
list_templatesList templatesARead-only
Lists contract templates available in the workspace, with optional filters by counterparty type and tags. Use get_template_metadata for a specific template's field definitions.
Inputs: tags, include_archived, exclude_multi_party.
list_usersList workspace usersARead-only
Lists users in the SpotDraft workspace, with optional filters by email or name prefix. This is also the recommended connectivity self-test for this server -- if it returns a roster, credentials and region are configured correctly.
Inputs: page, limit, user_name, user_email.
run_analytics_queryRun analytics queryARead-only
Runs a single read-only GoogleSQL SELECT query (optionally with WITH/UNION) against SpotDraft's analytics tables, returning result rows. Max query length 10,000 characters. This is a POST endpoint with no side effects (a query, not a mutation), so it is classified as a read operation. Use get_analytics_catalog first to see available tables/columns.
Inputs: query (required), user_scoped.
search_actionsSearch SpotDraft actionsARead-only
Searches the full SpotDraft API catalog (114 in-scope operations across v2.1 + v1-orphan endpoints) by keyword or tag. Returns matching operations with operationId, method, path, access level ('read' or 'write'), summary, and parameter shape (path/query/body). Use this to find the right operationId before calling execute_read_request or execute_write_request. This tool does NOT call the SpotDraft API itself -- it only searches the local catalog.
Inputs: intent (required), access.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 19 tools
Each tool has a clearly distinct purpose, with detailed descriptions that minimize ambiguity. For example, get_contract_content and get_contract_download_link are explicitly differentiated by output format and use case.
Tool names follow a consistent verb_noun pattern with underscores (e.g., list_contracts, get_contract_content, run_analytics_query). No mixing of conventions, making it easy for an agent to predict naming.
With 19 tools, the server is slightly over the typical well-scoped range of 3-15, but each tool serves a distinct read operation for a comprehensive API. The count is justified by the breadth of the domain.
The tool surface covers a wide range of read operations including contracts, counterparties, templates, analytics, and API catalog search. There are no obvious gaps for the stated read-only scope, and the inclusion of search_actions allows agents to discover additional endpoints.
Related MCP Connectors
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
MCP server for The Chancery Lane Project's climate-aligned contract clause knowledge graph.
B2B, GovCon & LegalTech MCP server for live RFPs, contract parsing, compliance & proposal tools.
JusPronto is case-management software for Brazilian law firms. Its remote MCP server (OAuth 2.1 with PKCE, per-permission scopes, audit log) lets Claude and ChatGPT read the firm's own cases, deadlines, agenda, recent court movements and case files with the page cited. Write actions require the lawyer's approval. Requires a JusPronto account.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server that connects Clio Manage to Claude via OAuth, enabling law firm management tasks like matter lookup, time tracking, billing, calendar, and document retrieval through natural language.41MIT
- FlicenseAqualityCmaintenanceA production-quality MCP server that exposes the official eCFR API as structured tools for AI-driven contract compliance, enabling retrieval of relevant Code of Federal Regulations by clauses extracted from contracts.8-
- FlicenseAqualityDmaintenanceMCP server for first-pass legal contract review. It loads txt/docx/pdf contracts, detects standard clauses, flags heuristic risks, summarizes, and compares agreements.8-
- FlicenseBqualityDmaintenanceA standalone MCP server that enables Claude Desktop to manage Clio legal practice matters, documents, billing, and more via ~46 tools, with secure OAuth and audit logging.46-