API REFERENCE

Use Modelvia from an agent host

Modelvia publishes one MCP server, so an agent host can list what a key may call, read a receipt, run an inference request or automate a reseller’s customer administration — with a URL and a key, and no plugin to install.

MCP here is tools, not model access

If what you want is to send Modelvia your prompts, you do not want MCP. Model access is the ordinary API: POST /v1/chat/completions in the OpenAI shape, POST /v1/messages in the Anthropic shape and POST /v1/embeddings for retrieval, all with a project key. Your first call has the base URL, the SDK recipes, the parameter tables and every refusal code. Point your host’s model provider setting there.

The MCP server is for the other half: things an agent does with Modelvia rather than through it — checking which routes a key may use, reading what a request cost, or, with a client integration key, signing a customer up, minting its serving key and checking business margins. Four tools, chat_completion, embeddings, decisions and web_search, do reach the model, for a host that has no model provider slot to point at us or wants structured decision and search tools.

The endpoint

POST https://api.modelvia.dev/mcp
Authorization: Bearer $MODELVIA_KEY
Content-Type: application/json
Accept: application/json, text/event-stream

{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}
Transport
Streamable HTTP at a single URL, POST https://api.modelvia.dev/mcp. There is no SSE endpoint to open first and no session id to carry.
Protocol
Stateless JSON-RPC 2.0. Every request stands alone and is authenticated on its own, so nothing is remembered between calls and a host may reconnect freely.
Authentication
Authorization: Bearer <key> or x-api-key: <key>. Send one; the key you send decides which tool set you get.
Operator tokens
Never accepted over HTTP, on this endpoint or any other. Operator actions — billing ownership, rate cards, commercial terms — are not reachable from an agent host at all.

With a project key

A project key is scoped to one project and one environment, and gives an agent host six tools.

The project-key tool set, and the route each one is.
ToolEffectWhat it is
models_listRead-only, freeGET /v1/models — exactly the routes this key may use, with context_length, max_output_tokens and the accepted price.
request_receiptRead-only, freeGET /v1/requests/{id} — the accounting record for one request. Never the prompt or the completion.
chat_completionPaid. Requires confirm: truePOST /v1/chat/completions — one inference request, charged to this key, carrying an Idempotency-Key so a host that retries is not charged twice.
embeddingsPaid. Requires confirm: truePOST /v1/embeddings — one or many strings turned into vectors on an embeddings route, charged to this key, carrying an Idempotency-Key for the same reason.
decisionsPaid. Requires confirm: truePOST /v1/decisions — structured multi-option decision scoring and ranking against weighted criteria, charged to this key.
web_searchPaid. Requires confirm: truePOST /v1/web-search — grounded web search and synthesis with cited sources, charged to this key.

chat_completion, embeddings, decisions and web_search spend money, so none of them will run on a model’s say-so alone: the call must carry confirm: true. Pass idempotencyKey for a guarantee that does not depend on timing; without it the gateway applies its header-less rule, so a host that resends after a lost reply gets the original receipt rather than a second charge, and a repeat whose answer was delivered earlier is served as a new request.

{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "chat_completion",
    "arguments": {
      "model": "auto",
      "messages": [{"role": "user", "content": "Summarise this ticket in one line."}],
      "confirm": true
    }
  }
}

With a client integration key

A client integration key (mgt_…) gets the client automation set instead: the same server-to-server provisioning and reporting routes described in Integrate your product, exposed as tools. Everything stays scoped to the key’s own client binding, exactly as it is over HTTP.

The client-key tool set. Every mutating tool requires confirm: true.
ToolEffectWhat it is
client_customers_listRead-onlyGET /v1/client/customers
customers_createMutating. Requires confirm: truePOST /v1/client/customers
projects_createMutating. Requires confirm: truePOST /v1/client/customers/{customerId}/projects
keys_listRead-onlyGET /v1/client/customers/{customerId}/projects/{projectId}/keys — records without secrets.
keys_mintMutating. Requires confirm: truePOST /v1/client/customers/{customerId}/projects/{projectId}/keys — the secret is returned once, and a repeat mints a second key.
keys_rotateMutating. Requires confirm: truePOST …/keys/{keyId}/rotate
keys_revokeMutating. Requires confirm: truePOST …/keys/{keyId}/revoke
customer_analyticsRead-onlyGET /v1/client/customers/{customerId}/analytics — the customer-safe projection, with its byDay, byModel and byProject groups and its recentRequests rows.
customer_billingRead-onlyGET /v1/client/customers/{customerId}/billing — the money view: period totals, invoices and where that customer pays.
customer_usage_summaryRead-onlyThe summary and coverage sections of the same customer analytics query — one customer's totals for a period, without the per-request rows.
client_marginsRead-onlyGET /v1/client/margins — your business-level wholesale cost, customer gross and net margin breakdown by customer and model.
client_analyticsRead-onlyGET /v1/client/analytics — your business-level usage and commercial analytics across every customer and project.

