Helper class for returning images from tools.
| 7 | |
| 8 | |
| 9 | class Image: |
| 10 | """Helper class for returning images from tools.""" |
| 11 | |
| 12 | def __init__( |
| 13 | self, |
| 14 | path: str | Path | None = None, |
| 15 | data: bytes | None = None, |
| 16 | format: str | None = None, |
| 17 | ): |
| 18 | if path is None and data is None: # pragma: no cover |
| 19 | raise ValueError("Either path or data must be provided") |
| 20 | if path is not None and data is not None: # pragma: no cover |
| 21 | raise ValueError("Only one of path or data can be provided") |
| 22 | |
| 23 | self.path = Path(path) if path else None |
| 24 | self.data = data |
| 25 | self._format = format |
| 26 | self._mime_type = self._get_mime_type() |
| 27 | |
| 28 | def _get_mime_type(self) -> str: |
| 29 | """Get MIME type from format or guess from file extension.""" |
| 30 | if self._format: # pragma: no cover |
| 31 | return f"image/{self._format.lower()}" |
| 32 | |
| 33 | if self.path: |
| 34 | suffix = self.path.suffix.lower() |
| 35 | return { |
| 36 | ".png": "image/png", |
| 37 | ".jpg": "image/jpeg", |
| 38 | ".jpeg": "image/jpeg", |
| 39 | ".gif": "image/gif", |
| 40 | ".webp": "image/webp", |
| 41 | }.get(suffix, "application/octet-stream") |
| 42 | return "image/png" # pragma: no cover # default for raw binary data |
| 43 | |
| 44 | def to_image_content(self) -> ImageContent: |
| 45 | """Convert to MCP ImageContent.""" |
| 46 | if self.path: |
| 47 | with open(self.path, "rb") as f: |
| 48 | data = base64.b64encode(f.read()).decode() |
| 49 | elif self.data is not None: # pragma: no cover |
| 50 | data = base64.b64encode(self.data).decode() |
| 51 | else: # pragma: no cover |
| 52 | raise ValueError("No image data available") |
| 53 | |
| 54 | return ImageContent(type="image", data=data, mime_type=self._mime_type) |
| 55 | |
| 56 | |
| 57 | class Audio: |
no outgoing calls