-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Added Audio to FastMCP #1130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Audio to FastMCP #1130
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @dragonier23 !
Looks good / in line w/ Image support! Suggesting some more tests before we can merge :-)
| content = result.content[0] | ||
| assert isinstance(content, AudioContent) | ||
| assert content.type == "audio" | ||
| assert content.mimeType == "audio/wav" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also add something to exercice the suffix-based mime type detection?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just added a test to test the mimetypes, do let me know if this is what you are looking for!
tests/server/fastmcp/test_server.py
Outdated
| @pytest.mark.anyio | ||
| async def test_tool_mixed_list_with_audio(self, tmp_path: Path): | ||
| """Test that lists containing Audio objects and other types are handled | ||
| correctly""" | ||
| # Create a test audio | ||
| audio_path = tmp_path / "test.wav" | ||
| audio_path.write_bytes(b"test audio data") | ||
|
|
||
| def mixed_list_fn() -> list: | ||
| return [ | ||
| "text message", | ||
| Audio(audio_path), | ||
| {"key": "value"}, | ||
| TextContent(type="text", text="direct content"), | ||
| ] | ||
|
|
||
| mcp = FastMCP() | ||
| mcp.add_tool(mixed_list_fn) | ||
| async with client_session(mcp._mcp_server) as client: | ||
| result = await client.call_tool("mixed_list_fn", {}) | ||
| assert len(result.content) == 4 | ||
| # Check text conversion | ||
| content1 = result.content[0] | ||
| assert isinstance(content1, TextContent) | ||
| assert content1.text == "text message" | ||
| # Check audio conversion | ||
| content2 = result.content[1] | ||
| assert isinstance(content2, AudioContent) | ||
| assert content2.mimeType == "audio/wav" | ||
| assert base64.b64decode(content2.data) == b"test audio data" | ||
| # Check dict conversion | ||
| content3 = result.content[2] | ||
| assert isinstance(content3, TextContent) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this test and add Audio on the above please.
tests/server/fastmcp/test_server.py
Outdated
| test_cases = [ | ||
| ("test.wav", "audio/wav"), | ||
| ("test.mp3", "audio/mpeg"), | ||
| ("test.ogg", "audio/ogg"), | ||
| ("test.flac", "audio/flac"), | ||
| ("test.aac", "audio/aac"), | ||
| ("test.m4a", "audio/mp4"), | ||
| ("test.unknown", "application/octet-stream"), # Unknown extension fallback | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use pytest.mark.parametrize, please.
| def __init__( | ||
| self, | ||
| path: str | Path | None = None, | ||
| data: bytes | None = None, | ||
| format: str | None = None, | ||
| ): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use @typing.override.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to get some clarity as to what we are tying to override, given the audio class dosent inherit from any class at the moment
| if path is None and data is None: | ||
| raise ValueError("Either path or data must be provided") | ||
| if path is not None and data is not None: | ||
| raise ValueError("Only one of path or data can be provided") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can do bool(path) ^ bool(data), and have a meaningful message: "Either path or data can be provided".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for this suggestion! should i also make these changes to the Image class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're up for it, please feel free to send a tiny follow up PR w/ both changes :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again!
| if path is None and data is None: | ||
| raise ValueError("Either path or data must be provided") | ||
| if path is not None and data is not None: | ||
| raise ValueError("Only one of path or data can be provided") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're up for it, please feel free to send a tiny follow up PR w/ both changes :-)
* Add regression test for stateless request memory cleanup (modelcontextprotocol#1140) * Implement RFC9728 - Support WWW-Authenticate header by MCP client (modelcontextprotocol#1071) * Add streamable HTTP starlette example to Python SDK docs (modelcontextprotocol#1111) * fix markdown error in README in main (modelcontextprotocol#1147) * README - replace code snippets with examples - add lowlevel to snippets (modelcontextprotocol#1150) * README - replace code snippets with examples - streamable http (modelcontextprotocol#1155) * chore: don't allow users to create issues outside the templates (modelcontextprotocol#1163) * Tests(cli): Add coverage for helper functions (modelcontextprotocol#635) * Docs: Update CallToolResult parsing in README (modelcontextprotocol#812) Co-authored-by: Felix Weinberger <fweinberger@anthropic.com> * docs: add pre-commit install guide on CONTRIBUTING.md (modelcontextprotocol#995) Co-authored-by: Felix Weinberger <fweinberger@anthropic.com> * fix flaky fix-test_streamablehttp_client_resumption test (modelcontextprotocol#1166) * README - replace code snippets with examples -- auth examples (modelcontextprotocol#1164) * Support falling back to OIDC metadata for auth (modelcontextprotocol#1061) * Add CODEOWNERS file for sdk (modelcontextprotocol#1169) * fix flaky test test_88_random_error (modelcontextprotocol#1171) * Make sure `RequestId` is not coerced as `int` (modelcontextprotocol#1178) * Fix: Replace threading.Lock with anyio.Lock for Ray deployment compatibility (modelcontextprotocol#1151) * fix: fix OAuth flow request object handling (modelcontextprotocol#1174) * update codeowners group (modelcontextprotocol#1191) * fix: perform auth server metadata discovery fallbacks on any 4xx (modelcontextprotocol#1193) * server: skip duplicate response on CancelledError (modelcontextprotocol#1153) Co-authored-by: ihrpr <inna@anthropic.com> * Unpack settings in FastMCP (modelcontextprotocol#1198) * chore: Remove unused prompt_manager.py file (modelcontextprotocol#1229) Co-authored-by: Tapan Chugh <tapanc@cs.washington.edu> * Improved supported for ProtectedResourceMetadata (modelcontextprotocol#1235) Co-authored-by: Paul Carleton <paulcarletonjr@gmail.com> * chore: Remove unused variable notification_options (modelcontextprotocol#1238) * Improve README around the Context object (modelcontextprotocol#1203) * fix: allow to pass `list[str]` to `token_endpoint_auth_signing_alg_values_supported` (modelcontextprotocol#1226) * Remove strict validation on `response_modes_supported` member of `OAuthMetadata` (modelcontextprotocol#1243) * Add pyright strict mode on the whole project (modelcontextprotocol#1254) * Consistent casing for default headers Accept and Content-Type (modelcontextprotocol#1263) * Update dependencies and fix type issues (modelcontextprotocol#1268) Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com> * fix: prevent async generator cleanup errors in StreamableHTTP transport (modelcontextprotocol#1271) Co-authored-by: David Soria Parra <167242713+dsp-ant@users.noreply.github.com> * chore: uncomment .idea/ in .gitignore (modelcontextprotocol#1287) Co-authored-by: Claude <noreply@anthropic.com> * docs: clarify streamable_http_path configuration when mounting servers (modelcontextprotocol#1172) * feat: Add CORS configuration for browser-based MCP clients (modelcontextprotocol#1059) Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com> Co-authored-by: Felix Weinberger <fweinberger@anthropic.com> * Added Audio to FastMCP (modelcontextprotocol#1130) * fix: avoid uncessary retries in OAuth authenticated requests (modelcontextprotocol#1206) Co-authored-by: Felix Weinberger <fweinberger@anthropic.com> * Add PATHEXT to default STDIO env vars in windows (modelcontextprotocol#1256) * fix: error too many values to unpack (expected 2) (modelcontextprotocol#1279) Signed-off-by: San Nguyen <vinhsannguyen91@gmail.com> Co-authored-by: Felix Weinberger <fweinberger@anthropic.com> Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com> * SDK Parity: Avoid Parsing Server Response for non-JsonRPCMessage Requests (modelcontextprotocol#1290) * types: Setting default value for method: Literal (modelcontextprotocol#1292) * changes structured temperature to not deadly (modelcontextprotocol#1328) * Update simple-resource example to use non-deprecated read_resource return type (modelcontextprotocol#1331) Co-authored-by: Claude <noreply@anthropic.com> * docs: Update README to include link to API docs for modelcontextprotocol#1329 (modelcontextprotocol#1330) * Allow ping requests before initialization (modelcontextprotocol#1312) * Python lint: Ruff rules for pylint and code complexity (modelcontextprotocol#525) * Fix context injection for resources and prompts (modelcontextprotocol#1336) * fix(fastmcp): propagate mimeType in resource template list (modelcontextprotocol#1186) Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com> * fix: allow elicitations accepted without content (modelcontextprotocol#1285) Co-authored-by: Olivier Schiavo <olivier.schiavo@wengo.com> * Use --frozen in pre-commit config (modelcontextprotocol#1375) * Return HTTP 403 for invalid Origin headers (modelcontextprotocol#1353) * Add test for ProtectedResourceMetadataParsing (modelcontextprotocol#1236) Co-authored-by: Paul Carleton <paulcarletonjr@gmail.com> Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com> Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com> * Fastmcp logging progress example (modelcontextprotocol#1270) Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com> * feat: add paginated list decorators for prompts, resources, and tools (modelcontextprotocol#1286) Co-authored-by: Claude <noreply@anthropic.com> * Remove "unconditionally" from conditional description (modelcontextprotocol#1289) * Use streamable-http consistently in examples (modelcontextprotocol#1389) * feat: Add SDK support for SEP-1034 default values in elicitation schemas (modelcontextprotocol#1337) Co-authored-by: Tapan Chugh <tapanc@cs.washington.edu> Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com> * Implementation of SEP 973 - Additional metadata + icons support (modelcontextprotocol#1357) * Merge upstream/main with custom filtering --------- Signed-off-by: San Nguyen <vinhsannguyen91@gmail.com> Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com> Co-authored-by: yurikunash <143175350+yurikunash@users.noreply.github.com> Co-authored-by: Pamela Fox <pamela.fox@gmail.com> Co-authored-by: Inna Harper <inna.hrpr@gmail.com> Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com> Co-authored-by: Ian Davenport <49379192+davenpi@users.noreply.github.com> Co-authored-by: Dagang Wei <functicons@gmail.com> Co-authored-by: Felix Weinberger <fweinberger@anthropic.com> Co-authored-by: Stanley Law <stanleylkal@gmail.com> Co-authored-by: Luca Chang <131398524+LucaButBoring@users.noreply.github.com> Co-authored-by: leweng <leweng@nvidia.com> Co-authored-by: Clare Liguori <liguori@amazon.com> Co-authored-by: lukacf <luka@peltarion.com> Co-authored-by: ihrpr <inna@anthropic.com> Co-authored-by: Tapan Chugh <chugh.tapan@gmail.com> Co-authored-by: Tapan Chugh <tapanc@cs.washington.edu> Co-authored-by: Yann Jouanin <4557670+yannj-fr@users.noreply.github.com> Co-authored-by: Paul Carleton <paulcarletonjr@gmail.com> Co-authored-by: Sreenath Somarajapuram <somarajapuram@gmail.com> Co-authored-by: Omer Korner <omerkorner@gmail.com> Co-authored-by: joesavage-silabs <159480754+joesavage-silabs@users.noreply.github.com> Co-authored-by: Gregory L <gregory.linford@mistral.ai> Co-authored-by: David Soria Parra <167242713+dsp-ant@users.noreply.github.com> Co-authored-by: Moustapha Ebnou <155577789+mous222@users.noreply.github.com> Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Jerome <jerome@anthropic.com> Co-authored-by: xavier <84836280+dragonier23@users.noreply.github.com> Co-authored-by: keurcien <keurcien.luu@gmail.com> Co-authored-by: Tim Esler <tim.esler@gmail.com> Co-authored-by: San Nguyen <22189661+sandangel@users.noreply.github.com> Co-authored-by: Justin Wang <89049861+justin-yi-wang@users.noreply.github.com> Co-authored-by: jess <jessachandler@gmail.com> Co-authored-by: Peter Alexander <pja@anthropic.com> Co-authored-by: Reid Geyer <12072650+reidg44@users.noreply.github.com> Co-authored-by: Eleftheria Stein-Kousathana <eleftheria.kousathana@gmail.com> Co-authored-by: Christian Clauss <cclauss@me.com> Co-authored-by: pchoudhury22 <pchoudhury22@apple.com> Co-authored-by: owengo <owengo@users.noreply.github.com> Co-authored-by: Olivier Schiavo <olivier.schiavo@wengo.com> Co-authored-by: Steve Billings <billings.steve@gmail.com> Co-authored-by: Mike Salvatore <mike.s.salvatore@gmail.com>
Motivation and Context
Adding Audio in FastMCP that can be used to send audio content back. Related to Issue Closes: #952
How Has This Been Tested?
Breaking Changes
Types of changes
Checklist
Additional context