Keyhole – Local files for ChatGPT
Provides a secure bridge for ChatGPT to read and edit local folders via OpenAI's Secure MCP Tunnel, with granular read-only or read-write access and an undoable change history.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Keyhole – Local files for ChatGPTRead README.md in my open project folder and summarize it."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Keyhole — local files for ChatGPT
Let ChatGPT read, and carefully edit, only the local folders you choose. No shell, no public port.
Keyhole is a small MCP server that runs on your Mac, plus a command-line
tool, keyhole. You open a folder with keyhole open; ChatGPT on the web can then read it through OpenAI's
official Secure MCP Tunnel. Give a folder
rw, and ChatGPT can also create and edit text files in it. Every edit is checked against the file's current
hash and recorded before it is applied. Individual file replacements are atomic; retained changes can be restored without overwriting later edits.
Unofficial project; not affiliated with OpenAI.
What you get
Read-only by default. ChatGPT sees a folder only after you open it, and cannot change a file until you say
--access rw. Nothing ChatGPT does can widen its own access: grants are managed by the local CLI only.Careful edits you can undo. Writes require the file's current SHA-256; updates based on a stale hash are refused. The previous content is kept in a private local history, and
restore_changerolls it back.Evidence-grade reading. Text, PDF, Word, PowerPoint, Excel and images come back with hashes and ranges, so answers can cite what was read. Document parsers have CPU, time and input-size limits, but run with your OS permissions; they are not an OS sandbox.
No shell, no public endpoint, no third-party relay. The only network path is the outbound connection from OpenAI's tunnel client on your Mac to OpenAI. Close the last folder and the tunnel stops.
Related MCP server: Local Supervisor Bridge
Start here
Set up Keyhole and read your first file →
That is the complete first-time path: check your account access, install the tools, connect your own tunnel, create a private ChatGPT app, and read a real demo file. Follow it once, from top to bottom. No Python, Git, Node, Docker or tmux installation is required. You need a Mac, ChatGPT Developer mode and permission to create an OpenAI Platform tunnel and restricted runtime key. Budget about 15 minutes after account access is ready.
The GitHub repository supplies the software. You create your own tunnel and private ChatGPT app; there is no public Keyhole app to add in one click. OpenAI's Secure MCP Tunnel is for private connections, not public plugin-store distribution.
What makes it useful
Open several folders independently, keep some read-only, and allow recoverable text edits in others. Read documents as well as source code, then close a folder when the task is finished. Folder access always stays under your local control.

