← All posts

Driving Vocion from Claude Code

A working setup for the v2.16 MCP surface in Claude Code: registration without leaking a token, exact CRM counts, on-demand call transcripts and mail threads, and writes that always wait for a human.

Vocion Teamvocion-v2.16.0

Vocion v2.16.0 serves the agent domain-tool registry over MCP. This post is the practical half: wiring it into Claude Code and the patterns that make it useful in a working session — pulled from our own dogfooding, where Claude Code sessions in a sales-collateral repo now read the CRM, pull call transcripts, and verify email threads through Vocion instead of screen-scraping or guessing.

Register it — at user scope, not in the repo

Issue a token on your Vocion install, then:

claude mcp add --scope user --transport http vocion \
  https://your-install/api/mcp \
  --header "Authorization: Bearer $VOCION_MCP_TOKEN"

Two deliberate choices here. User scope keeps the registration in ~/.claude.json, not in a project .mcp.json — if any tool in your pipeline ships the repo's files (static deploys are the classic case), an in-repo token is a published token. And the token itself belongs in a chmod 600 env file outside every repo, referenced when you need it — never pasted into project files. claude mcp list should show vocion … ✔ Connected.

For a local checkout instead, the stdio transport skips tokens entirely: claude mcp add vocion -- npm --prefix /path/to/checkout run mcp:serve with VOCION_ORG_ID set.

What a session can do

Exact counts, not vibes. get_hubspot_deals / _contacts / _companies return a real total from COUNT(*), facets that make filter values discoverable, and explicit pagination. Ask "how many open deals are in the Proposal stage?" and Claude Code answers from the mirror with a number that is actually true — search_knowledge is for "what was said", and can never count.

The verbatim transcript of that call. get_zoom_transcript takes a meeting UUID (from the recording share link) or numeric id (from the invite). If the transcript is already synced, the answer comes from the mirror with zero API calls; if not, it's fetched live from the Zoom cloud account and upserted into the index, so knowledge search sees it from then on. The response says which happened: source: "cache" or "live".

The full email thread, not the snippet. get_gmail_thread takes a thread id or any message id in it and returns every message, headers and bodies. It TTL-caches (15 minutes by default) — pass force_refresh: true when you're checking whether a reply just landed.

Freshness on demand. Quoting a count in a document? freshen_source with "hubspot" (or "gmail", "zoom") runs an incremental sync first, so the mirror reflects the last hour, not the last cron.

Writes that wait. propose_action drafts a gmail.send or hubspot.update — and never executes it. The proposal lands PENDING in Vocion's review queue under an agent principal; a human approves in the dashboard before anything reaches the outside world. Claude Code should report "queued for approval", never "sent". This holds regardless of the token's own permissions.

Whose tools? The agent_slug switch

Every bridged tool runs as an agent — by default your workspace lead. That agent's connected sources decide the surface: no Zoom source, no get_zoom_transcript. Pass agent_slug on any call to run as a different agent, re-gated per call. This isn't a workaround, it's the access model: agents are the unit of scoping, and the MCP client inherits it instead of bypassing it.

Patterns that hold up

Reference

The complete tool table, cache semantics, token CLI, and extension guide: MCP reference.