verify_local.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. """
  2. 本地验证脚本:直接调用 audio_server 里注册的 MCP 工具(不经过 WebSocket)
  3. ============================================================
  4. 用法(在 mcp-for-xiaozhi 目录下):
  5. python verify_local.py
  6. 要求:
  7. - 后端 audiobook 服务跑在 AUDIOBOOK_API_BASE(默认 127.0.0.1:3000)
  8. - 已安装依赖:pip install -r requirements.txt
  9. 它会:
  10. 1. import audio_server 注册到 FastMCP 实例的内部 tool 列表
  11. 2. 通过 mcp.ClientSession 用 stdio 启动 audio_server,列工具 + 调用若干工具
  12. """
  13. from __future__ import annotations
  14. import asyncio
  15. import os
  16. import sys
  17. from mcp import ClientSession, StdioServerParameters
  18. from mcp.client.stdio import stdio_client
  19. async def main() -> int:
  20. here = os.path.dirname(os.path.abspath(__file__))
  21. server_path = os.path.join(here, "audio_server.py")
  22. api_base = os.environ.get("AUDIOBOOK_API_BASE", "http://127.0.0.1:3000")
  23. print(f"[verify] api_base = {api_base}")
  24. params = StdioServerParameters(
  25. command=sys.executable,
  26. args=[server_path],
  27. env={**os.environ, "MCP_LOG_LEVEL": "WARNING"},
  28. )
  29. async with stdio_client(params) as (read, write):
  30. async with ClientSession(read, write) as session:
  31. await session.initialize()
  32. tools = await session.list_tools()
  33. print(f"[verify] list_tools -> {len(tools.tools)} tools")
  34. for t in tools.tools:
  35. print(f" - {t.name}: {t.description[:60] if t.description else ''}")
  36. # 用例 1:搜书
  37. r = await session.call_tool("search_audiobooks", {"keywords": "三国"})
  38. print("\n[verify] search_audiobooks('三国') ->")
  39. print((r.content[0].text if r.content else "")[:400])
  40. # 用例 2:分类
  41. r = await session.call_tool("list_categories", {})
  42. print("\n[verify] list_categories ->")
  43. print((r.content[0].text if r.content else "")[:400])
  44. # 用例 3:详情(用第一个搜索结果的 id)
  45. try:
  46. import json
  47. search_text = (await session.call_tool("search_audiobooks", {"keywords": "三国"})).content[0].text
  48. payload = json.loads(search_text)
  49. first_id = (payload.get("items") or [{}])[0].get("id")
  50. if first_id:
  51. r = await session.call_tool("get_book_details", {"book_id": int(first_id)})
  52. print(f"\n[verify] get_book_details({first_id}) ->")
  53. print((r.content[0].text if r.content else "")[:400])
  54. except Exception as e: # noqa: BLE001
  55. print(f"[verify] get_book_details skipped: {e}")
  56. print("\n[verify] OK")
  57. return 0
  58. if __name__ == "__main__":
  59. sys.exit(asyncio.run(main()))