MCP server
The agent drives. You approve.
The whole suite is built for an agent-first workflow. Three MCP servers expose it — pick by what you want the agent to do, or use the HTTP API for frameworks that don't speak MCP.
| If the agent should… | Use |
|---|---|
| Extract, draft, lint, compare, review, convert, query the vaults | contract-ops-mcp — one server, all nine CLIs |
| Send, sign, track, and verify signatures (human-gated) | sign-cli's MCP — the signing surface |
| Run a pre-signature drift gate only | compare-cli-mcp |
| Integrate from a framework that doesn't speak MCP | the /v1/* HTTP API |
All three servers — contract-ops-mcp, sign-cli, and
compare-cli-mcp — are published on the official
MCP Registry (namespace
io.github.DrBaher/*), so any MCP-aware runtime can discover them.
One connection, the whole suite — contract-ops-mcp
Wire it up once; it discovers your installed CLIs and exposes curated tools (plus catalog / run escape hatches), all riding the suite's uniform --catalog json contract.
{
"mcpServers": {
"contract-ops": { "command": "npx", "args": ["-y", "contract-ops-mcp"] }
}
}
Tools: extract_contract, lint_contract,
compare_versions, fill_template,
convert_to_pdf, review_nda,
template_vault_*, contract_vault_*, and read-only
verify_signature / verify_receipt /
audit_show — plus catalog(cli),
run(cli, args), and suite_status. File access is confined
to CONTRACT_OPS_MCP_BASE_DIR. Needs the CLIs installed (install page,
or the all-in-one container). Repo.
Signing is deliberately not in this server — it exposes only sign-cli's read/verify ops. To request or apply a signature, use sign-cli's own MCP below, where the per-signer human gate stays intact.
sign-cli's MCP — the signing surface
The deeper, signing-specific server: 19 tools for sending, tracking, detection, stamping, and verification — with the human gesture gated behind a per-signer token.
Start the server
# Boots the MCP server on stdio. Wire it into any MCP-aware client.
sign mcp serve
# Or via npx, no install required:
npx @drbaher/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):
{
"mcpServers": {
"sign-cli": {
"command": "npx",
"args": ["-y", "@drbaher/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:
{
"mcpServers": {
"sign-cli": {
"command": "npx",
"args": ["-y", "@drbaher/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 | Verify a signed PDF's PKCS#7: /ByteRange digest match and the signature value against the signer cert's public key (RSA/ECDSA), 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:4000/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
signtool 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 withSIGN_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.