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 Example

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

If you plan to run the launchd service, keep the clone outside ~/Desktop, ~/Documents, and ~/Downloads — see the TCC warning under "One-time setup".

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

TCC warning: the repo must live outside ~/Desktop, ~/Documents, and ~/Downloads. macOS blocks launchd background jobs from those folders, so the service dies at spawn with exit code 78 (EX_CONFIG) and empty logs — Python never starts. If launchctl list | grep gpt-tools shows 78, it's this or a stale Python path.

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.

Available Tools

4 tools
gpt_image_genA

Generate one or more images via ChatGPT image gen and save them to disk.

The prompt is sent directly to ChatGPT — phrase it as an image-generation request and let the prompt itself specify how many images you want.

For running multiple distinct prompts in parallel, use gpt_image_gen_batch instead — it fans out concurrently inside a single MCP call. Issuing two gpt_image_gen calls from one Claude message executes serially because the MCP harness serializes calls to the same server.

Args: prompt: Full image-gen prompt sent directly to ChatGPT. filename_prefix: Stem for saved files. Single image saves as <prefix>.<ext>; multiple images get numbered suffixes (<prefix>-1.<ext>, <prefix>-2.<ext>, ...). Defaults to a hash of the prompt. save_dir: Where to save images. Defaults to <cwd>/generated/ (created if missing). embed_images: When True, the saved images are returned in the tool response so Claude can analyze them. Set False during long iteration loops to keep context light — paths are still returned.

Returns a list of MCP content blocks: a text summary plus, if embed_images is True, the image blobs.

ParametersJSON Schema
NameRequiredDescriptionDefault
promptYes
filename_prefixNo
save_dirNo
embed_imagesNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully discloses behavioral traits: serialization behavior, default save directory, naming conventions for single vs. multiple images, and the effect of embed_images on the response. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with separate paragraphs for the core function, usage notes, and parameter details. It is reasonably concise, though the details about naming and defaults could be slightly more streamlined.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero schema coverage, no output schema, and no annotations, the description covers the return format (list of MCP content blocks, text summary, optional images) and key defaults. It lacks explicit output schema, but the qualitative description suffices for the agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must add meaning for all parameters. It explains prompt, filename_prefix (default naming), save_dir (default location), and embed_images (response impact). This fully compensates for the lack of schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Generate one or more images via ChatGPT image gen and save them to disk.' It uses a specific verb and resource, and distinguishes from the sibling tool gpt_image_gen_batch which handles parallel distinct prompts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool versus gpt_image_gen_batch (parallel runs), and notes that sequential calls via the MCP harness are serial. However, it does not explicitly contrast with the search siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

gpt_image_gen_batchA

Run multiple image-gen prompts in parallel via ChatGPT image gen.

Each request opens its own ChatGPT tab and runs concurrently with the others. This is how you actually parallelize image gen — issuing multiple separate gpt_image_gen tool calls from a single Claude message gets serialized by the MCP harness, but a single gpt_image_gen_batch call fans out internally and bypasses that.

Each item in requests is a dict with keys:

  • prompt (required, str): the full image-gen prompt

  • filename_prefix (optional, str): stem for saved files; falls back to a hash of the prompt

  • save_dir (optional, str): override save location for this item; defaults to <cwd>/generated/

embed_images is batch-level — applies to all items. Set False during long iteration loops to keep Claude's context light.

All items run concurrently, capped at 3 ChatGPT tabs at a time server-wide; larger batches queue internally. If one fails, the others still complete; failed items show up in the response as [<prefix>] FAILED: <error>.

Account-level rate limits may still apply under sustained concurrency.

Returns a list of MCP content blocks: per-item text summaries plus, if embed_images is True, the image blobs in order.

ParametersJSON Schema
NameRequiredDescriptionDefault
requestsYes
embed_imagesNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses key behaviors: concurrent execution capped at 3 tabs, queueing for larger batches, error handling (one fails, others complete), rate limit caveat, and batch-level embed_images behavior. No annotations provided, but description fully compensates.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is informative without being overly verbose. Each sentence adds value, though slightly longer than necessary. Front-loaded with purpose and key usage note.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and two parameters, the description covers all necessary context: parallel execution details, error behavior, return format (list of MCP content blocks with text and optionally images), and rate limits.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Adds rich meaning beyond schema: details each key in requests (prompt, filename_prefix, save_dir) and the batch-level embed_images flag. Schema coverage was 0%, so description carries full burden and executes well.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Run multiple image-gen prompts in parallel via ChatGPT image gen.' It distinguishes from sibling gpt_image_gen by explaining parallelization advantage over serialized calls.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use this tool over alternatives: 'This is how you actually parallelize image gen... issuing multiple separate gpt_image_gen tool calls... gets serialized... gpt_image_gen_batch fans out internally.' Also advises setting embed_images to false during long loops.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

