Skip to main content
Glama
kev489
by kev489

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.

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 chromium

Or clone and install locally:

git clone https://github.com/kev489/gpt-tool-use.git
cd gpt-tool-use
pip install .
playwright install chromium

Run once to log into ChatGPT (opens a browser window — sign in, then close the window):

gpt-tools-login    # or: python login.py from a clone

Login 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:

  • Labelcom.example.gpt-toolscom.YOURNAME.gpt-tools (any reverse-DNS string; this is also the filename you'll use in step 2)

  • ProgramArguments[0]/PATH/TO/python3 → your python3 absolute path (find with which 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 in launchctl list | grep gpt-tools).

  • ProgramArguments[1]/PATH/TO/gpt_tool_use/mcp_server.py → full path to mcp_server.py

  • WorkingDirectory, StandardOutPath, StandardErrorPath — replace /PATH/TO/gpt_tool_use with 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.plist

The 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 = 120

Claude 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 8788

Useful 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

  1. 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 provide prompt_file to read the prompt from a text file.

  2. Playwright waits for the response to finish streaming (up to 8 minutes)

  3. JavaScript DOM evaluation strips citation buttons, SVGs, accordion dropdowns, and other UI artifacts

  4. The cleaned HTML is converted to markdown via markdownify

  5. Inline citation markers ([1], [2], etc.) are stripped before returning to Claude or writing to output_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 ChatGPT

  • prompt_file (optional) — path to a text file containing the prompt. Use either query or prompt_file, not both.

  • output_file (optional) — path where the cleaned markdown response should be saved. Parent directories are created automatically.

  • return_output (optional) — when False, Claude only gets a short saved-path summary. Defaults to True unless output_file is provided; with output_file, it defaults to False to avoid filling Claude's context with the full response.

  • output_json (optional) — when True, 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

  1. Your prompt is sent to a fresh ChatGPT chat (each call resets — no context contamination across iterations)

  2. Playwright waits up to 8 minutes for the stop button to disappear AND <img> elements to settle

  3. Image URLs are downloaded via the browser's authenticated session (signed URLs work)

  4. Files are saved to <cwd>/generated/<prefix>.png (or <prefix>-1.png, <prefix>-2.png, ... for multiple)

  5. 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 prompt

  • filename_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, default True) — when False, 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.py

MCP server entry point (stdio or HTTP transport); registers the tools

browser.py

Playwright ChatGPT automation; both text-streaming and image-gen flows

gpt_search.py

Standalone CLI wrapper (text only)

login.py

First-run helper for ChatGPT login

tests/test_mcp_server.py

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_gen saves 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/ -q

The 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.

Install Server
F
license - not found
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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