Recorded with a synthetic demo folder on macOS, 2026-09-26. See the first-use guide to reproduce it with your own private app.
Compatibility
Surface | Verified / limitation |
macOS | Apple silicon, macOS 15.6 and 15.7.7. Intel and older macOS remain untested. |
Python | 3.11–3.14 in CI; |
Other OS | Linux has experimental unit tests only. Windows is unsupported; commands report this without a traceback. |
OpenAI client |
|
ChatGPT | Pro, web, Chat mode. Other eligible plans and fresh-account onboarding have not been tested here. |
Clean install | Release wheel tested with Git/Python developer-tool commands unavailable in a simulated environment; not a freshly erased Mac. |
How it works
flowchart LR
C[ChatGPT web] -->|tool call| T[OpenAI tunnel endpoint]
T <-->|outbound long-poll only| TC[tunnel-client on your Mac]
TC -->|stdio JSON-RPC| K[keyhole MCP server]
K -->|opened folders only| F[(Your files)]
CLI[keyhole CLI] -.->|grants, ro / rw| Ktunnel-client is OpenAI's open-source client. It opens an outbound connection and forwards each request to
the Keyhole server over stdio; no port on your Mac is exposed. The server reads and writes only inside folders
you opened, and refuses anything else.
Daily use
keyhole open ~/Documents/notes # read-only
keyhole open ~/code/app --access rw --name app # editable, shown to ChatGPT as "app"
keyhole open ~/code/app --exclude Private --exclude 'Secret/*'
keyhole access app ro # back to read-only
keyhole status # configuration, checks, runtime state
keyhole close --all # stop sharing; the tunnel stops too
keyhole resume --all # after a reboot, share the saved folders again
keyhole history --limit 20 # recent recoverable changesNothing is shared after a reboot until you run keyhole resume. Closing or forgetting a folder never touches
its files.
Example requests in ChatGPT:
Read
app/src/config.py, fix the typo in the error message, and read the file back to confirm.
Search
notesfor "invoice", then quote the matching lines with their file paths.
For an edit, ChatGPT reads the file and its hash, proposes the change, and calls apply_text_patch or
write_file. Whether ChatGPT asks you before a write is ChatGPT's own setting for the app (it asks by
default and can remember your answer for a conversation); check the app's details if you never see a prompt.
What ChatGPT can do with each file type
File type | Read | Create, replace, patch | Copy, move, rename, delete, restore |
UTF-8 text: code, Markdown, JSON, YAML, TOML, shell, HTML, CSS, plain text, any other extension not listed below | by line range | yes ( | yes ( |
UTF-16 / UTF-32 text with a BOM | by line range | no, convert to UTF-8 first | yes ( |
text per page, one page as an image; no OCR | no | yes ( | |
Word | body paragraphs and tables | no | yes ( |
PowerPoint | slide and table text | no | yes ( |
Excel | cells, formulas and cached values; no recalculation | no | yes ( |
PNG, JPEG, WebP | the image, downscaled if large | no | yes ( |
Archives, executables, databases, media, legacy Office ( | metadata only | no | yes ( |
Copy, move, delete and restore treat every regular file up to 8 MiB as opaque bytes, so they work for binaries too. Keyhole cannot write Office documents, PDFs or images, and does not run code, macros or formulas.
Limits: text files up to 8 MiB; documents and images up to 64 MiB; 400 lines or 64 KiB per read; 1 MiB per
write_file; single files only, no recursive directory operations. Every response says when it was truncated.
Recovery history
Every change ChatGPT makes is written to ~/.config/keyhole/changes.sqlite3 (readable by you only) before
the file is touched: the paths, hashes and, by default, the previous content. That is what restore_change
and keyhole history use. ChatGPT can see paths, hashes and change ids, never the stored content.
History is bounded to 1000 records or 450 MiB. When it is full, the oldest completed records are dropped automatically; an interrupted operation is never dropped. Recovery can temporarily reserve one extra record and 48 MiB so a full history does not prevent repair. Retry an interrupted restore with the same request id; successful recovery returns history to the normal limits.
Closing or forgetting a folder keeps its history.
keyhole purge-history --before 2026-01-01 --confirmdeletes completed records before a date. Eviction or purge removes both recovery and replay protection for those records; history is not a permanent audit log.Prefer your own version control?
keyhole open <dir> --access rw --recovery offkeeps paths and hashes only. Edits are still hash-checked and interrupted operations can still be repaired, butrestore_changerefuses committed edits for that folder.
Safety on one screen
Grants live in
~/.config/keyhole/grants.jsonand change only throughkeyhole. There is no remote tool to add folders, run commands, use Git, or fetch URLs.Names such as
.git,.ssh,.env*,*.key,*.pem,credentials.json,node_modulesand agent state directories are hidden at any depth, in any letter case.keyhole openprints the full list.Your own
--excluderules: a pattern without a slash hides matching names at any depth (Private,*.log); a pattern with a slash is anchored at the folder root and hides that subtree (Secret/*,docs/*.md). Matching ignores case and Unicode normalization.ChatGPT can never modify Keyhole's own code or environment, the state directory, or shell startup files such as
.zshrcand.envrc, whatever spelling of the path it uses.Symbolic links, hard-linked files and special files are refused; every path is opened component by component with
O_NOFOLLOWand re-checked before and after each operation.Hiding by file name is not secret detection: a token inside a shared source file is readable while the folder is open, and anything already sent to ChatGPT cannot be recalled by closing the folder.
Threat model, what is out of scope, and how to report a vulnerability: SECURITY.md.
Commands and tools
Command | What it does |
| Store the tunnel id and runtime key; |
| Share a folder and start the runtime; new folders are |
| Change a saved folder's mode |
| Stop sharing; saved paths and history stay |
| Re-verify saved folders and share them again |
| Stop sharing and remove the saved configuration |
| Configuration, environment checks, runtime state, open folders |
| Recent recoverable changes, including interrupted ones |
| Permanently delete completed history before a date |
Every command prints JSON; "ok": false comes with an error.code you can act on.
Tool ChatGPT calls | Effect |
| Open folders, their |
| Paged listing; literal search over names or plain text |
| Text ranges, document pages, images, or just the SHA-256 |
| Create or replace a UTF-8 file; apply exact literal replacements |
| Single-item file operations, each recoverable |
| Recent changes and undo |
The five read tools are marked read-only and the seven write tools destructive, which is what ChatGPT's write confirmation keys on. Full parameters, error codes and limits: docs/reference.md. Upgrades, custom paths and uninstall: maintenance.
Troubleshooting
Symptom | What to do |
| Run |
|
|
| The folder, the state directory, or one of their parents is behind a symbolic link. Use the physical path ( |
| macOS is protecting the folder. Allow your terminal app under System Settings → Privacy & Security → Files and Folders, then retry. |
|
|
Tools missing in ChatGPT after an upgrade | Open the app's details in ChatGPT and press Refresh, then start a new chat. New folders never need a refresh. |
Glossary
Workspace: one opened folder, shown to ChatGPT under its name. Not a ChatGPT workspace (the team account).
ro / rw: read-only / read-write. New folders are
ro.Runtime: the
tunnel-clientprocess that keeps your tunnel connected and runs the Keyhole server.Chat vs Work: ChatGPT composer modes. Keyhole was tested in plain Chat; Work is not required.
Non-goals, and when to use something else
Keyhole will not run shell commands, tests or Git, drive your screen, expose a public endpoint, or let the remote side manage grants. If you use the ChatGPT desktop app, its local Work mode may already cover your needs on that machine. If you want ChatGPT to run commands in a repository, use a coding-oriented tool. Keyhole is for ChatGPT on the web, documents as evidence, and careful edits.
Optional: Codex companion
skills/keyhole/ is a skill for OpenAI Codex that lets it run keyhole on your explicit instruction and
explains the boundaries. Link that directory into ~/.codex/skills/ (the layout Codex discovers);
.codex-plugin/plugin.json describes the same skill for Codex's plugin installer. Not needed for ChatGPT.
Repository
Tracked: the server and CLI (
src/keyhole/), tests, docs, the Codex skill. Runtime state, keys, grants and recovery history live in~/.config/keyhole/and are never part of the repository.Maintained by Jovi; best-effort, single maintainer. Bugs and ideas: issues. How to work on it: CONTRIBUTING.md. Changes: CHANGELOG.md.
License
MIT.
Available Tools
12 toolsapply_text_patchADestructiveIdempotent
Apply 1-64 literal replacements to an existing UTF-8 file <=8 MiB. Each edit has old/new text and exact match count (default 1); ambiguous matches are refused. Requires rw, observed SHA-256 and unique request_id. Preserves untouched content, BOM/newlines and permissions. Returns change_id for recovery.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| edits | Yes | ||
| workspace | Yes | ||
| request_id | Yes | ||
| expected_sha256 | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations, disclosing exact-match counting, ambiguous-match refusal, the SHA-256 and request_id requirements, preservation of BOM/newlines/permissions, and the change_id return for recovery. This aligns with destructiveHint=true and idempotentHint=true without contradicting them.
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 dense sentences front-load the core action and constraints, then cover preconditions, preservation guarantees, and return value. Every sentence adds essential information with no filler.
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?
With no output schema, the description still states the return value (change_id for recovery). It covers limits, safety behavior, concurrency guard, and preservation semantics. For a mutation tool with rich annotations, this is a complete and actionable description.
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 description coverage is 0%, so the description carries the full burden. It explains old/new text and exact match count (mapping to the TextEdit properties), expected_sha256, and unique request_id. It does not explicitly describe workspace or path semantics, but these are reasonably inferable from context.
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: 'Apply 1-64 literal replacements to an existing UTF-8 file <=8 MiB.' It clearly distinguishes this from sibling tools like write_file (whole-file writes) and delete_file, and the replacement semantics are 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?
The description gives clear context: the tool is for literal replacements in existing UTF-8 files up to 8 MiB, with exact match counts and refusal of ambiguous matches. It also lists preconditions (rw, observed SHA-256, unique request_id), but it does not explicitly name alternatives or state when write_file would be preferred over this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
copy_fileADestructiveIdempotent
Copy one regular file <=8 MiB within an rw workspace. Require source SHA-256 and an absent destination with an existing parent. No recursive trees, links or overwrite. Returns a recoverable change_id.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| workspace | Yes | ||
| request_id | Yes | ||
| destination | Yes | ||
| expected_sha256 | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true. The description adds valuable behavioral specifics: size limit, prohibition on links/overwrite, and the return of a recoverable change_id. These go beyond the annotations and clarify the operation's side effects and constraints.
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?
Two sentences, no filler. The first sentence front-loads the core action and constraint, the second adds prerequisites and return behavior. Every clause earns its place with zero 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?
While the description covers key constraints and return info, it omits any explanation of request_id, which is a required parameter. There is no output schema, so the description should clarify all parameters. The omission of request_id and lack of explicit per-parameter guidance leaves the tool less complete than ideal for a 5-parameter operation.
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 description coverage is 0%, so the description must compensate. It indirectly explains expected_sha256 (source SHA-256), destination (absent with existing parent), and workspace (rw workspace), but does not explicitly define request_id or clarify the relationship between path and workspace. The coverage is partial and leaves some parameters underspecified.
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 (copy), resource (one regular file <=8 MiB), and scope (within an rw workspace). It clearly distinguishes from siblings like move_file (copy vs move) and delete_file, and adds constraints that define its domain. This is unambiguous and highly discriminative.
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 prerequisites (source SHA-256, absent destination with existing parent) and exclusions (no recursive trees, links, overwrite), but it does not explicitly name alternatives or state when to prefer this over move_file or write_file. The usage context is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_directoryADestructiveIdempotent
Create one absent directory in an rw space; parent must exist. Returns a change_id; restore removes it only if empty and unchanged. Cannot modify the workspace root.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| workspace | Yes | ||
| request_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds valuable context: the operation returns a change_id, restore removes it only if empty and unchanged, and it cannot modify the workspace root. This goes beyond the annotations and warns about potential side effects (removal on restore) and limitations.
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 a single concise sentence that front-loads the core purpose and then adds critical constraints and side-effects. Every clause earns its place, with no filler or repetition.
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 the core operation, but it lacks parameter-level detail and doesn't state what the output (change_id) is used for beyond restoration. Given it's a mutating tool with a destructive hint, it could benefit from a note on error conditions (e.g., what if the directory already exists) or how to use the change_id. However, the output schema is absent, so the description carries that burden partially. Overall, adequate but with room for improvement.
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 description coverage is 0%, and the description does not explain any of the three parameters: 'path', 'workspace', 'request_id'. The description mentions 'rw space' which hints at 'workspace', but it doesn't clarify the format or purpose of 'request_id' or the expected structure of 'path'. This is a significant gap given the schema provides no descriptions.
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 action ('Create one absent directory') and the resource ('in an rw space'). It adds the constraint that the directory must be absent and the parent must exist, which goes beyond a generic definition. However, it doesn't explicitly distinguish itself from sibling tools like 'copy_file' or 'move_file', though the resource is distinct enough.
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 implies when to use this tool: to create a directory that does not exist, with an existing parent. It doesn't explicitly mention when not to use it or name alternatives, but the conditions are fairly clear (e.g., for creating files, one would use 'write_file' or 'apply_text_patch'). The absence of explicit exclusions is a minor gap.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_fileADestructiveIdempotent
Recoverably delete one regular file <=8 MiB from an rw space after checking its SHA-256. Stores original bytes in private local recovery history; use restore_change to undo. No directory or permanent deletion tool.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| workspace | Yes | ||
| request_id | Yes | ||
| expected_sha256 | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal destructive=true and readOnly=false, but the description adds essential behavioral context: recovery semantics, storage of original bytes in private local recovery history, size limit, SHA-256 verification, and undo route. No contradiction with annotations.
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 dense sentences with no filler. Every clause earns its place: operation, constraints, recovery behavior, undo path, and exclusions are all covered efficiently.
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 destructive but recoverable tool, the description covers prerequisites, recovery, undo, and scope well. The main gaps are the role of request_id and the post-delete return value, especially with no output schema, but these are minor relative to the rich behavioral guidance provided.
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 description coverage is 0%, so the description must compensate. It adds meaning to workspace (rw space), path (regular file ≤8 MiB), and expected_sha256 (checked before deletion), but request_id remains unexplained. This is partial compensation, not full.
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?
States a specific verb and resource ('Recoverably delete one regular file'), with clear constraints (≤8 MiB, rw space, SHA-256 check). Explicitly distinguishes itself from restore_change and from directory/permanent deletion 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?
Provides clear usage context: when to use it (deleting a regular file from an rw space), how to undo it ('use restore_change to undo'), and what it is not for ('No directory or permanent deletion tool'). This gives explicit routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_changesARead-onlyIdempotent
List 1-100 recent changes and interrupted commits for the current physical workspace. Returns paths, hashes, state and change_id, never backup contents. History persists offline; changing root identity does not inherit its history.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| workspace | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context: it never returns backup contents, history persists offline, and changing root identity does not inherit history. This goes beyond the annotations.
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 carrying distinct information: what it lists, what it returns, and persistence/identity behavior. No redundancy, front-loaded with the core purpose.
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 read-only list tool with strong annotations and a simple two-parameter schema, the description covers the key behavioral aspects. It doesn't describe the return format in detail, but no output schema exists and the description already lists returned fields (paths, hashes, state, change_id). Minor gap: no explicit mention of sorting order or error conditions.
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 description coverage is 0%, so the description must compensate. It explains the limit range (1-100) and the workspace scope ('current physical workspace'), but doesn't detail the format of the workspace parameter or the limit parameter beyond the schema's default. The description adds some meaning but not full compensation for zero schema coverage.
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 lists recent changes and interrupted commits for the current physical workspace, with a specific verb and resource. It distinguishes itself from siblings by focusing on change history rather than files or workspaces.
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 implies when to use this tool: when needing change history for the current workspace. It doesn't explicitly name alternatives or exclusions, but the sibling list and the phrase 'current physical workspace' provide context. It could be stronger by explicitly saying not to use it for file contents or other workspaces.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_directoryARead-onlyIdempotent
List 1-200 permitted entries at a workspace-relative directory. Follow next_cursor; changed content invalidates pagination.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | . | |
| limit | No | ||
| cursor | No | ||
| workspace | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description reinforces safety by noting only 'permitted entries' are shown. It adds valuable non-obvious behavior beyond annotations: the 1-200 entry limit and, crucially, that changed content invalidates pagination, warning agents not to reuse stale cursors.
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?
Two short sentences with no filler. The core scoping constraint is front-loaded, and the pagination warning is compressed into a single clear clause.
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 read-only listing tool with no output schema, the description covers the core invocation contract: scope, size limit, pagination, and cursor freshness. It does not enumerate the returned entry fields or error cases, but this is a minor gap for a list operation with a conventional response shape.
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 descriptions are entirely absent (0% coverage), so the description must compensate. It implicitly explains workspace and path via 'workspace-relative directory', limit via '1-200', and cursor via 'Follow next_cursor', but it leaves the cursor format, exact limit semantics, and returned entry fields to inference.
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 'List 1-200 permitted entries at a workspace-relative directory', naming the exact verb, resource, and operational constraint. This clearly distinguishes list_directory from siblings like search_files and read_file, which perform different 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 clear context: this tool is for enumerating directory entries within a workspace, not for searching content or manipulating files. It does not explicitly name alternatives or state when not to use it, but the sibling names and phrasing make the intended use obvious.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_workspacesARead-onlyIdempotent
Discover current open workspace names, availability, exclusions and read limits. Local absolute paths are never required remotely.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds valuable behavioral context beyond those annotations: it reports current open workspaces, availability, exclusions, read limits, and clarifies that local absolute paths are not needed remotely.
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?
Two sentences with no filler. The primary action and outputs are front-loaded in the first sentence, and the second sentence adds a meaningful operational constraint 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 zero-parameter tool with no output schema, the description is complete: it names the workspace-related outputs an agent would need and gives a key operational rule about remote paths. Nothing essential is missing for selecting and invoking this tool.
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 schema description coverage is 100%, so the schema leaves nothing undocumented. The description still adds meaning by explaining what the tool returns, which is the relevant semantic content for a parameterless discovery tool.
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 ('Discover') and names the exact resource and outputs: current open workspace names, availability, exclusions, and read limits. This clearly distinguishes it from the file-operation siblings like list_directory and read_file, which concern filesystem paths rather than workspaces.
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 for when this tool matters: it reveals workspace identifiers and constraints for remote operations. The statement 'Local absolute paths are never required remotely' implies that workspace names discovered here are the addressing mechanism for other tools, though it does not explicitly name alternatives or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_fileADestructiveIdempotent
Move or rename one regular file <=8 MiB within an rw workspace, requiring source SHA-256 and an absent destination. Destination is verified before source removal; interruption is recoverable, not a multi-file atomic transaction. No recursive directory moves.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| workspace | Yes | ||
| request_id | Yes | ||
| destination | Yes | ||
| expected_sha256 | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations, which only declare destructiveHint and idempotentHint. It reveals the verification order (destination verified before source removal), recoverability on interruption (not atomic), the size cap, and the SHA-256 integrity requirement. This gives the agent a clear picture of failure modes and operational constraints that annotations alone do not provide.
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 with zero filler. The first sentence front-loads the core action and key constraints; the second adds behavioral nuance; the third clarifies a limitation. Every sentence earns its place and the structure is efficient.
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 essential operational details for a move tool: prerequisites, constraints, behavior on interruption, and exclusion of directory moves. It does not explain the request_id field or potential error cases, but given the moderate complexity and absence of an output schema, it is sufficiently complete for an agent to invoke the tool 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 0%, so the description must explain parameters. It explicitly mentions the source SHA-256 (expected_sha256) and the absent destination, and implies the workspace ('within an rw workspace'). However, it does not explain the request_id parameter or the path parameter beyond context. It partially compensates but leaves some parameters underspecified.
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 action (move or rename) on a defined resource (one regular file) with explicit constraints (size limit, workspace type, SHA-256 requirement, absent destination). This clearly distinguishes it from siblings like copy_file (which leaves source intact) and delete_file (which only removes).
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 implies when to use this tool (moving/renaming within an rw workspace with size and integrity constraints) but does not explicitly state though alternatives like copy_file would be more appropriate for preserving the source or for larger files. The 'No recursive directory moves' note hints at a limitation but doesn't name a sibling alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_fileARead-onlyIdempotent
Read source with SHA-256 and ranges. Text: start/limit lines <=400, newline metadata for edits. PDF: pages <=5, mode=image renders one page, no OCR. DOCX: body blocks <=400. PPTX: slides <=20. XLSX: sheet and A1 cell_range <=2000 cells, formulas/caches without recalculation. Images return image content. mode=hash returns only SHA-256 for any permitted file <=64 MiB; mode=metadata avoids hashing/parsing. Never infer complete text from a truncated result.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | auto | |
| path | Yes | ||
| limit | No | ||
| sheet | No | ||
| start | No | ||
| workspace | Yes | ||
| cell_range | No | ||
| expected_sha256 | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations. It discloses specific behaviors: mode=hash returns only SHA-256, mode=metadata avoids hashing/parsing, mode=image for PDF renders one page without OCR, XLSX formulas/caches are not recalculated, and it warns 'Never infer complete text from a truncated result.' This adds substantial value beyond the readOnlyHint and idempotentHint annotations.
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 a single dense paragraph that packs a lot of information efficiently. It is front-loaded with the core purpose and then enumerates format-specific rules. While dense, each clause serves a purpose and no extraneous text is present. The structure could be improved with bullet points, but it remains appropriately concise for the amount of detail.
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 the tool's complexity (multiple file types, modes, and constraints) and the absence of an output schema, the description covers many essential aspects: it specifies return types (images return image content, mode=hash returns only SHA-256), constraints, and a caution about truncated results. It does not fully specify the return structure for text or other formats, but it provides enough for an agent to understand the basic behavior.
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?
With 0% schema description coverage, the description must explain parameters. It explains mode, start/limit, sheet, cell_range, and expected_sha256 implicitly via 'SHA-256'. However, it does not explicitly describe the 'expected_sha256' parameter or clarify that it is for verifying content. Workspace and path are not described, though they may be self-explanatory. The description partially compensates for the coverage gap but misses some parameter semantics.
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: 'Read source with SHA-256 and ranges.' It specifies the resource (files) and the action (read), and it distinguishes itself from sibling tools by detailing format-specific behaviors and modes. It goes beyond a simple restatement of the name, offering concrete details about what it 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 on when to use the tool and its constraints (line limits, page limits, cell count limits), which guides appropriate usage. However, it does not explicitly compare against alternative tools like search_files or list_directory, nor does it state 'use this instead of X.' The constraints imply usage boundaries but lack explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
restore_changeADestructiveIdempotent
Undo one committed or interrupted change in an rw space, only if every affected path still matches that operation. Refuses to overwrite later edits. Removes created files, restores deleted/edited files, reverses moves, and removes created directories only if empty. Returns a new recovery record.
| Name | Required | Description | Default |
|---|---|---|---|
| change_id | Yes | ||
| workspace | Yes | ||
| request_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint and idempotentHint, but the description goes well beyond them, enumerating exactly what gets removed (created files), restored (deleted/edited files), reversed (moves), and the condition that created directories are only removed if empty. It also discloses the refusal to overwrite later edits and the return of a new recovery record, adding significant behavioral context beyond the structured annotations.
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 with the primary action ('Undo one change'), followed by a clear condition and a list of behaviors. Every sentence contributes value—there is no fluff or redundancy. It is appropriately sized for the tool's complexity.
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 the tool's destructive nature and no output schema, the description covers the main behavior, preconditions, and return value ('Returns a new recovery record'). However, it omits parameter meaning, error handling, and how a caller obtains change_id or workspace. The lack of parameter guidance and brief output explanation makes it moderately complete but not thorough.
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 description coverage is 0%, so the description carries full responsibility for explaining parameters. It does not mention change_id, workspace, or request_id at all. While 'change' hints at change_id and 'rw space' hints at workspace, request_id is completely unexplained. The description fails to compensate for the lack of schema documentation.
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 specifies the verb ('Undo') and the resource ('one committed or interrupted change in an rw space'), and differentiates from siblings like list_changes by focusing on reversion. It details the scope and behavior, so an agent can immediately understand what the tool does and how it differs from other 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 implies when to use the tool (to undo a change) and gives a precondition (paths must still match), but it does not explicitly mention alternatives or state when not to use it. It lacks direction such as 'use list_changes to find change_id first' or 'prefer apply_text_patch for direct edits'. Usability is inferred rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_filesARead-onlyIdempotent
Literal name or plain-text search. Bounded scan reports omissions, incomplete scopes and next_cursor. PDF/Office/OCR content is not indexed.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | name | |
| path | No | . | |
| limit | No | ||
| query | Yes | ||
| cursor | No | ||
| workspace | Yes | ||
| case_sensitive | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and idempotentHint=true, so the description does not need to repeat safety. It adds value by disclosing that scans are bounded, may report omissions and incomplete scopes, and that next_cursor is used for pagination. It also notes that PDF/Office/OCR content is not indexed, which is a behavioral limitation. No contradiction with annotations.
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 short sentences with no filler. Purpose is front-loaded, followed by behavior and a limitation. Every sentence adds information and nothing is redundant.
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 the tool's complexity (7 parameters, no output schema, no parameter descriptions), the description covers only the search scope and a limitation. It does not explain how to use cursor for pagination, what path means, how limit works, or what the response format is. The bounded scan mention hints at completeness, but without parameter details the agent cannot reliably invoke the tool 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 description coverage is 0%, so the description must explain the parameters. It does not. The phrase 'literal name or plain-text search' hints at the query and kind parameters, but does not explain path, limit, cursor, case_sensitive, or workspace. With 7 parameters and zero schema descriptions, the agent is left guessing at parameter formats and defaults.
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 'Literal name or plain-text search' – a specific verb and resource, distinguishing it from sibling tools like list_directory or read_file. It also hints at the kind parameter (name vs content) and notes bounded scans, which differentiates it from a simple list operation.
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 context about what the tool does but does not explicitly state when to use it over alternatives. It mentions a key limitation (PDF/Office/OCR not indexed) which tells the agent when NOT to use it, but does not name any alternative tools or exclusion conditions. The intended use case is implied but not explicitly contrasted with list_directory or read_file.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
write_fileADestructiveIdempotent
Create or replace a UTF-8 text/code/Markdown/config file in an rw space. Supply full text <=1 MiB, observed SHA-256 (or 'absent' for create), and unique request_id. Preserve existing UTF-8 BOM, CRLF and permissions by default; line_ending can be preserve/lf/crlf. Returns recoverable change_id. Prefer apply_text_patch for partial reads. No document binaries or code execution.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| text | Yes | ||
| workspace | Yes | ||
| request_id | Yes | ||
| line_ending | No | preserve | |
| expected_sha256 | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive and idempotent behavior. The description adds valuable behavioral context: it preserves BOM, CRLF, and permissions; enforces a 1 MiB size cap; requires a unique request_id for idempotency; and returns a recoverable change_id. It even explains the SHA-256 semantics (supply observed hash or 'absent' for create). No contradiction with the annotations.
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 a tight paragraph that leads with the primary action, then packs constraints, parameters, and the alternative tool into a few sentences. Every sentence earns its place—no fluff, no repetition. The format is easy to scan.
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 there is no output schema, the description appropriately mentions the return value ('recoverable change_id'). It covers size limits, encoding preservation, line-ending options, and the distinction from apply_text_patch. It doesn't delve into error cases (e.g., SHA mismatch handling) but that is not essential for a basic write operation. It is complete enough for an agent to call the tool correctly in most scenarios.
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 gives no parameter descriptions (0% coverage), so the description must compensate. It does explain the critical parameters: expected_sha256 ('observed SHA-256 (or 'absent' for create)'), request_id ('unique'), line_ending ('preserve/lf/crlf'), and text ('full text <=1 MiB'). Workspace and path are self-explanatory from their names, so the description covers the key semantics well even though not every parameter is individually dissected.
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: 'Create or replace a UTF-8 text/code/Markdown/config file in an rw space.' It delimits file types and workspace type, and it contrasts with apply_text_patch by telling the agent to prefer that sibling for partial reads. An agent can immediately tell what this tool does and how it differs.
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 directs the agent to 'Prefer apply_text_patch for partial reads,' which is a clear alternative. It also sets boundaries with 'No document binaries or code execution.' However, it does not enumerate all use cases where the tool is inappropriate beyond partial reads, so it's strong but not exhaustive.
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.
12 tool updates
v0.3.2-demo.1- First observed
apply_text_patch - First observed
copy_file - First observed
create_directory - First observed
delete_file - First observed
list_changes - First observed
list_directory - First observed
list_workspaces - First observed
move_file - First observed
read_file - First observed
restore_change - First observed
search_files - First observed
write_file
TDQS
Scored across 12 tools
Every tool has a unique, well-defined purpose with no overlap. For example, list_directory enumerates entries, search_files performs content searches, and read_file retrieves file contents with hashing options. Even similar operations like write_file (full replace) and apply_text_patch (partial edits) are clearly separated.
All tool names follow a consistent verb_noun pattern in snake_case: list_workspaces, search_files, read_file, apply_text_patch, create_directory, copy_file, etc. There are no deviations in style or grammar, making the API predictable and easy to navigate.
12 tools is ideal for a file management server. The count is sufficient to cover the full lifecycle of file operations—listing, searching, reading, writing, patching, copying, moving, deleting, and undoing changes—without redundancy or bloat.
The tool surface covers the entire file management domain: discovery (list_workspaces, list_directory), search (search_files), read (read_file with multiple formats), write (write_file, apply_text_patch), directory operations (create_directory), file manipulation (copy_file, move_file, delete_file), and change management (list_changes, restore_change). No critical operations are missing for the stated purpose.
Maintenance
Related MCP Connectors
Safe folder access for ChatGPT and Claude: read, write and search files, risky tools opt-in.
Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.
Manage files and folders directly from your workspace. Read and write files, list directories, cre…
Securely search and manage workspace context files for AI agents and teams.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables file operations and bash command execution on the local workspace, securely exposed to ChatGPT via OpenAI Tunnel.2MIT
- AlicenseNot gradedqualityCmaintenanceEnables ChatGPT web to safely read and modify only explicitly allowed local project files through OpenAI Secure MCP Tunnel, including git operations, file edits, and running project scripts, while enforcing strict security boundaries.18MIT

PC FileBridgeofficial
AlicenseNot gradedqualityAmaintenanceEnables ChatGPT, Codex, and compatible MCP clients to read bounded UTF-8 text and create files or directories in operator-selected folders, with strict protections against overwrites, deletes, and path escapes.Apache 2.0- FlicenseNot gradedqualityCmaintenanceEnables ChatGPT to access and manage registered local development projects through controlled file, command, process, and Git operations, with batch tools, permission modes, and tunnel-based remote forwarding.-