Galley MCP
Allows using a local Ollama instance as the AI provider for Galley's document editing agent.
Allows using OpenAI or any OpenAI-compatible endpoint as the AI provider for Galley's document editing agent.
Allows importing Overleaf projects into Galley via .zip archives.
Allows importing references from Zotero/BibTeX (.bib) libraries into Galley.
A galley proof is the preliminary typeset version you check and correct before final layout — which is exactly this app's core loop: compile → inspect → correct → repeat.
Galley is, conceptually, "AI-enhanced ShareLaTeX, but Typst instead of LaTeX, open source, and not locked to one vendor's cloud or model." The differentiation is three bets a cloud-only, single-vendor product structurally cannot make:
Agentic, not autocomplete. Typst compiles in milliseconds and emits structured, machine-readable diagnostics. That makes a tight edit → compile → read errors → self-correct loop cheap. That loop is the product.
Local-first. The Typst compiler runs in the browser via WASM (
typst.ts). Your document and your compile stay on your machine. Server-side compile is an optional enhancement, never a dependency. (See the honest local-first definition — remote model endpoints still receive your document.)Bring-your-own-model. A provider abstraction runs the agent against any OpenAI-compatible endpoint, Anthropic, or a local Ollama. Model choice is config, never a fork.
Status
Galley works end-to-end in the browser today: a CodeMirror editor with a live
SVG preview (typst.ts compiling in a Web Worker) and the human-in-the-loop
agent loop — request → self-correct → diff → Accept/Reject → re-render.
Bring your own model (any OpenAI-compatible endpoint, Anthropic, or a local
Ollama) or use the built-in offline Demo agent. Real-time collaboration is
opt-in — one-click Share upgrades a project to Yjs CRDT co-editing with the
agent as a peer, presence, and per-author attribution (ADRs
0005–0012). Multi-file projects and templates, named versions
with visual compare, broad import/export (Markdown, LaTeX, Overleaf .zip,
Zotero/.bib in; PDF/PNG out), and opt-in MCP access behind an explicit
consent gate round it out. Self-host with Docker compose or Kubernetes; the
whole test suite (typecheck + unit + Playwright e2e) runs in Docker. See
the CHANGELOG for the full feature inventory and the
roadmap for what's next.
Default product & routes
Galley uses path-based routes (a tiny History-API router):
/— the Projects page, the landing surface (create / open / import projects)./p/<id>— a specific local-first project (auto-saved to the browser, reload-survivable)./library— the project dashboard./join/<room>— share-link entry (joins a collaboration room; carries?sync=/?role=)./settings— device-scoped settings.
Collaboration is an explicit Share action, never on by default. The only
editor-on-home hatch is ?seed=… (the seeded Einstein showcase, also the e2e entry).
Related MCP server: mcp-server-test
The core loop
User request
│
▼
Agent proposes edits (search/replace blocks)
│
▼
Apply to a SCRATCH copy ──► compile ──► read diagnostics
│ │
│ ◄── errors? revise (up to MAX_ITERS) ─┘
▼
Clean compile → present a reviewable diff
│
▼
User clicks Accept ──► apply to live document
or Reject ──► discard scratchIn the editor loop the human is always in control — the in-app agent never auto-applies an edit. (External MCP agents can be granted opt-in auto-accept — off by default, signed, checkpointed, and revertable — which only drives the same Accept path; see the security model.)
Bring your own agent (no API key)
Galley's built-in agent needs a provider API key, billed per token. You can skip that entirely: Galley ships a local MCP kernel that carries no model at all. No provider, no key, no inference. It is a bridge that exposes your project as tools to an agent you already run, so Claude Code or Codex drives Galley on the plan you already pay for.
# One-time: install the kernel's bin from your checkout
cd apps/mcp && pnpm link --global
# Share the project in the browser to mint a room id, then:
claude mcp add galley -- galley-mcp \
--sync ws://localhost:1234 --room <room-id> --file /main.typYour agent gets the live document, the file tree, query-relevant excerpts across
files, and real Typst diagnostics. What it does not get is write access:
propose_edit and propose_files publish a pending review card, and a human
clicks Accept. That gate is structural, not a preference.
Control mode goes further and lets the agent list your library and ask to open a project, behind a one-time pairing code, per-project read grants that default to zero, and a blocking confirmation for every open.
→ Use your own coding agent with Galley for the walkthrough, or the full kernel reference for every flag.
Monorepo layout
galley/
├─ apps/
│ ├─ web/ # React + Vite app: editor, preview, agent panel, diff UI
│ ├─ web-server/ # tiny Hono static server for the built SPA (self-host runtime)
│ ├─ sync/ # @galley/sync — optional y-websocket collaboration server
│ ├─ compile/ # optional server-side Typst compile service (Hono + @galley/compiler)
│ ├─ proxy/ # thin, optional, self-hostable model-API proxy (keys off the browser)
│ └─ mcp/ # inbound MCP local kernel: exposes the agent tools to external MCP clients
├─ packages/
│ ├─ compiler/ # typst.ts wrapper: check(), render(), export() — in a Worker
│ ├─ agent/ # agent loop, tools, provider abstraction
│ ├─ collab/ # Yjs CRDT doc, presence, and cross-peer author attribution
│ ├─ auth/ # generic OIDC (Auth Code + PKCE) auth core
│ ├─ persistence/ # ProjectStore / CrdtStore / VersionStore adapters
│ └─ shared/ # cross-package types: Diagnostic, EditBlock, AgentEvent, …
├─ docs/ # foundation docs (start here ↓)
├─ AGENTS.md # rules for AI agents working ON this repo
└─ CONTRIBUTING.mdcompiler and agent are framework-agnostic (no React) so they can be reused
server-side. The optional server pieces — apps/proxy (model proxy, keys off the
browser), apps/sync (collaboration relay), and apps/compile (server-side
compile) — are stateless, off by default, and self-hostable (see the
ADRs). The default single-user path needs none of them.
Documentation
Read these in order:
Doc | Purpose |
Product principles, the three bets, non-goals, honest definitions | |
Package boundaries, data flow, the worker model, source-of-truth rules | |
What's built, what activates with config, future directions | |
Threat model, per-surface posture, deployment hardening checklist | |
Docker compose + Kubernetes packaging | |
Server topology, accounts/auth, Yjs collaboration, agent-as-peer (design rationale) | |
The agent state machine, tools, iteration/error/cancel handling, event stream | |
Search/replace contract, scratch isolation, diff, Accept/Reject conflicts | |
typst.ts init, worker protocol, fonts, diagnostics normalization, preview/export | |
Provider types, capability probing, CORS/key caveats, local vs remote privacy | |
Drive Galley from Claude Code or Codex over MCP, on your own plan instead of an API key | |
Architecture Decision Records (ADRs) |
Quick start
The fastest path — run it with Docker (no toolchain needed):
docker compose up --build # → http://localhost:8080The Demo (offline) model lets you try the full agent loop with no provider or API key configured; open Settings to point at an OpenAI-compatible endpoint, Anthropic, or a local Ollama.
For development with a local toolchain (Node ≥ 20, pnpm 9):
pnpm install
pnpm dev # runs @galley/webTests build and run entirely in Docker:
# Full green-gate: typecheck + unit + web build + Playwright e2e
# (--build is required: plain `run` reuses a cached image and would test stale code)
docker compose -f docker-compose.test.yml run --rm --build test
# Fast typecheck + unit only
docker compose -f docker-compose.test.yml run --rm --build unitSelf-hosting
docker compose up --build runs Galley (web + proxy + sync) at
http://localhost:8080 — see docs/self-host.md. The web app
compiles Typst in the browser by default, so it is complete on its own.
Enabling server-side compile (opt-in). The heavier compile service isn't run
by default, so Settings → Compile → Server reports "Not configured." To wire it
up, use the ready-to-run overlay:
docker compose -f docker-compose.yml -f docker-compose.compile.yml \
--profile compile up --buildIt pre-sets GALLEY_COMPILE_URL=http://127.0.0.1:3001/compile (the
browser-reachable endpoint) so Server/Auto "just work"; the default
docker compose up stays web-only. Details in
docs/self-host.md.
License
Galley is licensed under AGPL-3.0-only (see LICENSE): use,
modify, and self-host freely; if you offer a modified Galley to others over
a network, you must publish your modified source under the same license. The
"Galley" name and logo are protected separately by the
trademark policy — forks must rename. Contributions require
the CLA (see CONTRIBUTING).
The Typst compiler Galley builds on is Apache-2.0 (permissive — building on
it is fine); keep the name distinct (don't name anything "Typst") and ship
Typst's NOTICE if you ever redistribute its binary. See
docs/vision.md#licensing--branding.
Available Tools
8 toolscompileCompile the document for diagnosticsA
Type-checks the shared project and returns its diagnostics (errors/warnings + page count); never modifies the document. Uses the configured loopback compile service when one is set (--compile-url); otherwise falls back to the paired browser's live preview compiler. Call this after propose_files/propose_edit to confirm the change set type-checks before asking the human to Accept.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. It explicitly discloses safety ('never modifies the document'), the two possible compile backends (loopback service or browser live preview), and the output shape (errors/warnings + page count). This is strong disclosure beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: what it does, how it does it, and when to invoke it. Front-loaded with the core action and result, with the usage guidance placed last as a natural follow-up.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a zero-parameter, no-output-schema tool. It tells the agent the result format, the safety guarantee, the backend selection mechanism, and the precise workflow placement relative to siblings. No critical information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The description correctly avoids inventing parameter semantics and instead focuses on what the tool does and returns. Nothing is missing here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Type-checks') with a clear resource ('the shared project') and states what it returns ('diagnostics (errors/warnings + page count)'). It also clarifies a key boundary ('never modifies the document'), distinguishing it from the propose_* sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to call the tool: 'Call this after propose_files/propose_edit to confirm the change set type-checks before asking the human to Accept.' This is clear context, though it does not spell out when not to use it or name direct alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
galley_pingPing the Galley MCP kernelB
Liveness check. Returns 'pong' with the kernel version.
| Name | Required | Description | Default |
|---|---|---|---|
| echo | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It does state the primary behavior (returns 'pong' with kernel version), but it does not disclose what the 'echo' parameter does, any side effects, or permissions required. This is a partial disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise—two short sentences with no wasted words. The primary purpose is front-loaded. However, it omits crucial details about the parameter, so the conciseness comes at the expense of completeness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with one optional parameter and no annotations, the description is incomplete. It lacks any explanation of the 'echo' parameter, does not describe potential error conditions, and provides no information on return format beyond the string 'pong'. The tool could be called with an unexpected parameter value, and the agent would have no guidance.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has one optional parameter 'echo' with no description, and the tool description does not mention it at all. With 0% schema description coverage, the description must compensate, but it fails to explain the parameter's purpose or effect. An agent cannot infer what 'echo' does.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose as a liveness check that returns 'pong' with the kernel version. The title 'Ping the Galley MCP kernel' reinforces the specific action. It is distinct from sibling tools like read_document or propose_edit, which handle file operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It does not mention that it is for connectivity checks or any conditions for invocation. The agent is left to infer usage from the tool name and title.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_filesList the project's filesA
Lists the live (non-deleted) files of the shared project — exact path + size (UTF-8 bytes when sizeExact, else a cheap lower bound), deterministic order; duplicate-path conflicts are flagged per entry. BINARY files (images/PDFs) appear too, carrying a { kind:"binary", hash, mime } pointer descriptor with an exact sizeBytes — pass that path to read_file to get the pointer. Read-only context: edits still go through propose_edit and target only the session's file.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It discloses size semantics (UTF-8 bytes when sizeExact, else a cheap lower bound), deterministic ordering, duplicate-path conflict flags, binary file pointer descriptors with exact sizeBytes, and the read-only nature of the operation. This is exceptionally transparent for a tool with no annotation support.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences pack in the core action, output details, binary-file handling, and read-only context without redundancy. The most important information is front-loaded, and every clause adds value. The use of em-dashes and semicolons keeps related ideas together without bloating the text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless tool with no output schema, the description fully explains what the agent will receive: paths, sizes, duplicate flags, and binary pointers. It also explains how to proceed with binary files (pass to read_file) and clarifies the mutation boundary (propose_edit). Nothing needed to invoke or interpret the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The description does not need to explain parameters; it instead focuses on output semantics. It mentions 'sizeExact' as a field, not a parameter, which is appropriate. No parameter-related gap exists.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Lists the live (non-deleted) files of the shared project.' It then details exactly what is returned (path, size, deterministic order, duplicate-path flags) and distinguishes itself from read_file by explaining how binary file pointers are consumed by that sibling. This leaves no ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: it is a read-only listing operation, and edits are explicitly routed to propose_edit. It also tells the agent to pass binary file paths to read_file for the pointer. It does not explicitly compare against project_context or galley_ping, but the read-only/edit exclusion and the read_file handoff give enough practical guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
project_contextQuery-relevant project contextA
Returns the most RELEVANT excerpts across ALL the project's live files for a query (lexical ranking over structural chunks), each with provenance: file path, 1-based line range, and Typst heading path. Budget-limited and read-only: files with duplicate-path conflicts or over the per-file cap are skipped (listed in skipped with a reason), and selectionTruncated reports when relevant chunks did not fit the budget. Use read_file for a complete file.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | What you are looking for — ranks chunks across the whole project. | |
| budget | No | Response budget in characters of excerpt text (default 6144). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure, and it does so thoroughly. It states the tool is read-only and budget-limited, explains skip conditions (duplicate-path conflicts, per-file cap), and reports the `skipped` and `selectionTruncated` signals. This is far more than the minimal mutation/read distinction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two dense sentences with no filler. The core purpose and scope are front-loaded, and each additional clause covers an important behavioral caveat or a pointer to the sibling tool. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must explain return semantics, and it does: each excerpt has file path, 1-based line range, and Typst heading path; skipped files are listed with reasons; truncation is reported. It also covers budget limits and the read-only nature, making it complete for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3 because both parameters are already documented. The description adds meaningful context beyond the schema: it explains the ranking behavior for `query` (lexical ranking over structural chunks) and clarifies that `budget` overflow surfaces as `selectionTruncated`, which is genuinely useful behavioral detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the specific action (returns relevant excerpts), the resource (all live project files), and the distinguishing mechanism (lexical ranking over structural chunks). It also differentiates itself from read_file by explicitly stating the latter is for a complete file.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells the agent when to prefer this tool versus an alternative: 'Use read_file for a complete file.' This is a clear when/when-not boundary that helps an agent choose correctly without opening either implementation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_editPropose an edit (published for review)A
Applies search/replace edits to a scratch copy of the session's file and publishes the result as a proposal. It never edits the document directly: the change is published for review — if this project has agent auto-accept armed it may apply automatically (the response says status "applied"), otherwise it awaits a human Accept in Galley. Inspect the returned status to know what happened. Each search must match the current text exactly once; failures come back as structured data (status: "edit_failed") — refine and retry.
| Name | Required | Description | Default |
|---|---|---|---|
| edits | Yes | Search/replace blocks, applied in order against the running text. | |
| request | Yes | A short human-readable title for the change (shown in the review card). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does this well: it discloses that the document is never edited directly, that auto-apply may occur, that the response reports `applied` or `edit_failed`, and that searches must match exactly once. This gives the agent an accurate safety model and expected outcomes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the first sentence states the core action, and each subsequent sentence adds directly useful operational detail. There is no filler or redundant scaffolding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the important behavioral dimensions: non-destructive proposal, review flow, auto-apply, status values, and failure recovery. Since there is no output schema, it does not enumerate the full response shape, but it provides enough for an agent to invoke and interpret the result correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description reinforces the exact-match requirement already present in the schema but does not add meaningful parameter semantics beyond it. Both `request` and `edits` are already adequately documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('applies'), a resource ('the session's file'), and a concrete mechanism ('search/replace edits') that publishes a proposal. It clearly distinguishes itself from read-only siblings and from propose_files by emphasizing that it edits an existing file's content rather than proposing files or compiling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear operational context: changes are proposed for review, auto-application is possible, and the caller should inspect `status` to determine the outcome. It does not explicitly name alternatives such as propose_files, but the context strongly implies when this tool is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
propose_filesPropose a multi-file change (published for review)A
Proposes a change set across MULTIPLE files as ONE atomic proposal — create new files, edit existing ones, rename/move them (rename also moves into a folder), or delete them (e.g. add chapters/intro.typ and #include it from main.typ). It never changes the project directly: the set is published for review — if this project has agent auto-accept armed it may apply automatically (the response says status "applied"), otherwise it awaits a human Accept in Galley. Inspect the returned status to know what happened; the whole set lands all-or-nothing. For edit ops each search must match that file's current text exactly once; failures come back as structured data — refine and retry. Delete is a recoverable soft-delete. Paths must be safe in-tree project paths (leading slash, no traversal, not under /.galley). For binary files you may either inline the bytes (create-binary, base64) or, when the source already lives on the machine running the Galley kernel, reference it by ABSOLUTE local path (create-binary-path) so no base64 transfer is needed — both publish the same content-addressed pointer. A single proposal is capped at 32 ops (with aggregate size limits); to change more files, split the work across multiple sequential propose_files calls — each is reviewed and lands independently (there is no import-group transaction spanning proposals).
| Name | Required | Description | Default |
|---|---|---|---|
| ops | Yes | The file operations — applied all-or-nothing on Accept. | |
| request | Yes | A short human-readable title for the whole change set (shown in the review card). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden and does so thoroughly. It discloses that the proposal is published for review rather than applied directly, may auto-apply, returns a status to inspect, lands all-or-nothing, requires exact-once matches for edits, uses recoverable soft-delete for deletions, imposes safe-path constraints, and has no cross-proposal transaction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place because the tool is genuinely complex with six operation kinds and several behavioral caveats. The core purpose is front-loaded in the first sentence, and constraints are grouped logically rather than buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description tells the agent what to inspect after the call (status), what failure looks like (structured data), and all key behavioral outcomes. Combined with the detailed input schema, an agent has enough context to invoke this tool correctly and react to its results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds substantial meaning beyond the schema: it explains atomicity, the review workflow, exact-match edit semantics, soft-delete behavior, binary transfer alternatives, path safety requirements, and the 32-op cap. This materially helps an agent choose correct parameter values and interpret results.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it 'Proposes a change set across MULTIPLE files as ONE atomic proposal' and enumerates the supported operations. This clearly differentiates it from the single-file sibling propose_edit without needing to inspect that tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear use context: it is for multi-file atomic proposals, and it explicitly instructs splitting work across multiple sequential calls when the 32-op cap is exceeded. However, it never explicitly names propose_edit as the single-file alternative or states when not to use this tool, so it falls short of full exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_documentRead the Galley documentA
Returns the current text of the session's target file from the live shared project.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. 'Returns' supports a read-only interpretation, and 'live shared project' hints at freshness, but the description does not explicitly state that the operation is non-mutating or describe failure behavior or prerequisites. It is adequate but minimal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence with no filler. Every word contributes to the meaning, and the structure is well suited to a zero-parameter read operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and no output schema, the description adequately explains what the agent will receive: the current text of the session's target file. It does leave the concept of 'session's target file' implicit and does not contrast with read_file, but for a simple read tool this is largely complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema is empty, so there is no parameter semantics burden on the description. The description usefully clarifies that the implicit target is the session's target file, which is enough given the absence of parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Returns') and clearly identifies the resource (current text of the session's target file) and source (live shared project). It is clear in purpose, though it does not explicitly differentiate itself from the sibling read_file.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives like read_file, nor any mention of prerequisites, exclusions, or context that would help an agent decide between tools. The description only states what the tool does.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_fileRead a project file by pathA
Returns the live replicated text of any project file by EXACT path (as listed by list_files — no normalization, no globbing). Read-only. Files over 2097152 UTF-8 bytes are refused with an error, never truncated. A BINARY file (image/PDF) returns structured metadata { kind: "binary", path, hash, size, mime } instead of text — its bytes are not available through this tool.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Exact file path as returned by list_files, e.g. /notes.typ. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses read-only behavior, size limit with error (never truncated), and binary file metadata response. This is thorough behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loads the core function, and packs size and binary behavior into a single sentence without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool, the description covers the key behaviors: exact path requirement, size limit, binary handling, and read-only nature. It is complete for an agent to call correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes the path parameter fully. The description adds that no normalization or globbing is allowed, reinforcing exactness. This adds semantic value beyond the schema's description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns the live replicated text of a project file by exact path, and distinguishes itself from list_files by requiring exact paths. It also mentions binary handling, making its purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It instructs that paths must come from list_files, implying you should list files first. It also notes read-only nature. However, it does not explicitly contrast with read_document or other alternatives, so it lacks explicit exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v0.1.0- First observed
compile - First observed
galley_ping - First observed
list_files - First observed
project_context - First observed
propose_edit - First observed
propose_files - First observed
read_document - First observed
read_file
TDQS
Scored across 8 tools
Tools map to distinct actions: ping, read, list, search, propose, compile. The close pairs read_document/read_file and propose_edit/propose_files are separated clearly by session-target convenience vs exact-path reads and single-file vs atomic multi-file proposals.
Most tools follow a readable snake_case verb_noun pattern (read_document, list_files, propose_edit), but project_context is a noun phrase, compile is a bare verb, and galley_ping uses a server prefix unlike the others. These are minor deviations rather than chaotic naming.
8 tools is well-scoped for a collaborative document editing server. Each tool earns its place and the count sits comfortably within the ideal 3-15 range.
The surface covers the main workflow: inspect files, search the project, propose single or multi-file changes, and compile to verify. Minor gaps like no proposal history or binary byte retrieval don't create dead ends because statuses are returned and binary pointers are provided.
Maintenance
Related MCP Connectors
MCP server for Product Management
Related MCP Servers
- -
- -
- AGPL 3.0
- MIT