The two sets do not overlap: a project key never reaches a provisioning tool, and a client integration key never reaches chat_completion. A host configured with the wrong key for the job simply does not see the tools it wanted.

customers_create and projects_create are closed by default: unless the Modelvia operator has opened customer provisioning for your client, both are refused with 403 onboarding_operator_only.

Host configuration

Put the key in the environment as MODELVIA_KEY and reference it; do not paste a literal key into a file you commit.

Claude Code

claude mcp add --transport http modelvia https://api.modelvia.dev/mcp \
  --header "Authorization: Bearer $MODELVIA_KEY"

Cursor

// .cursor/mcp.json
{
  "mcpServers": {
    "modelvia": {
      "url": "https://api.modelvia.dev/mcp",
      "headers": {
        "Authorization": "Bearer ${MODELVIA_KEY}"
      }
    }
  }
}

OpenClaw

// openclaw config — one remote MCP server entry
{
  "mcpServers": {
    "modelvia": {
      "type": "http",
      "url": "https://api.modelvia.dev/mcp",
      "headers": {
        "Authorization": "Bearer ${MODELVIA_KEY}"
      }
    }
  }
}

Hermes

# ~/.hermes/config.yaml
mcp_servers:
  modelvia:
    url: https://api.modelvia.dev/mcp
    headers:
      Authorization: Bearer ${MODELVIA_KEY}
    enabled: true

The local stdio alternative

The same server runs locally over stdio, for a host that cannot attach headers to a remote server. It reads everything from its environment: PLATFORM_API_URL, the gateway it calls, on every tool call, and one credential — a project key in MODELVIA_API_KEY, or a client integration key in PLATFORM_CLIENT_KEY:

# a project key: the project-key tools
PLATFORM_API_URL=https://api.modelvia.dev MODELVIA_API_KEY=$MODELVIA_KEY npm --prefix managed-gateway run mcp

# a client integration key: the client-key tools
PLATFORM_API_URL=https://api.modelvia.dev PLATFORM_CLIENT_KEY=$MODELVIA_KEY npm --prefix managed-gateway run mcp
// the same server over stdio, for a host that cannot send headers
{
  "mcpServers": {
    "modelvia": {
      "command": "npm",
      "args": ["--prefix", "managed-gateway", "run", "mcp"],
      "env": {
        "PLATFORM_API_URL": "https://api.modelvia.dev",
        "MODELVIA_API_KEY": "${MODELVIA_KEY}"
      }
    }
  }
}
// the same, with a client integration key instead of a project key
{
  "mcpServers": {
    "modelvia": {
      "command": "npm",
      "args": ["--prefix", "managed-gateway", "run", "mcp"],
      "env": {
        "PLATFORM_API_URL": "https://api.modelvia.dev",
        "PLATFORM_CLIENT_KEY": "${MODELVIA_KEY}"
      }
    }
  }
}

The tool sets are the same as over HTTP, but here the variable decides which one you get, not the key: anything in MODELVIA_API_KEY is treated as a project key, so a client integration key belongs in PLATFORM_CLIENT_KEY. Set one or the other; the server refuses to start with both. A local process is not a weaker boundary but it is a longer one: the key now sits in a shell environment on that machine as well as in the host’s configuration.

What a key in a host’s configuration means

  • A key in a host’s configuration is that party’s own credential. Whatever the host does with it is done as you, billed to you and audited as you. Configure your own key in your own host; do not hand one to someone else’s.
  • The host must be trusted with it. An MCP host reads its configuration, can log what it sends, and may run tools a model chose. Give it a key whose authority you would give that software directly — for provisioning work, that means a client integration key that can mint credentials for your customers.
  • A chat_completion from a host is a paid request on that key. It goes through the same admission, caps, rate card and settlement as any other call, and produces the same receipt. An agent loop that calls it repeatedly spends real money; confirm: true is there so each of those is a deliberate act.
  • Scope down rather than up. Mint a project key per environment, so revoking the one a host holds stops nothing else, and keep the client integration key on your own server wherever a project key would do.