# Install

`POST /mcp` is MCP Streamable HTTP. `GET /mcp` is 405. There is no legacy SSE endpoint. Auth on every client below is none. The anonymous free tier is 60 `tools/call` requests per 60 seconds per client.

Tools, in list order: `score`, `heard_as`, `recognize`, `create_upload`, `score_attempt`. Every tool sends `title`, `inputSchema`, `outputSchema`, and `annotations.readOnlyHint`, `openWorldHint`, and `destructiveHint`.

Chat, Claude, and Gemini pass JSON. They do not attach microphone audio to a tool call. Send `ipa`, `audio_base64` (a WAV, at most 256 KiB decoded), or `audio_url`. `ipa` wins when it is also sent. A larger clip calls `create_upload`, PUTs the wav to `upload_url` with `Content-Type: audio/wav`, and passes `audio_url`. This build stores that wav in process memory for 15 minutes. It does not sign Cloudflare R2.

`score` and `score_attempt` point at the record widget `ui://ipa/record.html` ([/apps/record](/apps/record)). The widget MIME type is `text/html;profile=mcp-app`. Codex Desktop and ChatGPT on iOS deny `getUserMedia` even when `ui.permissions.microphone` is declared. ChatGPT on desktop Chrome can grant it.

## ChatGPT

[Creating custom MCP apps in ChatGPT](https://help.openai.com/en/articles/12584461-creating-custom-mcp-apps-in-chatgpt): Plugins, then the plus, then Add custom MCP server. URL `https://ipa.raymati.com/mcp`. Auth none. Create as a plugin.

App review is the OpenAI plugin submission, not a self-serve listing. Review checks the HTTP `Content-Security-Policy` and the widget `_meta.ui.csp` (`connectDomains` and `resourceDomains` are `https://ipa.raymati.com`).

## Claude

In the Claude app: Customize, Connectors, Add custom connector, URL `https://ipa.raymati.com/mcp`.

Directory submission is separate: <https://claude.ai/directory/manage>. Steps are in [Submitting](/docs/submitting.md).

## Claude Code

```bash
claude mcp add --transport http ipa https://ipa.raymati.com/mcp
```

A JSON entry has to include `"type": "http"`. A `url` without `type` is treated as stdio and skipped. `streamable-http` is an alias for `http`. Source: <https://code.claude.com/docs/en/mcp>.

## Cursor

`~/.cursor/mcp.json` or `.cursor/mcp.json`. Source: <https://cursor.com/docs/mcp>.

```json
{"mcpServers":{"ipa":{"url":"https://ipa.raymati.com/mcp"}}}
```

## VS Code

`.vscode/mcp.json` on VS Code 1.101 or newer.

```json
{"servers":{"ipa":{"type":"http","url":"https://ipa.raymati.com/mcp"}}}
```

## Gemini CLI

```bash
gemini mcp add --transport http ipa https://ipa.raymati.com/mcp
```

`settings.json` uses `httpUrl`, not `url`. Source: <https://geminicli.com/docs/tools/mcp-server/>.

## Content-Security-Policy

HTML responses, including this page and `/apps/record`, send:

```text
default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self'; img-src 'self'; connect-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'self' https://chatgpt.com https://chat.openai.com https://claude.ai
```

`'unsafe-inline'` is there so the landing `application/ld+json` block and the inline record widget can run. Widget review uses `_meta.ui.csp` as well as this header.

## robots.txt

`ALLOW_TRAINING_CRAWLERS` in `scripts/build_api_docs.py` is one flag. It defaults to `True`.

When it is true, `GPTBot`, `ClaudeBot`, `Google-Extended`, and `CCBot` get `Allow: /`. When it is false, those four get `Disallow: /`.

These stay `Allow: /` either way: `ChatGPT-User`, `OAI-SearchBot`, `Claude-User`, `Claude-SearchBot`, `PerplexityBot`, `Perplexity-User`, and `User-agent: *`. A named group wins over `*` for that bot.

`Google-Extended` and `Applebot-Extended` are control tokens, not HTTP user-agents. Bytespider is listed and is widely reported to ignore `robots.txt`.
