# MCP server

- **Status:** current on 2026-11-06, for version 0.
- **Related documents:** [Surface for agents](https://surface.solenovis.com/docs/ai.md), [the `surf` command](https://surface.solenovis.com/docs/commands.md), [ADR-0107](https://git.solenovis.com/henning.liemant/surface/src/branch/main/docs/adr/0107-an-mcp-server-for-agents.md)

The Model Context Protocol (MCP) is the standard way to give an agent tools. The MCP server of Surface gives the documents of this version, and it checks and formats Surf code.

There are two ways to use it:

- **Local:** `surf mcp`. The agent starts it on your computer. It uses the `surf` command that you installed, so the documents and the checks match your version.
- **Remote:** `https://surface.solenovis.com/mcp`. It needs no install. It has the documents and the checks of the version of `surf` that this website runs.

---

## 1. Tools, resources and prompt

| Name | Kind | What it does |
|---|---|---|
| `list_sections` | Tool | Gives the id, the title and the summary of each document. |
| `get_documentation` | Tool | Gives the text of one or more documents, by id. |
| `check_code` | Tool | Runs `surf check` and `surf lint` on source text. Each error and each finding has the file, the line, the column, a message and a fix hint. |
| `format_code` | Tool | Runs `surf fmt` on the text of one file. |
| `surf://docs/<id>.md` | Resource | One document. |
| `surf_task` | Prompt | The steps that an agent follows to write Surf code with these tools. |

`check_code` takes an object of file names and source text, for example `{"App.surf": "...", "model.surfs": "..."}`. A file can also be an `.svg` icon or `style.toml`. The server reads no file of your project, and it runs no code of the text.

The server speaks revision `2026-07-28` of the protocol, and the four earlier revisions.

---

## 2. Local setup

The local server needs the `surf` command. [The `surf` command](https://surface.solenovis.com/docs/commands.md) has the install. The command is `surf mcp`, and it uses stdin and stdout.

A desktop app can start with another `PATH` than your shell. If the app does not find `surf`, use the full path, for example `/Users/you/.surf/bin/surf`.

The settings of a client can change with a new version of the client. If a setting does not work, read the documents of the client.

### Claude Code

Run this command. The scope is `user`, `project` or `local`:

```bash
claude mcp add -t stdio -s user surface -- surf mcp
```

The [plugin](https://surface.solenovis.com/docs/plugins.md) also adds the server.

### Claude Desktop

1. Open Settings, then Developer, then Edit Config.
2. Add the server to `claude_desktop_config.json`:

   ```json
   {
     "mcpServers": {
       "surface": { "command": "surf", "args": ["mcp"] }
     }
   }
   ```

3. Start Claude Desktop again.

### Codex CLI

Add the server to `~/.codex/config.toml`:

```toml
[mcp_servers.surface]
command = "surf"
args = ["mcp"]
```

The [plugin](https://surface.solenovis.com/docs/plugins.md) also adds the server.

### Cursor

1. Open the command palette, and run "View: Open MCP Settings".
2. Select "Add custom MCP". Cursor opens its file of MCP servers.
3. Add the server:

   ```json
   {
     "mcpServers": {
       "surface": { "command": "surf", "args": ["mcp"] }
     }
   }
   ```

### VS Code

1. Open the command palette, and run "MCP: Add Server...".
2. Select "Command (stdio)".
3. Type the command `surf mcp`, and the name `surface`.

The same server in `.vscode/mcp.json`:

```json
{
  "servers": {
    "surface": { "type": "stdio", "command": "surf", "args": ["mcp"] }
  }
}
```

### Zed

1. Open the command palette, and run "agent: open settings".
2. Under Model Context Protocol (MCP) Servers, select Add Server, then Add Custom Server.
3. Add the server:

   ```json
   {
     "surface": { "command": "surf", "args": ["mcp"] }
   }
   ```

### Other clients

Use a stdio server with the command `surf` and the argument `mcp`.

---

## 3. Remote setup

The address of the hosted server is `https://surface.solenovis.com/mcp`. It uses the Streamable HTTP transport.

### Claude Code

```bash
claude mcp add -t http -s user surface https://surface.solenovis.com/mcp
```

### Claude Desktop

1. Open Settings, then Connectors.
2. Select Add Custom Connector.
3. Type the name `surface` and the address `https://surface.solenovis.com/mcp`.

### Codex CLI

Add the server to `~/.codex/config.toml`:

```toml
experimental_use_rmcp_client = true

[mcp_servers.surface]
url = "https://surface.solenovis.com/mcp"
```

### Cursor

```json
{
  "mcpServers": {
    "surface": { "url": "https://surface.solenovis.com/mcp" }
  }
}
```

### VS Code

1. Open the command palette, and run "MCP: Add Server...".
2. Select HTTP.
3. Type the address `https://surface.solenovis.com/mcp`, and the name `surface`.

The same server in `.vscode/mcp.json`:

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

### Other clients

Read the documents of the client for a remote server, and use the address above.

---

## 4. Limits of the hosted server

The hosted server has no sign-in. So it trusts nothing that a client sends:

| Limit | Value | Result above the limit |
|---|---|---|
| The body of a request | 1 MB | Status 413 |
| The head of a request | 16 KB | Status 431 |
| Open connections | 32 | Status 503 |
| The time of one request | 10 seconds | Status 408, or a tool error for a compile |
| Items in one result of `check_code` | 100 | The result has `truncated: true` |
| The `Origin` header | Absent, a loopback origin, or the origin of the website | Status 403 |

A new process compiles each text, with its own limits of time and memory. The server logs no text of a request. The reverse proxy in front of the server limits the rate of each client.

---

## 5. Run your own hosted server

`surf mcp --http <port>` serves the same tools at `/mcp`:

```bash
surf mcp --http 8080 --bind 0.0.0.0 --origin https://example.com
```

- `--bind` sets the address. The default is `127.0.0.1`.
- `--origin` adds an accepted `Origin` header. You can give it more than once.

The server has no TLS and no rate limit. Put a reverse proxy in front of it, with TLS and a limit for each client. [Security](https://surface.solenovis.com/docs/security.md) lists the settings of a server behind a proxy.
