# Vruum MCP (`@vruum/mcp`) [![npm](https://img.shields.io/npm/v/@vruum/mcp)](https://www.npmjs.com/package/@vruum/mcp) [![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE) [![registry](https://img.shields.io/badge/MCP%20registry-ai.vruum%2Fmcp-6E56CF)](https://registry.modelcontextprotocol.io) Official MCP access to [**Vruum**](https://vruum.ai), the AI revenue platform. Give your agent the whole revenue motion — research prospects, build pipeline, run email and LinkedIn outreach, triage replies, manage deals through close, and read Stripe-backed revenue truth — through **35 compound tools** rather than a sprawl of endpoints. Outreach runs inside **objectives**: a goal, the people it targets, and the policy for reaching them. This package is a **stdio bridge**: it serves the tool surface locally (no credentials needed to introspect) and proxies execution to `https://api.vruum.ai/mcp` under your token. Every call is authorized server-side — the bridge grants no authority your Vruum account doesn't already have. > [!TIP] > **Using a client that supports remote MCP? Connect directly instead.** > Claude Code, Claude Desktop, Cursor, Codex and friends should point straight at `https://api.vruum.ai/mcp` (OAuth 2.1). Fewer moving parts and no token in an env var. This bridge exists for **stdio-only clients** and for **credential-free tool introspection**. See [vruum.ai/docs/mcp](https://vruum.ai/docs/mcp). ## Quickstart You need Node 20+ and a Vruum account. Create a personal access token in the web app under **Settings → API tokens** (`vk_live_…`).
Claude Desktop / Claude Code — claude_desktop_config.json or .mcp.json ```json { "mcpServers": { "vruum": { "command": "npx", "args": ["-y", "@vruum/mcp"], "env": { "VRUUM_MCP_TOKEN": "vk_live_…" } } } } ```
Cursor — ~/.cursor/mcp.json ```json { "mcpServers": { "vruum": { "command": "npx", "args": ["-y", "@vruum/mcp"], "env": { "VRUUM_MCP_TOKEN": "vk_live_…" } } } } ```
Codex CLI — ~/.codex/config.toml ```toml [mcp_servers.vruum] command = "npx" args = ["-y", "@vruum/mcp"] env = { VRUUM_MCP_TOKEN = "vk_live_…" } ```
Already use the Vruum CLI? — no token needed here ```sh npx @vruum/cli login --token vk_live_… ``` The CLI needs Node 22+. Credentials land in `~/.vruum/credentials` and the bridge picks them up automatically — omit the `env` block entirely.
Verify it works without configuring anything: ```sh npx -y @modelcontextprotocol/inspector --cli npx -y @vruum/mcp --method tools/list ``` ## What you can ask for Once connected, these are ordinary requests to your agent: | You say | What happens | | --- | --- | | *"What should I work on today?"* | `get_daily_briefing` — pending approvals, new replies, stalled deals, warm paths, one recommended next action | | *"Review my outreach drafts"* | `get_outreach_review` → you approve, edit, or reject each one | | *"Research Acme Corp and tell me if they fit"* | `research` — website, funding, careers signals, ICP match with reasoning | | *"Find a warm intro to this person"* | `find_warm_path` — separates verified paths from unverified connector candidates | | *"Which objectives are actually working?"* | `get_objective_outcomes` — contacted, replied, and meetings booked, compared across objectives | | *"What's at risk in my pipeline?"* | `inspect_pipeline` — the 5 most at-risk deals, risk-first | | *"Draft a LinkedIn post about X"* | `manage_content` — your agent writes it, you approve, Vruum schedules and publishes | Your harness authors outreach copy, replies, LinkedIn posts, and comments through their review surfaces. It can also chat with Vruum through `manage_assistant` (`start_conversation`, `append_message`): the same chat as the app's floating panel, which reads your records and applies reversible record changes with Undo. The chat does not draft or send messages. ## Tool surface 35 compound tools. Read operations inspect saved data; write operations mutate it. Some writes buy provider work or produce external effects. Each tool describes its own authorization and retry contract. | Area | Tools | | --- | --- | | **Daily operating** | `get_daily_briefing` · `get_next_actions` · `inspect_pipeline` | | **Search & research** | `search` · `fetch` · `research` · `research_lookup` · `import_prospects` · `find_warm_path` | | **People** | `get_person_360` · `manage_person` | | **Relationship identity** | `get_network_identity_review` · `manage_network_identity_resolution` | | **Objectives & outreach** | `inspect_objective` · `get_outreach_review` · `manage_messages` · `manage_outreach` · `manage_relationship_action` | | **Engagement & content** | `get_engagement_review` · `manage_engagements` · `get_content_review` · `manage_content` | | **Performance** | `get_objective_outcomes` · `get_performance_metrics` | | **Deals** | `get_deal_360` · `manage_deal` | | **Revenue** | `get_revenue` · `manage_revenue` | | **Accounts & knowledge** | `manage_account` · `manage_kb` | | **Imports & assistant** | `manage_history_import` · `manage_assistant` | | **Workspaces, config & skills** | `get_operator_companies` · `manage_settings` · `skill` | `manage_outreach` also creates, configures, launches, and pauses objectives; `inspect_objective` reads an objective's setup, audience, forecast, and sourcing plan. No tool mixes reads with writes: `research_lookup` holds the external lookups (work email, LinkedIn profile, company website, careers page, LinkedIn people search), which can spend provider credits or LinkedIn budget. `get_operator_companies` lists the workspaces your login can act in; it is not limited to Vruum staff. Full schemas, descriptions and MCP safety annotations live in [`tools.json`](tools.json) — generated from the live server definition, never hand-edited. The current package also carries the retained-email decision instructions in `manage_messages`. A saved email uses its displayed Action version, proposal revision, and fingerprint. Approval is not a delivery receipt; changed content requires new work. Chat with Vruum through `manage_assistant`. `start_conversation` takes `payload={request_id, message, context?}` and waits up to 50 seconds for the answer; `append_message` takes `id=` and the same payload. The result names the chat, the turn's state, the question, the answer, `changes` (each record change the chat applied, with its Undo state) and `cards`. A turn still running after 50 seconds returns `running`; read the chat later with `inspect_assistant action=read id=`. Actions Undo cannot reverse, and actions that reach a customer or spend, come back as a card with the exact call, and the turn returns `awaiting_approval`. `manage_assistant action=decide_card id= payload={decision: approved|declined}` decides one, only with the user's own answer: approved runs that exact call once under your credentials, declined never runs it; it waits up to 50 seconds for the turn. `manage_assistant action=undo id=` runs a change's exact inverse and is refused when the record was edited since; `action=rate id=` rates an answer. Keep the same `request_id` on a retry after an uncertain response: the server runs each request once. ## Configuration | Env var | Meaning | Default | | --- | --- | --- | | `VRUUM_MCP_TOKEN` | Vruum personal access token | falls back to `VRUUM_TOKEN`, then `~/.vruum/credentials` | | `VRUUM_MCP_URL` | Hosted MCP endpoint | `https://api.vruum.ai/mcp` | | `VRUUM_MCP_TIMEOUT_MS` | Per-call timeout — research and imports run long | `300000` | | `VRUUM_CONFIG_DIR` | Credentials directory | `~/.vruum` | ## How it works ``` your agent ──stdio/JSON-RPC──▶ @vruum/mcp │ tools/list ──────┤ served locally from tools.json │ (no network, no credentials) │ tools/call ──────┴──HTTPS+Bearer──▶ api.vruum.ai/mcp (authorized server-side) ``` Listings are a **static snapshot** bundled at release. That's what makes credential-free introspection possible, and it means a newly added tool won't *appear* until the next release — calls still execute correctly, since they proxy through. In the monorepo, a snapshot test fails any change that lets `tools.json` drift from the server definition, so a release never ships a stale listing. ## Safety and credentials - **Server-side authorization.** The bridge adds no permissions. Your token is exactly your Vruum account, and role/tenant checks happen on the server. - **No automatic retries.** A failed `tools/call` is never replayed. Many of these tools send outreach or spend money, and an ambiguous failure may mean the server already executed — a silent retry could double-send. The connection is discarded, the error says so, and your agent decides whether re-running is safe. - **Your token never leaves your machine** except as a `Bearer` header to `api.vruum.ai`. > [!WARNING] > **The bridge picks up ambient credentials.** With no `VRUUM_MCP_TOKEN` set it falls back to `~/.vruum/credentials`. If you are logged in with the Vruum CLI, then running this server — via the MCP Inspector, a client, or a script — executes **against your real account and real data**. Write tools will really write. > > To poke at it with no credentials, pass an explicit env that reaches the process: > > ```sh > env -i PATH="$PATH" HOME=/tmp/empty node dist/index.js > ``` > > Note that MCP clients following the SDK default only forward an allowlist (`HOME`, `PATH`, `SHELL`, `TERM`, `USER`, `LOGNAME`) to spawned servers — so setting `VRUUM_CONFIG_DIR` in your shell may be **stripped before it reaches the bridge**, while `HOME` survives and the credentials file is found anyway. Set credentials in the client's own `env` block instead. ## Development This repo is a **build artifact of the Vruum monorepo**, resynced automatically on release. `tools.json` is generated from the server definition, and a snapshot test in the monorepo fails when the two differ. Between releases, the hosted server can be ahead of this snapshot. ``` src/index.ts the bridge — token resolution, static listings, proxied calls tools.json generated tool surface (do not edit by hand) test/ black-box tests: spawn the built binary, speak raw JSON-RPC ``` ```sh npm install npm test # builds, then runs the black-box suite npm run typecheck ``` Tests drive the built binary over stdin/stdout and assert **at the wire level** rather than through an SDK client — an SDK-mediated test hides protocol mistakes, since it will happily hand back a result object whether the server returned `result` or `error`. They cover the initialize handshake, credential-free listing, protocol-vs-execution error semantics, cursor rejection, capability declaration, and stdout hygiene. **Issues and PRs are welcome here.** Maintainers apply accepted changes upstream in the monorepo and they flow back on the next sync — so a merged fix here may appear as part of a sync commit rather than your original one. Changes to `tools.json` must come from the generator, not by hand. ## Links [Vruum](https://vruum.ai) · [MCP docs](https://vruum.ai/docs/mcp) · [Getting started](https://vruum.ai/docs/getting-started) · [CLI reference](https://vruum.ai/docs/cli-reference) Registry entry `ai.vruum/mcp` · Claude & Codex plugin [`vruum-gtm/skills`](https://github.com/vruum-gtm/skills) ## License [MIT](LICENSE)