# From a script

> Call the MCP server without an agent, with curl and an API key. Stateless, over POST, as SSE or plain JSON.

For a script, the [REST API](https://docs.rustine.io/en/api/projects/list.md) is simpler. But you can also talk to the MCP server directly, for example to test your key or reproduce what your agent sees.

## The handshake

The server is **stateless**: no `initialize`, no session header. Every request is a `POST` to `https://mcp.rustine.io` with:

- `Authorization: Bearer rst_...`;
- `Content-Type: application/json`;
- `Accept: application/json, text/event-stream` (otherwise `406`).

Without an `MCP-Protocol-Version` header, the answer comes as SSE: an `event: message` line, then `data: {…}` with the JSON-RPC answer.

## As plain JSON

With the `2026-07-28` revision of the protocol, the answer is plain JSON. Add the `MCP-Protocol-Version`, `Mcp-Method` and `Mcp-Name` headers, and the `_meta` keys in `params`:

```bash
curl -s https://mcp.rustine.io \
  -H "Authorization: Bearer $RUSTINE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/call" \
  -H "Mcp-Name: list_projects" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_projects","arguments":{},"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"my-script","version":"1.0.0"},"io.modelcontextprotocol/clientCapabilities":{}}}}'
```

## Answers to know

- **401** `invalid_token` with a `WWW-Authenticate` header: missing, revoked or mistyped key.
- **406**: `Accept` lacks `text/event-stream` or `application/json`.
- **Quota used up or plan without MCP**: never a `403`. The answer is a tool result with `isError: true` and readable text, with the link to change plans.
- **Rate**: 120 requests per minute per key, like the API.

Each tool's parameters: [The tools](https://docs.rustine.io/en/mcp/tools.md).

## Examples

### tools/list

```bash
curl -s https://mcp.rustine.io \
  -H "Authorization: Bearer $RUSTINE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

### list_projects

```bash
curl -s https://mcp.rustine.io \
  -H "Authorization: Bearer $RUSTINE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_projects","arguments":{}}}'
```

### Response: 200 OK

```text
event: message
data: {"result":{"content":[{"type":"text","text":"…"}]},"jsonrpc":"2.0","id":1}
```
