From 97b34627667fd699f4e0e054533eb89a205a2878 Mon Sep 17 00:00:00 2001 From: tanaka takashi Date: Sun, 13 Sep 2026 14:12:41 +0900 Subject: feat: return composed WAV as MCP audio content Replace the server-local wav_path result with a protocol-native multimedia response. - Split internal composition execution from MCP ToolResult serialization so filesystem paths never enter public payloads. - Return every successfully composed WAV as AudioContent with the audio/wav MIME type, regardless of file size. - Keep structured audio metadata, duration, note sequence, and validation details alongside the multimedia content. - Use CallToolResult.isError as the authoritative MCP execution status while retaining compose success and validate valid as domain fields. - Treat invalid compose/API requests and runtime failures as tool errors, while invalid MML discovered by validate remains a successful validation operation. - Sanitize synthesis, file-write, audio-serialization, and unexpected failure responses so internal paths and exception details are not exposed. - Add protocol-level coverage for base64 round trips, content block types, error semantics, ResourceLink absence, and path non-disclosure. - Update existing tests for the separated execution layer and path-free result contract. - Document AudioContent and isError behavior in the README, MCP schema, and design specification. - Require the tested FastMCP 3.4.4 API line and exclude the incompatible 4.x major version. Verification: 487 tests passed; ruff check passed; git diff --check passed; uv lock --check passed; and a manual MCP call returned TextContent plus AudioContent with no wav_path. --- tests/test_server.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'tests/test_server.py') diff --git a/tests/test_server.py b/tests/test_server.py index 533c88b..f858e0f 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -1,6 +1,10 @@ """Tests for MCP server compose_mml tool.""" -from mml_composemusic_mcp.server import compose_mml +from mml_composemusic_mcp.server import _execute_compose_mml + + +def compose_mml(**kwargs): + return _execute_compose_mml(**kwargs).result PPMCK_MML = """#TITLE "Test" A t120 l4 o4 v15 q2 @@ -11,7 +15,8 @@ A t120 l4 o4 v15 q2 def test_compose_ppmck(): result = compose_mml(action="compose", mml=PPMCK_MML, mode="ppmck") assert result["success"] is True - assert result["wav_path"] is not None + assert result["audio"]["mime_type"] == "audio/wav" + assert "wav_path" not in result assert result["duration_sec"] > 0 -- cgit v1.2.3