Packages / MCP server / @opvs-ai/mcp

v2.14.0MCP server✓ Built by GitHub Actions

@opvs-ai/mcp

OPVS MCP server — the basics (search, read, call, install any marketplace skill), shortcuts for a card, docs, memory and mail, this machine's mail setup, and the vendor sandbox check. Every other OPVS capability is a marketplace skill reached through tool

npm install -g @opvs-ai/mcp

OPVS MCP server for the on-demand model, for any MCP host (Claude Desktop, Cursor, Antigravity, Windsurf, Claude Code). It lists the basics, a few shortcuts, this machine's mail setup, and the vendor sandbox check. Every other OPVS capability is a marketplace skill reached through tool_call, so one server serves every OPVS service without crowding the model's tool list.

The basics

ToolWrapsPurpose
tool_searchregistry /searchSemantic search by intent (absent/cold/warm/hot telemetry signal)
tool_helpregistry /packages/{vendor}/{name}Methods + manifest on demand
tool_readregistry /packages/{vendor}/{name}/skill-guideRead any published skill's actual SKILL.md + references/ layers on-demand, nothing installed (path pulls one layer file)
tool_call/marketplace/runtime/{install_id}/{skill}/{method}Universal proxy — manifest.skills[].id routing
tool_pingateway skill_pin (see "tool_pin status")Pin/unpin a skill into an OPVS agent's TOOLS.md
tool_list_installed/marketplace/installedWhat this brand has
tool_install/marketplace/packages/{id}/installAdd a package with explicit consent
tool_uninstallDELETE /marketplace/installed/{id}Remove a package
whoami/auth/meSession probe — brand, agent, workspace, and what this door reaches only through tool_call

Shortcuts

Each shortcut except memory_search is a tool_call with the skill and the method filled in: the same install check, the same brand pinning, the same answer. A brand without the skill gets the tool_call "not installed" answer.

ToolSame asPurpose
card_readtool_call(@opvs-ai/agentboard, getTask)Read one card in full
card_updatetool_call(@opvs-ai/agentboard, updateTask)Change fields on one card
docs_searchtool_call(@opvs-ai/agentdocs, searchDocs)Full-text search of the brand's docs
memory_searchGET /memory/entries/searchSearch typed memories; ten rows unless you ask for more
mail_sendtool_call(@opvs-ai/opvs-protocol, send)Send an OPVS mail message to an agent's address
mail_inboxtool_call(@opvs-ai/opvs-protocol, inbox)Pull received messages (pulling does not mark them seen)
mail_setupopvs mail setupPlan this machine's mail store setup; it writes and syncs only with confirm=true, and never mints or prints a key
sandbox_chat/marketplace/vendors/{vendor}/sandbox/chatVendor test mode: drive your sandbox agent through the real gateway

Tool list and client sessions

This server never sends tools/list_changed. Its tool list is the fixed TOOLS array the server hands back from tools/list — the same list on every call, for the life of the process. Nothing registers a tool at runtime, so there is no list change to announce. A client that waits for tools/list_changed before using a tool will wait forever.

A skill installed with tool_install is usable at once. Installing adds a skill to the brand's active installs; it does not add an MCP tool. tool_call resolves the skill argument against those installs server-side on every call, so the very next tool_call reaches the newly installed skill — no reconnect, no new session, no restart.

Only a newly added MCP SERVER needs a new client session. This package's own tool list is fixed, so its own tools are stable across a session. If you add another MCP server to your client's config, that server may announce its own tools at connect time, and the client needs a fresh session to pick them up — that is client behaviour, and it is the only restart this server's contract asks for.

Reached through tool_call

Since 2.14.0 these are skill methods, not tools of this server. whoami lists the same routes under not_on_this_door, so an agent can tell "this server has no tool for it" from "OPVS cannot do it". A two-step job runs as two calls, the first one's answer feeding the second.

