MCP server

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

Connection

SettingValue
Endpointhttps://api.trytree.house/api/mcp
TransportStreamable HTTP, stateless (no session id), JSON responses
Authx-api-key: <key> header. Authorization: Bearer is not accepted.
OAuthNot supported. The key header is the only credential.
Server nametreehouse
mcp.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 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.

Two tool sets

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

KeyTools
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 and 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.

ParameterTypeRequiredDescription
namestringYesWorkspace name.
iconstringNoAn emoji or an Iconify name. For an image, create first, then call set_workspace_image_icon.
colorstringNoblue, 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.

ParameterTypeRequiredDescription
namestringNoNew name.
iconstringNoAn emoji or an Iconify name.
colorstringNoblue, violet, emerald, amber, rose, cyan, slate or neutral.
themestringNolight, 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.

ParameterTypeRequiredDescription
contentstringYesBase64-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.

Files

list_files

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

ParameterTypeRequiredDescription
prefixstringNoFolder to list, such as Projects. Omit for the whole workspace.
limitintegerNoMaximum entries. Default and maximum 1000.
offsetintegerNoEntry 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.

ParameterTypeRequiredDescription
querystringYesText to match.
limitintegerNoMaximum 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.

ParameterTypeRequiredDescription
pathstringYesFile path.
encodingstringNoutf8 (default) or base64. Use base64 for images, PDFs and other binary files.
maxBytesintegerNoRead at most this many bytes, starting at offset.
offsetintegerNoByte 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.

ParameterTypeRequiredDescription
pathstringYesFile path. Missing parent folders are created implicitly.
contentstringYesThe complete new content.
baseVersionintegerNoThe version you last read. Omit only when creating a new file.
encodingstringNoutf8 (default) or base64.
OutcomestructuredContent
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 explains the rules in full.

move_file

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

ParameterTypeRequiredDescription
fromstringYesCurrent path.
tostringYesNew 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.

ParameterTypeRequiredDescription
pathstringYesFile path.
baseVersionintegerYesThe 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.

ParameterTypeRequiredDescription
pathstringYesFile or folder path, up to 1024 characters.
iconstringNoAn 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.

ParameterTypeRequiredDescription
pathstringYesFile or folder path, up to 1024 characters.
kindstringNofile or folder. Defaults to folder, so pass file for a file.
privatebooleanNotrue (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.

ParameterTypeRequiredDescription
pathstringYesFile path.
versionintegerYesVersion number to read.
encodingstringNoutf8 (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.

ParameterTypeRequiredDescription
pathstringYesFile path.
targetVersionintegerYesThe 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.

ParameterTypeRequiredDescription
pathstringYesFile or folder path.
kindstringYesfile or folder.
accessstringNoOnly 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

ParameterTypeRequiredDescription
pathstringYesFile or folder path.

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

revoke_share

ParameterTypeRequiredDescription
shareIdstringYesThe 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 for how they look to people.

list_comments

ParameterTypeRequiredDescription
pathstringNoOnly threads on this file.
threadIdstringNoRead one thread.
statusstringNoopen or resolved.
anchorStatusstringNoanchored, ambiguous or outdated.
authorstringNoOnly threads started by this user id.
limitintegerNoThreads per page. Default 50, maximum 200.
offsetintegerNoThread to start from.
entriesLimitintegerNoReplies per thread. Default 20, maximum 100.
entriesOffsetintegerNoReply 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.

ParameterTypeRequiredDescription
pathstringYesMarkdown file path.
bodystringYesThe comment, up to 64 KiB.
quotestringFor rangeThe exact text being commented on, up to 4 KiB.
contextBeforestringNoText just before the quote (or the point), up to 512 bytes.
contextAfterstringNoText just after, up to 512 bytes.
occurrenceintegerNoWhich match to use (from 1) when the quote appears more than once.
kindstringNorange (default) or point. A point needs both contexts and no quote.
baseVersionintegerNoThe version you copied the quote from.
OutcomestructuredContent
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

ParameterTypeRequiredDescription
threadIdstringYesThe thread.
bodystringYesThe reply, up to 64 KiB.
dedupeKeystringNoAny 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

ParameterTypeRequiredDescription
threadIdstringYesThe thread.
resolvedbooleanYestrue to resolve, false to reopen.

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

Limits

LimitValue
read_file response1 MiB per call; page larger files with maxBytes and offset
list_files entries1000 per call; page with offset
search_files resultsDefault 50, maximum 200, no paging
File size on writeYour plan's per-file limit
Comment body / reply64 KiB
Comment quote4 KiB
Comment context (each side)512 bytes
Threads per list_comments pageDefault 50, maximum 200
Replies per thread per pageDefault 20, maximum 100
Workspace image icon1 MiB
  • Connect Claude Code

    Give Claude Code access to a workspace through your synced folder, the Treehouse MCP server, or both.

  • Connect other agents

    Connection settings for Cursor, VS Code, Codex, Gemini CLI, Claude Desktop and any other MCP client.

  • Versions and conflicts

    The concurrency contract every Treehouse client shares - version numbers, compare-and-swap writes, conflicted copies, deletes, moves and restores.

Last updated