ReadTeardownsPricingDocsMCPOpen the chatRecipesWhat we never takeOpt out a siteChangelogStatusvorluno.dev
INSTALLnpm i -g @mvoom/mcp
LICENCEMIT
SOURCEthis page is the package README
OTHERS/docs/cli · /docs/sdk
DOCS / 03 · MCP

@mvoom/mcp

Your agent measures. You sign. Four tools, one of which can spend money — and that one asks a person first.

README

Your agent measures. You sign. The mvoom connector for any MCP client — four tools, one of which can spend money, and that one asks a person first.

npm i -g @mvoom/mcp   # the binary is `mvoom-mcp`
The hosted service is not live yet. Until api.mvoom.com opens, point MVOOM_API at a service you run yourself (npm run api in the mvoom repository). The package is published now so the install path is real from day one.

{
  "mcpServers": {
    "mvoom": { "command": "mvoom-mcp" }
  }
}

Run mvoom auth once (from [@mvoom/cli](https://www.npmjs.com/package/@mvoom/cli)) and the connector is signed in — it reads the same key, from MVOOM_API_KEY or ~/.mvoom/credentials. No arguments, no config file.

The four tools

ToolWhat it doesMoney
mvoom_get_wallet_balancecredits available, the ceiling your agent may spend alone, last movementsnone
mvoom_discover_pagewhat moves on a page — each piece with a selector and a price rangenone
mvoom_inspect_componentmeasures one piece in a real browser and returns the brief plus a signed quotenone — spends one read of your allowance
mvoom_purchase_and_injectbuys the component behind a quote and writes its files into the projectdebits credits

Quoting and buying are separate tools on purpose: an agent that could only learn the price by buying would buy to learn the price.

Above the autonomous ceiling, a person signs. Not the model — the model is the one asking. The connector puts the question in front of you through the client, with the exact figure, and only "yes" buys. The ceiling is set in your account; you can only tighten it (mvoom budget).

How the signature reaches you

Two channels, in this order:

  1. Through the client — MCP's own elicitation/create. If your client declared it at

initialize, the question appears in its interface, whatever that is, and the answer comes back to the connector. Only accept with authorize: true is a signature. Decline, cancel, an empty answer or anything that is not exactly true is a no.

  1. In the terminal — if the connector was launched from one. It opens the console device

(/dev/tty, or CONIN$/CONOUT$ on Windows) alongside the protocol channel and prints:

MVOOM · WALLET GATE
Component:        art_7f3a
This will debit:  1,860 credits  (≈ $18.60 USD)
Your balance:     4,200 credits
Do you authorize your agent to debit this component from your wallet? [y/N]
If neither channel exists, the purchase is refused. A client that cannot ask and a process with no terminal have no way to obtain a signature, so the tool returns NO_SIGNATURE_CHANNEL with the numbers and where to buy instead (mvoom.cc). It does not assume yes, does not lower the ceiling, and does not ask the model. Set MVOOM_HEADLESS=1 when the connector is launched by an application that is not a terminal: an inherited console nobody is looking at would otherwise hold the question forever.

The server enforces it too. POST /v1/purchase above the ceiling without signed: true answers SIGNATURE_REQUIRED — a patched client does not get around the rule, it just gets the refusal from somewhere else.

Refusals carry numbers

A model given "not enough credits" has to guess the figures, and when it cannot find them it invents them. So every refusal carries a context:

{
  "ok": false,
  "code": "INSUFFICIENT_CREDITS",
  "message": "not enough credits: 1860 needed, 100 available",
  "context": { "requiredCredits": 1860, "availableCredits": 100, "missingCredits": 1760, "rechargeUrl": "https://mvoom.cc/wallet" }
}
CodeWhenWhat to do
INSUFFICIENT_CREDITSthe wallet cannot cover the piecea person recharges at the URL — no signature is asked for something that cannot be paid
USER_DENIED_TRANSACTIONthe person said nonothing was charged; do not retry
NO_SIGNATURE_CHANNELabove the ceiling and no way to askbuy at mvoom.cc
SIGNATURE_REQUIREDthe server was asked without a signatureyou should not see this from this connector

What goes into the context window

A summary, never the spec. Each response lands in someone's context and every token there is paid by them and degrades their model. A piece travels as its brief — what moves, how long, on what curve, and the price. The code, which is what is sold, travels once at purchase and goes to disk.

mvoom_purchase_and_inject writes only inside the project — the directory the connector was started in. A targetPath with ../ in it, or an absolute path elsewhere, is refused before the service is even asked. The service never learns where your files live.

Optional: adapt with your own local model

Off by default. Set MVOOM_LOCAL_MODEL=http://localhost:11434 (Ollama, or anything that speaks its /api/generate) and, if you like, MVOOM_LOCAL_MODEL_NAME=qwen2.5-coder:7b, and a fifth tool appears: mvoom_adapt_locally. It takes a file you already own and an instruction — port this to Vue, move it to CSS modules, restyle it — and writes the result next to the original (Hero.adapted.tsx), never over it. It runs on your machine and costs nothing.

What it does not do: name a piece, price it, or write the recipe that carries mvoom's name. Those are measured and signed by the service; what your model writes is your text, and the output says so in its first line.

Zero dependencies, including the protocol

MCP over stdio is JSON-RPC 2.0, one message per line. A server with four tools needs five methods, and they fit in one file you can read in a sitting — which is the only honest way to trust a program your agent runs with your key. stdout carries protocol and nothing else; logs go to stderr.

Support

VersioningSemantic, with a hand-written changelog
Securitysecurity@vorluno.dev — first response within 48 hours
LicenceMIT. The engine that produces the measurements is not — see ADR-MV016

<sub>Built and maintained by Vorluno Software, S.A. Every figure the connector shows was measured in a real browser, never inferred from a screenshot.</sub>

THE OTHER TWO