mcp-image2text 2026.10.8.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.
@@ -0,0 +1,6 @@
1
+ ACEDATACLOUD_API_TOKEN=
2
+ ACEDATACLOUD_API_BASE_URL=https://api.acedata.cloud
3
+ IMAGE2TEXT_REQUEST_TIMEOUT=120
4
+ MCP_TRANSPORT=stdio
5
+ MCP_SERVER_NAME=image2text
6
+ LOG_LEVEL=INFO
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 AceDataCloud
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,109 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-image2text
3
+ Version: 2026.10.8.0
4
+ Summary: MCP server for AceDataCloud Image2Text captcha APIs
5
+ Project-URL: Homepage, https://github.com/AceDataCloud/MCPs
6
+ Project-URL: Documentation, https://platform.acedata.cloud/services/2aaa7faf-099e-410e-82f3-8d78170f25bb?utm_source=pypi&utm_medium=referral&utm_campaign=evergreen&utm_content=image2text_mcp_package_quick_start
7
+ Project-URL: Repository, https://github.com/AceDataCloud/MCPs
8
+ Project-URL: Issues, https://github.com/AceDataCloud/MCPs/issues
9
+ Author-email: AceDataCloud <support@acedata.cloud>
10
+ Maintainer-email: AceDataCloud <support@acedata.cloud>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: acedata,captcha,image2text,mcp,model-context-protocol
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Internet :: WWW/HTTP
23
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: cryptography>=42.0.0
26
+ Requires-Dist: httpx>=0.27.0
27
+ Requires-Dist: loguru>=0.7.0
28
+ Requires-Dist: mcp<2,>=1.2.0
29
+ Requires-Dist: pydantic>=2.0.0
30
+ Requires-Dist: python-dotenv>=1.0.0
31
+ Requires-Dist: redis<7,>=5.0.0
32
+ Provides-Extra: all
33
+ Requires-Dist: build>=1.2.0; extra == 'all'
34
+ Requires-Dist: mypy>=1.10.0; extra == 'all'
35
+ Requires-Dist: pre-commit>=3.7.0; extra == 'all'
36
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'all'
37
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'all'
38
+ Requires-Dist: pytest>=8.0.0; extra == 'all'
39
+ Requires-Dist: respx>=0.21.0; extra == 'all'
40
+ Requires-Dist: ruff>=0.4.0; extra == 'all'
41
+ Requires-Dist: twine>=5.0.0; extra == 'all'
42
+ Provides-Extra: dev
43
+ Requires-Dist: mypy>=1.10.0; extra == 'dev'
44
+ Requires-Dist: pre-commit>=3.7.0; extra == 'dev'
45
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
46
+ Provides-Extra: release
47
+ Requires-Dist: build>=1.2.0; extra == 'release'
48
+ Requires-Dist: twine>=5.0.0; extra == 'release'
49
+ Provides-Extra: test
50
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
51
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
52
+ Requires-Dist: pytest>=8.0.0; extra == 'test'
53
+ Requires-Dist: respx>=0.21.0; extra == 'test'
54
+ Description-Content-Type: text/markdown
55
+
56
+ <!-- Generated by scripts/marketing_readmes.py from README.md; do not edit. -->
57
+ # MCP Image2Text Server
58
+
59
+ A Model Context Protocol (MCP) server for AceDataCloud's Image2Text captcha-solving APIs.
60
+
61
+ ## Features
62
+ - Recognize text from base64-encoded captcha or challenge images.
63
+ - Bearer-token authentication through AceDataCloud
64
+
65
+ ## Connect locally
66
+
67
+ Use the local stdio package and an AceDataCloud API token. The public hosted HTTPS endpoint could not be verified, so this README does not offer it as a connection option. The local MCP process still calls AceDataCloud's API; it does not run the underlying service offline.
68
+
69
+ Get an API credential through [AceDataCloud Platform](https://platform.acedata.cloud?utm_source=pypi&utm_medium=referral&utm_campaign=evergreen&utm_content=image2text_mcp_package_platform), keep it out of committed files, and review current pricing before a billable call.
70
+
71
+ ### Local stdio
72
+
73
+ Install the package and give the local process an API token:
74
+
75
+ ```bash
76
+ python -m pip install mcp-image2text
77
+ export ACEDATACLOUD_API_TOKEN='YOUR_API_TOKEN'
78
+ mcp-image2text
79
+ ```
80
+
81
+ For Claude Desktop local MCP, merge this entry into the file opened by its developer settings (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS). `uvx` requires [uv](https://docs.astral.sh/uv/) on `PATH`:
82
+
83
+ ```json
84
+ {
85
+ "mcpServers": {
86
+ "image2text": {
87
+ "command": "uvx",
88
+ "args": ["mcp-image2text"],
89
+ "env": {"ACEDATACLOUD_API_TOKEN": "YOUR_API_TOKEN"}
90
+ }
91
+ }
92
+ }
93
+ ```
94
+
95
+ Keep this user-level file private. Self-hosted HTTP uses `mcp-image2text --transport http --port 8000`; expose it only with suitable network and TLS controls. Local execution still calls the AceDataCloud API.
96
+
97
+ ### Check the connection
98
+
99
+ Confirm that the MCP client loads its tools. `image2text_get_usage_guide` returns reference information; it does not prove downstream API access or balance. A real service request can be billed. If it returns 401, check the API token; if it returns 403 or an account/balance error, read that response before retrying.
100
+
101
+ ## Tools
102
+ - `image2text_recognize` — Recognize text from an image
103
+ - `image2text_get_usage_guide` — Get image2text usage guide
104
+ - `image2text_get_api_info` — Get image2text API information
105
+
106
+ ## Service details
107
+
108
+ <!-- canonical-documentation -->
109
+ [Service details](https://platform.acedata.cloud/services/2aaa7faf-099e-410e-82f3-8d78170f25bb?utm_source=pypi&utm_medium=referral&utm_campaign=evergreen&utm_content=image2text_mcp_package_quick_start)
@@ -0,0 +1,53 @@
1
+ # MCP Image2Text Server
2
+
3
+ A Model Context Protocol (MCP) server for AceDataCloud's Image2Text captcha-solving APIs.
4
+
5
+ ## Features
6
+ - Recognize text from base64-encoded captcha or challenge images.
7
+ - Bearer-token authentication through AceDataCloud
8
+
9
+ ## Connect locally
10
+
11
+ Use the local stdio package and an AceDataCloud API token. The public hosted HTTPS endpoint could not be verified, so this README does not offer it as a connection option. The local MCP process still calls AceDataCloud's API; it does not run the underlying service offline.
12
+
13
+ Get an API credential through [AceDataCloud Platform](https://platform.acedata.cloud?utm_source=github&utm_medium=referral&utm_campaign=evergreen&utm_content=image2text_mcp_readme_platform), keep it out of committed files, and review current pricing before a billable call.
14
+
15
+ ### Local stdio
16
+
17
+ Install the package and give the local process an API token:
18
+
19
+ ```bash
20
+ python -m pip install mcp-image2text
21
+ export ACEDATACLOUD_API_TOKEN='YOUR_API_TOKEN'
22
+ mcp-image2text
23
+ ```
24
+
25
+ For Claude Desktop local MCP, merge this entry into the file opened by its developer settings (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS). `uvx` requires [uv](https://docs.astral.sh/uv/) on `PATH`:
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "image2text": {
31
+ "command": "uvx",
32
+ "args": ["mcp-image2text"],
33
+ "env": {"ACEDATACLOUD_API_TOKEN": "YOUR_API_TOKEN"}
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ Keep this user-level file private. Self-hosted HTTP uses `mcp-image2text --transport http --port 8000`; expose it only with suitable network and TLS controls. Local execution still calls the AceDataCloud API.
40
+
41
+ ### Check the connection
42
+
43
+ Confirm that the MCP client loads its tools. `image2text_get_usage_guide` returns reference information; it does not prove downstream API access or balance. A real service request can be billed. If it returns 401, check the API token; if it returns 403 or an account/balance error, read that response before retrying.
44
+
45
+ ## Tools
46
+ - `image2text_recognize` — Recognize text from an image
47
+ - `image2text_get_usage_guide` — Get image2text usage guide
48
+ - `image2text_get_api_info` — Get image2text API information
49
+
50
+ ## Service details
51
+
52
+ <!-- canonical-documentation -->
53
+ [Service details](https://platform.acedata.cloud/services/2aaa7faf-099e-410e-82f3-8d78170f25bb?utm_source=github&utm_medium=referral&utm_campaign=evergreen&utm_content=image2text_mcp_readme_quick_start)
@@ -0,0 +1,54 @@
1
+ <!-- Generated by scripts/marketing_readmes.py from README.md; do not edit. -->
2
+ # MCP Image2Text Server
3
+
4
+ A Model Context Protocol (MCP) server for AceDataCloud's Image2Text captcha-solving APIs.
5
+
6
+ ## Features
7
+ - Recognize text from base64-encoded captcha or challenge images.
8
+ - Bearer-token authentication through AceDataCloud
9
+
10
+ ## Connect locally
11
+
12
+ Use the local stdio package and an AceDataCloud API token. The public hosted HTTPS endpoint could not be verified, so this README does not offer it as a connection option. The local MCP process still calls AceDataCloud's API; it does not run the underlying service offline.
13
+
14
+ Get an API credential through [AceDataCloud Platform](https://platform.acedata.cloud?utm_source=pypi&utm_medium=referral&utm_campaign=evergreen&utm_content=image2text_mcp_package_platform), keep it out of committed files, and review current pricing before a billable call.
15
+
16
+ ### Local stdio
17
+
18
+ Install the package and give the local process an API token:
19
+
20
+ ```bash
21
+ python -m pip install mcp-image2text
22
+ export ACEDATACLOUD_API_TOKEN='YOUR_API_TOKEN'
23
+ mcp-image2text
24
+ ```
25
+
26
+ For Claude Desktop local MCP, merge this entry into the file opened by its developer settings (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS). `uvx` requires [uv](https://docs.astral.sh/uv/) on `PATH`:
27
+
28
+ ```json
29
+ {
30
+ "mcpServers": {
31
+ "image2text": {
32
+ "command": "uvx",
33
+ "args": ["mcp-image2text"],
34
+ "env": {"ACEDATACLOUD_API_TOKEN": "YOUR_API_TOKEN"}
35
+ }
36
+ }
37
+ }
38
+ ```
39
+
40
+ Keep this user-level file private. Self-hosted HTTP uses `mcp-image2text --transport http --port 8000`; expose it only with suitable network and TLS controls. Local execution still calls the AceDataCloud API.
41
+
42
+ ### Check the connection
43
+
44
+ Confirm that the MCP client loads its tools. `image2text_get_usage_guide` returns reference information; it does not prove downstream API access or balance. A real service request can be billed. If it returns 401, check the API token; if it returns 403 or an account/balance error, read that response before retrying.
45
+
46
+ ## Tools
47
+ - `image2text_recognize` — Recognize text from an image
48
+ - `image2text_get_usage_guide` — Get image2text usage guide
49
+ - `image2text_get_api_info` — Get image2text API information
50
+
51
+ ## Service details
52
+
53
+ <!-- canonical-documentation -->
54
+ [Service details](https://platform.acedata.cloud/services/2aaa7faf-099e-410e-82f3-8d78170f25bb?utm_source=pypi&utm_medium=referral&utm_campaign=evergreen&utm_content=image2text_mcp_package_quick_start)
@@ -0,0 +1,15 @@
1
+ """Core module for MCP Image2Text server."""
2
+
3
+ from core.client import Image2TextClient
4
+ from core.config import settings
5
+ from core.exceptions import Image2TextAPIError, Image2TextAuthError, Image2TextValidationError
6
+ from core.server import mcp
7
+
8
+ __all__ = [
9
+ "Image2TextClient",
10
+ "settings",
11
+ "mcp",
12
+ "Image2TextAPIError",
13
+ "Image2TextAuthError",
14
+ "Image2TextValidationError",
15
+ ]
@@ -0,0 +1,113 @@
1
+ """HTTP client for Image2Text API."""
2
+
3
+ import contextvars
4
+ import json
5
+ from typing import Any
6
+
7
+ import httpx
8
+ from loguru import logger
9
+
10
+ from core.config import settings
11
+ from core.exceptions import (
12
+ Image2TextAPIError,
13
+ Image2TextAuthError,
14
+ Image2TextError,
15
+ Image2TextTimeoutError,
16
+ )
17
+
18
+ _request_api_token: contextvars.ContextVar[str | None] = contextvars.ContextVar(
19
+ "_request_api_token", default=None
20
+ )
21
+
22
+
23
+ def set_request_api_token(token: str | None) -> None:
24
+ _request_api_token.set(token)
25
+
26
+
27
+ def get_request_api_token() -> str | None:
28
+ return _request_api_token.get()
29
+
30
+
31
+ def _apply_async_flag(payload: dict[str, Any], async_: bool | None) -> None:
32
+ if async_ is not None:
33
+ payload["async"] = async_
34
+
35
+
36
+ class Image2TextClient:
37
+ """Async HTTP client for the AceDataCloud Image2Text API."""
38
+
39
+ def __init__(self, api_token: str | None = None, base_url: str | None = None):
40
+ self.api_token = api_token if api_token is not None else settings.api_token
41
+ self.base_url = base_url or settings.api_base_url
42
+ self.timeout = settings.request_timeout
43
+ logger.info(f"Image2TextClient initialized with base_url: {self.base_url}")
44
+
45
+ def _get_headers(self) -> dict[str, str]:
46
+ token = get_request_api_token() or self.api_token
47
+ if not token:
48
+ raise Image2TextAuthError("API token not configured")
49
+ return {
50
+ "accept": "application/json",
51
+ "authorization": "******",
52
+ "content-type": "application/json",
53
+ }
54
+
55
+ def _handle_error_response(self, response: httpx.Response) -> None:
56
+ status = response.status_code
57
+ try:
58
+ body = response.json()
59
+ except Exception:
60
+ body = {}
61
+ error_obj = body.get("error", {}) if isinstance(body, dict) else {}
62
+ code = error_obj.get("code", f"http_{status}")
63
+ message = (
64
+ error_obj.get("message")
65
+ or (body.get("detail") if isinstance(body, dict) else None)
66
+ or response.text
67
+ or f"HTTP {status}"
68
+ )
69
+ if status in (401, 403):
70
+ raise Image2TextAuthError(message)
71
+ raise Image2TextAPIError(message=message, code=code, status_code=status)
72
+
73
+ async def request(
74
+ self,
75
+ method: str,
76
+ endpoint: str,
77
+ *,
78
+ payload: dict[str, Any] | None = None,
79
+ timeout: float | None = None,
80
+ ) -> dict[str, Any]:
81
+ method_upper = method.upper()
82
+ url = f"{self.base_url}{endpoint}"
83
+ request_timeout = timeout or self.timeout
84
+ if payload is not None:
85
+ logger.debug(f"Request payload: {json.dumps(payload, ensure_ascii=False, indent=2)}")
86
+ async with httpx.AsyncClient() as http_client:
87
+ try:
88
+ response = await http_client.request(
89
+ method_upper,
90
+ url,
91
+ json=payload,
92
+ headers=self._get_headers(),
93
+ timeout=request_timeout,
94
+ )
95
+ if response.status_code >= 400:
96
+ self._handle_error_response(response)
97
+ return response.json() # type: ignore[no-any-return]
98
+ except httpx.TimeoutException as e:
99
+ raise Image2TextTimeoutError(
100
+ f"Request to {endpoint} timed out after {request_timeout}s"
101
+ ) from e
102
+ except Image2TextError:
103
+ raise
104
+ except Exception as e:
105
+ raise Image2TextAPIError(message=str(e)) from e
106
+
107
+ async def recognize(self, image: str, async_: bool | None = None) -> dict[str, Any]:
108
+ payload: dict[str, Any] = {"image": image}
109
+ _apply_async_flag(payload, async_)
110
+ return await self.request("POST", "/captcha/recognition/image2text", payload=payload)
111
+
112
+
113
+ client = Image2TextClient()
@@ -0,0 +1,53 @@
1
+ """Configuration management for MCP Image2Text server."""
2
+
3
+ import os
4
+ from dataclasses import dataclass, field
5
+ from pathlib import Path
6
+
7
+ from dotenv import load_dotenv
8
+
9
+ _env_path = Path(__file__).parent.parent / ".env"
10
+ load_dotenv(dotenv_path=_env_path)
11
+
12
+
13
+ @dataclass
14
+ class Settings:
15
+ """Application settings loaded from environment variables."""
16
+
17
+ api_base_url: str = field(
18
+ default_factory=lambda: os.getenv("ACEDATACLOUD_API_BASE_URL", "https://api.acedata.cloud")
19
+ )
20
+ api_token: str = field(default_factory=lambda: os.getenv("ACEDATACLOUD_API_TOKEN", ""))
21
+ request_timeout: float = field(
22
+ default_factory=lambda: float(os.getenv("IMAGE2TEXT_REQUEST_TIMEOUT", "120"))
23
+ )
24
+ server_name: str = field(default_factory=lambda: os.getenv("MCP_SERVER_NAME", "image2text"))
25
+ transport: str = field(default_factory=lambda: os.getenv("MCP_TRANSPORT", "stdio"))
26
+ log_level: str = field(default_factory=lambda: os.getenv("LOG_LEVEL", "INFO"))
27
+ server_url: str = field(default_factory=lambda: os.getenv("MCP_SERVER_URL", ""))
28
+ auth_base_url: str = field(
29
+ default_factory=lambda: os.getenv(
30
+ "ACEDATACLOUD_AUTH_BASE_URL", "https://auth.acedata.cloud"
31
+ )
32
+ )
33
+ platform_base_url: str = field(
34
+ default_factory=lambda: os.getenv(
35
+ "ACEDATACLOUD_PLATFORM_BASE_URL", "https://platform.acedata.cloud"
36
+ )
37
+ )
38
+ oauth_client_id: str = field(
39
+ default_factory=lambda: os.getenv("ACEDATACLOUD_OAUTH_CLIENT_ID", "")
40
+ )
41
+
42
+ def validate(self) -> None:
43
+ if not self.api_token:
44
+ raise ValueError(
45
+ "ACEDATACLOUD_API_TOKEN environment variable is required. Get your token from https://platform.acedata.cloud"
46
+ )
47
+
48
+ @property
49
+ def is_configured(self) -> bool:
50
+ return bool(self.api_token)
51
+
52
+
53
+ settings = Settings()
@@ -0,0 +1,29 @@
1
+ """Custom exceptions for MCP Image2Text server."""
2
+
3
+
4
+ class Image2TextError(Exception):
5
+ def __init__(self, message: str, code: str = "unknown"):
6
+ self.message = message
7
+ self.code = code
8
+ super().__init__(self.message)
9
+
10
+
11
+ class Image2TextAuthError(Image2TextError):
12
+ def __init__(self, message: str = "Authentication failed"):
13
+ super().__init__(message, code="auth_error")
14
+
15
+
16
+ class Image2TextAPIError(Image2TextError):
17
+ def __init__(self, message: str, code: str = "api_error", status_code: int | None = None):
18
+ self.status_code = status_code
19
+ super().__init__(message, code)
20
+
21
+
22
+ class Image2TextValidationError(Image2TextError):
23
+ def __init__(self, message: str):
24
+ super().__init__(message, code="validation_error")
25
+
26
+
27
+ class Image2TextTimeoutError(Image2TextError):
28
+ def __init__(self, message: str = "Request timed out"):
29
+ super().__init__(message, code="timeout_error")