# Connect your AI agent to the cost calculator

Source: https://calc.onpremeasy.com/agents/

Let an AI agent size and price self-hosted infrastructure for you. The calculator is available as a remote MCP server and as a REST API. The agent picks a product, reads its parameters, sends a workload, and gets back a monthly cost with line items, assumptions, price sources, the price snapshot date and a link to a human-readable result.

## What you can ask

- "How much does it cost to host Kafka on-prem? We need 3 brokers and about 1 TB retained."
- "Compare the monthly cost of a small PostgreSQL HA setup and a Qdrant vector store for our RAG prototype."
- "Which products can you price for self-hosted search, and what workload numbers do you need from me?"

## Quick start

1. Create an API key. Sign in on the calculator with your email, open [Agent keys](https://calc.onpremeasy.com/agent-keys), and create a key. It looks like `ope_live_` followed by 64 hex characters and is shown once, so copy it then.
2. Add the server to your client. Use the URL `https://calc-api.onpremeasy.com/mcp` and send the key as `Authorization: Bearer <key>`. Copy-paste setups for common clients are below.
3. Ask. For example: "Use the onpremeasy tools to estimate the monthly cost of Kafka with 3 brokers and 1000 GB retained data."

You can skip step 1 to try the free read-only tools: `list_products` and `describe_product` need no key. `estimate` needs a key at the moment (see [Limits](#limits)).

## Connect your client

The server uses streamable HTTP, is stateless, and authenticates with a bearer key in the `Authorization` header. It has no OAuth flow. A client therefore has to be able to send a fixed header. Clients that only offer OAuth or no authentication cannot send the key, see [Clients that cannot send a key](#no-header).

In the examples, replace `ope_live_YOUR_KEY` with your key. Prefer the environment-variable forms where a client supports them, so the key does not end up in a committed file or in shell history.

### Claude Code

Terminal:

```bash
claude mcp add --transport http onpremeasy https://calc-api.onpremeasy.com/mcp \
  --header "Authorization: Bearer ope_live_YOUR_KEY"
```

Docs: https://code.claude.com/docs/en/mcp

This stores the key in your Claude Code configuration. To keep it out of the command line, put the server in a project `.mcp.json` and read the key from an environment variable you set yourself (Claude Code expands `${VAR}` in `headers`). Avoid variable names Claude Code treats specially, such as `ANTHROPIC_API_KEY`.

.mcp.json:

```json
{
  "mcpServers": {
    "onpremeasy": {
      "type": "http",
      "url": "https://calc-api.onpremeasy.com/mcp",
      "headers": {
        "Authorization": "Bearer ${ONPREMEASY_API_KEY}"
      }
    }
  }
}
```

Docs: https://code.claude.com/docs/en/mcp

Do not run `/mcp` to sign in to this server: it uses a header, not OAuth. Use `/mcp` only to check that it is connected.

### Cursor

Add this to `.cursor/mcp.json` in a project, or `~/.cursor/mcp.json` for all projects. Cursor reads `${env:NAME}` in `headers`.

.cursor/mcp.json:

```json
{
  "mcpServers": {
    "onpremeasy": {
      "url": "https://calc-api.onpremeasy.com/mcp",
      "headers": {
        "Authorization": "Bearer ${env:ONPREMEASY_API_KEY}"
      }
    }
  }
}
```

Docs: https://cursor.com/docs/context/mcp

### VS Code with GitHub Copilot

Add this to `.vscode/mcp.json` in the workspace. VS Code uses the key `servers` (not `mcpServers`). The `inputs` entry makes VS Code ask for the key once and hide what you type, so nothing secret is in the file.

.vscode/mcp.json:

```json
{
  "inputs": [
    {
      "type": "promptString",
      "id": "onpremeasy-key",
      "description": "onpremeasy API key",
      "password": true
    }
  ],
  "servers": {
    "onpremeasy": {
      "type": "http",
      "url": "https://calc-api.onpremeasy.com/mcp",
      "headers": {
        "Authorization": "Bearer ${input:onpremeasy-key}"
      }
    }
  }
}
```

Docs: https://code.visualstudio.com/docs/agents/reference/mcp-configuration

You can also run **MCP: Add Server** from the Command Palette and choose HTTP. Organisations that manage Copilot may have MCP servers switched off by policy.

### Codex CLI

Add this to `~/.codex/config.toml` (shared by the Codex CLI, IDE extension and desktop app). `bearer_token_env_var` names an environment variable; Codex sends its value as the bearer token. The `codex mcp add --url` command exists but, per the docs, has no flag for a bearer token, so edit the file.

~/.codex/config.toml:

```toml
[mcp_servers.onpremeasy]
url = "https://calc-api.onpremeasy.com/mcp"
bearer_token_env_var = "ONPREMEASY_API_KEY"
```

Docs: https://learn.chatgpt.com/docs/extend/mcp?surface=cli

### Setting the environment variable

Terminal:

```bash
export ONPREMEASY_API_KEY=ope_live_YOUR_KEY
```

Docs: https://code.claude.com/docs/en/mcp

Set it in the shell that launches the client, or in your shell profile. A desktop client started from a launcher may not see variables from a terminal.

### Clients that cannot send a key

Some chat apps add MCP servers as "connectors" and only offer OAuth or no sign-in. They cannot send our bearer key, and this server has no OAuth. What works instead:

- **claude.ai custom connectors.** Anthropic documents a Request headers section for API keys and bearer tokens (choose "No sign-in", add a header named `authorization` with the value `Bearer ope_live_YOUR_KEY`). Anthropic describes it as a beta available to a limited set of organisations, so it may not appear in your account. We have not tested it. See [Anthropic: add a connector by URL](https://claude.com/docs/connectors/custom/add-unlisted). If you do not see it, use Claude Code or another client above.
- **ChatGPT connectors.** As far as we could verify, OpenAI documents OAuth, no authentication, or a mixed mode for custom MCP apps, and no field for a fixed bearer key. We have not tested it, and we do not claim support. A connector set to no authentication can use the free `list_products` and `describe_product` tools only; `estimate` will answer 401.
- **Any agent that can make HTTP calls.** Use the [REST API](#rest) with the same key. It is the same data and the same limits.
- **Other MCP clients.** Use the server URL and send the header `Authorization: Bearer ope_live_YOUR_KEY` wherever the client allows custom headers. For clients that only launch local commands, a bridge such as `mcp-remote` can pass a header; we have not tested one.

### Try it with curl (MCP)

This is the raw protocol, useful to check your key. Send both `Accept` types. The server is stateless: each request stands alone, with no session id.

initialize:

```bash
curl -sS https://calc-api.onpremeasy.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "Authorization: Bearer $ONPREMEASY_API_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'
```

Docs: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports

tools/list:

```bash
curl -sS https://calc-api.onpremeasy.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "Authorization: Bearer $ONPREMEASY_API_KEY" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
```

Docs: https://modelcontextprotocol.io/specification/2025-06-18/server/tools

tools/call: describe_product (free, no key needed):

```bash
curl -sS https://calc-api.onpremeasy.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"describe_product","arguments":{"product":"kafka-cluster"}}}'
```

Docs: https://modelcontextprotocol.io/specification/2025-06-18/server/tools

tools/call: estimate (key needed, uses one daily slot):

```bash
curl -sS https://calc-api.onpremeasy.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "Authorization: Bearer $ONPREMEASY_API_KEY" \
  -d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"estimate","arguments":{"product":"kafka-cluster","workload":{"broker_count":3,"retained_data_gb":1000,"partition_count":100}}}}'
```

Docs: https://modelcontextprotocol.io/specification/2025-06-18/server/tools

## Tools

| Tool | What it does | Key | Quota |
| --- | --- | --- | --- |
| `list_products` | Lists every product the calculator can size, with its id, category, a short summary and the names of the workload fields `estimate` needs. Call it first. | No | None |
| `describe_product` | Returns one product's workload parameters (type, minimum, default, units), topology templates with minimum node counts, and dependency products. | No | None |
| `estimate` | Returns the monthly cost of a workload: recommended servers per component, monthly price per line item and in total, assumptions, price sources, the price snapshot date and a result link. | Yes, currently | 1 slot per fresh estimate |

Typical flow: `list_products`, then `describe_product` to learn the exact parameter names and units, then `estimate`. Unknown workload fields are rejected, and rejected requests are free.

## REST API and OpenAPI

The same data is available over plain HTTP under `https://calc-api.onpremeasy.com/agent/v1`. The machine-readable description is the [OpenAPI document](https://calc-api.onpremeasy.com/agent/v1/openapi.json). Crawlers and agents that read documentation can start from [llms.txt](https://calc.onpremeasy.com/llms.txt), [llms-full.txt](https://calc.onpremeasy.com/llms-full.txt) or the Markdown version of any product page, for example [/product/kafka-cluster.md](https://calc.onpremeasy.com/product/kafka-cluster.md).

| Endpoint | Key | Purpose |
| --- | --- | --- |
| `GET /agent/v1/products` | No | List products |
| `GET /agent/v1/products/{id}` | No | Parameters, topologies, dependencies and a reference price range |
| `GET /agent/v1/reference` | No | Providers, currencies and the current billing and quota facts |
| `POST /agent/v1/estimate` | Yes, currently | Estimate a workload (JSON body, 16 KiB maximum) |

List products (no key):

```bash
curl -sS https://calc-api.onpremeasy.com/agent/v1/products
```

Docs: https://calc-api.onpremeasy.com/agent/v1/openapi.json

Estimate (key needed):

```bash
curl -sS https://calc-api.onpremeasy.com/agent/v1/estimate \
  -H "Authorization: Bearer $ONPREMEASY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"product":"kafka-cluster","workload":{"broker_count":3,"retained_data_gb":1000,"partition_count":100}}'
```

Docs: https://calc-api.onpremeasy.com/agent/v1/openapi.json

Optional body fields are `provider` and `currency`. Keyed callers may also send an `Idempotency-Key` header so a retried request is not counted twice.

## What an estimate contains

- `line_items` and `totals`: the recommended server configuration per component with its monthly price, and the total.
- `assumptions`: what the calculator assumed about your workload.
- `price_sources` and `price_snapshot_date`: which public price lists were used and the date of the snapshot.
- `result_url`: a link a person can open to see the full result.
- `billing`: whether the answer came from the cache and how many daily slots it used.

Prices are indicative. They are generated automatically from public price lists and are not quotes. Check the snapshot date, and confirm with the provider before you buy.

## Limits and fair use

- **Free read-only tools.** Listing, describing and reading reference data need no key and use no quota.
- **20 fresh estimates per account per UTC day.** The count is shared by all keys of one account and resets at 00:00 UTC. You can have up to 5 active keys.
- **Cache hits are free.** An identical repeated request (same product, workload, provider and currency) is served from the cache and uses no slot. Failed estimates are not counted.
- **Keyless estimates.** An anonymous quota exists in the server but is switched off, so `estimate` without a key answers 401 today. This may change.
- **Service-wide daily cap.** A cap on fresh estimates across all callers protects the service. When it is reached, `estimate` answers 503 until 00:00 UTC.
- **Rate limits.** 30 requests per minute per key and 10 per minute per IP for keyless calls (429 with `Retry-After`).
- These numbers can change. `GET /agent/v1/reference` shows the current facts, and the 402 and 503 bodies state the reset time.

## Troubleshooting

| Symptom | Meaning and fix |
| --- | --- |
| 401 `authentication_required` | `estimate` was called without a key. Add the `Authorization` header. |
| 401 `invalid_api_key` | The key is wrong, revoked or malformed. Check that the whole `ope_live_` key is there, with `Bearer ` in front and no extra spaces. Create a new key at [Agent keys](https://calc.onpremeasy.com/agent-keys) if needed. A bad key never falls back to keyless access. |
| 402 `payment_required` | Your account used its free estimates for today. The body gives `quota_resets_at` (00:00 UTC), `retry_after_seconds`, and a contact address. Wait for the reset; do not retry in a loop. Cached answers do not help once the quota is spent, because the slot is reserved before the lookup. |
| 503 `capacity_reached` | The service-wide daily cap is used up. `Retry-After` and `quota_resets_at` say when to try again. Free read-only tools keep working. |
| 429 `rate_limited` | Too many requests in a minute. Wait for `Retry-After`. |
| 422 or `invalid_request` | A workload field is missing, unknown or out of range. `problems` names it. Call `describe_product` and use its names and units. |
| Timeout or `llm_unavailable` | A fresh estimate calls a language model and can take a while, or be temporarily unavailable. Allow a generous timeout, then retry later. A failed estimate is not charged. |
| Server shows as connected but no tools appear | Restart the client and check the URL ends in `/mcp`. Make sure the client supports streamable HTTP (not only SSE or local commands). |

## Privacy

Each tool call is logged for operations and abuse control: which tool, the product, the result status, timing, and a salted hash that stands in for the client. The log has no raw IP address, no key material and no request body. Keys are stored only as a hash. See the [Privacy Policy](https://calc.onpremeasy.com/privacy.html). Do not put secrets or personal data in workload fields.

## Contact

Questions, a client that does not work, or a need for more capacity: [support@onpremeasy.com](mailto:support@onpremeasy.com).
