StartConceptsPlaybooksFeature docsAPI & MCPChangelog
← All feature docs
Feature docs · /settings/api-keys

API Keys & MCP

Issue a Bearer token, paste it into Claude Cowork or any MCP-compatible agent, and your brain becomes scriptable. Six tools cover the verbs that matter: log a capture, update a prospect, append to a plan, mark a meeting outcome, read an account, pull a brief.

Overview

The API keys surface turns salesascode into a tenant-scoped MCP server. Issue a key at /settings/api-keys, paste it into Claude Cowork (or any MCP client), and the agent gets six tools it can call against your account — every write hits the same panel_data store the in-app panels use, so external and in-app activity stay in sync.

Different from Connect to Cowork — that's your control-plane home (plan, entitlements, install steps). API keys are the credential the plugins actually authenticate with.

How it helps you

How to use it

  1. Open /settings/api-keys → click + New key.
  2. Name it (e.g. "Claude Cowork"), pick the scopes the agent needs.
  3. Copy the key — it's shown once. Paste it into the agent's credential field.
  4. Point the agent at https://<your-domain>/api/v1/mcp as the MCP server URL.
  5. The agent calls tools/list to introspect, then tools/call to invoke. Every call lands in your audit log.

The six tools

// capture.write

log_capture

Drop a free-form note or transcript into the brain. Optionally attach to an account or prospect.

// prospect.write

update_prospect

Create or update a prospect (name, title, email, notes, arbitrary fields).

// plan.write

add_to_plan

Append content to a named section of an account plan ("next_steps", "risks", "champion_notes").

// meeting.write

mark_meeting_outcome

Record the outcome of a meeting ("advance" / "stall" / "lost" or free-form) with notes + next step.

// account.read

read_account

Read an account record. Optionally pull in the plan, recent meetings, or recent captures.

// brief.read

pull_brief

Structured "today / week" summary — accounts active, recent captures, recent meetings, open plan sections.

// usage.write

POST /api/ingest/usage

Push product-usage / consumption data for an account by domain (seats used, active users, contract terms, usage signals). A vendor-neutral REST endpoint — point your warehouse job or ETL at it and the pre-call brief renders consumption-vs-contract, each line cited to the ingested telemetry.

// meddpicc.write

set_meddpicc

Put MEDDPICC evidence on an opportunity by id — any of the eight dimensions as short text. Provided dimensions merge onto the existing record; others are left untouched. This is how a deal earns the evidence the curiosity engine reads to find the gaps worth asking about, without a CRM.

Control-plane tools (Sales as Code plugins)

The Sales as Code Cowork plugins call five more tools against this same MCP endpoint. They are the bridge between the work surface (Cowork) and the control plane (salesascode.com): every skill verifies the licensed session first, then reports run telemetry and brain state when it finishes. These tools need no extra scope — a valid key acting on its own account is enough.

// session

verify_session

Returns the account, plan, and entitled plugins. Every skill calls this first and stops if it errors.

// license

check_entitlement

Is this account licensed for a named plugin? Skills stop and ask the user to connect their account if not.

// telemetry

emit_telemetry

Record a run event — plugin, skill, counts, outcome, duration. Metadata only. Powers the dashboard rollup.

// brain

sync_brain

Push brain state for a scope (signal-weights, icp-registry, decision-log, funnel-brain, ...). No raw contact PII by default.

// config

pull_config

Pull the account's plan, entitled plugins, and feature flags so a skill can adapt at run start.

These back the per-account rollup dashboard. The plugins and the full contract live in cowork-marketplace/ (see docs/control-plane-mcp.md).

Entitlement is now enforced per tool. Any tool that reads or writes your data or brain — the six data verbs plus emit_telemetry, sync_brain, start_run, run_heartbeat, connect_integration, and the studio tools — requires the account to hold at least one active paid entitlement (a plugin, bundle, suite, membership, or team seat). Without one, the server returns not_entitled (MCP error -32003 / HTTP 403) with a pointer to /pricing. The onboarding trio stays open on purpose: verify_session, check_entitlement, and pull_config are always callable so a new user can connect a plugin and check status before buying. Entitlement is additive to the scope check — a call must clear both.

Security model

Use cases

// cowork

Claude Cowork integration

Have Cowork log captures and update prospects as you work — your salesascode brain stays current without context-switching.

// scripts

Cron-driven workflows

A nightly script pulls your brief, summarizes it, posts to Slack. Or a meeting bot logs the outcome into your account plan automatically.

// custom agents

Build your own agent

Wire any Claude API loop to the MCP server. Tools/list discovers everything; you don't ship custom integrations.

// team automation

Team-wide workflows

An ops team can issue per-process keys ("post-call writer", "weekly forecaster") with the minimum scopes each needs.

Transports: HTTP, REST, and stdio

HTTP is the canonical MCP transport — point any HTTP MCP client at /api/v1/mcp. Every tool is also a plain REST endpoint (below). For clients that only speak stdio (Claude Desktop, some Cowork setups), the repo ships a thin local bridge that forwards stdio JSON-RPC to that same HTTP endpoint:

  1. Issue a key here and set it as SALES_AS_CODE_API_KEY.
  2. Run npm run mcp:stdio, or point Claude Desktop's claude_desktop_config.json at node scripts/mcp-stdio.mjs with the key in the server's env block.
  3. The bridge relays each message to /api/v1/mcp — same tools, same scopes, same audit log. It holds no logic of its own.

Full config example: /docs/api → stdio.

Team keys

By default a key is per-user — it authorizes against your own plan. A team owner can toggle Issue as a team key in the New key dialog to mint a team key instead. A team key still writes into the owner's workspace, but the control-plane tools (verify_session, check_entitlement, pull_config) resolve entitlements against the team's plan: the union of the owner's grants and every plugin the team's seat packs license. Per-user keys are unchanged and keep working exactly as before.

OAuth-provider mode (optional)

Pasting a key is the default. When a deployment enables it (MCP_OAUTH_ENABLED=true), a client can instead obtain access through a standard OAuth 2.0 authorization-code + PKCE flow — you approve it on a consent screen using your existing login, and the client never sees a key you had to copy. The clever part: the OAuth access token is a managed key. It's minted as a scoped api_keys row, shows up in this list as OAuth (<client>), and you revoke it here like any other.

The HTTP REST surface

The same tools are also available as plain REST endpoints if you prefer not to speak MCP. POST JSON to /api/v1/tools/<name> with a Bearer auth header. Same Bearer key, same scopes, same audit log.

curl -X POST https://salesascode.com/api/v1/tools/log_capture \
  -H 'authorization: Bearer sak_…' \
  -H 'content-type: application/json' \
  -d '{"source":"cowork","text":"Acme champion confirmed budget for Q3"}'

Related

// deep walkthrough · 2 min