chatgpt-jules-mcp
# chatgpt-jules-mcp
Secure MCP server allowing ChatGPT to manage Google Jules sessions through OpenAI Secure MCP Tunnel.
## Architecture
```
ChatGPT
-> OpenAI Secure MCP Tunnel
-> tunnel-client (your MacBook)
-> chatgpt-jules-mcp (stdio)
-> jules-agent-sdk
-> Google Jules
-> GitHub repository
```
**No public HTTP. No Tailscale Funnel. No raw arbitrary HTTP.**
## Security Features
- **Policy-based access control** (`policy.yaml`) — allowlist sources, titles, tools
- **Confirmation gate** for `jules.approve_plan`
- **Audit logging** (JSONL) — every tool call recorded with metadata
- **Secret redaction** — JULES_API_KEY, tokens, private keys scrubbed from all output
- **Rate limiting** — per-tool, configurable via policy
- **Error boundary** — all exceptions caught, sanitized, never leak secrets
- **No generic HTTP tools** — only Jules-specific operations
## Quick Start
```bash
# Install from PyPI
pip install chatgpt-jules-mcp
# Or install in development mode
pip install -e ".[dev]"
# Set credentials
export JULES_API_KEY="your-jules-api-key"
# Configure policy
mkdir -p ~/.config/chatgpt-jules-mcp
cp config/policy.example.yaml ~/.config/chatgpt-jules-mcp/policy.yaml
# Edit: add your sources to allowed_sources
# Run MCP server (module)
python -m chatgpt_jules_mcp
# Or with CLI script (installed via pip)
chatgpt-jules-mcp
# Or with custom config
python -m chatgpt_jules_mcp --config /path/to/policy.yaml
chatgpt-jules-mcp --config /path/to/policy.yaml
```
## MCP Tools (14)
| Tool | Category | Description |
|------|----------|-------------|
| `jules.health` | Diagnostics | Server status, API key check, policy load |
| `jules.list_sources` | Sources | List allowed GitHub sources |
| `jules.get_source` | Sources | Get single source details |
| `jules.find_source` | Sources | Fuzzy search sources (client-side) |
| `jules.create_session` | Sessions | Create Jules session with policy checks |
| `jules.get_session` | Sessions | Get session status |
| `jules.list_sessions` | Sessions | List sessions (filtered by policy) |
| `jules.approve_plan` | Sessions | Approve plan (requires confirmation) |
| `jules.send_message` | Sessions | Send follow-up message |
| `jules.wait_for_completion` | Sessions | Poll until session completes |
| `jules.list_activities` | Activities | List session activities |
| `jules.get_activity` | Activities | Get single activity |
| `jules.summarize_session` | Convenience | Best-effort session summary |
| `jules.extract_result` | Convenience | Extract final result from activities |
## Project Structure
```
chatgpt-jules-mcp/
├── src/chatgpt_jules_mcp/
│ ├── server.py # FastMCP server, tool registration
│ ├── policy.py # Policy engine (YAML load, validate, enforce)
│ ├── audit.py # JSONL audit logger
│ ├── redaction.py # Secret pattern redaction
│ ├── errors.py # Custom exceptions, error boundary
│ ├── ratelimit.py # In-memory rate limiter
│ ├── shutdown.py # Graceful shutdown (SIGTERM/SIGINT)
│ ├── tools/
│ │ ├── health.py # jules.health
│ │ ├── sources.py # list_sources, get_source, find_source
│ │ ├── sessions.py # create_session, get_session, list_sessions, approve_plan, send_message, wait_for_completion
│ │ ├── activities.py # list_activities, get_activity
│ │ └── convenience.py # summarize_session, extract_result
├── tests/ # 50 tests across 10 test files
├── config/
│ └── policy.example.yaml # Example policy configuration
├── scripts/
│ └── emergency-stop.sh # Kill switch
└── docs/
└── openai-secure-mcp-tunnel.md # Tunnel setup guide
```
## Configuration
Policy is controlled via `~/.config/chatgpt-jules-mcp/policy.yaml`:
```yaml
jules:
allowed_sources:
- "sources/your-repo"
default_require_plan_approval: true
sessions:
allowed_title_prefixes:
- "ChatGPT:"
max_prompt_chars: 12000
max_message_chars: 8000
tools:
allow:
- "jules.health"
- "jules.list_sources"
# ... see policy.example.yaml for full list
require_confirmation:
- "jules.approve_plan"
audit:
path: "~/.local/share/chatgpt-jules-mcp/audit.jsonl"
redact_secrets: true
```
## Tests
```bash
pip install pytest pytest-asyncio
PYTHONPATH=src python -m pytest tests/ -v
```
50 tests covering: policy engine, audit logging, redaction, rate limiting, all 13 tools, error handling.
## OpenAI Secure MCP Tunnel
See [docs/openai-secure-mcp-tunnel.md](docs/openai-secure-mcp-tunnel.md) for full setup.
Quick version:
```bash
export CONTROL_PLANE_API_KEY="sk-..."
export CONTROL_PLANE_TUNNEL_ID="tunnel_..."
export JULES_API_KEY="..."
tunnel-client init \
--sample sample_mcp_stdio_local \
--profile chatgpt-jules-mcp-local \
--tunnel-id "$CONTROL_PLANE_TUNNEL_ID" \
--mcp-command "python -m chatgpt_jules_mcp"
tunnel-client doctor --profile chatgpt-jules-mcp-local --explain
tunnel-client run --profile chatgpt-jules-mcp-local
```
## Emergency Stop
```bash
./scripts/emergency-stop.sh
```
## License
Apache-2.0
TDQS
Scored across 14 tools
Tool names are generally distinct with clear actions (get vs list, find vs get) but some pairs like get_activity and list_activities could cause confusion. Without descriptions, an agent might misselect between similar resource-targeting tools.
All tools consistently use snake_case with a verb_noun pattern (e.g., create_session, list_sources). The only exception is health, which is a common standalone name. This pattern aids predictability.
14 tools is well within the ideal 3-15 range for a focused assistant system. Each tool appears to serve a distinct function without redundancy, making the set appropriately scoped.
The surface covers querying and creating sessions, activities, and sources, but lacks update and delete operations for these resources. This leaves gaps that may hinder full lifecycle management.