zoo_mcp 0.9.2__py3-none-any.whl
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.
- zoo_mcp/__init__.py +77 -0
- zoo_mcp/__main__.py +15 -0
- zoo_mcp/ai_tools.py +256 -0
- zoo_mcp/kcl_docs.py +268 -0
- zoo_mcp/kcl_samples.py +313 -0
- zoo_mcp/server.py +760 -0
- zoo_mcp/utils/__init__.py +0 -0
- zoo_mcp/utils/image_utils.py +100 -0
- zoo_mcp/zoo_tools.py +1179 -0
- zoo_mcp-0.9.2.dist-info/METADATA +154 -0
- zoo_mcp-0.9.2.dist-info/RECORD +14 -0
- zoo_mcp-0.9.2.dist-info/WHEEL +4 -0
- zoo_mcp-0.9.2.dist-info/entry_points.txt +3 -0
- zoo_mcp-0.9.2.dist-info/licenses/LICENSE +21 -0
|
File without changes
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import io
|
|
3
|
+
import tempfile
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from mcp.server.fastmcp.utilities.types import Image
|
|
7
|
+
from mcp.types import ImageContent
|
|
8
|
+
from PIL import Image as PILImage
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def create_image_collage(image_byte_list: list[bytes]) -> bytes:
|
|
12
|
+
assert len(image_byte_list) == 4, (
|
|
13
|
+
"Exactly 4 images are required to create a 2x2 collage."
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# Load images
|
|
17
|
+
images = []
|
|
18
|
+
for img_bytes in image_byte_list:
|
|
19
|
+
img = PILImage.open(io.BytesIO(img_bytes))
|
|
20
|
+
img = img.convert("RGB") if img.mode != "RGB" else img
|
|
21
|
+
images.append(img)
|
|
22
|
+
|
|
23
|
+
# Verify all are same size
|
|
24
|
+
widths, heights = zip(*(img.size for img in images))
|
|
25
|
+
if len(set(widths)) > 1 or len(set(heights)) > 1:
|
|
26
|
+
raise ValueError("All images must have the same dimensions.")
|
|
27
|
+
|
|
28
|
+
img_w, img_h = images[0].size
|
|
29
|
+
|
|
30
|
+
# Create blank canvas 2x2
|
|
31
|
+
collage = PILImage.new("RGB", (img_w * 2, img_h * 2))
|
|
32
|
+
positions = [
|
|
33
|
+
(0, 0), # Top-left
|
|
34
|
+
(img_w, 0), # Top-right
|
|
35
|
+
(0, img_h), # Bottom-left
|
|
36
|
+
(img_w, img_h), # Bottom-right
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
for img, pos in zip(images, positions):
|
|
40
|
+
collage.paste(img, pos)
|
|
41
|
+
|
|
42
|
+
# Scale down by 2x
|
|
43
|
+
collage = collage.resize((img_w, img_h), PILImage.Resampling.LANCZOS)
|
|
44
|
+
|
|
45
|
+
# Save to bytes
|
|
46
|
+
out = io.BytesIO()
|
|
47
|
+
collage.save(out, format="JPEG", quality=95)
|
|
48
|
+
collage_bytes = out.getvalue()
|
|
49
|
+
|
|
50
|
+
# Cleanup
|
|
51
|
+
for img in images:
|
|
52
|
+
img.close()
|
|
53
|
+
collage.close()
|
|
54
|
+
out.close()
|
|
55
|
+
|
|
56
|
+
return collage_bytes
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def encode_image(img_bytes: bytes) -> ImageContent:
|
|
60
|
+
"""
|
|
61
|
+
Encodes a PIL Image to a format compatible with ImageContent.
|
|
62
|
+
"""
|
|
63
|
+
img_obj = Image(data=img_bytes, format="jpeg")
|
|
64
|
+
return img_obj.to_image_content()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def save_image_to_disk(image: ImageContent, output_path: str | None = None) -> str:
|
|
68
|
+
"""
|
|
69
|
+
Saves an ImageContent object to disk.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
image: The ImageContent object containing base64-encoded image data.
|
|
73
|
+
output_path: The path where the image should be saved. If a directory is
|
|
74
|
+
provided, a file named 'image.png' will be created in that directory.
|
|
75
|
+
If None, a temporary file will be created.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
str: The absolute path to the saved image file.
|
|
79
|
+
"""
|
|
80
|
+
if output_path is None:
|
|
81
|
+
# Create a temporary file
|
|
82
|
+
_, temp_path = tempfile.mkstemp(suffix=".png")
|
|
83
|
+
path = Path(temp_path)
|
|
84
|
+
else:
|
|
85
|
+
path = Path(output_path)
|
|
86
|
+
|
|
87
|
+
# If path is a directory, create a default filename
|
|
88
|
+
if path.is_dir():
|
|
89
|
+
path = path / "image.png"
|
|
90
|
+
|
|
91
|
+
# Ensure parent directory exists
|
|
92
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
93
|
+
|
|
94
|
+
# Decode base64 data
|
|
95
|
+
image_data = base64.b64decode(image.data)
|
|
96
|
+
|
|
97
|
+
# Write to disk
|
|
98
|
+
path.write_bytes(image_data)
|
|
99
|
+
|
|
100
|
+
return str(path.resolve())
|