---
title: "MCP server"
description: "Every tool the Treehouse MCP server exposes, with parameters, outputs, limits and the instructions it gives connected agents."
canonical_url: "https://trytree.house/docs/agents/reference/mcp-server"
last_updated: "2026-09-29"
---

# MCP server

Every tool the Treehouse MCP server exposes, with parameters, outputs, limits and the instructions it gives connected agents.

## Connection

| Setting | Value |
| --- | --- |
| Endpoint | `https://api.trytree.house/api/mcp` |
| Transport | Streamable HTTP, stateless (no session id), JSON responses |
| Auth | `x-api-key: <key>` header. `Authorization: Bearer` is not accepted. |
| OAuth | Not supported. The key header is the only credential. |
| Server name | `treehouse` |

**mcp.json**

```json
{
  "mcpServers": {
    "treehouse": {
      "type": "http",
      "url": "https://api.trytree.house/api/mcp",
      "headers": { "x-api-key": "th_example_key" }
    }
  }
}
```

The exact configuration format depends on your client; [connect other agents](https://trytree.house/docs/agents/connect/other-agents) has examples. Every tool call is attributed to the key's actor type (`agent` or `human`) and name, exactly as a REST request would be. See [authentication](https://trytree.house/docs/agents/reference/authentication).

## Two tool sets

Which tools a client sees depends on the key it connects with.

| Key | Tools |
| --- | --- |
| Account-wide (created in the web app) | All the tools below. Every tool except `list_workspaces` and `create_workspace` takes a required `workspaceId` string, checked against your membership on each call. |
| Workspace-scoped (device flow) | The same tools without `list_workspaces` and `create_workspace`, and without a `workspaceId` parameter: every call acts on the key's workspace. |

The parameter tables below omit `workspaceId`. Add it when you use an account-wide key.

## Server instructions

Connected clients receive these instructions with the tool list. They are quoted exactly:

```text
Treehouse is a shared file workspace for humans and agents. Files are plain bytes; a markdown file may begin with a YAML front-matter block (--- ... ---) carrying metadata.

Read AGENTS.md at the workspace root before doing anything else, if it exists. It carries that workspace's own conventions — how it is organised and what belongs where. In a workspace that has not been set up yet, it instead carries a setup guide: follow it when the user asks you to set up, bootstrap, or organise the workspace.

Front-matter conventions the web UI understands — set them by writing the file, no special API needed:
- "date: YYYY-MM-DD" on a markdown file places it on its folder's Calendar view for that day. Change the date to reschedule it; remove it to take it off the calendar. Only files with a valid date appear there.
- A folder's README.md (or index.md) front matter can declare "view: calendar" to make the folder open as a calendar, and "title:" to give the folder a human-readable heading (shown instead of the raw folder name).

Anything the web UI does with front matter is a plain-file operation, so reading and writing files is enough to participate in those. Comments are the exception: they are review threads held by the server, not files, and only the comment tools can see them.

Reviewers comment on markdown files by quoting the text they mean — there are no line numbers. When asked to address comments on a file: list_comments for that path, read_file it (note the returned version), write_file your revision with that version as baseVersion, then reply_comment on each thread saying what you changed, and resolve_comment only the threads you actually fixed. Don't resolve what you didn't fix — reply instead. A thread whose anchorStatus is not "anchored" refers to text that has since changed: read_file_version at its pinnedVersion to see the document it was written against. Use add_comment to raise a question of your own, quoting the passage it is about.
```

The front-matter conventions are described in [front matter](https://trytree.house/docs/files/front-matter) and [folder pages](https://trytree.house/docs/files/folder-pages).

## Result conventions

- Most tools return a short text summary plus a `structuredContent` object. Read values such as `version` from `structuredContent`, not by parsing the text: file content can contain anything.
- **Hard errors** set `isError: true` with a text message: not found, invalid path, file too large, read-only workspace, a refused share, a stale delete, and malformed input. Paths you can't see (another member's private files) are reported as not found.
- **Recoverable outcomes** are returned as data with `ok: false`, so the agent keeps its work and can retry: a `write_file` version conflict (your content is saved as a conflicted copy), a storage or file-count limit, and an `add_comment` quote that can't be placed.
- Paths are workspace-relative with `/` separators, such as `Projects/plan.md`. A leading `/` and `.` segments are ignored; `..`, backslashes, null bytes and an empty path are rejected with `Invalid path: …`.

## Workspaces

### list_workspaces

Lists the workspaces the key can reach. Account-wide keys only. No parameters.

Output: `{ workspaces: [{ id, name }] }`.

### create_workspace

Creates a workspace owned by you, with no other members. Account-wide keys only. Subject to your plan's workspace allowance.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | Yes | Workspace name. |
| `icon` | string | No | An emoji or an Iconify name. For an image, create first, then call `set_workspace_image_icon`. |
| `color` | string | No | `blue`, `violet`, `emerald`, `amber`, `rose`, `cyan`, `slate` or `neutral`. |

Output: `{ id, name }`. New workspaces start with a `README.md` and an `AGENTS.md` setup guide unless the server disables seeding.

### set_workspace

Updates the workspace's display settings. Pass an empty string to clear `icon`, `color` or `theme`. An empty `name` is ignored.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | No | New name. |
| `icon` | string | No | An emoji or an Iconify name. |
| `color` | string | No | `blue`, `violet`, `emerald`, `amber`, `rose`, `cyan`, `slate` or `neutral`. |
| `theme` | string | No | `light`, `dark`, `dracula`, `nord`, `solarized-light`, `rose-pine` or `treehouse`. |

Output: `{ id, name, icon, color, theme }`.

### set_workspace_image_icon

Sets an image as the workspace icon.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `content` | string | Yes | Base64-encoded PNG, JPEG, GIF or WebP, up to 1 MiB. Square images around 256×256 look best; other shapes are letterboxed, never cropped. |

Output: `{ id, name, icon }`.

### get_usage

Storage and file-count usage against the workspace's plan. No parameters.

Output: `{ usedBytes, limitBytes, remainingBytes, warning, usedFiles, limitFiles, remainingFiles }`. Limits and remaining values are `null` when unlimited. `warning` is `true` once the file count reaches 90% of its limit. See [plans and limits](https://trytree.house/docs/account/plans-and-limits).

## Files

### list_files

Lists files under an optional folder, sorted by path. Hidden `.keep` placeholders are omitted.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `prefix` | string | No | Folder to list, such as `Projects`. Omit for the whole workspace. |
| `limit` | integer | No | Maximum entries. Default and maximum 1000. |
| `offset` | integer | No | Entry to start from, for paging. |

Output: text only, one line per file in the form `path<TAB>(v3, 1204 bytes)`. When there are more entries, the last line says how many and which `offset` to pass next. An empty result is `(no files)`.

### search_files

Fuzzy search over file and folder names and paths, not contents. The characters of the query must appear in order but need not be adjacent: `clinot` matches `Clients/acme/notes.md`. Results are ranked best first and there is no paging, so narrow the query instead.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `query` | string | Yes | Text to match. |
| `limit` | integer | No | Maximum results. Default 50, maximum 200. |

Output: `{ results: [{ path, name, isDir }], totalMatches }`. `totalMatches` counts every match before the limit. The text summary frames names as untrusted data, because anyone in the workspace can name a file.

### read_file

Reads a file's current bytes and version.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | string | Yes | File path. |
| `encoding` | string | No | `utf8` (default) or `base64`. Use `base64` for images, PDFs and other binary files. |
| `maxBytes` | integer | No | Read at most this many bytes, starting at `offset`. |
| `offset` | integer | No | Byte offset to start from. |

Output: `{ version, contentType, content }`. Keep `version`: it is the `baseVersion` for your next write.

A single response is capped at 1 MiB. A larger file read without `maxBytes` or `offset` is refused with its size, and `maxBytes` above the cap is clamped to it. Read a large file in windows by advancing `offset`.

### write_file

Creates or updates a file.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | string | Yes | File path. Missing parent folders are created implicitly. |
| `content` | string | Yes | The complete new content. |
| `baseVersion` | integer | No | The version you last read. Omit only when creating a new file. |
| `encoding` | string | No | `utf8` (default) or `base64`. |

| Outcome | `structuredContent` |
| --- | --- |
| Written | `{ ok: true, version }` |
| Version conflict | `{ ok: false, currentVersion, conflictCopyPath }`. Your content was saved at `conflictCopyPath`. |
| Storage limit reached | `{ ok: false, quotaExceeded: true, usedBytes, limitBytes }`. Nothing written. |
| File limit reached | `{ ok: false, fileCountExceeded: true, usedFiles, limitFiles }`. Nothing written. |

How `baseVersion` is handled:

- **Omitted, path doesn't exist:** the file is created at version 1.
- **Omitted, path exists:** if your content is byte-for-byte identical, the call succeeds and returns the existing version. If it differs, nothing is overwritten: your content is saved as a conflicted copy and the result is `ok: false`.
- **Matches the current version:** the file is updated and the version goes up by one.
- **Stale:** identical content succeeds without a new version; different content becomes a conflicted copy. If the file was deleted since you read it, your write recreates it at version 1.

A file larger than the workspace's per-file limit is a hard error. A read-only workspace (lapsed subscription) is a hard error. [Versions and conflicts](https://trytree.house/docs/agents/handbook/versions-and-conflicts) explains the rules in full.

### move_file

Moves or renames one file. Folders are moved by moving their files.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `from` | string | Yes | Current path. |
| `to` | string | Yes | New path. |

Output: text only. Fails if `to` already exists. There is no `baseVersion`: the move applies to whatever the current version is. The file restarts at **version 1** at its new path, and its comment threads move with it. Re-read before writing to the new path.

### delete_file

Deletes a file.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | string | Yes | File path. |
| `baseVersion` | integer | Yes | The version you last read. |

Output: text only. If the file has changed since `baseVersion`, nothing is deleted and the call returns an error naming the current version. Re-read before deciding again.

### set_file_icon

Sets the icon shown for a file or folder.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | string | Yes | File or folder path, up to 1024 characters. |
| `icon` | string | No | An emoji or an Iconify name such as `solar:document-bold-duotone`, up to 64 characters. Empty or omitted clears it. |

Output: text only.

### set_private

Makes a file or folder private to the key's owner, or shared again. A private folder hides its whole subtree from other members.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | string | Yes | File or folder path, up to 1024 characters. |
| `kind` | string | No | `file` or `folder`. Defaults to `folder`, so pass `file` for a file. |
| `private` | boolean | No | `true` (default) to make private, `false` to share again. |

Output: text only. Only the owner can make a private item shared again.

## History

### read_file_version

Reads the bytes of an earlier version.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | string | Yes | File path. |
| `version` | integer | Yes | Version number to read. |
| `encoding` | string | No | `utf8` (default) or `base64`. |

Output: `{ version, contentType, content }`. If that version's content isn't available, the call returns an error.

### restore_file

Restores an earlier version as a new version on top of the history. Nothing is overwritten or removed.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | string | Yes | File path. |
| `targetVersion` | integer | Yes | The version to bring back. |

Output: `{ status: "ok", version, restoredFrom }`, or `{ status: "conflict", conflictCopyPath }` if other writes kept winning and the restored content was saved as a conflicted copy instead.

## Sharing

### create_share

Creates a member link to a file or folder: a link that only workspace members can open.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | string | Yes | File or folder path. |
| `kind` | string | Yes | `file` or `folder`. |
| `access` | string | No | Only `member` is accepted. `public` is refused. |

Output: `{ id, path, access, memberUrl }`. Public and password-protected links can only be made by a person signed in to the web app, so a leaked key can't publish your files. Private items can't be shared.

### list_shares

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | string | Yes | File or folder path. |

Output: `{ shares: [...] }`, the active shares on exactly that path.

### revoke_share

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `shareId` | string | Yes | The share's `id`. |

Output: text only.

## Comments

Comment threads live on markdown files and are anchored by quoting text, never by line or character position. See [comments](https://trytree.house/docs/sharing/comments) for how they look to people.

### list_comments

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | string | No | Only threads on this file. |
| `threadId` | string | No | Read one thread. |
| `status` | string | No | `open` or `resolved`. |
| `anchorStatus` | string | No | `anchored`, `ambiguous` or `outdated`. |
| `author` | string | No | Only threads started by this user id. |
| `limit` | integer | No | Threads per page. Default 50, maximum 200. |
| `offset` | integer | No | Thread to start from. |
| `entriesLimit` | integer | No | Replies per thread. Default 20, maximum 100. |
| `entriesOffset` | integer | No | Reply to start from, to read past the first 100. |

Output: `{ threads, total, more, nextOffset, truncated }`. Each thread has `id`, `path`, `status`, `anchorKind`, `quote`, `contextBefore`, `contextAfter`, `currentText` (the matching text now, or `null` once the anchor stops resolving), `pinnedVersion` (the version it was written against), `anchorStatus`, `createdBy`, `entries`, `entryCount` and resolution details. `nextOffset` is `null` on the last page. `truncated: true` means an `anchorStatus` filter stopped scanning early; narrow the other filters rather than paging.

### add_comment

Starts a thread on a markdown file.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `path` | string | Yes | Markdown file path. |
| `body` | string | Yes | The comment, up to 64 KiB. |
| `quote` | string | For `range` | The exact text being commented on, up to 4 KiB. |
| `contextBefore` | string | No | Text just before the quote (or the point), up to 512 bytes. |
| `contextAfter` | string | No | Text just after, up to 512 bytes. |
| `occurrence` | integer | No | Which match to use (from 1) when the quote appears more than once. |
| `kind` | string | No | `range` (default) or `point`. A point needs both contexts and no quote. |
| `baseVersion` | integer | No | The version you copied the quote from. |

| Outcome | `structuredContent` |
| --- | --- |
| Created | `{ ok: true, thread }` |
| Quote appears several times | `{ ok: false, error: "anchor_ambiguous", occurrences }` |
| Quote not in the file | `{ ok: false, error: "anchor_not_found" }` |
| File changed too much | `{ ok: false, error: "base_version_conflict", baseVersion, currentVersion, reason }` |

Nothing is created on an `ok: false` result. A non-markdown file is a hard error.

### reply_comment

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `threadId` | string | Yes | The thread. |
| `body` | string | Yes | The reply, up to 64 KiB. |
| `dedupeKey` | string | No | Any string unique to this reply. Send one every time: a retried call with the same key records one reply, not two. |

Output: `{ ok: true, entry, deduped }`. `deduped: true` means the reply already existed.

### resolve_comment

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `threadId` | string | Yes | The thread. |
| `resolved` | boolean | Yes | `true` to resolve, `false` to reopen. |

Output: `{ ok: true, resolved, changed, resolvedAt, resolvedAtVersion, resolvedBy }`. Idempotent: `changed: false` means it was already in that state.

## Limits

| Limit | Value |
| --- | --- |
| `read_file` response | 1 MiB per call; page larger files with `maxBytes` and `offset` |
| `list_files` entries | 1000 per call; page with `offset` |
| `search_files` results | Default 50, maximum 200, no paging |
| File size on write | Your plan's per-file limit |
| Comment body / reply | 64 KiB |
| Comment quote | 4 KiB |
| Comment context (each side) | 512 bytes |
| Threads per `list_comments` page | Default 50, maximum 200 |
| Replies per thread per page | Default 20, maximum 100 |
| Workspace image icon | 1 MiB |

## Related

- [Connect Claude Code](https://trytree.house/docs/agents/connect/claude-code): Give Claude Code access to a workspace through your synced folder, the Treehouse MCP server, or both.
- [Connect other agents](https://trytree.house/docs/agents/connect/other-agents): Connection settings for Cursor, VS Code, Codex, Gemini CLI, Claude Desktop and any other MCP client.
- [Versions and conflicts](https://trytree.house/docs/agents/handbook/versions-and-conflicts): The concurrency contract every Treehouse client shares - version numbers, compare-and-swap writes, conflicted copies, deletes, moves and restores.
