You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/servers/media.md
+23-15Lines changed: 23 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,17 +6,17 @@ The SDK ships two helpers for binary results (**`Image`** and **`Audio`**) and a
6
6
7
7
## Returning an image
8
8
9
-
Annotate the return type as `Image`and return one:
9
+
Annotate the return type as `Image`, point it at a file, and return it:
10
10
11
-
```python title="server.py" hl_lines="14 16"
11
+
```python title="server.py" hl_lines="8 12 14"
12
12
--8<--"docs_src/media/tutorial001.py"
13
13
```
14
14
15
-
*`Image` takes exactly one of `data` (raw bytes) or `path` (a file to read).
16
-
*`format="png"` becomes the MIME type the client sees:`image/png`.
17
-
*The bytes here are a one-pixel placeholder so the file runs on its own. In a real server they come from Pillow, matplotlib, a headless browser, or anything else that hands you `bytes`.
15
+
*`Image` takes exactly one of `path` (a file to read) or `data` (raw bytes).
16
+
*The MIME type the client sees is guessed from the suffix: `logo.png` is announced as`image/png`.
17
+
*Nothing here is special about logos. Any PNG next to `server.py` works: a chart your code rendered, a diagram, a photo.
18
18
19
-
`Image` is an SDK convenience, not a protocol type. On the wire your return value becomes an **`ImageContent`** block (your bytes base64-encoded, plus the MIME type):
19
+
`Image` is an SDK convenience, not a protocol type. On the wire your return value becomes an **`ImageContent`** block (the file's bytes base64-encoded, plus the MIME type):
*`data` is base64. You returned raw `bytes`; the SDK did the encoding.
28
+
*`data` is base64. You never touched the bytes; the SDK read the file and did the encoding.
29
29
*`structured_content` is `None`. An `Image` is content for the model to look at, not data for the application to parse: there is no output schema. (Contrast **[Structured Output](structured-output.md)**, where the return annotation *is* the schema.)
30
30
31
31
!!! info
@@ -35,32 +35,40 @@ Two things to notice:
35
35
36
36
### Try it
37
37
38
+
Drop any PNG next to `server.py`, name it `logo.png`, and run:
39
+
38
40
```console
39
41
uv run mcp dev server.py
40
42
```
41
43
42
-
Open the **Tools** tab and call `logo`. The result is not a string: it is an `image` content block, and the Inspector renders it as a picture. You returned `bytes`; everything between that and the pixels on screen was the SDK.
44
+
Open the **Tools** tab and call `logo`. The result is not a string: it is an `image` content block, and the Inspector renders your picture. Everything between the file on disk and the pixels on screen was the SDK.
43
45
44
46
## Returning audio
45
47
46
-
`Audio` is the same shape:
48
+
`Audio` is the same shape. Keep `logo.png` where it was, and put any WAV beside it as `chime.wav`:
Same deal: raw bytes in, base64 and a MIME type out, no output schema.
61
+
Same deal: a file on disk in, base64 and a MIME type out, no output schema.
60
62
61
63
## Bytes or a file
62
64
63
-
Both helpers also accept `path=` instead of `data=`. The file is read when the result is built, and the MIME type is guessed from the suffix:
65
+
Both helpers also accept `data=` (raw bytes) instead of `path=`. That is the mode for bytes that never came from a file of their own — a database column, an HTTP response, something Pillow just drew:
66
+
67
+
```python title="server.py" hl_lines="14 15"
68
+
--8<--"docs_src/media/tutorial003.py"
69
+
```
70
+
71
+
With `path=` there is nothing to declare: the file is read when the result is built, and the MIME type is guessed from the suffix:
@@ -78,7 +86,7 @@ A suffix it doesn't recognise falls back to `application/octet-stream`.
78
86
An `Icon` is metadata, not content. It doesn't carry the image; it points at one with a URI, and a client may fetch it and show it next to your server's name, a tool, a resource, or a prompt.
*`src` is a URI the client can resolve: `https:`, or a `data:` URI if you want the icon embedded with no extra fetch.
@@ -100,7 +108,7 @@ A tool's icons are on the `Tool` object from `tools/list`, a resource's on the `
100
108
## Recap
101
109
102
110
* Return an `Image` or `Audio` from a tool and the client receives an `ImageContent` / `AudioContent` block: your bytes base64-encoded, with a MIME type.
103
-
* Build one from in-memory `data=`plus an explicit `format=`, or from a `path=`and let the suffix decide.
111
+
* Build one from a `path=`and let the suffix decide the MIME type, or from in-memory `data=`plus an explicit `format=`.
104
112
* Media results carry no `structured_content` and no output schema.
105
113
* An `Icon` is a pointer: a `src` URI plus optional `mime_type`, `sizes`, and `theme`.
106
114
*`icons=[...]` works on the server, on tools, on resources, and on prompts, and clients find them on the matching objects.
0 commit comments