#1204·TrendRadar

stdio 模式下启动 banner 打到 stdout,污染 MCP 协议导致客户端加载失败

Author: davidjackk571-hueCreated Aug 14, 2026Updated Aug 14, 2026

问题描述

mcp_server/server.pyrun_server() 在调用 mcp.run(transport='stdio') 之前,用 print()stdout 打印了约 60 行启动 banner(TrendRadar MCP Server - FastMCP 2.0 及工具列表)。

MCP over stdio 协议要求 stdout 只能承载 JSON-RPC 消息,任何非 JSON 输出都会破坏握手。实测 stdout 输出如下(banner 与响应混杂):

============================================================
  TrendRadar MCP Server - FastMCP 2.0
============================================================
  传输模式: STDIO
  ...
============================================================

{"jsonrpc":"2.0","id":1,"result":{...}}

结果:Claude Code 等严格遵循 stdio 协议的客户端无法解析 initialize 响应,MCP server 加载失败(工具列表里看不到 trendradar 的任何工具)。

根因

run_server() 中 banner 打印未区分传输模式,无条件写 stdout(server.py 约 1135–1201 行)。

附带问题:冷启动耗时约 26 秒

trendradar/ai/client.py 顶部 from litellm import completion 会在 import 阶段触发 litellm 从 raw.githubusercontent.com 拉取模型价格表。在无法直连 GitHub 的环境下,SSL 握手超时(约 25 秒)后才回退本地,导致 server 冷启动约 26 秒,进一步加剧客户端加载失败。建议在文档中提示设置 LITELLM_LOCAL_MODEL_COST_MAP=True,或将 litellm 改为延迟 import。

建议修复

stdio 模式下将 banner 重定向到 stderr(仅 4 行改动):

    # 打印启动信息(stdio 模式下 stdout 是 JSON-RPC 通道,banner 必须走 stderr)
    import sys
    _banner_stdout = sys.stdout
    if transport == 'stdio':
        sys.stdout = sys.stderr
    print()
    print("=" * 60)
    # ... 原有 banner ...
    print()
    sys.stdout = _banner_stdout

环境

  • TrendRadar v6.10.0(MCP server 上报 1.16.0)
  • Python 3.14(项目 .venv)
  • 客户端:Claude Code(stdio transport)