gpt_search_batchA

Run multiple ChatGPT search/research prompts concurrently.

Each request opens its own ChatGPT tab and runs concurrently with the others. This is the text equivalent of gpt_image_gen_batch. The server runs at most 3 ChatGPT tabs at a time across all calls and sessions; larger batches queue internally.

Each item in requests is a dict with keys:

  • query (optional, str): the full prompt

  • prompt_file (optional, str): path to a text file containing the prompt

  • output_file (optional, str): path where the cleaned markdown response should be saved

  • label (optional, str): heading used for this item in the combined response; defaults to output_file, then prompt_file, then request_<n>

  • return_output (optional, bool): overrides the batch-level return_output for this item

  • output_json (optional, bool): overrides the batch-level output_json for this item

Provide either query or prompt_file for each item. Relative file paths resolve from the MCP server process working directory.

return_output is batch-level unless overridden per item. When omitted, each item defaults to returning the full output only if it has no output_file. output_json is batch-level unless overridden per item. When enabled, the response is parsed/repaired after ChatGPT returns. For file outputs, raw output is saved first and overwritten only when JSON post-processing succeeds.

Returns a markdown summary. If outputs are returned, they are grouped under per-request headings.

ParametersJSON Schema
NameRequiredDescriptionDefault
requestsYes
return_outputNo
output_jsonNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It thoroughly discloses concurrency behavior, internal queuing, server limits, file path resolution, output handling, and JSON post-processing with potential overwriting, providing comprehensive behavioral transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the primary purpose and is dense with necessary information, but it is somewhat lengthy. Every sentence adds value, but slight trimming could improve conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (batch processing, multiple optional overrides, concurrency limits, file handling), the description covers all essential aspects. The output schema exists but the description still explains the return format (markdown summary with per-request headings), leaving no obvious gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, but the description fully compensates by explaining each key in the requests array (query, prompt_file, output_file, label, return_output, output_json) with defaults and behavior, and also clarifies batch-level overrides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Run multiple ChatGPT search/research prompts concurrently,' specifying the verb, resource, and concurrency aspect, and distinguishes from siblings by mentioning gpt_image_gen_batch as the image equivalent and implying it's the batch version of gpt_search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use this tool (for concurrent batch requests) and notes the server limit of 3 tabs. It indirectly suggests using gpt_search for single queries by naming the sibling, but does not explicitly state when not to use this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.7/5.0
Disambiguation5/5

The four tools are clearly separated into image generation (gpt_image_gen, gpt_image_gen_batch) and search (gpt_search, gpt_search_batch), with distinct purposes explained in detail. The batch variants explicitly state when to use them instead of the single variants, leaving no ambiguity.

Naming Consistency5/5

All tool names follow a consistent pattern: the prefix 'gpt_' followed by a descriptive task ('image_gen' or 'search') and an optional '_batch' for concurrent execution. This makes naming predictable and intuitive.

Tool Count5/5

With only 4 tools, the server is well-scoped for its two core functionalities (image generation and search), each offered in single and batch variants. The count is appropriate and avoids unnecessary complexity.

Completeness5/5

The tool surface covers the primary operations for image generation and search/research, including parallel execution via batch variants. There are no obvious missing tools for the server's stated purpose of interacting with ChatGPT for these tasks.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to control a browser through Playwright automation tools, allowing them to perform web tasks like navigation, typing, clicking, and taking screenshots. Deployed on Cloudflare Workers and compatible with various AI platforms including Claude Desktop and VS Code.
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to control a web browser via Playwright on Cloudflare Workers for automated tasks like navigation, clicking, typing, and taking screenshots. It integrates with platforms like Claude Desktop and GitHub Copilot to perform web automation through a standardized toolset.
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables browser automation and web interaction control through Playwright, allowing Claude Code to navigate, click, fill forms, take screenshots, and manage sessions.
    158
    7
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables natural language browser automation through Claude, wrapping Playwright to execute commands like navigation, clicking, form filling, and screenshots.
    20
    30
    MIT

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