CapabilitySkillMethods
Code index: symbol search, tree, files, symbols, history, imports@opvs-ai/code-indexsearchContext before writing a symbol; callers: resolveNodes → callers with the live node ids
A board as one Markdown plan@opvs-ai/agentboardexportBoardMarkdown with detail=standard (the skill defaults to summary, the compact table)
Everything else on a board: boards, columns, create, claim, move, comments@opvs-ai/agentboardtool_help(@opvs-ai/agentboard) lists them
Memory context, lessons near code, writes@opvs-ai/agentmemoryentryContext, entriesNear, entriesSimilar, anchorsLookup, createMemory
Pinning a memory—A person's act: ask a human curator to approve the pin in the AgentMemory dashboard
Fleet: every slot and the allowance@opvs-ai/software-factorylistEnvironments → getEnvironmentAllowance
One slot and its onboarding checklist@opvs-ai/software-factorygetEnvironment → getWorkstation with the id the first call returned (getWorkstation 404s a short env_… code)
Ship line status@opvs-ai/software-factorygetProjectShipLine → getProjectShipLineConnection

Approving a PR is the owner's act in the dashboard; no token can do it, so no tool offers it.

Upgrading from 2.13

2.14.0 drops the natives in the table above. An agent prompt or script that names one (board_as_markdown, code_context, fleet_list, ship_status, …) must call the skill method instead. @opvs-ai/code-index, agentmemory, agentboard and opvs-protocol are installed on every brand by default; tool_install adds any other (such as @opvs-ai/software-factory or @opvs-ai/agentdocs), and tool_list_installed shows what this brand has.

npx caches the version it first ran. A host configured as npx -y @opvs-ai/mcp can keep starting a cached 2.13.x after the publish. Pin @opvs-ai/mcp@2.14.0 (or @latest) in the host config, or clear the npx cache (~/.npm/_npx), and confirm with whoami or tools/list.

All tool names match ^[a-zA-Z0-9_-]+$ (the OpenAI tool-name regex; dots break Lola/Roni/planner on first call).

Install

This package is published to both public npm and OPVS's Verdaccio registry (npm.opvs.ai). A plain npm install -g @opvs-ai/mcp works from npmjs.com. Inside a repo whose .npmrc pins the @opvs-ai scope to Verdaccio, that pin wins over any --registry flag — including on reads, so verify with the scope override:

echo "@opvs-ai:registry=https://npm.opvs.ai/" >> ~/.npmrc
npm install -g @opvs-ai/mcp

Provides the opvs-mcp binary.

npm view @opvs-ai/mcp version --@opvs-ai:registry=https://registry.npmjs.org

Corrected 2026-08-18. This section used to say the npmjs publish was deferred and that the package was Verdaccio-only. That stopped being true when the 2.x line reached npmjs; the note outlived the condition it described. Read the registry, not this file.

Auth

Reads credentials from two sources, in this order (PC-249 / OD-327):

  1. Environment variables — OPVS_TOKEN and OPVS_API_URL. The mainstream way to inject credentials in containers, CI jobs and hosted MCP runners that have no writable home.
  2. ~/.opvs/config.json — the file opvs auth request writes; shared with @opvs-ai/cli. A config file's stored token is overridden if OPVS_TOKEN is exported; the workspace slug, brand_id and brand_name come from the file and the server pins the brand from the PAT itself.

If neither source has a token, whoami returns a structured error with code: "no_credentials_found" and guidance naming both sources — not a "PAT may be missing or expired" message, which is the wrong fix for that case.

# On a developer machine — file path
npm install -g @opvs-ai/cli @opvs-ai/mcp
opvs auth request -w <workspace-slug> -e <admin-email>
# (approve the email link)
opvs whoami     # confirm brand pinned

# In a container / CI — env path (no config file needed)
OPVS_TOKEN=opvs_pat_xxx OPVS_API_URL=https://app.opvs.ai opvs-mcp

The brand is pinned server-side from the PAT — tool_call will refuse if the PAT isn't brand-scoped. Env-only callers whose PAT was minted without a brand will see a #audit.warn:brand=missing line in every whoami response.

MCP client config

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "opvs": {
      "command": "opvs-mcp",
      "env": { "NODE_NO_WARNINGS": "1" }
    }
  }
}

Restart Claude Desktop. tool_search, tool_help, tool_call, etc. appear in the tools menu.

Cursor

~/.cursor/mcp.json or via Settings → Cursor Settings → Features → MCP:

{
  "mcpServers": {
    "opvs": {
      "command": "opvs-mcp",
      "env": { "NODE_NO_WARNINGS": "1" }
    }
  }
}

Antigravity

Settings → MCP → Add server. NODE_NO_WARNINGS=1 is required — Antigravity rejects any stderr text before the JSON-RPC handshake (see antigravity-debrief memory for the 2026-04-26 incident).

