GPT Tools MCP Server
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., "@GPT Tools MCP Serverresearch the latest AI news"
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.
GPT Tools MCP Server
MCP tools for Claude Code that drive ChatGPT via Playwright browser automation. The tools:
gpt_search— routes research queries through ChatGPT and returns clean markdown, or saves it directly to disk to keep the MCP client context light.gpt_image_gen— sends an image-gen prompt, saves the generated images to disk, and returns them so Claude can analyze the result.gpt_search_batch/gpt_image_gen_batch— run several prompts concurrently inside one MCP call, each in its own ChatGPT tab.
Why
Claude Code can use MCP tools. This lets it delegate web research and image generation to ChatGPT, using your existing ChatGPT subscription instead of a separate API key.
Token efficiency (search)
When Claude does web research natively, it burns tokens on search results, page fetches, and reasoning about what it found. With this tool, ChatGPT does all the thinking — it searches, reads sources, reasons through the answer, and uses its own thinking tokens. Claude just gets back a clean result.
Design loop (image gen)
Image gen lets Claude iterate on visual designs without you having to shuttle screenshots manually. Generated images land in ./generated/ and are embedded in the tool response so Claude can critique, suggest changes, and re-prompt.
The tradeoff with both is speed. Browser automation is slower than a direct API call. If you're multitasking, it doesn't matter — Claude kicks off the call and you come back to a finished result.
Related MCP server: Cloudflare Playwright MCP
Setup
pip install git+https://github.com/kev489/gpt-tool-use.git
playwright install chromiumOr clone and install locally:
git clone https://github.com/kev489/gpt-tool-use.git
cd gpt-tool-use
pip install .
playwright install chromiumRun once to log into ChatGPT (opens a browser window — sign in, then close the window):
gpt-tools-login # or: python login.py from a cloneLogin state is stored in chatgpt_profile/ next to the installed code (gitignored in a clone). With the pip install, set GPT_TOOLS_HOME to a writable directory (e.g. ~/.gpt-tools) so the profile and debug screenshots don't land inside site-packages — set it both for the login command and in the MCP server's environment. You only need to log in once per machine.
Then add to your Claude Code MCP config (~/.claude.json under mcpServers, or via claude mcp add):
{
"mcpServers": {
"gpt-tools": {
"command": "gpt-tools",
"args": []
}
}
}This is the stdio transport: Claude Code spawns one MCP server subprocess per session. Simple, but if you run multiple Claude Code sessions at once, each spawns its own server, and they fight over the persistent ChatGPT profile lock — only one session can use image gen at a time. See "Running as a long-lived service" below for the multi-session setup.
Running as a long-lived service
If you have multiple Codex or Claude Code sessions open and want them all to use gpt_image_gen simultaneously, switch from stdio (one server per session) to HTTP (one shared server, all sessions are clients). The browser lives in the server, so there's only ever one Chromium accessing the profile.
One-time setup
1. Edit the launchd plist template. launchd.plist.template ships with placeholder paths and a generic Label — replace each one with values for your machine:
Label—com.example.gpt-tools→com.YOURNAME.gpt-tools(any reverse-DNS string; this is also the filename you'll use in step 2)ProgramArguments[0]—/PATH/TO/python3→ yourpython3absolute path (find withwhich python3). If you upgrade Python later, update this path and reload the plist (launchctl unload+launchctl load); otherwise the service silently fails to start at next login (visible only as a non-zero exit code inlaunchctl list | grep gpt-tools).ProgramArguments[1]—/PATH/TO/gpt_tool_use/mcp_server.py→ full path tomcp_server.pyWorkingDirectory,StandardOutPath,StandardErrorPath— replace/PATH/TO/gpt_tool_usewith the absolute path to this repo
2. Install the plist. Use whatever you set for Label as the filename:
cp launchd.plist.template ~/Library/LaunchAgents/com.YOURNAME.gpt-tools.plist
launchctl load ~/Library/LaunchAgents/com.YOURNAME.gpt-tools.plistThe server will now start at login and stay running. Logs go to debug/launchd-stdout.log and debug/launchd-stderr.log inside the repo.
3. Switch your MCP config to HTTP.
Codex (~/.codex/config.toml, and any alternate CODEX_HOME such as ~/.codex-app-alt/config.toml):
[mcp_servers.gpt-tools]
url = "http://127.0.0.1:8788/mcp"
tool_timeout_sec = 1800
startup_timeout_sec = 120Claude Code:
{
"mcpServers": {
"gpt-tools": {
"type": "http",
"url": "http://127.0.0.1:8788/mcp"
}
}
}Restart the MCP client. All sessions now share the long-lived server. Multiple sessions can call gpt_image_gen / gpt_image_gen_batch at the same time.
Manual run (no launchd)
python mcp_server.py --transport http --port 8788Useful for testing the HTTP path before installing as a service. Avoid --headless for ChatGPT automation unless you have verified the account is not being stopped by browser verification.
Reverting to stdio
Unload the launchd agent (launchctl unload ~/Library/LaunchAgents/com.YOURNAME.gpt-tools.plist) and put back the original stdio config. No code changes needed — the server supports both transports.
How gpt_search works
Your query is sent directly to ChatGPT as a prompt (no system prompt — you control the output). You can pass the prompt directly as
query, or provideprompt_fileto read the prompt from a text file.Playwright waits for the response to finish streaming (up to 8 minutes)
JavaScript DOM evaluation strips citation buttons, SVGs, accordion dropdowns, and other UI artifacts
The cleaned HTML is converted to markdown via
markdownifyInline citation markers (
[1],[2], etc.) are stripped before returning to Claude or writing tooutput_file
With output_json=true, the tool treats JSON cleanup as a best-effort post-processing step. It does not change the prompt, and it reads the response through the raw text path instead of the markdown conversion path so JSON string escapes survive. If output_file is provided, the raw ChatGPT output is saved first; then the tool tries to extract, repair, parse, and format valid JSON. On success it overwrites the file with normalized JSON. On failure it leaves the raw output in place and reports that JSON post-processing did not succeed.
Parameters:
query(optional) — the full prompt to send to ChatGPTprompt_file(optional) — path to a text file containing the prompt. Use eitherqueryorprompt_file, not both.output_file(optional) — path where the cleaned markdown response should be saved. Parent directories are created automatically.return_output(optional) — whenFalse, Claude only gets a short saved-path summary. Defaults toTrueunlessoutput_fileis provided; withoutput_file, it defaults toFalseto avoid filling Claude's context with the full response.output_json(optional) — whenTrue, best-effort normalize the response to valid JSON after ChatGPT returns; if parsing/repair fails, leave the raw output unchanged.
Relative file paths resolve from the MCP server process working directory. Use absolute paths if the server is running as a long-lived HTTP/launchd service.
Example:
{
"prompt_file": "prompts/research.txt",
"output_file": "research/chatgpt-answer.md"
}JSON output example:
{
"query": "List three current low-cost index funds as an array of objects with ticker, fund_name, and expense_ratio.",
"output_file": "research/funds.json",
"output_json": true
}For multiple text prompts, use gpt_search_batch. Each request opens its own ChatGPT tab and runs concurrently inside one MCP call. This is the preferred way to batch text research because some MCP clients serialize multiple separate tool calls to the same server. The server runs at most 3 ChatGPT tabs at a time across all calls and sessions; larger batches queue internally. Each request also accepts an optional label, used as its heading in the combined response.
{
"requests": [
{
"prompt_file": "/absolute/path/prompts/topic-1.txt",
"output_file": "/absolute/path/outputs/topic-1.md"
},
{
"prompt_file": "/absolute/path/prompts/topic-2.txt",
"output_file": "/absolute/path/outputs/topic-2.json",
"output_json": true
}
]
}How gpt_image_gen works
Your prompt is sent to a fresh ChatGPT chat (each call resets — no context contamination across iterations)
Playwright waits up to 8 minutes for the stop button to disappear AND
<img>elements to settleImage URLs are downloaded via the browser's authenticated session (signed URLs work)
Files are saved to
<cwd>/generated/<prefix>.png(or<prefix>-1.png,<prefix>-2.png, ... for multiple)The tool returns a text summary with paths, plus (by default) the image bytes inline so Claude can see them
Concurrent calls are supported. All tools share a single Chromium context held in module state; each individual request gets its own page (= its own fresh ChatGPT tab/chat). The server caps itself at 3 concurrent ChatGPT tabs across all calls and sessions; anything beyond that queues internally.
To actually run multiple image-gen prompts in parallel from Claude, use gpt_image_gen_batch. Issuing several separate gpt_image_gen tool calls from one assistant message gets serialized by the MCP harness — but a batch call fans out internally with asyncio.gather, running up to 3 tabs at a time and queuing the rest. Pass requests=[{prompt, filename_prefix?, save_dir?}, ...]. Account-level rate limits may apply at high concurrency.
If ChatGPT shows the "Too many requests" conversation-protection modal, the browser automation saves a debug screenshot under debug/, clicks "Got it", and continues waiting for the response. It raises ChatGPTRateLimitError only if the dialog cannot be dismissed, persists after dismissal, or no usable response arrives afterward. Batch tools report the affected item as failed while letting other in-flight items finish.
Parameters:
prompt(required) — the full image-gen promptfilename_prefix(optional) — descriptive stem for saved files. Falls back to a hash if omitted.save_dir(optional) — overrides the default<cwd>/generated/embed_images(optional, defaultTrue) — whenFalse, Claude only gets the paths back. Use this during long iteration loops where embedded image bytes would flood Claude's context.
Files
File | Purpose |
| MCP server entry point (stdio or HTTP transport); registers the tools |
| Playwright ChatGPT automation; both text-streaming and image-gen flows |
| Standalone CLI wrapper (text only) |
| First-run helper for ChatGPT login |
| Unit tests for the JSON-normalization and prompt helpers |
Notes
The
chatgpt_profile/directory stores your persistent Chromium session. It's gitignored — you need to log in on each machine.Browser runs headed by default so you can complete the ChatGPT login on first run, and so you can watch image gen progress when debugging.
gpt_image_gensaves images relative to the Claude Code cwd, not the MCP server's source directory — so files land in whatever project Claude is working on.Failures raise: send timeouts, stream timeouts, and rate-limit dead ends surface as tool-call errors (with a debug screenshot path under
debug/) instead of error text masquerading as a response.
Development
pip install -e ".[dev]"
python3 -m pytest tests/ -qThe tests cover the pure helpers (JSON extraction/repair, citation stripping, prompt-source validation). The browser flows have no automated coverage — verify those against real ChatGPT.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
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/kev489/gpt-tool-use'
If you have feedback or need assistance with the MCP directory API, please join our Discord server