claude-gpt 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of claude-gpt might be problematic. Click here for more details.
- claude_gpt-0.1.0/.env.example +23 -0
- claude_gpt-0.1.0/.gitignore +15 -0
- claude_gpt-0.1.0/LICENSE +21 -0
- claude_gpt-0.1.0/PKG-INFO +182 -0
- claude_gpt-0.1.0/README.md +148 -0
- claude_gpt-0.1.0/config.example.toml +63 -0
- claude_gpt-0.1.0/pyproject.toml +66 -0
- claude_gpt-0.1.0/src/claude_gpt/__init__.py +3 -0
- claude_gpt-0.1.0/src/claude_gpt/__main__.py +391 -0
- claude_gpt-0.1.0/src/claude_gpt/app.py +92 -0
- claude_gpt-0.1.0/src/claude_gpt/config.py +517 -0
- claude_gpt-0.1.0/src/claude_gpt/costs.py +99 -0
- claude_gpt-0.1.0/src/claude_gpt/dashboard/__init__.py +1 -0
- claude_gpt-0.1.0/src/claude_gpt/dashboard/app.py +357 -0
- claude_gpt-0.1.0/src/claude_gpt/dashboard/static/app.js +415 -0
- claude_gpt-0.1.0/src/claude_gpt/dashboard/static/style.css +65 -0
- claude_gpt-0.1.0/src/claude_gpt/dashboard/templates/base.html +25 -0
- claude_gpt-0.1.0/src/claude_gpt/dashboard/templates/index.html +8 -0
- claude_gpt-0.1.0/src/claude_gpt/dashboard/templates/job.html +8 -0
- claude_gpt-0.1.0/src/claude_gpt/dashboard/templates/session.html +8 -0
- claude_gpt-0.1.0/src/claude_gpt/engine.py +76 -0
- claude_gpt-0.1.0/src/claude_gpt/errors.py +50 -0
- claude_gpt-0.1.0/src/claude_gpt/events.py +230 -0
- claude_gpt-0.1.0/src/claude_gpt/fake_engine.py +118 -0
- claude_gpt-0.1.0/src/claude_gpt/files.py +770 -0
- claude_gpt-0.1.0/src/claude_gpt/jobs.py +922 -0
- claude_gpt-0.1.0/src/claude_gpt/log.py +55 -0
- claude_gpt-0.1.0/src/claude_gpt/openai_client.py +644 -0
- claude_gpt-0.1.0/src/claude_gpt/outputs.py +201 -0
- claude_gpt-0.1.0/src/claude_gpt/prompts.py +109 -0
- claude_gpt-0.1.0/src/claude_gpt/registry.py +965 -0
- claude_gpt-0.1.0/src/claude_gpt/server.py +510 -0
- claude_gpt-0.1.0/src/claude_gpt/sessions.py +261 -0
- claude_gpt-0.1.0/src/claude_gpt/stdio_guard.py +81 -0
- claude_gpt-0.1.0/src/claude_gpt/util.py +146 -0
- claude_gpt-0.1.0/tests/conftest.py +117 -0
- claude_gpt-0.1.0/tests/fake_openai.py +308 -0
- claude_gpt-0.1.0/tests/fixtures/make_fixtures.py +125 -0
- claude_gpt-0.1.0/tests/fixtures/sample.csv +4 -0
- claude_gpt-0.1.0/tests/fixtures/sample.docx +0 -0
- claude_gpt-0.1.0/tests/fixtures/sample.md +6 -0
- claude_gpt-0.1.0/tests/fixtures/sample.pdf +0 -0
- claude_gpt-0.1.0/tests/fixtures/sample.png +0 -0
- claude_gpt-0.1.0/tests/fixtures/sample.pptx +0 -0
- claude_gpt-0.1.0/tests/fixtures/sample.py +2 -0
- claude_gpt-0.1.0/tests/fixtures/sample.xlsx +0 -0
- claude_gpt-0.1.0/tests/helpers/stray_print_server.py +29 -0
- claude_gpt-0.1.0/tests/test_cli.py +54 -0
- claude_gpt-0.1.0/tests/test_config.py +99 -0
- claude_gpt-0.1.0/tests/test_costs.py +91 -0
- claude_gpt-0.1.0/tests/test_dashboard.py +160 -0
- claude_gpt-0.1.0/tests/test_files.py +85 -0
- claude_gpt-0.1.0/tests/test_hardening.py +348 -0
- claude_gpt-0.1.0/tests/test_jobs.py +203 -0
- claude_gpt-0.1.0/tests/test_language.py +38 -0
- claude_gpt-0.1.0/tests/test_multi_instance.py +89 -0
- claude_gpt-0.1.0/tests/test_openai_engine.py +238 -0
- claude_gpt-0.1.0/tests/test_outputs.py +117 -0
- claude_gpt-0.1.0/tests/test_pipeline.py +167 -0
- claude_gpt-0.1.0/tests/test_reasoning_effort.py +91 -0
- claude_gpt-0.1.0/tests/test_recovery.py +72 -0
- claude_gpt-0.1.0/tests/test_registry.py +132 -0
- claude_gpt-0.1.0/tests/test_sandbox_paths.py +118 -0
- claude_gpt-0.1.0/tests/test_stdio_protocol.py +138 -0
- claude_gpt-0.1.0/tests/test_tools_timing.py +113 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Development-only overrides. Copy to .env in the project directory.
|
|
2
|
+
# Environment variables beat ~/.claude-gpt/config.toml, which beats this file.
|
|
3
|
+
# Do not put the real API key here in a shared checkout; prefer ~/.claude-gpt/config.toml (mode 600).
|
|
4
|
+
|
|
5
|
+
# OPENAI_API_KEY=sk-...
|
|
6
|
+
CLAUDE_GPT_ENGINE=openai # openai | fake (canned replies, no network)
|
|
7
|
+
CLAUDE_GPT_MODEL=astra # astra | sol | terra | luna, or a model ID
|
|
8
|
+
# CLAUDE_GPT_STATE_DIR=~/.claude-gpt
|
|
9
|
+
# CLAUDE_GPT_OUTPUT_ROOT=~/ClaudeGPT
|
|
10
|
+
# CLAUDE_GPT_ALLOWED_ROOTS=~ # colon-separated
|
|
11
|
+
# CLAUDE_GPT_DASHBOARD_HOST=127.0.0.1
|
|
12
|
+
# CLAUDE_GPT_DASHBOARD_PORT=8765
|
|
13
|
+
# CLAUDE_GPT_DEFAULT_WEB_SEARCH=false
|
|
14
|
+
# CLAUDE_GPT_DEFAULT_CODE_INTERPRETER=true
|
|
15
|
+
# CLAUDE_GPT_DEFAULT_REASONING_EFFORT=high
|
|
16
|
+
# CLAUDE_GPT_DEFAULT_OUTPUT_MODE=auto
|
|
17
|
+
# CLAUDE_GPT_INLINE_MAX_WORDS=700
|
|
18
|
+
# CLAUDE_GPT_MAX_CONCURRENT_JOBS=3
|
|
19
|
+
# CLAUDE_GPT_MAX_FILE_MB=100
|
|
20
|
+
# CLAUDE_GPT_SESSION_BUDGET_USD=25
|
|
21
|
+
# CLAUDE_GPT_DAILY_BUDGET_USD=100
|
|
22
|
+
# CLAUDE_GPT_LOG_LEVEL=INFO
|
|
23
|
+
# CLAUDE_GPT_FAKE_DELAY_SECONDS=3
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
.venv/
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
.env
|
|
6
|
+
dist/
|
|
7
|
+
build/
|
|
8
|
+
*.egg-info/
|
|
9
|
+
.DS_Store
|
|
10
|
+
.venv.nosync/
|
|
11
|
+
|
|
12
|
+
# Secrets: the live key lives in ~/.claude-gpt/config.toml (outside this folder); never commit a copy
|
|
13
|
+
config.toml
|
|
14
|
+
*.local.toml
|
|
15
|
+
.claude-gpt/
|
claude_gpt-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Karl Foster
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: claude-gpt
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server that lets Claude Desktop delegate heavy work to OpenAI models: persistent sessions, file attachments, background jobs, live dashboard, cost tracking.
|
|
5
|
+
Project-URL: Homepage, https://github.com/karlfoster/claude-gpt
|
|
6
|
+
Project-URL: Repository, https://github.com/karlfoster/claude-gpt
|
|
7
|
+
Project-URL: Issues, https://github.com/karlfoster/claude-gpt/issues
|
|
8
|
+
Author: Karl Foster
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agents,chatgpt,claude,claude-desktop,delegation,gpt-6,mcp,openai
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: MacOS X
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Communications :: Chat
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Requires-Dist: aiohttp>=3.10
|
|
24
|
+
Requires-Dist: jinja2>=3.1
|
|
25
|
+
Requires-Dist: mammoth>=1.9
|
|
26
|
+
Requires-Dist: mcp>=2.1
|
|
27
|
+
Requires-Dist: openai>=3.8
|
|
28
|
+
Requires-Dist: openpyxl>=3.1
|
|
29
|
+
Requires-Dist: pillow-heif>=0.20
|
|
30
|
+
Requires-Dist: pillow>=11
|
|
31
|
+
Requires-Dist: pypdf>=5
|
|
32
|
+
Requires-Dist: python-pptx>=1.0
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
<p align="center">
|
|
36
|
+
<img src="https://raw.githubusercontent.com/karlfoster/claude-gpt/main/docs/screenshots/dashboard-job.png" alt="Claude GPT dashboard showing a research job with its reasoning, searches and rendered result" width="900">
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
<h1 align="center">Claude GPT</h1>
|
|
40
|
+
|
|
41
|
+
<p align="center">
|
|
42
|
+
Hand heavy work from Claude Desktop to OpenAI's frontier models and get the result back in the same chat.<br>
|
|
43
|
+
Persistent sessions, real file attachments, background jobs that survive restarts, a live dashboard, and cost tracking.
|
|
44
|
+
</p>
|
|
45
|
+
|
|
46
|
+
<p align="center">
|
|
47
|
+
<a href="https://github.com/karlfoster/claude-gpt/actions/workflows/ci.yml"><img src="https://github.com/karlfoster/claude-gpt/actions/workflows/ci.yml/badge.svg" alt="Tests"></a>
|
|
48
|
+
<img src="https://img.shields.io/badge/platform-macOS-lightgrey" alt="macOS only">
|
|
49
|
+
<img src="https://img.shields.io/badge/python-3.12%2B-blue" alt="Python 3.12+">
|
|
50
|
+
<img src="https://img.shields.io/badge/licence-MIT-green" alt="MIT licence">
|
|
51
|
+
</p>
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
Claude stays in charge. It holds your files, skills and memory, decides what needs heavy lifting, hands that work to GPT-6 Astra (or GPT-5.6 Sol) with the right brief and attachments, and relays the answer. You say things like:
|
|
56
|
+
|
|
57
|
+
> "Hand ~/Downloads/board-pack.pdf to ChatGPT and ask it for a summary with the key figures."
|
|
58
|
+
|
|
59
|
+
> "Give the deck and the brand guidelines to ChatGPT and have it rewrite the narrative."
|
|
60
|
+
|
|
61
|
+
> "Is ChatGPT done?"
|
|
62
|
+
|
|
63
|
+
Claude calls the bridge's tools; the model works in the background on OpenAI's side; short answers come straight back into the chat, long ones land on disk with a preview, and charts appear as images.
|
|
64
|
+
|
|
65
|
+
## Why
|
|
66
|
+
|
|
67
|
+
- **Overflow.** When Claude credits run low on a heavy day, the same chat can delegate to another frontier model without copy-pasting between apps.
|
|
68
|
+
- **Cheap orchestrator, expensive engine.** Run a lighter Claude model for the conversation and still get frontier-quality output on the delegated parts.
|
|
69
|
+
- **Whole documents, not pasted text.** Decks, spreadsheets, PDFs and images reach the model as files. The tools refuse pasted contents, so nothing gets lost in extraction.
|
|
70
|
+
- **No timeouts, no lost work.** Every tool call returns in seconds. Jobs run on OpenAI's side in background mode with a stored cursor, so a restart of Claude Desktop, or of your Mac, resumes rather than restarts.
|
|
71
|
+
- **Watch it think.** The dashboard streams reasoning summaries, web searches, code execution and output as they happen.
|
|
72
|
+
|
|
73
|
+
## Quick start
|
|
74
|
+
|
|
75
|
+
macOS only for now. You need [uv](https://docs.astral.sh/uv/), an OpenAI API key (a project key with a monthly budget is wise) and, for pptx and docx attachments, LibreOffice.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv tool install git+https://github.com/karlfoster/claude-gpt # or: uv tool install claude-gpt, once on PyPI
|
|
79
|
+
claude-gpt set-key # prompts for the key; stored privately, never echoed
|
|
80
|
+
claude-gpt setup --register # checks the key and LibreOffice, registers in Claude Desktop
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Restart Claude Desktop and the seven `chatgpt_*` tools appear. Optional: `brew install --cask libreoffice`.
|
|
84
|
+
|
|
85
|
+
<p align="center">
|
|
86
|
+
<img src="https://raw.githubusercontent.com/karlfoster/claude-gpt/main/docs/screenshots/cli-setup.png" alt="The setup command in a terminal" width="760">
|
|
87
|
+
</p>
|
|
88
|
+
|
|
89
|
+
Working from a clone instead? `uv sync` then `uv run claude-gpt setup --register`. The [design notes](docs/DESIGN.md) explain why registration points at the interpreter rather than `uv run`.
|
|
90
|
+
|
|
91
|
+
## What you can do
|
|
92
|
+
|
|
93
|
+
| Ask Claude | What happens |
|
|
94
|
+
|---|---|
|
|
95
|
+
| "Hand this PDF to ChatGPT for a summary" | A session starts, the file is uploaded whole, the summary comes back inline |
|
|
96
|
+
| "Attach the 20,000-row workbook and ask for revenue by month with a chart" | The sheet is previewed as tables and uploaded for Python; the chart returns as an image and a file |
|
|
97
|
+
| "Research the Gulf basketball market with web search" | Searches stream on the dashboard; a 1,200-word briefing lands on disk with a preview |
|
|
98
|
+
| "Send the changed files back for a second look" | The same session continues with the earlier context cached |
|
|
99
|
+
| "Fork the session, focusing on pricing" | A summary seeds a fresh session and the old one is archived |
|
|
100
|
+
| "Cancel that" or "close the session" | Immediate, from Claude or from the dashboard |
|
|
101
|
+
|
|
102
|
+
Before the first call of a session Claude asks which reasoning level you want (low, medium, high, xhigh or max) and reports the level used in every reply. Change it on any turn.
|
|
103
|
+
|
|
104
|
+
## Tools
|
|
105
|
+
|
|
106
|
+
Seven MCP tools, all returning within seconds, all answering with plain JSON that any Claude model can follow:
|
|
107
|
+
|
|
108
|
+
`chatgpt_start` creates a session with a brief and attachments · `chatgpt_send` sends a turn · `chatgpt_status` collects the result, waiting up to 45 seconds · `chatgpt_list` shows sessions, spend and the dashboard URL · `chatgpt_fork` carries a summary into a fresh session · `chatgpt_cancel` stops a job · `chatgpt_close` archives a session.
|
|
109
|
+
|
|
110
|
+
## Attachments
|
|
111
|
+
|
|
112
|
+
| Type | What the model receives |
|
|
113
|
+
|---|---|
|
|
114
|
+
| pdf | The file itself |
|
|
115
|
+
| pptx, docx | Converted to PDF with LibreOffice, plus the speaker notes as text |
|
|
116
|
+
| xlsx, xlsm, csv, tsv | Each sheet as a capped Markdown table; over the cap, the whole file is uploaded for Python analysis |
|
|
117
|
+
| png, jpg, gif, webp, heic | Resized and sent inline as an image |
|
|
118
|
+
| md, txt, json, yaml, xml, html and source code | Sent as fenced text, truncated only past 200,000 characters |
|
|
119
|
+
|
|
120
|
+
Files are deduplicated by content hash across sessions, and the same file is never attached twice to one conversation. In a Cowork session, where Claude works inside a sandbox, upload paths such as `/mnt/user-data/uploads/deck.pptx` are matched to the copy on your Mac by name, and every response says which file was used.
|
|
121
|
+
|
|
122
|
+
## Dashboard
|
|
123
|
+
|
|
124
|
+
`http://127.0.0.1:8765` while the server runs. Home shows every session with status, turns and spend, plus today's and the last 30 days' totals. A session page lists its brief, attached files and jobs, with close and fork buttons. A job page streams the activity live and renders the result as Markdown when it finishes, with generated files and image previews. It recovers after a browser refresh mid-job.
|
|
125
|
+
|
|
126
|
+
<p align="center">
|
|
127
|
+
<img src="https://raw.githubusercontent.com/karlfoster/claude-gpt/main/docs/screenshots/dashboard-home.png" alt="Dashboard home listing sessions" width="900">
|
|
128
|
+
</p>
|
|
129
|
+
|
|
130
|
+
<p align="center">
|
|
131
|
+
<img src="https://raw.githubusercontent.com/karlfoster/claude-gpt/main/docs/screenshots/dashboard-session.png" alt="A session page with attached files and jobs" width="900">
|
|
132
|
+
</p>
|
|
133
|
+
|
|
134
|
+
## Models, costs and budgets
|
|
135
|
+
|
|
136
|
+
GPT-6 Astra is the default; Sol, Terra and Luna are a `model: "sol"` away per session. Costs are computed per job from an editable price table (checked against OpenAI's pricing page on 4 September 2026), rolled up per session and per day, and shown in every status reply and on the dashboard. A session budget ($25) and a daily budget ($100) refuse new jobs when exceeded; Claude can override per call when you say so.
|
|
137
|
+
|
|
138
|
+
## Configuration
|
|
139
|
+
|
|
140
|
+
Precedence: environment variables, then `~/.claude-gpt/config.toml`, then a project `.env`, then defaults. The first run writes a private `config.toml` with every setting commented out; `claude-gpt set-key` fills in the key.
|
|
141
|
+
|
|
142
|
+
| Setting | Default | Purpose |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| `CLAUDE_GPT_MODEL` | `astra` | Model alias or ID for new sessions |
|
|
145
|
+
| `CLAUDE_GPT_DEFAULT_REASONING_EFFORT` | `high` | Default reasoning level |
|
|
146
|
+
| `CLAUDE_GPT_DEFAULT_WEB_SEARCH` | `false` | Web search on by default |
|
|
147
|
+
| `CLAUDE_GPT_DEFAULT_CODE_INTERPRETER` | `true` | Code interpreter on by default |
|
|
148
|
+
| `CLAUDE_GPT_INLINE_MAX_WORDS` | `700` | Longer results go to disk |
|
|
149
|
+
| `CLAUDE_GPT_SESSION_BUDGET_USD` | `25` | Per-session guardrail |
|
|
150
|
+
| `CLAUDE_GPT_DAILY_BUDGET_USD` | `100` | Daily guardrail across sessions |
|
|
151
|
+
| `CLAUDE_GPT_OUTPUT_ROOT` | `~/ClaudeGPT` | Where results are written |
|
|
152
|
+
|
|
153
|
+
Every setting is listed in `.env.example` and `config.example.toml`.
|
|
154
|
+
|
|
155
|
+
## Commands
|
|
156
|
+
|
|
157
|
+
| Command | What it does |
|
|
158
|
+
|---|---|
|
|
159
|
+
| `claude-gpt` | Serve MCP over stdio (what Claude Desktop launches) |
|
|
160
|
+
| `claude-gpt set-key [--from-env]` | Store the OpenAI API key privately |
|
|
161
|
+
| `claude-gpt setup [--register]` | Check the key online, check LibreOffice, register in Claude Desktop |
|
|
162
|
+
| `claude-gpt check-config` | Validate the configuration and show where each value came from |
|
|
163
|
+
| `claude-gpt purge-uploads` | Delete every cached OpenAI file upload |
|
|
164
|
+
| `claude-gpt prune --days 30` | Delete old per-job event logs |
|
|
165
|
+
|
|
166
|
+
## Security and privacy
|
|
167
|
+
|
|
168
|
+
- Attachments are uploaded to OpenAI under your API key and are subject to OpenAI's data policies; background mode stores response data on their side for a limited time.
|
|
169
|
+
- The key lives in `~/.claude-gpt/config.toml`, readable only by your user, and is redacted from logs. The state directory and database are private to your user.
|
|
170
|
+
- The dashboard binds to 127.0.0.1 only. File reads are confined to your home folder by default (`CLAUDE_GPT_ALLOWED_ROOTS`), symlinks are resolved before the check, and the model gets no tool that acts on your Mac.
|
|
171
|
+
|
|
172
|
+
## Under the hood
|
|
173
|
+
|
|
174
|
+
Python 3.12, the official MCP SDK over stdio, the OpenAI Responses API with Conversations for server-side state and background streaming with a resumable cursor, SQLite in WAL mode for the registry, JSONL event logs per job, and aiohttp for the dashboard. Two copies of the server can share one registry safely: Claude Desktop starts a second copy for its Cowork and Code sessions, so every state change is an atomic, conditional write and one active job per session is a database invariant. The [design notes](docs/DESIGN.md) cover the reasoning, the recovery model and the verification history.
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
uv sync && uv run pytest # 102 tests, no network calls
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Licence
|
|
181
|
+
|
|
182
|
+
MIT. Built by Karl Foster with Claude.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/karlfoster/claude-gpt/main/docs/screenshots/dashboard-job.png" alt="Claude GPT dashboard showing a research job with its reasoning, searches and rendered result" width="900">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Claude GPT</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
Hand heavy work from Claude Desktop to OpenAI's frontier models and get the result back in the same chat.<br>
|
|
9
|
+
Persistent sessions, real file attachments, background jobs that survive restarts, a live dashboard, and cost tracking.
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://github.com/karlfoster/claude-gpt/actions/workflows/ci.yml"><img src="https://github.com/karlfoster/claude-gpt/actions/workflows/ci.yml/badge.svg" alt="Tests"></a>
|
|
14
|
+
<img src="https://img.shields.io/badge/platform-macOS-lightgrey" alt="macOS only">
|
|
15
|
+
<img src="https://img.shields.io/badge/python-3.12%2B-blue" alt="Python 3.12+">
|
|
16
|
+
<img src="https://img.shields.io/badge/licence-MIT-green" alt="MIT licence">
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
Claude stays in charge. It holds your files, skills and memory, decides what needs heavy lifting, hands that work to GPT-6 Astra (or GPT-5.6 Sol) with the right brief and attachments, and relays the answer. You say things like:
|
|
22
|
+
|
|
23
|
+
> "Hand ~/Downloads/board-pack.pdf to ChatGPT and ask it for a summary with the key figures."
|
|
24
|
+
|
|
25
|
+
> "Give the deck and the brand guidelines to ChatGPT and have it rewrite the narrative."
|
|
26
|
+
|
|
27
|
+
> "Is ChatGPT done?"
|
|
28
|
+
|
|
29
|
+
Claude calls the bridge's tools; the model works in the background on OpenAI's side; short answers come straight back into the chat, long ones land on disk with a preview, and charts appear as images.
|
|
30
|
+
|
|
31
|
+
## Why
|
|
32
|
+
|
|
33
|
+
- **Overflow.** When Claude credits run low on a heavy day, the same chat can delegate to another frontier model without copy-pasting between apps.
|
|
34
|
+
- **Cheap orchestrator, expensive engine.** Run a lighter Claude model for the conversation and still get frontier-quality output on the delegated parts.
|
|
35
|
+
- **Whole documents, not pasted text.** Decks, spreadsheets, PDFs and images reach the model as files. The tools refuse pasted contents, so nothing gets lost in extraction.
|
|
36
|
+
- **No timeouts, no lost work.** Every tool call returns in seconds. Jobs run on OpenAI's side in background mode with a stored cursor, so a restart of Claude Desktop, or of your Mac, resumes rather than restarts.
|
|
37
|
+
- **Watch it think.** The dashboard streams reasoning summaries, web searches, code execution and output as they happen.
|
|
38
|
+
|
|
39
|
+
## Quick start
|
|
40
|
+
|
|
41
|
+
macOS only for now. You need [uv](https://docs.astral.sh/uv/), an OpenAI API key (a project key with a monthly budget is wise) and, for pptx and docx attachments, LibreOffice.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
uv tool install git+https://github.com/karlfoster/claude-gpt # or: uv tool install claude-gpt, once on PyPI
|
|
45
|
+
claude-gpt set-key # prompts for the key; stored privately, never echoed
|
|
46
|
+
claude-gpt setup --register # checks the key and LibreOffice, registers in Claude Desktop
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Restart Claude Desktop and the seven `chatgpt_*` tools appear. Optional: `brew install --cask libreoffice`.
|
|
50
|
+
|
|
51
|
+
<p align="center">
|
|
52
|
+
<img src="https://raw.githubusercontent.com/karlfoster/claude-gpt/main/docs/screenshots/cli-setup.png" alt="The setup command in a terminal" width="760">
|
|
53
|
+
</p>
|
|
54
|
+
|
|
55
|
+
Working from a clone instead? `uv sync` then `uv run claude-gpt setup --register`. The [design notes](docs/DESIGN.md) explain why registration points at the interpreter rather than `uv run`.
|
|
56
|
+
|
|
57
|
+
## What you can do
|
|
58
|
+
|
|
59
|
+
| Ask Claude | What happens |
|
|
60
|
+
|---|---|
|
|
61
|
+
| "Hand this PDF to ChatGPT for a summary" | A session starts, the file is uploaded whole, the summary comes back inline |
|
|
62
|
+
| "Attach the 20,000-row workbook and ask for revenue by month with a chart" | The sheet is previewed as tables and uploaded for Python; the chart returns as an image and a file |
|
|
63
|
+
| "Research the Gulf basketball market with web search" | Searches stream on the dashboard; a 1,200-word briefing lands on disk with a preview |
|
|
64
|
+
| "Send the changed files back for a second look" | The same session continues with the earlier context cached |
|
|
65
|
+
| "Fork the session, focusing on pricing" | A summary seeds a fresh session and the old one is archived |
|
|
66
|
+
| "Cancel that" or "close the session" | Immediate, from Claude or from the dashboard |
|
|
67
|
+
|
|
68
|
+
Before the first call of a session Claude asks which reasoning level you want (low, medium, high, xhigh or max) and reports the level used in every reply. Change it on any turn.
|
|
69
|
+
|
|
70
|
+
## Tools
|
|
71
|
+
|
|
72
|
+
Seven MCP tools, all returning within seconds, all answering with plain JSON that any Claude model can follow:
|
|
73
|
+
|
|
74
|
+
`chatgpt_start` creates a session with a brief and attachments · `chatgpt_send` sends a turn · `chatgpt_status` collects the result, waiting up to 45 seconds · `chatgpt_list` shows sessions, spend and the dashboard URL · `chatgpt_fork` carries a summary into a fresh session · `chatgpt_cancel` stops a job · `chatgpt_close` archives a session.
|
|
75
|
+
|
|
76
|
+
## Attachments
|
|
77
|
+
|
|
78
|
+
| Type | What the model receives |
|
|
79
|
+
|---|---|
|
|
80
|
+
| pdf | The file itself |
|
|
81
|
+
| pptx, docx | Converted to PDF with LibreOffice, plus the speaker notes as text |
|
|
82
|
+
| xlsx, xlsm, csv, tsv | Each sheet as a capped Markdown table; over the cap, the whole file is uploaded for Python analysis |
|
|
83
|
+
| png, jpg, gif, webp, heic | Resized and sent inline as an image |
|
|
84
|
+
| md, txt, json, yaml, xml, html and source code | Sent as fenced text, truncated only past 200,000 characters |
|
|
85
|
+
|
|
86
|
+
Files are deduplicated by content hash across sessions, and the same file is never attached twice to one conversation. In a Cowork session, where Claude works inside a sandbox, upload paths such as `/mnt/user-data/uploads/deck.pptx` are matched to the copy on your Mac by name, and every response says which file was used.
|
|
87
|
+
|
|
88
|
+
## Dashboard
|
|
89
|
+
|
|
90
|
+
`http://127.0.0.1:8765` while the server runs. Home shows every session with status, turns and spend, plus today's and the last 30 days' totals. A session page lists its brief, attached files and jobs, with close and fork buttons. A job page streams the activity live and renders the result as Markdown when it finishes, with generated files and image previews. It recovers after a browser refresh mid-job.
|
|
91
|
+
|
|
92
|
+
<p align="center">
|
|
93
|
+
<img src="https://raw.githubusercontent.com/karlfoster/claude-gpt/main/docs/screenshots/dashboard-home.png" alt="Dashboard home listing sessions" width="900">
|
|
94
|
+
</p>
|
|
95
|
+
|
|
96
|
+
<p align="center">
|
|
97
|
+
<img src="https://raw.githubusercontent.com/karlfoster/claude-gpt/main/docs/screenshots/dashboard-session.png" alt="A session page with attached files and jobs" width="900">
|
|
98
|
+
</p>
|
|
99
|
+
|
|
100
|
+
## Models, costs and budgets
|
|
101
|
+
|
|
102
|
+
GPT-6 Astra is the default; Sol, Terra and Luna are a `model: "sol"` away per session. Costs are computed per job from an editable price table (checked against OpenAI's pricing page on 4 September 2026), rolled up per session and per day, and shown in every status reply and on the dashboard. A session budget ($25) and a daily budget ($100) refuse new jobs when exceeded; Claude can override per call when you say so.
|
|
103
|
+
|
|
104
|
+
## Configuration
|
|
105
|
+
|
|
106
|
+
Precedence: environment variables, then `~/.claude-gpt/config.toml`, then a project `.env`, then defaults. The first run writes a private `config.toml` with every setting commented out; `claude-gpt set-key` fills in the key.
|
|
107
|
+
|
|
108
|
+
| Setting | Default | Purpose |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| `CLAUDE_GPT_MODEL` | `astra` | Model alias or ID for new sessions |
|
|
111
|
+
| `CLAUDE_GPT_DEFAULT_REASONING_EFFORT` | `high` | Default reasoning level |
|
|
112
|
+
| `CLAUDE_GPT_DEFAULT_WEB_SEARCH` | `false` | Web search on by default |
|
|
113
|
+
| `CLAUDE_GPT_DEFAULT_CODE_INTERPRETER` | `true` | Code interpreter on by default |
|
|
114
|
+
| `CLAUDE_GPT_INLINE_MAX_WORDS` | `700` | Longer results go to disk |
|
|
115
|
+
| `CLAUDE_GPT_SESSION_BUDGET_USD` | `25` | Per-session guardrail |
|
|
116
|
+
| `CLAUDE_GPT_DAILY_BUDGET_USD` | `100` | Daily guardrail across sessions |
|
|
117
|
+
| `CLAUDE_GPT_OUTPUT_ROOT` | `~/ClaudeGPT` | Where results are written |
|
|
118
|
+
|
|
119
|
+
Every setting is listed in `.env.example` and `config.example.toml`.
|
|
120
|
+
|
|
121
|
+
## Commands
|
|
122
|
+
|
|
123
|
+
| Command | What it does |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `claude-gpt` | Serve MCP over stdio (what Claude Desktop launches) |
|
|
126
|
+
| `claude-gpt set-key [--from-env]` | Store the OpenAI API key privately |
|
|
127
|
+
| `claude-gpt setup [--register]` | Check the key online, check LibreOffice, register in Claude Desktop |
|
|
128
|
+
| `claude-gpt check-config` | Validate the configuration and show where each value came from |
|
|
129
|
+
| `claude-gpt purge-uploads` | Delete every cached OpenAI file upload |
|
|
130
|
+
| `claude-gpt prune --days 30` | Delete old per-job event logs |
|
|
131
|
+
|
|
132
|
+
## Security and privacy
|
|
133
|
+
|
|
134
|
+
- Attachments are uploaded to OpenAI under your API key and are subject to OpenAI's data policies; background mode stores response data on their side for a limited time.
|
|
135
|
+
- The key lives in `~/.claude-gpt/config.toml`, readable only by your user, and is redacted from logs. The state directory and database are private to your user.
|
|
136
|
+
- The dashboard binds to 127.0.0.1 only. File reads are confined to your home folder by default (`CLAUDE_GPT_ALLOWED_ROOTS`), symlinks are resolved before the check, and the model gets no tool that acts on your Mac.
|
|
137
|
+
|
|
138
|
+
## Under the hood
|
|
139
|
+
|
|
140
|
+
Python 3.12, the official MCP SDK over stdio, the OpenAI Responses API with Conversations for server-side state and background streaming with a resumable cursor, SQLite in WAL mode for the registry, JSONL event logs per job, and aiohttp for the dashboard. Two copies of the server can share one registry safely: Claude Desktop starts a second copy for its Cowork and Code sessions, so every state change is an atomic, conditional write and one active job per session is a database invariant. The [design notes](docs/DESIGN.md) cover the reasoning, the recovery model and the verification history.
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
uv sync && uv run pytest # 102 tests, no network calls
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Licence
|
|
147
|
+
|
|
148
|
+
MIT. Built by Karl Foster with Claude.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Claude GPT configuration.
|
|
2
|
+
# Environment variables take precedence over this file. Keys under [settings] use the
|
|
3
|
+
# environment variable name without the CLAUDE_GPT_ prefix, in lower case.
|
|
4
|
+
# Keep this file private (mode 600): it is the recommended home for the API key.
|
|
5
|
+
|
|
6
|
+
[settings]
|
|
7
|
+
# openai_api_key = "sk-..."
|
|
8
|
+
# engine = "openai" # "fake" gives canned replies without any network calls
|
|
9
|
+
# background = true # background mode makes jobs resumable after a restart
|
|
10
|
+
# model = "astra" # astra | sol | terra | luna, or a model ID
|
|
11
|
+
# default_web_search = false
|
|
12
|
+
# default_code_interpreter = true
|
|
13
|
+
# default_reasoning_effort = "high"
|
|
14
|
+
# default_output_mode = "auto"
|
|
15
|
+
# inline_max_words = 700
|
|
16
|
+
# max_concurrent_jobs = 3
|
|
17
|
+
# session_budget_usd = 25
|
|
18
|
+
# daily_budget_usd = 100
|
|
19
|
+
# log_level = "INFO"
|
|
20
|
+
|
|
21
|
+
[models.aliases]
|
|
22
|
+
sol = "gpt-5.6-sol" # confirmed against the models endpoint on 4 September 2026
|
|
23
|
+
terra = "gpt-5.6-terra"
|
|
24
|
+
luna = "gpt-5.6-luna"
|
|
25
|
+
astra = "gpt-6-astra" # listed on the pricing page; API access is rolling out
|
|
26
|
+
|
|
27
|
+
# Prices per million tokens, checked against https://developers.openai.com/api/docs/pricing on
|
|
28
|
+
# 4 September 2026 (standard tier, short context). Re-check when OpenAI changes them; Sol's
|
|
29
|
+
# figures are promotional until at least 21 November 2026. Reasoning tokens are billed as output.
|
|
30
|
+
|
|
31
|
+
[prices.models."gpt-6-astra"]
|
|
32
|
+
input_per_m = 10.00
|
|
33
|
+
cached_input_per_m = 1.00
|
|
34
|
+
cache_write_per_m = 12.50
|
|
35
|
+
output_per_m = 50.00
|
|
36
|
+
|
|
37
|
+
[prices.models."gpt-5.6-sol"]
|
|
38
|
+
input_per_m = 4.00
|
|
39
|
+
cached_input_per_m = 0.40
|
|
40
|
+
cache_write_per_m = 5.00
|
|
41
|
+
output_per_m = 20.00
|
|
42
|
+
|
|
43
|
+
[prices.models."gpt-5.6-terra"]
|
|
44
|
+
input_per_m = 2.00
|
|
45
|
+
cached_input_per_m = 0.20
|
|
46
|
+
cache_write_per_m = 2.50
|
|
47
|
+
output_per_m = 12.00
|
|
48
|
+
|
|
49
|
+
[prices.models."gpt-5.6-luna"]
|
|
50
|
+
input_per_m = 0.20
|
|
51
|
+
cached_input_per_m = 0.02
|
|
52
|
+
cache_write_per_m = 0.25
|
|
53
|
+
output_per_m = 1.20
|
|
54
|
+
|
|
55
|
+
[prices.tools]
|
|
56
|
+
web_search_per_call = 0.01 # $10 per 1,000 calls
|
|
57
|
+
code_interpreter_per_session = 0.03 # 1 GB container per 20-minute session
|
|
58
|
+
|
|
59
|
+
[prices.multipliers]
|
|
60
|
+
long_context_threshold_tokens = 272000
|
|
61
|
+
long_context_input_multiplier = 2.0 # input and cached input double above the threshold
|
|
62
|
+
long_context_output_multiplier = 1.5 # output is 1.5x above the threshold
|
|
63
|
+
fast_mode_multiplier = 2.0 # service_tier "fast" (formerly priority)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "claude-gpt"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "MCP server that lets Claude Desktop delegate heavy work to OpenAI models: persistent sessions, file attachments, background jobs, live dashboard, cost tracking."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
authors = [{ name = "Karl Foster" }]
|
|
10
|
+
keywords = ["mcp", "claude", "claude-desktop", "openai", "chatgpt", "gpt-6", "delegation", "agents"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 4 - Beta",
|
|
13
|
+
"Environment :: MacOS X",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"Intended Audience :: End Users/Desktop",
|
|
16
|
+
"Operating System :: MacOS",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Topic :: Communications :: Chat",
|
|
21
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"mcp>=2.1",
|
|
25
|
+
"aiohttp>=3.10",
|
|
26
|
+
"jinja2>=3.1",
|
|
27
|
+
"openai>=3.8",
|
|
28
|
+
"pillow>=11",
|
|
29
|
+
"pillow-heif>=0.20",
|
|
30
|
+
"pypdf>=5",
|
|
31
|
+
"python-pptx>=1.0",
|
|
32
|
+
"openpyxl>=3.1",
|
|
33
|
+
"mammoth>=1.9",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/karlfoster/claude-gpt"
|
|
38
|
+
Repository = "https://github.com/karlfoster/claude-gpt"
|
|
39
|
+
Issues = "https://github.com/karlfoster/claude-gpt/issues"
|
|
40
|
+
|
|
41
|
+
[project.scripts]
|
|
42
|
+
claude-gpt = "claude_gpt.__main__:main"
|
|
43
|
+
|
|
44
|
+
[dependency-groups]
|
|
45
|
+
dev = [
|
|
46
|
+
"pytest>=8.3",
|
|
47
|
+
"pytest-asyncio>=0.24",
|
|
48
|
+
"python-docx>=1.2.0",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[build-system]
|
|
52
|
+
requires = ["hatchling"]
|
|
53
|
+
build-backend = "hatchling.build"
|
|
54
|
+
|
|
55
|
+
[tool.hatch.build.targets.wheel]
|
|
56
|
+
packages = ["src/claude_gpt"]
|
|
57
|
+
|
|
58
|
+
[tool.hatch.build.targets.sdist]
|
|
59
|
+
include = ["src", "tests", "README.md", "LICENSE", "config.example.toml", ".env.example", "pyproject.toml"]
|
|
60
|
+
exclude = ["tests/fixtures/*.heic"]
|
|
61
|
+
|
|
62
|
+
[tool.pytest.ini_options]
|
|
63
|
+
asyncio_mode = "auto"
|
|
64
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
65
|
+
testpaths = ["tests"]
|
|
66
|
+
addopts = "-q"
|