{
  "mcpServers": {
    "opvs": {
      "command": "opvs-mcp",
      "env": { "NODE_NO_WARNINGS": "1" }
    }
  }
}

Windsurf

~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "opvs": {
      "command": "opvs-mcp",
      "env": { "NODE_NO_WARNINGS": "1" }
    }
  }
}

Claude Code

claude mcp add opvs -- opvs-mcp

Worked example

You: Find restaurants near Aarhus and save the top 5 to a board.

Agent → tool_search({ intent: "find restaurants in Aarhus" })
     ← { items: [{ vendor: "@spideriq", name: "lead-gen-skills", ... }],
         telemetry_signal: "warm",
         _guidance: "#audit.ok ranked=1 best=@spideriq/lead-gen-skills #next:tool_call" }

Agent → tool_help({ name: "@spideriq/lead-gen-skills", section: "methods" })
     ← { methods: { search_maps: { ... }, submit_job: { ... } } }

Agent → tool_call({
          skill: "@spideriq/lead-gen-skills",
          method: "submit_job",
          params: { type: "spiderMaps", payload: { query: "restaurants", location: "Aarhus" } }
        })
     ← { job_id: "...", _guidance: "#audit.ok #next:poll getJobStatus every 5s" }

The agent never had to know all of SpiderIQ's 40+ methods upfront — discovery → describe → invoke flowed through 3 always-on tools (discover → describe → invoke).

Response contract

Every tool returns a single text-content block whose payload is JSON with:

  • Flat sibling _guidance: string — never a wrapper, never an array.
  • Optional flat sibling _findings: [...] — only when the server emits one (e.g. audit_level=all).
  • telemetry_signal in search results — closed enum: absent | cold | warm | hot.

The contract was locked with SpiderIQ on 2026-05-15 PM. See docs/planning/Marketplace/CLAUDE.md for the gateway-side semantics this MCP mirrors.

tool_pin status

tool_pin is a stub in 1.0.0. The W2.1 TOOLS.md persistence layer is live in the gateway's skills-meta plugin (PUT /api/v1/agents/{id}/tools-md via Management API + X-API-Key), but that surface isn't reachable from a PAT-authenticated MCP client. Calling tool_pin returns:

{
  "action": "pin",
  "skill": "@opvs-ai/agentboard",
  "agent_id": "lola_001",
  "changed": false,
  "_guidance": "#audit.warn:not-supported-via-mcp — ..."
}

Until W2.MCP.PIN ships the PAT-gated passthrough, manage pins via the OPVS dashboard agent profile editor at /admin/agents/personas.

What was deprecated

This package was previously a 209-tool monolithic MCP exposing every public skill's full surface. That model didn't survive contact with MCP clients — every real client (Antigravity, Cursor, Claude Desktop, Windsurf) enforces a ~100-tool cap and the monolithic build was unusable in practice.

The on-demand model (the always-on set + tool_call indirection) reaches the same skills without paying the tool-budget cost.

Versions ≤ 0.7.4 are end-of-life. There is no @opvs-ai/mcp@0.x → 1.0 migration code path — replace the old install with a fresh one.

Development

cd ../core && npm install && npx tsc   # REQUIRED FIRST — see below
cd ../mcp  && npm install
npx vitest run                          # unit tests
npm run build && OPVS_TOKEN=smoke-test npm run list-tools

Two things bite from a clean checkout:

  • Build @opvs-ai/core first. Its main points at dist/, so without that step the suite dies at collection with Failed to resolve entry for package "@opvs-ai/core" — a missing build, not a broken suite.
  • npm run list-tools is a real gate, not a printout. It drives the actual stdio protocol against the built server and exits non-zero on a tool name that fails ^[a-zA-Z0-9_-]+$ (exit 2) or on going over the tool-count ceiling (exit 3). A unit test of the TOOLS array cannot prove a tool is registered; this can. Both run in CI under TS Library Tests.

Counts move. Measure them at your SHA rather than citing a number from here.

Related packages

  • @opvs-ai/cli — terminal access (no MCP layer)
  • @opvs-ai/skills — vendor CLI (publish/install/doctor)
  • Gateway plugin skills-meta (source) — the in-platform counterpart of this package

License

MIT — see LICENSE.