# Claude and MCP

Every endpoint on this platform is also an MCP tool, served from a single
endpoint:

```
POST https://api.quasslabs.com/mcp
```

This is the intended way to use the API from an AI assistant. You do not write
HTTP clients, you do not maintain tool definitions, and you do not update
anything when we ship a new endpoint — the tool list is served live from the same
source that defines the REST surface, so a new tool simply appears.

## Connect

### Claude Code

```bash
claude mcp add --transport http quasslabs https://api.quasslabs.com/mcp \
  --header "Authorization: Bearer qlk_YOUR_API_KEY"
```

### Claude Desktop, and other hosts that use a JSON config

```json
{
  "mcpServers": {
    "quasslabs": {
      "type": "http",
      "url": "https://api.quasslabs.com/mcp",
      "headers": {
        "Authorization": "Bearer qlk_YOUR_API_KEY"
      }
    }
  }
}
```

Once connected, ask for what you want in plain language — "score this paragraph
for AI tells", "which model should I use for this and what will it cost", "check
this diagram for contrast failures" — and the assistant will pick the right tool
and fill in the arguments from your schema.

## How the transport works

The endpoint speaks **JSON-RPC 2.0 over Streamable HTTP**. It is **stateless**:
no session is negotiated, no session id is required, and each request can be sent
independently. That makes it cheap to call from serverless code and safe to retry.

Supported methods:

| Method | Purpose |
| --- | --- |
| `initialize` | Handshake. Returns the protocol version and server info. |
| `notifications/initialized` | Client acknowledgement. Returns `202` with no body. |
| `ping` | Liveness check. Returns an empty result. |
| `tools/list` | The available tools, with their JSON Schemas. |
| `tools/call` | Invoke one tool. |

A JSON-RPC **batch** — an array of request objects — is also accepted, and
notifications are filtered out of the response array automatically.

## Calling it directly

Listing the tools takes no authentication:

```bash
curl -sS https://api.quasslabs.com/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Calling one does:

```bash
curl -sS https://api.quasslabs.com/mcp \
  -H "Authorization: Bearer qlk_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "humanizer_score",
      "arguments": {"text": "Let us delve into this transformative paradigm."}
    }
  }'
```

The tool result arrives as `result.content[0].text`, containing the same JSON body
the REST endpoint would have returned.

## Auth and billing are identical to REST

`tools/call` forwards your Bearer key to the underlying endpoint. Authentication,
per-key rate limiting and credit metering all happen there, exactly as they would
if you had called the endpoint yourself. **The gateway itself is not metered**, so
going through MCP never costs more than going direct — there is no double charge.

The practical consequence: an MCP tool call can fail for any of the reasons a REST
call can. A `402 insufficient_credits` or `429 rate_limit_exceeded` surfaces as a
tool result with `isError: true` whose text is the same error body documented in
[errors and limits](errors.md).

## The advertised tool list is never larger than reality

`tools/list` returns only tools whose endpoint is currently deployed and enabled.
If an endpoint is taken down with the kill switch, or has not shipped yet, it does
not appear.

If your client is holding a cached tool list and calls something that has since
been disabled, you get an explicit result rather than a mystery:

```json
{"error": "endpoint_disabled", "tool": "convert_diagram"}
```

This matters more than it sounds. The alternative — advertising a tool with no
route behind it — produces a bare `{"message":"Not Found"}` from the load balancer,
which gives the caller no way to distinguish an outage from a malformed request.
We shipped that bug once. The tool list is now derived from what is actually
deployed so that it cannot recur.

## Tools that are not listed

Two tools exist in the codebase but are not currently served: `convert_diagram`
and `supply_chain_scan`. Their container images are not yet published, so they
have no route, and they are correctly absent from both `tools/list` and the
OpenAPI spec. They will appear when they ship.

## If the server is offline

An administratively disabled MCP endpoint returns HTTP `503` with
`{"error": "endpoint_disabled"}` for the whole JSON-RPC surface, rather than a
JSON-RPC error inside a `200`. That is deliberate: a transport-level failure is
what an MCP client should see when the server is offline, and it matches how every
other endpoint reports the same condition.
