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.
- mcp_image2text-2026.10.8.0/.env.example +6 -0
- mcp_image2text-2026.10.8.0/LICENSE +21 -0
- mcp_image2text-2026.10.8.0/PKG-INFO +109 -0
- mcp_image2text-2026.10.8.0/README.md +53 -0
- mcp_image2text-2026.10.8.0/README.pypi.md +54 -0
- mcp_image2text-2026.10.8.0/core/__init__.py +15 -0
- mcp_image2text-2026.10.8.0/core/client.py +113 -0
- mcp_image2text-2026.10.8.0/core/config.py +53 -0
- mcp_image2text-2026.10.8.0/core/exceptions.py +29 -0
- mcp_image2text-2026.10.8.0/core/oauth.py +416 -0
- mcp_image2text-2026.10.8.0/core/oauth_state.py +149 -0
- mcp_image2text-2026.10.8.0/core/server.py +42 -0
- mcp_image2text-2026.10.8.0/main.py +188 -0
- mcp_image2text-2026.10.8.0/prompts/__init__.py +13 -0
- mcp_image2text-2026.10.8.0/pyproject.toml +66 -0
- mcp_image2text-2026.10.8.0/tests/__init__.py +0 -0
- mcp_image2text-2026.10.8.0/tests/conftest.py +13 -0
- mcp_image2text-2026.10.8.0/tests/test_smoke.py +58 -0
- mcp_image2text-2026.10.8.0/tools/__init__.py +5 -0
- mcp_image2text-2026.10.8.0/tools/captcha_tools.py +34 -0
- mcp_image2text-2026.10.8.0/tools/info_tools.py +27 -0
|
@@ -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")
|