# Connect your agent

> Set up the Zombye MCP server in Claude Code, Claude Desktop, Codex, Gemini CLI, Cursor, VS Code, the agent SDKs and any other MCP client.

Zombye's agent interface is `zombye-server --mcp`: one program that speaks the
[Model Context Protocol](https://modelcontextprotocol.io) over standard input and output. Your agent's app starts it,
talks to it, and stops it when it closes. Any app that can run a local (stdio) MCP server can play. Apps that only
connect to a server over the network use [the HTTP server](#over-the-network-the-http-server) instead.

## 1. Build the server

From the repository's root:

```bash
cargo build --release -p zombye-server -p zombye-client
```

That makes `target/release/zombye-server` and, next to it, `target/release/zombye`, the game itself, which the
`screenshot` tool runs offscreen to draw pictures. There are no prebuilt downloads yet.

## 2. Add it to your agent

<McpSetup />

<Tabs syncKey="mcp-client">
<TabItem label="Claude Code">

```bash
claude mcp add --scope user zombye -- /path/to/zombye/target/release/zombye-server --mcp --zombies 1000
```

`--scope user` makes it available in every project; leave it out to add it to this folder only. Everything after
`--` is the server's own command line. Check it's connected with `/mcp`.

Working in the Zombye repository itself? Its [`.mcp.json`](https://github.com/deadcommons/zombye/blob/main/.mcp.json)
already registers the server: start Claude Code in the repository's root and approve `zombye` when asked.

</TabItem>
<TabItem label="Claude Desktop">

Open **Settings → Developer → Edit Config** and add the server to `claude_desktop_config.json`
(`~/Library/Application Support/Claude/` on macOS, `%APPDATA%\Claude\` on Windows):

```json
{
  "mcpServers": {
    "zombye": {
      "command": "/path/to/zombye/target/release/zombye-server",
      "args": ["--mcp", "--zombies", "1000"]
    }
  }
}
```

Quit Claude Desktop completely and start it again. If the server doesn't appear, its log is
`~/Library/Logs/Claude/mcp-server-zombye.log` on macOS.

</TabItem>
<TabItem label="Codex">

The Codex CLI and IDE extension share one config. Add the server with:

```bash
codex mcp add zombye -- /path/to/zombye/target/release/zombye-server --mcp --zombies 1000
```

Or write it into `~/.codex/config.toml` yourself:

```toml
[mcp_servers.zombye]
command = "/path/to/zombye/target/release/zombye-server"
args = ["--mcp", "--zombies", "1000"]
tool_timeout_sec = 120
```

A longer `tool_timeout_sec` gives slow calls (a long `sleep`, a big `step_ticks`) room to finish.
See OpenAI's [MCP guide for Codex](https://learn.chatgpt.com/docs/extend/mcp).

</TabItem>
<TabItem label="Gemini CLI">

```bash
gemini mcp add -s user zombye /path/to/zombye/target/release/zombye-server --mcp --zombies 1000
```

Or add it to `~/.gemini/settings.json`:

```json
{
  "mcpServers": {
    "zombye": {
      "command": "/path/to/zombye/target/release/zombye-server",
      "args": ["--mcp", "--zombies", "1000"]
    }
  }
}
```

Google is moving Gemini CLI users to the Antigravity CLI, which takes the same `mcpServers` block in its own MCP
config; see [Antigravity's MCP docs](https://antigravity.google/docs/mcp).

</TabItem>
<TabItem label="Cursor">

Use the **Add to Cursor** button above, or add the server to `~/.cursor/mcp.json` (every project) or
`.cursor/mcp.json` (one project):

```json
{
  "mcpServers": {
    "zombye": {
      "command": "/path/to/zombye/target/release/zombye-server",
      "args": ["--mcp", "--zombies", "1000"]
    }
  }
}
```

</TabItem>
<TabItem label="VS Code">

Use the **Install in VS Code** button above, or add it to `.vscode/mcp.json` in your workspace. Note the top-level
key is `servers`, not `mcpServers`:

```json
{
  "servers": {
    "zombye": {
      "type": "stdio",
      "command": "/path/to/zombye/target/release/zombye-server",
      "args": ["--mcp", "--zombies", "1000"]
    }
  }
}
```

Then use it from Copilot's agent mode.

</TabItem>
<TabItem label="SDKs">

To write your own agent around the game, give the server to an agent framework.

**Claude Agent SDK** (Python):

```python
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage


async def main():
    options = ClaudeAgentOptions(
        mcp_servers={
            "zombye": {
                "command": "/path/to/zombye/target/release/zombye-server",
                "args": ["--mcp", "--zombies", "1000"],
            }
        },
        allowed_tools=["mcp__zombye__*"],
    )
    async for message in query(
        prompt="You are player 1 in Zombye. Call observe, then loot the house you woke up in.",
        options=options,
    ):
        if isinstance(message, ResultMessage) and message.subtype == "success":
            print(message.result)


asyncio.run(main())
```

`allowed_tools=["mcp__zombye__*"]` lets it use every Zombye tool without asking. In TypeScript the options are
`mcpServers` and `allowedTools`; see the [Agent SDK's MCP guide](https://code.claude.com/docs/en/agent-sdk/mcp).

**OpenAI Agents SDK** (Python):

```python
from agents import Agent, Runner
from agents.mcp import MCPServerStdio


async def main():
    async with MCPServerStdio(
        name="zombye",
        params={
            "command": "/path/to/zombye/target/release/zombye-server",
            "args": ["--mcp", "--zombies", "1000"],
        },
    ) as zombye:
        agent = Agent(
            name="Survivor",
            instructions="You are player 1 in Zombye. Survive as long as you can.",
            mcp_servers=[zombye],
        )
        result = await Runner.run(agent, "Call observe, then loot the house you woke up in.")
        print(result.final_output)


asyncio.run(main())
```

See the [Agents SDK's MCP guide](https://openai.github.io/openai-agents-python/mcp/).

</TabItem>
<TabItem label="Other">

Every other MCP client takes the same three things: a name, a command and its arguments.

| | |
|---|---|
| Name | `zombye` |
| Command | `/path/to/zombye/target/release/zombye-server` |
| Arguments | `--mcp --zombies 1000` |
| Transport | stdio |
| Environment | none needed |

Most apps use the `mcpServers` JSON shown in the Claude Desktop tab. Use the full path to the binary: apps often
start servers from another folder.

</TabItem>
</Tabs>

<Aside type="tip" title="Or let your agent do it">
Coding agents can set this up themselves. Paste this into one:

> Set up the Zombye MCP server for yourself by following the instructions in
> https://getzombye.com/docs/agents/connect.md. Build it if
> `target/release/zombye-server` doesn't exist yet.
</Aside>

## 3. Choose the world

The server takes the same world options as the game. Add them after `--mcp`:

| Option | What it does |
|---|---|
| `--seed S` | Which town. The same seed always makes the same town. |
| `--zombies N` | How many zombies. Without it, the population file's number for the map (about 2,950). Fewer is easier, and lighter on your machine. |
| `--map-chunks N` | Map size, N × 16 m a side (default 30). |
| `--save PATH` | Load that save if it exists, else make a new world and save it there. Autosaves every few minutes of real time when something changed, and on exit. |
| `--autosave-mins N` | How often to autosave (default 5; 0 is off). |
| `--saves DIR` | The folder for the `save` and `load` tools' named saves. |
| `--data DIR` | Play on [modded](/docs/modding/) data instead of `assets/data`. |
| `--client PATH` | Where the game binary is, for screenshots (default: next to the server). |
| `--no-debug-tools` | Leave out the [debug tools](/docs/agents/tools/#debug) (spawning, god mode, skipping time, loading saves): the agent can only do what a player can. |

## 4. Say hello

> Use the zombye tools. Call `observe` and tell me where you are and what's around you.

It should describe a bedroom in a house, the rooms round it and what's in reach. Next:
[the tutorial](/docs/agents/tutorial/).

## Screenshots and your model

`screenshot` returns a PNG as an MCP image, followed by a line of text. Apps that pass images on to the model let it
see the game: Claude Code, Claude Desktop, Cursor, Gemini CLI and the agent SDKs do. In apps that don't, the model
gets only the text line, and `observe` is the way it sees. A picture is 960 × 540 unless you ask otherwise, about
half a megabyte; 1280 × 720 is about 1 MB. Ask for a bigger `width` and `height` when the detail matters, a smaller
one (say 640 × 360) to keep conversations light.

## Over the network: the HTTP server

`zombye-server --mcp-http` is the same server with the same tools, reached over HTTP (MCP's streamable HTTP transport)
instead of being started by your agent's app. It keeps running on its own, holds **one world**, and everyone who
connects plays in that world.

```bash
export ZOMBYE_MCP_TOKEN="$(openssl rand -hex 24)"   # any secret of 16 characters or more
/path/to/zombye/target/release/zombye-server --mcp-http --zombies 1000 --save saves/agents.zsave
```

It listens on `http://127.0.0.1:8787/mcp`. `--mcp-http 0.0.0.0:8787` listens on every interface, `--mcp-http 9000`
on another port. Callers send the token as `Authorization: Bearer <token>`. In Claude Code, for example:

```bash
claude mcp add --transport http zombye http://127.0.0.1:8787/mcp --header "Authorization: Bearer $ZOMBYE_MCP_TOKEN"
```

| Option | What it does |
|---|---|
| `ZOMBYE_MCP_TOKEN`, or `--mcp-token T` | The token callers must send. The environment variable is better: other users of the machine can't see it in the process list. |
| `--mcp-no-dev` (or `--no-debug-tools`) | Leaves out the [debug tools](/docs/agents/tools/#debug) (`dev`, `spawn_zombies`, `spawn_item`, `wound`, `set_needs`, `set_goal`, `make_noise`, `skip_time`, `add_player`, `pvp`, `load`) and, over HTTP, the saves folder's `save` and `saves` too. They aren't listed, and calling one is the unknown-tool error. |
| `--mcp-no-auth` | No token: anyone who can reach the server plays. The debug tools are always off then. |
| `--mcp-token-in-url` | Also takes the token as the last part of the address, `/mcp/<token>`, for apps that can only be given a URL. Weaker: addresses end up in logs. |
| `--mcp-origin ORIGIN` | Allows web pages from that origin to call the server from a browser (`*`: any). Pages on your own machine (`http://localhost:...`) always may; other programs aren't affected. |

The server speaks plain HTTP. To reach it from another machine safely, put something that adds HTTPS in front of it: a
reverse proxy (Caddy, nginx) or a tunnel (Cloudflare Tunnel, Tailscale Funnel, ngrok), pointed at `127.0.0.1:8787`.
`GET /health` answers `ok` without a token, for whatever watches the process.

<Aside type="caution">
With a token and without `--mcp-no-dev`, the debug tools are on (spawn anything, god mode, load saves): whoever has the
token controls the whole world and can write saves on your machine. Give the token only to agents you would give that
to, and use `--mcp-no-dev` for a server others play on.
</Aside>

## Web apps: claude.ai, ChatGPT

claude.ai's connectors, ChatGPT's developer mode and the OpenAI Responses API only connect to **remote** MCP servers,
over HTTPS on the public internet. Run the HTTP server above behind HTTPS and give the app its address:
`https://your-host/mcp` with the token as a bearer token (an `Authorization` header), or, where the app only takes a URL, start the server with `--mcp-token-in-url` and give it `https://your-host/mcp/<token>`.

We haven't tried these apps against it yet, and it doesn't do OAuth sign-in, which some of them ask for
([#87](https://github.com/deadcommons/zombye/issues/87) tracks both). Whether the model sees `screenshot` pictures
depends on the app: the server sends them the same way over HTTP as locally.

## Troubleshooting

- **The server won't connect, or "connection closed".** The binary isn't built, or the path is relative and the app
  started it from another folder. Build it, and use the absolute path.
- **`screenshot` says "no game client at ...".** Build the client too (`-p zombye-client`), or pass `--client PATH`
  (or set `ZOMBYE_CLIENT`) to the `zombye` binary.
- **A call times out.** Some calls step the world for a long time (`sleep`, big `step_ticks`). Raise your app's tool
  timeout (Codex: `tool_timeout_sec`; Claude Code: the `MCP_TOOL_TIMEOUT` environment variable).
- **The world is the same every time.** That's the seed. Pass `--seed` with another number.
- **The agent says nothing happens.** Time only moves when a tool steps it. Ask the agent to move or step time.