Metadata-Version: 2.4
Name: twocaptcha-mcp
Version: 0.6.0
Summary: MCP server exposing the full 2Captcha API surface (~31 captcha types + management + pingback CRUD) to Claude Code
Project-URL: Homepage, https://github.com/aruxojuyu665/2Captcha-MCP
Project-URL: Repository, https://github.com/aruxojuyu665/2Captcha-MCP
Project-URL: Issues, https://github.com/aruxojuyu665/2Captcha-MCP/issues
Project-URL: Changelog, https://github.com/aruxojuyu665/2Captcha-MCP/blob/main/CHANGELOG.md
Author: 2Captcha MCP Contributors
License: MIT
License-File: LICENSE
Keywords: 2captcha,ai-agent,captcha,claude-code,mcp
Requires-Python: >=3.11
Requires-Dist: 2captcha-python<3.0,>=2.0
Requires-Dist: httpx>=0.27
Requires-Dist: mcp>=1.2.0
Requires-Dist: pydantic-settings>=2.3
Requires-Dist: pydantic>=2.7
Requires-Dist: python-dotenv>=1.0
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pillow>=10.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# 2Captcha MCP

[![PyPI version](https://img.shields.io/pypi/v/twocaptcha-mcp.svg)](https://pypi.org/project/twocaptcha-mcp/)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![CI](https://github.com/aruxojuyu665/2Captcha-MCP/actions/workflows/ci.yml/badge.svg)](https://github.com/aruxojuyu665/2Captcha-MCP/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/aruxojuyu665/2Captcha-MCP/branch/main/graph/badge.svg)](https://codecov.io/gh/aruxojuyu665/2Captcha-MCP)
[![mypy: strict](https://img.shields.io/badge/mypy-strict-success.svg)](https://mypy.readthedocs.io/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](#license)

MCP server exposing the **full 2Captcha API surface** — 31 captcha types, 5 management tools, 3 pingback CRUD tools, 3 webhook event-store tools, and 1 composite solve-and-wait tool (**43 tools total**) — to Claude Code via stdio.

Built on the official `2captcha-python` SDK (`AsyncTwoCaptcha`), so retry/polling/parsing are handled upstream and every captcha type the SDK supports is available the moment the SDK adds it.

## Quick start

```bash
pip install twocaptcha-mcp
# or for development:
pip install -e ".[dev]"
```

Create a `.env` next to the project root:

```bash
2Captcha_API_KEY=your_2captcha_key_here
```

Verify it works:

```bash
python -m twocaptcha_mcp           # starts the stdio server (Ctrl+C to stop)
```

Register the server with Claude Code:

```bash
claude mcp add 2captcha -e 2Captcha_API_KEY=your_2captcha_key_here -- python -m twocaptcha_mcp
```

After a `claude` restart, prompt the model with:

> "Use twocaptcha_balance to check my account."

## Configuration

All settings are environment-driven. Aliases in priority order:

| Setting | Aliases | Default | Range |
|---|---|---|---|
| API key (required) | `2Captcha_API_KEY`, `TWOCAPTCHA_API_KEY`, `2CAPTCHA_API_KEY`, `API_KEY_2CAPTCHA` | — | — |
| Server | `TWOCAPTCHA_SERVER` | `2captcha.com` | `2captcha.com`, `rucaptcha.com` |
| Default timeout | `TWOCAPTCHA_DEFAULT_TIMEOUT` | `120` s | 1..600 |
| reCAPTCHA timeout | `TWOCAPTCHA_RECAPTCHA_TIMEOUT` | `600` s | 1..1200 |
| Polling interval | `TWOCAPTCHA_POLLING_INTERVAL` | `10` s | 1..120 |
| Soft id | `TWOCAPTCHA_SOFT_ID` | `4580` | — |
| Log level | `TWOCAPTCHA_LOG_LEVEL` | `INFO` | DEBUG/INFO/WARNING/ERROR/CRITICAL |
| Default pingback URL | `TWOCAPTCHA_DEFAULT_CALLBACK` | _unset_ | https URL |

## Tools

### Captcha solvers (31)

| Tool | SDK method | Required arguments |
|---|---|---|
| `twocaptcha_solve_normal` | `normal` | `file_path` xor `file_base64` |
| `twocaptcha_solve_text` | `text` | `text` |
| `twocaptcha_solve_audio` | `audio` | file (xor), `audio_lang` |
| `twocaptcha_solve_grid` | `grid` | file (xor) |
| `twocaptcha_solve_canvas` | `canvas` | file (xor) |
| `twocaptcha_solve_coordinates` | `coordinates` | file (xor) |
| `twocaptcha_solve_rotate` | `rotate` | `files: list` |
| `twocaptcha_solve_vkimage` | `vkimage` | `files`, `steps` |
| `twocaptcha_solve_recaptcha` | `recaptcha` | `sitekey`, `url`, `version`, `enterprise` |
| `twocaptcha_solve_hcaptcha` | `hcaptcha` | `sitekey`, `url` |
| `twocaptcha_solve_turnstile` | `turnstile` | `sitekey`, `url` (+ `data`/`pagedata` for CF Challenge) |
| `twocaptcha_solve_funcaptcha` | `funcaptcha` | `sitekey`, `url` |
| `twocaptcha_solve_geetest` | `geetest` | `gt`, `challenge`, `url` |
| `twocaptcha_solve_geetest_v4` | `geetest_v4` | `captcha_id`, `url` |
| `twocaptcha_solve_capy` | `capy` | `sitekey`, `url` |
| `twocaptcha_solve_keycaptcha` | `keycaptcha` | `s_s_c_user_id`, `s_s_c_session_id`, two signs, `url` |
| `twocaptcha_solve_lemin` | `lemin` | `captcha_id`, `div_id`, `url` |
| `twocaptcha_solve_mtcaptcha` | `mtcaptcha` | `sitekey`, `url` |
| `twocaptcha_solve_friendly_captcha` | `friendly_captcha` | `sitekey`, `url` |
| `twocaptcha_solve_cutcaptcha` | `cutcaptcha` | `misery_key`, `apikey`, `url` |
| `twocaptcha_solve_amazon_waf` | `amazon_waf` | `sitekey`, `iv`, `context`, `url` |
| `twocaptcha_solve_tencent` | `tencent` | `app_id`, `url` |
| `twocaptcha_solve_atb_captcha` | `atb_captcha` | `app_id`, `api_server`, `url` |
| `twocaptcha_solve_datadome` ⚑ | `datadome` | `proxy`, `user_agent`, `captcha_url`, `pageurl` |
| `twocaptcha_solve_captchafox` ⚑ | `captchafox` | `proxy`, `user_agent`, `sitekey`, `pageurl` |
| `twocaptcha_solve_vkcaptcha` ⚑ | `vkcaptcha` | `proxy`, `user_agent`, `redirect_uri` |
| `twocaptcha_solve_prosopo` | `prosopo` | `sitekey`, `pageurl` |
| `twocaptcha_solve_temu` | `temu` | `body`, `part1..3` |
| `twocaptcha_solve_altcha` | `altcha` | `pageurl` |
| `twocaptcha_solve_cybersiara` | `cybersiara` | `master_url_id`, `pageurl`, `cyber_user_agent` |
| `twocaptcha_solve_yandex_smart` | `yandex_smart` | `sitekey`, `url` |

⚑ — `proxy` and `user_agent` are **required** by the SDK signature.

All solver tools accept the same set of optional kwargs (mixin `SolverKwargs`):

- `proxy: {type, uri}` (HTTP/HTTPS/SOCKS4/SOCKS5)
- `pingback: HttpUrl` — per-call pingback URL (must be pre-registered)
- `soft_id: int`
- `cookies: str`
- `user_agent: str`
- `lang: str`
- `header_acao: 0|1`

### Management (5)

- `twocaptcha_balance` — current balance in USD
- `twocaptcha_report_good` / `twocaptcha_report_bad` — report a captcha id within 15 minutes
- `twocaptcha_get_result` — poll a captcha id manually (paired with `send_raw`)
- `twocaptcha_send_raw` — escape hatch for SDK methods this server does not yet expose

### Pingback CRUD (3)

- `twocaptcha_register_pingback` — whitelist a callback URL
- `twocaptcha_list_pingbacks` — list whitelisted addresses
- `twocaptcha_delete_pingback` — delete one or `addr="all"`

## Development

```bash
pytest --cov=twocaptcha_mcp --cov-branch --cov-fail-under=92 -v
ruff check . && ruff format --check .
mypy --strict twocaptcha_mcp
```

Run live tests against the real 2Captcha API (consumes credits):

```bash
pytest -m live --run-live          # balance + solve_normal + concurrent_balance
pytest -m e2e --run-e2e             # full MCP protocol roundtrip via mcp.client.session
```

## Architecture

```
twocaptcha_mcp/
├── __main__.py            # stdio entrypoint
├── server.py              # build_server + dispatch_tool_call
├── config.py              # pydantic-settings (.env)
├── logger.py              # stderr-only logger (stdout is reserved for stdio MCP)
├── client/
│   ├── solver.py          # SolverClient — async wrapper over AsyncTwoCaptcha
│   ├── pingback.py        # httpx wrapper for legacy res.php
│   ├── rate_limiter.py    # async sliding-window per-method rate limiter
│   └── errors.py          # internal CaptchaError hierarchy
├── schemas/               # Pydantic request/response models per captcha family
├── tools/                 # @captcha_tool handlers per captcha family + composite
└── webhook_receiver/      # Starlette app + SQLite store (twocaptcha-mcp-webhook)
```

Tool handlers depend only on the `SolverClient` / `PingbackClient` abstractions — the SDK is never imported from a handler. Adding a new captcha type is a 3-step process: schema → tool handler → snapshot test count bump.

## Webhook receiver (optional, since 0.3.0)

For long-running solves (recaptcha v3 up to 600 s), the polling-mode SDK call
holds the MCP request slot for the entire duration. Run the optional
`twocaptcha-mcp-webhook` server to flip into pingback mode — 2Captcha POSTs the
result to your URL, the receiver writes it to SQLite, and the MCP tools read
asynchronously without blocking.

- **Composite tool**: [`twocaptcha_solve_and_wait_pingback`](TROUBLESHOOTING.md#server-hangs-forever-on-a-solve_recaptcha-call)
  sends the captcha and waits on the local store
- **Read tools**: `twocaptcha_pingback_events_list/get/clear`
- **Deployment**: [docs/DEPLOY-WEBHOOK.md](docs/DEPLOY-WEBHOOK.md)
- **Troubleshooting**: [TROUBLESHOOTING.md](TROUBLESHOOTING.md#webhook-receiver)

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for the dev loop, code conventions, and the SemVer policy for the MCP tool surface.

## Security

See [SECURITY.md](SECURITY.md). Vulnerabilities are reported privately via GitHub Security Advisory.

## License

MIT — see [LICENSE](LICENSE).
