mcp-chatgpt-file-store
This server provides secure, sandboxed file management for AI models. You can:
List allowed directories, browse directory contents, and create folders.
Read, write, append, move/rename, and delete files and directories, with automatic parent directory creation.
Search for files using glob patterns, and get file metadata.
Generate a comprehensive knowledge document (Markdown or PlantUML) from all stored files for quick context.
Optionally, use a password-protected web interface to browse the file store.
Click on "Install 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., "@mcp-chatgpt-file-storeSave the summary of our conversation to notes/summary.md"
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.
ChatGPT File Store — MCP Server
A Model Context Protocol server that lets ChatGPT (or any MCP client) save and manage files inside a sandboxed local folder on your Mac.
Everything ChatGPT does is confined to an allowed directory — it cannot read or write anywhere else on your machine.
What it does
ChatGPT gets these tools:
Tool | Purpose |
| Shows where ChatGPT is allowed to save/read |
| Lists files and folders in the store |
| Reads a text file |
| File metadata (size, modified time) |
| Finds files matching a pattern ( |
| Returns the whole store as one body of knowledge — Markdown, or PlantUML when it describes a flow |
| Saves a file (creates folders automatically) |
| Appends to a running log/notes file |
| Creates folders |
| Moves/renames files |
| Deletes a file or folder |
Related MCP server: Local Files MCP Server
Installation
Requirements: Node.js 18 or newer (node -v to check) and git.
# 1. Clone the repo
git clone https://github.com/tanongkiat/mcp-chatgpt-file-store.git
cd mcp-chatgpt-file-store
# 2. Install dependencies
npm install
# 3. Build (optional — dist/ is committed, so a fresh clone already runs)
npm run buildVerify the install by starting the server over HTTP and hitting the health endpoint from a second terminal:
npm run start:httpcurl http://localhost:8080/health
# {"status":"ok","sessions":0}Ctrl+C stops it, or npm run stop from another terminal.
That's the whole install. Next: pick your sandbox folder (Setup), then connect a client — ChatGPT or Claude. Exposing the server beyond localhost? Read Authentication first.
Folder layout
mcp-chatgpt-file-store/
├── src/
│ ├── index.ts # entrypoint — stdio or HTTP mode
│ ├── http.ts # Streamable HTTP server (stateful sessions)
│ ├── server.ts # MCP server + tool registration
│ ├── filesystem.ts # sandboxed file operations + path safety
│ └── knowledge.ts # knowledge gathering + PlantUML flow extraction
├── scripts/
│ ├── generate-token.sh # create + save an auth token
│ ├── start-with-auth.sh # generate token and start the HTTP server
│ ├── start-daemon.sh # start detached (nohup + disown), logs to logs/
│ ├── stop.sh # stop the HTTP server by port
│ ├── setup-claude.sh # register this server with Claude
│ └── test-auth.sh # verify auth is enforced
├── dist/ # compiled output (committed, so no build needed to run)
├── Storage/ # default sandbox — <folder where server runs>/Storage
└── package.jsonDocumentation
Doc | Covers |
First run, start to finish | |
Shortest path to an authenticated server | |
Registering the server with Claude | |
How token auth works end to end | |
What each script in | |
Full OAuth 2.0 for multi-user setups | |
Project overview |
Two ways to run it
The server supports two transports — pick whichever your client wants:
Mode | Command | Endpoint |
stdio (default) |
| n/a (local process) |
Streamable HTTP |
|
|
Setup
1. Choose where ChatGPT can save
By default the sandbox is <folder where the server runs>/Storage (i.e. the
Storage/ folder inside this project). To use your own folder(s), set an
environment variable:
export CHATGPT_FILE_STORE_DIRS="/path/to/my/notes,/path/to/another"2. Test it locally (optional but recommended)
npm run inspectThis opens the MCP Inspector where you can call each tool before wiring it to ChatGPT.
3a. Connect over stdio
In ChatGPT, add a custom MCP server with this command:
node /absolute/path/to/mcp-chatgpt-file-store/dist/index.jsTip: point the command at the built
dist/index.js(notsrc), and use the absolute path. If you setCHATGPT_FILE_STORE_DIRS, make sure that environment variable is visible to the process ChatGPT launches.
3b. Connect over Streamable HTTP
Start the HTTP server (default port 8080):
npm run start:httpOr with a custom port/host:
node dist/index.js --http --port 9090 --host 0.0.0.0
# or via environment variables
MCP_HTTP_PORT=9090 MCP_HTTP=1 node dist/index.jsVia the npm script, pass flags after --:
npm run start:http -- --port 9090 --host 0.0.0.0Then register http://localhost:8080/mcp as the MCP server URL in ChatGPT.
3c. Connect to Claude Desktop
Any MCP client works, not just ChatGPT. For Claude Desktop, run the interactive
setup script — it resolves the absolute path to dist/index.js, asks which
folder to sandbox, and writes the entry into claude_desktop_config.json:
./scripts/setup-claude.shRestart Claude Desktop afterwards, then confirm the server appears in its MCP server list. See CLAUDE_SETUP.md for the manual config.
For Claude Code, register it from the command line instead:
claude mcp add file-store -- node /absolute/path/to/mcp-chatgpt-file-store/dist/index.jsAuthentication (recommended for any non-localhost deployment)
Set MCP_AUTH_TOKEN to require a Bearer token on every /mcp request:
MCP_AUTH_TOKEN=$(openssl rand -hex 32) node dist/index.js --httpThe server accepts tokens via two methods:
Authorization header (standard):
curl -H "Authorization: Bearer <token>" http://localhost:8080/mcpQuery parameter (convenient for some clients):
curl http://localhost:8080/mcp?token=<token>
Both methods are validated using constant-time comparison for security. Requests
without a valid token receive 401 Unauthorized. The /health endpoint stays
open (no token needed) for liveness checks.
Query-parameter tokens land in browser history and proxy/nginx access logs in a way headers do not. Prefer the header wherever the client allows it.
Sessions
Streamable HTTP is session-based, so a URL alone is not a connection.
POST /mcp with initialize mints a session and returns it in the
Mcp-Session-Id response header; every later request must present that id, via
the header or a ?session=<id> query parameter. GET /mcp only opens the SSE
stream for an existing session — it is not how you call the server.
This is why pasting the /mcp URL into a browser returns
Missing session: a browser sends a bare GET with no session, and it cannot
send Accept: text/event-stream either. Use /health for a browser-friendly
check, or drive the handshake with curl:
URL="http://localhost:8080/mcp?token=<token>"
SID=$(curl -s -D- -X POST "$URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}' \
-o /dev/null | grep -i '^mcp-session-id' | tr -d '\r' | awk '{print $2}')
curl -s -X POST "$URL&session=$SID" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'A real MCP client does all of this for you — you only give it the URL.
When registering the connector in ChatGPT, add the token as a custom header:
Authorization: Bearer <token>.
If MCP_AUTH_TOKEN is not set, the server logs a startup warning and accepts
unauthenticated requests — fine for quick local testing, not for anything
reachable from the internet.
For full OAuth 2.0 implementation (multi-user scenarios), see OAUTH_GUIDE.md.
Quick Start with Authentication
For the easiest way to start with authentication:
# Auto-generate token and start server
npm run start:authThis script will:
Generate a secure 64-character token
Save it to
.mcp-tokenfor reuseStart the HTTP server with authentication
Display the token and usage examples
Or generate a token separately:
# Generate and save token
npm run generate-token
# Start server manually
source .env && npm run start:httpSee QUICKSTART.md for more details.
Running detached (servers, remote hosts)
start:auth and start:http hold the terminal. To leave the server running
after you log out — the usual case on a VPS:
npm run start:daemonIt reuses the token from .mcp-token, starts the server under nohup and
disown so it survives SIGHUP, appends output to logs/mcp-server.log, and
writes the PID to .mcp-server.pid. It refuses to start if the port is already
taken, and reports the log tail if the server dies on startup instead of
leaving you with a silent failure.
npm run start:daemon -- --port 9090 --host 127.0.0.1
tail -f logs/mcp-server.log
npm run stopBoth logs/ and .mcp-server.pid are gitignored.
For a machine that reboots, prefer a real supervisor (
systemdon Linux,launchdon macOS) —nohupsurvives logout, not restarts.
Stopping the server
start:auth and start:http run in the foreground, so Ctrl+C stops them. If
the server is running detached or in another terminal, stop it by port:
npm run stop # stops the server on port 8080
npm run stop -- --port 9090 # a different port
npm run stop -- --force # SIGKILL if it ignores SIGTERMIt sends SIGTERM first, waits up to 5 seconds for the port to free, and
exits 0 if nothing was listening.
HTTP Transport
The server implements the MCP Streamable HTTP transport:
POST /mcp— JSON-RPC requests (first call creates a session and returns aMcp-Session-Idheader; send it back on subsequent requests)GET /mcp— SSE stream for server-initiated messagesDELETE /mcp— ends a sessionGET /health— liveness check ({"status":"ok","sessions":N})
Web login + browse (/login → /mcp/browse)
In addition to the JSON-RPC API, the HTTP server serves a small password-protected
file browser so you can view /Storage from a normal web browser:
GET /login— login form (username + password)POST /login— validates credentials, then sets anHttpOnlysession cookieGET /mcp/browse— the authenticated file browser for/StorageGET /mcp/browse?path=docs— navigate into a subfolderGET /mcp/browse?view=notes.md— view a file's contentsGET|POST /logout— clears the session cookie
Authentication is username/password (separate from the MCP bearer token), not
OAuth. Sessions are HttpOnly, SameSite=Lax cookies signed with an HMAC key.
Every path is still resolved through the same sandbox as the MCP tools, so an
authenticated user can never read or navigate outside the allowed directories.
Configuration (all optional — sensible defaults apply):
Variable | Default | Notes |
|
| Login username |
| falls back to | Login password |
| falls back to | HMAC key for session cookies |
If neither MCP_BROWSE_PASSWORD nor MCP_AUTH_TOKEN is configured, web login is
disabled (the server logs a warning). When using start:auth or start:daemon,
MCP_AUTH_TOKEN is already exported, so you can log in with username admin and
your bearer token as the password.
# Quick manual start with explicit credentials
MCP_BROWSE_USER=admin MCP_BROWSE_PASSWORD=secret \
node dist/index.js --http --port 8080
# Then open http://localhost:8080/mcp/browseKnowledge retrieval
get_knowledge reads everything in the store at once, rather than making the
model open files one by one:
get_knowledge({
"query": "auth", // optional: only docs whose path or text matches
"format": "auto", // "auto" | "markdown" | "plantuml"
"max_bytes": 100000 // budget across all documents
})Formats:
markdown— every document concatenated under## path/to/file.mdheadings.plantuml— diagrams only. A document yields a diagram three ways: an existing@startumlblock or```plantumlfence is passed through unchanged; two or moreA -> B: labellines become a sequence diagram; two or more numbered steps become an activity diagram.auto(default) — Markdown, with a PlantUML section prepended when any document describes a flow.
So 1. User submits the form / 2. Service validates the email turns into:
@startuml
start
:User submits the form;
:Service validates the email;
stop
@endumlBinary files and unknown extensions are skipped, and files are read through the same sandbox checks as every other tool.
The extraction is deterministic pattern-matching, not interpretation — it finds flows that are already written as diagrams, arrows, or numbered steps. For prose that merely implies a process, use
format: "markdown"and let the model author the diagram.
Example usage
Once connected, you can tell ChatGPT things like:
"Save the summary of our conversation to
notes/summary.md""Append today's ideas to
ideas.md""List everything in the
projectsfolder""Search for files containing draft in the name"
Security notes
Every path is resolved and checked against the allowed roots before any operation.
..traversal and paths outside the roots are rejected with an error.In stdio mode the server exposes no network port at all.
In HTTP mode the server binds to
0.0.0.0:8080by default — use--host 127.0.0.1to restrict it to localhost only. Sessions are tracked by random UUID. SetMCP_AUTH_TOKEN(see Authentication above) before exposing this server beyond localhost — without it, anyone who finds the URL can read/write files in the sandbox.Only the configured directory is readable/writable — treat the sandbox as not secret (ChatGPT content is processed by the model provider).
Commands
npm run build # compile TypeScript
npm run watch # recompile on change
npm run start # run compiled server over stdio
npm run start:http # run compiled server over Streamable HTTP (port 8080)
npm run start:auth # generate a token and start the HTTP server with auth
npm run start:daemon # start detached (survives logout), logs to logs/
npm run stop # stop the HTTP server (SIGTERM, then --force for SIGKILL)
npm run generate-token # create a token and save it to .mcp-token
npm run dev # run stdio mode with tsx (no build step)
npm run dev:http # run HTTP mode with tsx (no build step)
npm run inspect # open MCP Inspector UIMaintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Flicense-qualityDmaintenanceEnables file system operations such as listing, reading, and creating files within a scoped local project directory. It provides a secure way to manage local files through standardized MCP tools built with FastMCP.
- FlicenseAqualityDmaintenanceProvides safe local file operations through MCP, including reading, writing, searching, organizing, and protected deletion with configurable path restrictions.122
- Alicense-qualityBmaintenanceEnables file system operations such as listing directories, reading, writing, creating, and deleting files or directories through MCP.24MIT
- FlicenseAqualityDmaintenanceEnables listing, reading, and searching local files and directories through MCP tools.4
Related MCP Connectors
A MCP server built for developers enabling Git based project management with project and personal…
MCP server for freefirecommunity documentation, generated by doc2mcp.
MCP-native open-source Notion alternative: read & write pages, databases and kanban boards.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/tanongkiat/mcp-chatgpt-file-store'
If you have feedback or need assistance with the MCP directory API, please join our Discord server