Skip to main content
Glama
README.md
# Amika MCP Server

[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/Neolithic/amika-mcp)

A remote [MCP](https://modelcontextprotocol.io) server for [Amika](https://docs.amika.dev):
manage your sandboxes and agent sessions from any MCP client — including the **Claude
mobile app**, so you can check on and steer your coding agents from your phone.

You deploy your own instance to Cloudflare Workers (free tier is plenty) with your own
Amika API key. Nothing is shared: your key stays in your worker.

## Tools

| Tool | What it does |
| --- | --- |
| `check_auth` | Verify the API key is configured and accepted by Amika (no data touched) |
| `list_sandboxes` | List all sandboxes with their state |
| `get_sandbox` | Details/state of one sandbox |
| `create_sandbox` | Create a sandbox — optionally clone a git repo, pick a preset (`coder` / `coder-dind`), set env vars, a setup script, and auto-stop/auto-delete intervals. Waits briefly for provisioning, then poll `get_sandbox` |
| `start_sandbox` / `stop_sandbox` | Start or stop a sandbox (waits for the state change) |
| `list_sessions` | List agent sessions in a sandbox |
| `get_latest_session` | Most recent session in a sandbox |
| `get_session` | Fetch one session by id |
| `create_session` | Create an empty session with optional metadata |
| `update_session` | Update a session's status/metadata (e.g. mark completed) |
| `send_to_agent` | Send a message to the Claude/Codex agent in a sandbox; returns a `task_id` immediately while the agent works in the background — resumes the latest session by default, or pass `new_session` / `session_id`. Pass `wait_seconds` to wait briefly for quick prompts |
| `poll_agent_task` | Check a `send_to_agent` task: status, session info, and the agent's reply once completed |
| `list_agent_tasks` | Recent agent tasks (last 24h) with their status |

## Long-running agent tasks

Agent turns routinely take minutes — up to **~10 minutes** for big tasks — while
Cloudflare drops idle HTTP connections after ~100 seconds (HTTP 524). So `send_to_agent`
doesn't block on the agent: it starts the task in a Durable Object and returns a
`task_id` right away. Poll with `poll_agent_task` (every 15–30 s is plenty) until the
status settles:

- `running` — the agent is still working; keep polling.
- `completed` — `result` contains the agent's reply.
- `failed` — the agent or the API returned an error; see `error`.
- `send_interrupted` — the connection to the Amika API died mid-task (e.g. its own
  ~100 s gateway limit) while the agent kept working. Each poll refreshes
  `session_status`; once the session is no longer running, send a short follow-up to the
  same session asking the agent to summarize what it did — the original reply text can't
  be recovered over the dead connection.
- `lost` — the worker restarted mid-task; check `session_status` the same way.

For quick prompts, pass `wait_seconds` (up to 55) to `send_to_agent` and it will return
the completed result in a single call when the agent answers in time. Tasks are kept for
24 hours and are visible from any conversation connected to the same server.

## Troubleshooting auth

Every tool fails with setup instructions when `AMIKA_API_KEY` is missing, and with a
"replace the key" message on HTTP 401/403 (invalid or expired key). Run `check_auth`
after deploying — it makes one lightweight authenticated call and confirms the
credentials work without touching any data.

## Deploy

### One-click

1. Click **Deploy to Cloudflare** above. Cloudflare copies this repo into your GitHub
   account and creates a Worker that redeploys on every push.
2. Add two secrets to the worker (dashboard → your worker → **Settings** →
   **Variables and Secrets**, type *Secret*):
   - `AMIKA_API_KEY` — generate at [app.amika.dev/settings](https://app.amika.dev/settings)
     (API Key section)
   - `MCP_PATH_SECRET` — a long random string, e.g. from `openssl rand -hex 24`

> [!NOTE]
> **Durable Object migrations need a full deploy.** Releases that add a Durable
> Object class (like v0.2.0's `AmikaTaskStore`) ship a migration, and Cloudflare
> rejects those from `wrangler versions upload` with error 10211 — that's what
> git-connected builds run for non-production branches (previews) and what some
> setups use as the deploy command. Push/merge to the production branch so the
> build runs `npx wrangler deploy`, or apply it once by hand with
> `npx wrangler deploy` from a checkout. After the migration is applied once,
> version uploads and preview builds work again.

Your MCP endpoint is:

```
https://<worker-name>.<your-subdomain>.workers.dev/<MCP_PATH_SECRET>/mcp
```

### CLI

```bash
git clone https://github.com/Neolithic/amika-mcp
cd amika-mcp && npm install
npx wrangler login                       # or: export CLOUDFLARE_API_TOKEN=<token>
npx wrangler secret put AMIKA_API_KEY
npx wrangler secret put MCP_PATH_SECRET
npm run deploy
```

If `wrangler login`'s browser flow can't reach you (headless/remote machine), create an
API token with the "Edit Cloudflare Workers" template at
[dash.cloudflare.com/profile/api-tokens](https://dash.cloudflare.com/profile/api-tokens)
and set `CLOUDFLARE_API_TOKEN` instead.

## Connect a client

**Claude (including the mobile app)** — requires a Pro/Max/Team plan:

1. [claude.ai/settings/connectors](https://claude.ai/settings/connectors) → **Add custom
   connector** → name it `Amika`, paste your full endpoint URL (including the secret
   segment). Leave the OAuth fields empty.
2. In any Claude app (web, desktop, mobile), enable the connector in the tools menu and
   ask things like *"list my amika sandboxes"* or *"send 'run the tests' to the agent in
   dev-box"*.

**Claude Code:**

```bash
claude mcp add --transport http amika https://<worker>/<secret>/mcp
```

Any other MCP client that speaks Streamable HTTP works the same way.

## Security model

- **Single-tenant by design.** Each deployment serves exactly one Amika account. The
  worker holds your `AMIKA_API_KEY` as a Cloudflare secret; it is never sent to clients.
- **The URL is the credential.** There is no OAuth — the endpoint is guarded by the
  secret path segment. Treat the full URL like a password: don't share it, don't post
  screenshots of it, and rotate it if it leaks
  (`wrangler secret put MCP_PATH_SECRET`, or edit it in the dashboard).
- **Never share your deployed endpoint with other people.** Anyone with the URL has
  full control of your Amika account's sandboxes and agents. Other users should deploy
  their own instance — that's what the button is for.
- Requests with a wrong or missing path secret get a `404` without touching the Amika
  API.

## Local development

```bash
cp .dev.vars.example .dev.vars   # fill in AMIKA_API_KEY and MCP_PATH_SECRET
npm run dev                      # serves http://localhost:8787/<secret>/mcp
npm run typecheck
```

## Notes & limitations

- Amika's agent-send endpoint itself is synchronous. The worker calls it in the
  background with a 10-minute client timeout and exposes the result through
  `poll_agent_task` (see [Long-running agent tasks](#long-running-agent-tasks)); a
  gateway drop on that background call is reported as `send_interrupted`, not a failure.
- The Amika SDK stores an unbound `fetch` reference, which throws "Illegal invocation"
  on Workers. The client passes `fetch: (input, init) => fetch(input, init)` to work
  around it ([src/index.ts](src/index.ts)) — don't remove it.
- Built with [`@amika/sdk`](https://www.npmjs.com/package/@amika/sdk), the
  [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk), and
  Cloudflare's [`agents`](https://www.npmjs.com/package/agents) framework
  (Streamable HTTP via `McpAgent`).

## License

[MIT](LICENSE)

Maintenance

ActivitySlowing
ResponsivenessNo issues