fix: read track from item["item"] key to match updated Spotify API response shape

Spotify's playlist_items endpoint now nests the track object under "item"
instead of "track" in each playlist entry. The old key is absent, causing
item.get("track") to return None for every entry and silently drop all tracks.

Also adds stderr debug traces at each component boundary (tool dispatch,
API page summary, per-item accept/skip) to make future silent-empty issues
diagnosable, and switches popularity to .get() since it is absent in the
new response shape.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 18:27:31 +02:00
parent d5fa1f65c3
commit 6ee9cde391
2 changed files with 33 additions and 4 deletions

View File

@@ -8,6 +8,10 @@ from mcp.types import Tool, TextContent
import spotify_client
def _dbg(msg: str) -> None:
print(f"[spotify-mcp] {msg}", file=sys.stderr, flush=True)
server = Server("spotify-mcp")
@@ -112,6 +116,7 @@ async def handle_list_tools() -> list[Tool]:
@server.call_tool()
async def handle_call_tool(name: str, arguments: dict | None) -> list[TextContent]:
arguments = arguments or {}
_dbg(f"tool={name!r} args={arguments!r}")
try:
if name == "list_playlists":
result = await asyncio.to_thread(spotify_client.list_playlists)
@@ -145,8 +150,11 @@ async def handle_call_tool(name: str, arguments: dict | None) -> list[TextConten
else:
raise ValueError(f"Unknown tool: {name}")
except Exception as e:
_dbg(f"tool={name!r} raised {type(e).__name__}: {e}")
return [TextContent(type="text", text=f"Error: {e}")]
result_len = len(result) if isinstance(result, list) else "n/a"
_dbg(f"tool={name!r} returning {result_len} items")
return [TextContent(type="text", text=json.dumps(result, ensure_ascii=False, indent=2))]