langchain-micompress 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MiCompress (https://micompress.com)
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,72 @@
1
+ Metadata-Version: 2.4
2
+ Name: langchain-micompress
3
+ Version: 0.1.0
4
+ Summary: LangChain tools for MiCompress: compress images, PDFs, video, audio, Office documents and archives
5
+ Author-email: MiCompress <support@micompress.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://micompress.com/mcp-server
8
+ Project-URL: Issues, https://github.com/micompress/micompress-mcp/issues
9
+ Keywords: langchain,tool,agent,compress,compression,image,pdf,micompress
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: langchain-core<2,>=0.3
20
+ Requires-Dist: pydantic>=2
21
+ Dynamic: license-file
22
+
23
+ # langchain-micompress
24
+
25
+ LangChain tools for [MiCompress](https://micompress.com): let your agent compress
26
+ **images, PDFs, video, audio, Office documents, EPUB books and archives**.
27
+
28
+ ```bash
29
+ pip install langchain-micompress
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ```python
35
+ from langchain_micompress import MiCompressCompressFile
36
+
37
+ tool = MiCompressCompressFile() # anonymous, or MiCompressCompressFile(api_key="mc_...")
38
+ print(tool.invoke({"path": "report.pdf", "preset": "extreme"}))
39
+ # Compressed report.pdf → report-min.pdf: 4.2MB → 610.3KB (86% smaller).
40
+ ```
41
+
42
+ With an agent:
43
+
44
+ ```python
45
+ from langchain_micompress import MiCompressToolkit
46
+
47
+ tools = MiCompressToolkit().get_tools() # micompress_compress_file, micompress_list_formats
48
+ agent = create_agent(model, tools) # any LangChain / LangGraph agent
49
+ ```
50
+
51
+ | Tool | What it does |
52
+ | --- | --- |
53
+ | `micompress_compress_file` | Compress a local file and write the smaller copy (default: `<name>-min.<ext>`). Arguments: `path`, optional `output_path`, `preset` (`lossless`, `recommended`, `extreme`), `max_width` (images). |
54
+ | `micompress_list_formats` | List the supported extensions by category. |
55
+
56
+ ## API key (optional)
57
+
58
+ Without a key the tools work anonymously within per-format size limits. For larger files
59
+ create a free key at [micompress.com/account](https://micompress.com/account) and set
60
+ `MICOMPRESS_API_KEY`, or pass `api_key=`.
61
+
62
+ ## What is sent where
63
+
64
+ The file is uploaded to micompress.com over HTTPS to be compressed. Uploaded originals are
65
+ deleted within about 10 minutes and results within 24 hours —
66
+ [privacy policy](https://micompress.com/privacy). Files reachable by URL can also be
67
+ compressed with the hosted MCP server at `https://micompress.com/mcp`
68
+ ([docs](https://micompress.com/mcp-server)).
69
+
70
+ ## License
71
+
72
+ MIT
@@ -0,0 +1,50 @@
1
+ # langchain-micompress
2
+
3
+ LangChain tools for [MiCompress](https://micompress.com): let your agent compress
4
+ **images, PDFs, video, audio, Office documents, EPUB books and archives**.
5
+
6
+ ```bash
7
+ pip install langchain-micompress
8
+ ```
9
+
10
+ ## Usage
11
+
12
+ ```python
13
+ from langchain_micompress import MiCompressCompressFile
14
+
15
+ tool = MiCompressCompressFile() # anonymous, or MiCompressCompressFile(api_key="mc_...")
16
+ print(tool.invoke({"path": "report.pdf", "preset": "extreme"}))
17
+ # Compressed report.pdf → report-min.pdf: 4.2MB → 610.3KB (86% smaller).
18
+ ```
19
+
20
+ With an agent:
21
+
22
+ ```python
23
+ from langchain_micompress import MiCompressToolkit
24
+
25
+ tools = MiCompressToolkit().get_tools() # micompress_compress_file, micompress_list_formats
26
+ agent = create_agent(model, tools) # any LangChain / LangGraph agent
27
+ ```
28
+
29
+ | Tool | What it does |
30
+ | --- | --- |
31
+ | `micompress_compress_file` | Compress a local file and write the smaller copy (default: `<name>-min.<ext>`). Arguments: `path`, optional `output_path`, `preset` (`lossless`, `recommended`, `extreme`), `max_width` (images). |
32
+ | `micompress_list_formats` | List the supported extensions by category. |
33
+
34
+ ## API key (optional)
35
+
36
+ Without a key the tools work anonymously within per-format size limits. For larger files
37
+ create a free key at [micompress.com/account](https://micompress.com/account) and set
38
+ `MICOMPRESS_API_KEY`, or pass `api_key=`.
39
+
40
+ ## What is sent where
41
+
42
+ The file is uploaded to micompress.com over HTTPS to be compressed. Uploaded originals are
43
+ deleted within about 10 minutes and results within 24 hours —
44
+ [privacy policy](https://micompress.com/privacy). Files reachable by URL can also be
45
+ compressed with the hosted MCP server at `https://micompress.com/mcp`
46
+ ([docs](https://micompress.com/mcp-server)).
47
+
48
+ ## License
49
+
50
+ MIT
@@ -0,0 +1,14 @@
1
+ """LangChain integration for MiCompress (https://micompress.com)."""
2
+
3
+ from ._version import __version__
4
+ from .client import MiCompressClient, MiCompressError
5
+ from .tools import MiCompressCompressFile, MiCompressListFormats, MiCompressToolkit
6
+
7
+ __all__ = [
8
+ "MiCompressClient",
9
+ "MiCompressError",
10
+ "MiCompressCompressFile",
11
+ "MiCompressListFormats",
12
+ "MiCompressToolkit",
13
+ "__version__",
14
+ ]
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,141 @@
1
+ """Minimal stdlib client for the MiCompress compression API.
2
+
3
+ Kept separate from the ``micompress`` CLI package on purpose: the server tells
4
+ integrations apart by ``X-MiCompress-Client``, and this one reports itself as
5
+ ``langchain`` so its usage is measurable on its own.
6
+ """
7
+
8
+ import json
9
+ import os
10
+ import urllib.error
11
+ import urllib.request
12
+ import uuid
13
+
14
+ from ._version import __version__
15
+
16
+ DEFAULT_BASE = "https://micompress.com"
17
+ USER_AGENT = "micompress-langchain/%s (+https://micompress.com)" % __version__
18
+ CLIENT_ID = "langchain/%s" % __version__
19
+ ACCOUNT_URL = DEFAULT_BASE + "/account"
20
+ PRESETS = ("lossless", "recommended", "extreme")
21
+
22
+
23
+ class MiCompressError(Exception):
24
+ """A compression request failed. ``code`` is the API's machine-readable code, if any."""
25
+
26
+ def __init__(self, message, code=None):
27
+ super().__init__(message)
28
+ self.code = code
29
+
30
+
31
+ def _ext(filename):
32
+ base = os.path.basename(filename).lower()
33
+ return base.rsplit(".", 1)[1] if "." in base else ""
34
+
35
+
36
+ class MiCompressClient:
37
+ """Compress local files through https://micompress.com.
38
+
39
+ ``api_key`` is optional (personal ``mc_...`` key from micompress.com/account);
40
+ without it the API works anonymously within per-format size limits.
41
+ It falls back to the ``MICOMPRESS_API_KEY`` environment variable.
42
+ """
43
+
44
+ def __init__(self, api_key=None, base_url=DEFAULT_BASE, timeout=300):
45
+ self.api_key = api_key if api_key is not None else os.environ.get("MICOMPRESS_API_KEY") or None
46
+ self.base_url = base_url.rstrip("/")
47
+ self.timeout = timeout
48
+ self._formats = None
49
+
50
+ def _headers(self, extra=None):
51
+ headers = {"User-Agent": USER_AGENT, "X-MiCompress-Client": CLIENT_ID, "Accept": "application/json"}
52
+ if self.api_key:
53
+ headers["X-API-Key"] = self.api_key
54
+ if extra:
55
+ headers.update(extra)
56
+ return headers
57
+
58
+ def _request(self, url, data=None, headers=None, method="GET"):
59
+ req = urllib.request.Request(url, data=data, headers=headers or {}, method=method)
60
+ try:
61
+ with urllib.request.urlopen(req, timeout=self.timeout) as resp:
62
+ return resp.read()
63
+ except urllib.error.HTTPError as e:
64
+ raw = e.read().decode("utf-8", "replace")
65
+ try:
66
+ payload = json.loads(raw)
67
+ except ValueError:
68
+ raise MiCompressError("HTTP %s from %s" % (e.code, url), "HTTP_%s" % e.code)
69
+ code = payload.get("code")
70
+ message = payload.get("error") or "HTTP %s" % e.code
71
+ if code == "LOGIN_REQUIRED":
72
+ message = ("The file is over the anonymous size limit. Use a free API key from %s "
73
+ "(MICOMPRESS_API_KEY) for larger files." % ACCOUNT_URL)
74
+ raise MiCompressError(message, code or "API_ERROR")
75
+ except urllib.error.URLError as e:
76
+ raise MiCompressError("Network error: %s" % e.reason, "NETWORK")
77
+
78
+ def formats(self):
79
+ """Supported extensions → {group, endpoint, maxBytes} for this caller (cached)."""
80
+ if self._formats is None:
81
+ raw = self._request(self.base_url + "/api/v1/capabilities", headers=self._headers())
82
+ self._formats = json.loads(raw.decode("utf-8"))["formats"]
83
+ return self._formats
84
+
85
+ def compress(self, input_path, output_path=None, preset=None, max_width=None):
86
+ """Compress ``input_path`` and write the result. Returns a summary dict.
87
+
88
+ ``output_path`` defaults to the input path with a ``-min`` suffix.
89
+ """
90
+ if preset and preset not in PRESETS:
91
+ raise MiCompressError("preset must be one of %s" % ", ".join(PRESETS), "BAD_PRESET")
92
+ if not os.path.isfile(input_path):
93
+ raise MiCompressError("File not found: %s" % input_path, "ENOENT")
94
+
95
+ filename = os.path.basename(input_path)
96
+ info = self.formats().get(_ext(filename))
97
+ if not info:
98
+ raise MiCompressError(
99
+ 'Unsupported file type ".%s". Supported: %s'
100
+ % (_ext(filename) or "?", ", ".join(sorted(self.formats()))), "UNSUPPORTED")
101
+
102
+ fields = {"preset": preset or "recommended"}
103
+ if max_width:
104
+ fields["maxWidth"] = str(int(max_width))
105
+ boundary = uuid.uuid4().hex
106
+ body = bytearray()
107
+ for name, value in fields.items():
108
+ body += ("--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n"
109
+ % (boundary, name, value)).encode("utf-8")
110
+ body += ("--%s\r\nContent-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n"
111
+ "Content-Type: application/octet-stream\r\n\r\n"
112
+ % (boundary, filename.replace('"', "_"))).encode("utf-8")
113
+ with open(input_path, "rb") as fh:
114
+ body += fh.read()
115
+ body += ("\r\n--%s--\r\n" % boundary).encode("utf-8")
116
+
117
+ raw = self._request(self.base_url + info["endpoint"], data=bytes(body), method="POST",
118
+ headers=self._headers({"Content-Type": "multipart/form-data; boundary=%s" % boundary}))
119
+ payload = json.loads(raw.decode("utf-8"))
120
+ if not payload.get("success"):
121
+ raise MiCompressError(payload.get("error") or "Compression failed", payload.get("code"))
122
+
123
+ data = self._request(self.base_url + payload["downloadUrl"], headers={"User-Agent": USER_AGENT})
124
+ if not output_path:
125
+ stem, dot_ext = os.path.splitext(input_path)
126
+ # The server may change the extension (e.g. a PNG that is really a JPEG).
127
+ served_ext = os.path.splitext(payload["downloadUrl"])[1] or dot_ext
128
+ output_path = stem + "-min" + served_ext
129
+ parent = os.path.dirname(os.path.abspath(output_path))
130
+ os.makedirs(parent, exist_ok=True)
131
+ with open(output_path, "wb") as fh:
132
+ fh.write(data)
133
+
134
+ return {
135
+ "output_path": output_path,
136
+ "input_size": payload.get("inputSize"),
137
+ "output_size": payload.get("outputSize"),
138
+ "saved_percent": payload.get("savedPercent"),
139
+ "format": payload.get("format"),
140
+ "note": payload.get("note"),
141
+ }
@@ -0,0 +1,113 @@
1
+ """LangChain tools for MiCompress."""
2
+
3
+ from typing import Literal, Optional, Type
4
+
5
+ from langchain_core.tools import BaseTool, ToolException
6
+ from pydantic import BaseModel, Field, PrivateAttr
7
+
8
+ from .client import MiCompressClient, MiCompressError
9
+
10
+
11
+ def _human(n):
12
+ if n is None:
13
+ return "?"
14
+ for unit in ("B", "KB", "MB", "GB"):
15
+ if n < 1024 or unit == "GB":
16
+ return ("%.1f%s" % (n, unit)) if unit != "B" else "%d%s" % (n, unit)
17
+ n /= 1024.0
18
+
19
+
20
+ class CompressFileInput(BaseModel):
21
+ path: str = Field(description="Path of the local file to compress.")
22
+ output_path: Optional[str] = Field(
23
+ default=None,
24
+ description='Where to write the result. Defaults to the input path with a "-min" suffix.')
25
+ preset: Optional[Literal["lossless", "recommended", "extreme"]] = Field(
26
+ default=None,
27
+ description="lossless keeps quality identical; recommended (default) balances size and quality; "
28
+ "extreme gives the smallest file.")
29
+ max_width: Optional[int] = Field(default=None, description="Images only: resize down to this width in pixels.")
30
+
31
+
32
+ class MiCompressCompressFile(BaseTool):
33
+ """Compress a local image, PDF, video, audio file, Office document or archive.
34
+
35
+ The file is uploaded to https://micompress.com over HTTPS and the smaller copy is
36
+ written back to disk. Set ``MICOMPRESS_API_KEY`` (or pass ``api_key``) for larger files.
37
+
38
+ Example:
39
+ .. code-block:: python
40
+
41
+ from langchain_micompress import MiCompressCompressFile
42
+ tool = MiCompressCompressFile()
43
+ tool.invoke({"path": "report.pdf", "preset": "extreme"})
44
+ """
45
+
46
+ name: str = "micompress_compress_file"
47
+ description: str = (
48
+ "Compress a local file (images such as JPG, PNG, WebP, GIF, HEIC or RAW; PDF; video; audio; "
49
+ "Word, Excel, PowerPoint; EPUB; ZIP/7Z/RAR) and write the smaller copy to disk. "
50
+ "Returns the output path and the size before and after."
51
+ )
52
+ args_schema: Type[BaseModel] = CompressFileInput
53
+ handle_tool_error: bool = True
54
+
55
+ api_key: Optional[str] = None
56
+ base_url: str = "https://micompress.com"
57
+ _client: MiCompressClient = PrivateAttr()
58
+
59
+ def __init__(self, **kwargs):
60
+ super().__init__(**kwargs)
61
+ self._client = MiCompressClient(api_key=self.api_key, base_url=self.base_url)
62
+
63
+ def _run(self, path: str, output_path: Optional[str] = None, preset: Optional[str] = None,
64
+ max_width: Optional[int] = None, run_manager=None) -> str:
65
+ try:
66
+ r = self._client.compress(path, output_path=output_path, preset=preset, max_width=max_width)
67
+ except MiCompressError as e:
68
+ raise ToolException(str(e))
69
+ text = "Compressed %s → %s: %s → %s (%s%% smaller)." % (
70
+ path, r["output_path"], _human(r["input_size"]), _human(r["output_size"]), r["saved_percent"])
71
+ if r.get("note"):
72
+ text += " Note: %s" % r["note"]
73
+ return text
74
+
75
+
76
+ class MiCompressListFormats(BaseTool):
77
+ """List the file extensions MiCompress can compress, grouped by category."""
78
+
79
+ name: str = "micompress_list_formats"
80
+ description: str = "List the file extensions that micompress_compress_file accepts, grouped by category."
81
+ handle_tool_error: bool = True
82
+
83
+ api_key: Optional[str] = None
84
+ base_url: str = "https://micompress.com"
85
+ _client: MiCompressClient = PrivateAttr()
86
+
87
+ def __init__(self, **kwargs):
88
+ super().__init__(**kwargs)
89
+ self._client = MiCompressClient(api_key=self.api_key, base_url=self.base_url)
90
+
91
+ def _run(self, run_manager=None) -> str:
92
+ try:
93
+ formats = self._client.formats()
94
+ except MiCompressError as e:
95
+ raise ToolException(str(e))
96
+ groups = {}
97
+ for ext, info in formats.items():
98
+ groups.setdefault(info["group"], []).append(ext)
99
+ return "\n".join("%s: %s" % (g, ", ".join(sorted(exts))) for g, exts in sorted(groups.items()))
100
+
101
+
102
+ class MiCompressToolkit:
103
+ """Convenience wrapper returning both MiCompress tools."""
104
+
105
+ def __init__(self, api_key: Optional[str] = None, base_url: str = "https://micompress.com"):
106
+ self.api_key = api_key
107
+ self.base_url = base_url
108
+
109
+ def get_tools(self):
110
+ return [
111
+ MiCompressCompressFile(api_key=self.api_key, base_url=self.base_url),
112
+ MiCompressListFormats(api_key=self.api_key, base_url=self.base_url),
113
+ ]
@@ -0,0 +1,72 @@
1
+ Metadata-Version: 2.4
2
+ Name: langchain-micompress
3
+ Version: 0.1.0
4
+ Summary: LangChain tools for MiCompress: compress images, PDFs, video, audio, Office documents and archives
5
+ Author-email: MiCompress <support@micompress.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://micompress.com/mcp-server
8
+ Project-URL: Issues, https://github.com/micompress/micompress-mcp/issues
9
+ Keywords: langchain,tool,agent,compress,compression,image,pdf,micompress
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: langchain-core<2,>=0.3
20
+ Requires-Dist: pydantic>=2
21
+ Dynamic: license-file
22
+
23
+ # langchain-micompress
24
+
25
+ LangChain tools for [MiCompress](https://micompress.com): let your agent compress
26
+ **images, PDFs, video, audio, Office documents, EPUB books and archives**.
27
+
28
+ ```bash
29
+ pip install langchain-micompress
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ```python
35
+ from langchain_micompress import MiCompressCompressFile
36
+
37
+ tool = MiCompressCompressFile() # anonymous, or MiCompressCompressFile(api_key="mc_...")
38
+ print(tool.invoke({"path": "report.pdf", "preset": "extreme"}))
39
+ # Compressed report.pdf → report-min.pdf: 4.2MB → 610.3KB (86% smaller).
40
+ ```
41
+
42
+ With an agent:
43
+
44
+ ```python
45
+ from langchain_micompress import MiCompressToolkit
46
+
47
+ tools = MiCompressToolkit().get_tools() # micompress_compress_file, micompress_list_formats
48
+ agent = create_agent(model, tools) # any LangChain / LangGraph agent
49
+ ```
50
+
51
+ | Tool | What it does |
52
+ | --- | --- |
53
+ | `micompress_compress_file` | Compress a local file and write the smaller copy (default: `<name>-min.<ext>`). Arguments: `path`, optional `output_path`, `preset` (`lossless`, `recommended`, `extreme`), `max_width` (images). |
54
+ | `micompress_list_formats` | List the supported extensions by category. |
55
+
56
+ ## API key (optional)
57
+
58
+ Without a key the tools work anonymously within per-format size limits. For larger files
59
+ create a free key at [micompress.com/account](https://micompress.com/account) and set
60
+ `MICOMPRESS_API_KEY`, or pass `api_key=`.
61
+
62
+ ## What is sent where
63
+
64
+ The file is uploaded to micompress.com over HTTPS to be compressed. Uploaded originals are
65
+ deleted within about 10 minutes and results within 24 hours —
66
+ [privacy policy](https://micompress.com/privacy). Files reachable by URL can also be
67
+ compressed with the hosted MCP server at `https://micompress.com/mcp`
68
+ ([docs](https://micompress.com/mcp-server)).
69
+
70
+ ## License
71
+
72
+ MIT
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ langchain_micompress/__init__.py
5
+ langchain_micompress/_version.py
6
+ langchain_micompress/client.py
7
+ langchain_micompress/tools.py
8
+ langchain_micompress.egg-info/PKG-INFO
9
+ langchain_micompress.egg-info/SOURCES.txt
10
+ langchain_micompress.egg-info/dependency_links.txt
11
+ langchain_micompress.egg-info/requires.txt
12
+ langchain_micompress.egg-info/top_level.txt
13
+ tests/test_live.py
@@ -0,0 +1,2 @@
1
+ langchain-core<2,>=0.3
2
+ pydantic>=2
@@ -0,0 +1 @@
1
+ langchain_micompress
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "langchain-micompress"
7
+ dynamic = ["version"]
8
+ description = "LangChain tools for MiCompress: compress images, PDFs, video, audio, Office documents and archives"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "MiCompress", email = "support@micompress.com" }]
13
+ keywords = ["langchain", "tool", "agent", "compress", "compression", "image", "pdf", "micompress"]
14
+ dependencies = ["langchain-core>=0.3,<2", "pydantic>=2"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Topic :: Multimedia :: Graphics :: Graphics Conversion",
21
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
22
+ ]
23
+
24
+ [project.urls]
25
+ Homepage = "https://micompress.com/mcp-server"
26
+ Issues = "https://github.com/micompress/micompress-mcp/issues"
27
+
28
+ [tool.setuptools]
29
+ packages = ["langchain_micompress"]
30
+
31
+ [tool.setuptools.dynamic]
32
+ version = { attr = "langchain_micompress._version.__version__" }
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,33 @@
1
+ """Live end-to-end test against micompress.com (needs network)."""
2
+
3
+ import os
4
+ import tempfile
5
+ import urllib.request
6
+
7
+ from langchain_micompress import MiCompressCompressFile, MiCompressListFormats, MiCompressToolkit
8
+
9
+ SAMPLE = "https://micompress.com/samples/photo.jpg"
10
+
11
+
12
+ def test_compress_and_list():
13
+ with tempfile.TemporaryDirectory() as d:
14
+ src = os.path.join(d, "photo.jpg")
15
+ req = urllib.request.Request(SAMPLE, headers={"User-Agent": "micompress-langchain-test"})
16
+ with urllib.request.urlopen(req) as r, open(src, "wb") as fh:
17
+ fh.write(r.read())
18
+ out = MiCompressCompressFile().invoke({"path": src})
19
+ assert "smaller" in out, out
20
+ assert os.path.exists(os.path.join(d, "photo-min.jpg"))
21
+ assert os.path.getsize(os.path.join(d, "photo-min.jpg")) < os.path.getsize(src)
22
+
23
+ err = MiCompressCompressFile().invoke({"path": os.path.join(d, "nope.xyz")})
24
+ assert "not found" in err.lower(), err
25
+
26
+ formats = MiCompressListFormats().invoke({})
27
+ assert "image:" in formats and "pdf" in formats, formats
28
+ assert len(MiCompressToolkit().get_tools()) == 2
29
+
30
+
31
+ if __name__ == "__main__":
32
+ test_compress_and_list()
33
+ print("ok")