server.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. """
  2. TrendRadar MCP Server - FastMCP 2.0 实现
  3. 使用 FastMCP 2.0 提供生产级 MCP 工具服务器。
  4. 支持 stdio 和 HTTP 两种传输模式。
  5. """
  6. import json
  7. from typing import List, Optional, Dict
  8. from fastmcp import FastMCP
  9. from .tools.data_query import DataQueryTools
  10. from .tools.analytics import AnalyticsTools
  11. from .tools.search_tools import SearchTools
  12. from .tools.config_mgmt import ConfigManagementTools
  13. from .tools.system import SystemManagementTools
  14. # 创建 FastMCP 2.0 应用
  15. mcp = FastMCP('trendradar-news')
  16. # 全局工具实例(在第一次请求时初始化)
  17. _tools_instances = {}
  18. def _get_tools(project_root: Optional[str] = None):
  19. """获取或创建工具实例(单例模式)"""
  20. if not _tools_instances:
  21. _tools_instances['data'] = DataQueryTools(project_root)
  22. _tools_instances['analytics'] = AnalyticsTools(project_root)
  23. _tools_instances['search'] = SearchTools(project_root)
  24. _tools_instances['config'] = ConfigManagementTools(project_root)
  25. _tools_instances['system'] = SystemManagementTools(project_root)
  26. return _tools_instances
  27. # ==================== 数据查询工具 ====================
  28. @mcp.tool
  29. async def get_latest_news(
  30. platforms: Optional[List[str]] = None,
  31. limit: int = 50,
  32. include_url: bool = False
  33. ) -> str:
  34. """
  35. 获取最新一批爬取的新闻数据,快速了解当前热点
  36. Args:
  37. platforms: 平台ID列表,如 ['zhihu', 'weibo', 'douyin']
  38. - 不指定时:使用 config.yaml 中配置的所有平台
  39. - 支持的平台来自 config/config.yaml 的 platforms 配置
  40. - 每个平台都有对应的name字段(如"知乎"、"微博"),方便AI识别
  41. limit: 返回条数限制,默认50,最大1000
  42. 注意:实际返回数量可能少于请求值,取决于当前可用的新闻总数
  43. include_url: 是否包含URL链接,默认False(节省token)
  44. Returns:
  45. JSON格式的新闻列表
  46. **重要:数据展示建议**
  47. 本工具会返回完整的新闻列表(通常50条)给你。但请注意:
  48. - **工具返回**:完整的50条数据 ✅
  49. - **建议展示**:向用户展示全部数据,除非用户明确要求总结
  50. - **用户期望**:用户可能需要完整数据,请谨慎总结
  51. **何时可以总结**:
  52. - 用户明确说"给我总结一下"或"挑重点说"
  53. - 数据量超过100条时,可先展示部分并询问是否查看全部
  54. **注意**:如果用户询问"为什么只显示了部分",说明他们需要完整数据
  55. """
  56. tools = _get_tools()
  57. result = tools['data'].get_latest_news(platforms=platforms, limit=limit, include_url=include_url)
  58. return json.dumps(result, ensure_ascii=False, indent=2)
  59. @mcp.tool
  60. async def get_trending_topics(
  61. top_n: int = 10,
  62. mode: str = 'current'
  63. ) -> str:
  64. """
  65. 获取个人关注词的新闻出现频率统计(基于 config/frequency_words.txt)
  66. 注意:本工具不是自动提取新闻热点,而是统计你在 config/frequency_words.txt 中
  67. 设置的个人关注词在新闻中出现的频率。你可以自定义这个关注词列表。
  68. Args:
  69. top_n: 返回TOP N关注词,默认10
  70. mode: 模式选择
  71. - daily: 当日累计数据统计
  72. - current: 最新一批数据统计(默认)
  73. Returns:
  74. JSON格式的关注词频率统计列表
  75. """
  76. tools = _get_tools()
  77. result = tools['data'].get_trending_topics(top_n=top_n, mode=mode)
  78. return json.dumps(result, ensure_ascii=False, indent=2)
  79. @mcp.tool
  80. async def get_news_by_date(
  81. date_query: Optional[str] = None,
  82. platforms: Optional[List[str]] = None,
  83. limit: int = 50,
  84. include_url: bool = False
  85. ) -> str:
  86. """
  87. 获取指定日期的新闻数据,用于历史数据分析和对比
  88. Args:
  89. date_query: 日期查询,可选格式:
  90. - 自然语言: "今天", "昨天", "前天", "3天前"
  91. - 标准日期: "2024-01-15", "2024/01/15"
  92. - 默认值: "今天"(节省token)
  93. platforms: 平台ID列表,如 ['zhihu', 'weibo', 'douyin']
  94. - 不指定时:使用 config.yaml 中配置的所有平台
  95. - 支持的平台来自 config/config.yaml 的 platforms 配置
  96. - 每个平台都有对应的name字段(如"知乎"、"微博"),方便AI识别
  97. limit: 返回条数限制,默认50,最大1000
  98. 注意:实际返回数量可能少于请求值,取决于指定日期的新闻总数
  99. include_url: 是否包含URL链接,默认False(节省token)
  100. Returns:
  101. JSON格式的新闻列表,包含标题、平台、排名等信息
  102. **重要:数据展示建议**
  103. 本工具会返回完整的新闻列表(通常50条)给你。但请注意:
  104. - **工具返回**:完整的50条数据 ✅
  105. - **建议展示**:向用户展示全部数据,除非用户明确要求总结
  106. - **用户期望**:用户可能需要完整数据,请谨慎总结
  107. **何时可以总结**:
  108. - 用户明确说"给我总结一下"或"挑重点说"
  109. - 数据量超过100条时,可先展示部分并询问是否查看全部
  110. **注意**:如果用户询问"为什么只显示了部分",说明他们需要完整数据
  111. """
  112. tools = _get_tools()
  113. result = tools['data'].get_news_by_date(
  114. date_query=date_query,
  115. platforms=platforms,
  116. limit=limit,
  117. include_url=include_url
  118. )
  119. return json.dumps(result, ensure_ascii=False, indent=2)
  120. # ==================== 高级数据分析工具 ====================
  121. @mcp.tool
  122. async def analyze_topic_trend(
  123. topic: str,
  124. analysis_type: str = "trend",
  125. time_range: str = "7d",
  126. granularity: str = "day",
  127. threshold: float = 3.0,
  128. time_window: int = 24,
  129. lookback_days: int = 7,
  130. lookahead_hours: int = 6,
  131. confidence_threshold: float = 0.7
  132. ) -> str:
  133. """
  134. 统一话题趋势分析工具 - 整合多种趋势分析模式
  135. Args:
  136. topic: 话题关键词(必需)
  137. analysis_type: 分析类型,可选值:
  138. - "trend": 热度趋势分析(追踪话题的热度变化)
  139. - "lifecycle": 生命周期分析(从出现到消失的完整周期)
  140. - "viral": 异常热度检测(识别突然爆火的话题)
  141. - "predict": 话题预测(预测未来可能的热点)
  142. time_range: 时间范围(trend模式),默认"7d"(7d/24h/1w/1m/2m)
  143. granularity: 时间粒度(trend模式),默认"day"(仅支持 day,因为底层数据按天聚合)
  144. threshold: 热度突增倍数阈值(viral模式),默认3.0
  145. time_window: 检测时间窗口小时数(viral模式),默认24
  146. lookback_days: 回溯天数(lifecycle模式),默认7
  147. lookahead_hours: 预测未来小时数(predict模式),默认6
  148. confidence_threshold: 置信度阈值(predict模式),默认0.7
  149. Returns:
  150. JSON格式的趋势分析结果
  151. Examples:
  152. - analyze_topic_trend(topic="人工智能", analysis_type="trend", time_range="7d")
  153. - analyze_topic_trend(topic="特斯拉", analysis_type="lifecycle", lookback_days=7)
  154. - analyze_topic_trend(topic="比特币", analysis_type="viral", threshold=3.0)
  155. - analyze_topic_trend(topic="ChatGPT", analysis_type="predict", lookahead_hours=6)
  156. """
  157. tools = _get_tools()
  158. result = tools['analytics'].analyze_topic_trend_unified(
  159. topic=topic,
  160. analysis_type=analysis_type,
  161. time_range=time_range,
  162. granularity=granularity,
  163. threshold=threshold,
  164. time_window=time_window,
  165. lookback_days=lookback_days,
  166. lookahead_hours=lookahead_hours,
  167. confidence_threshold=confidence_threshold
  168. )
  169. return json.dumps(result, ensure_ascii=False, indent=2)
  170. @mcp.tool
  171. async def analyze_data_insights(
  172. insight_type: str = "platform_compare",
  173. topic: Optional[str] = None,
  174. date_range: Optional[Dict[str, str]] = None,
  175. min_frequency: int = 3,
  176. top_n: int = 20
  177. ) -> str:
  178. """
  179. 统一数据洞察分析工具 - 整合多种数据分析模式
  180. Args:
  181. insight_type: 洞察类型,可选值:
  182. - "platform_compare": 平台对比分析(对比不同平台对话题的关注度)
  183. - "platform_activity": 平台活跃度统计(统计各平台发布频率和活跃时间)
  184. - "keyword_cooccur": 关键词共现分析(分析关键词同时出现的模式)
  185. topic: 话题关键词(可选,platform_compare模式适用)
  186. date_range: 日期范围,格式: {"start": "YYYY-MM-DD", "end": "YYYY-MM-DD"}
  187. min_frequency: 最小共现频次(keyword_cooccur模式),默认3
  188. top_n: 返回TOP N结果(keyword_cooccur模式),默认20
  189. Returns:
  190. JSON格式的数据洞察分析结果
  191. Examples:
  192. - analyze_data_insights(insight_type="platform_compare", topic="人工智能")
  193. - analyze_data_insights(insight_type="platform_activity", date_range={...})
  194. - analyze_data_insights(insight_type="keyword_cooccur", min_frequency=5, top_n=15)
  195. """
  196. tools = _get_tools()
  197. result = tools['analytics'].analyze_data_insights_unified(
  198. insight_type=insight_type,
  199. topic=topic,
  200. date_range=date_range,
  201. min_frequency=min_frequency,
  202. top_n=top_n
  203. )
  204. return json.dumps(result, ensure_ascii=False, indent=2)
  205. @mcp.tool
  206. async def analyze_sentiment(
  207. topic: Optional[str] = None,
  208. platforms: Optional[List[str]] = None,
  209. date_range: Optional[Dict[str, str]] = None,
  210. limit: int = 50,
  211. sort_by_weight: bool = True,
  212. include_url: bool = False
  213. ) -> str:
  214. """
  215. 分析新闻的情感倾向和热度趋势
  216. Args:
  217. keywords: 关键词列表,如 ["AI", "人工智能"]
  218. date_range: 日期范围(天数),如 7 表示最近7天,默认3天
  219. platforms: 平台ID列表,如 ['zhihu', 'weibo', 'douyin']
  220. - 不指定时:使用 config.yaml 中配置的所有平台
  221. - 支持的平台来自 config/config.yaml 的 platforms 配置
  222. - 每个平台都有对应的name字段(如"知乎"、"微博"),方便AI识别
  223. limit: 返回新闻数量,默认50,最大100
  224. 注意:本工具会对新闻标题进行去重(同一标题在不同平台只保留一次),
  225. 因此实际返回数量可能少于请求的 limit 值
  226. sort_by_weight: 是否按热度权重排序,默认True
  227. include_url: 是否包含URL链接,默认False(节省token)
  228. Returns:
  229. JSON格式的分析结果,包含情感分布、热度趋势和相关新闻
  230. **重要:数据展示策略**
  231. - 本工具返回完整的分析结果和新闻列表
  232. - **默认展示方式**:展示完整的分析结果(包括所有新闻)
  233. - 仅在用户明确要求"总结"或"挑重点"时才进行筛选
  234. """
  235. tools = _get_tools()
  236. result = tools['analytics'].analyze_sentiment(
  237. topic=topic,
  238. platforms=platforms,
  239. date_range=date_range,
  240. limit=limit,
  241. sort_by_weight=sort_by_weight,
  242. include_url=include_url
  243. )
  244. return json.dumps(result, ensure_ascii=False, indent=2)
  245. @mcp.tool
  246. async def find_similar_news(
  247. reference_title: str,
  248. threshold: float = 0.6,
  249. limit: int = 50,
  250. include_url: bool = False
  251. ) -> str:
  252. """
  253. 查找与指定新闻标题相似的其他新闻
  254. Args:
  255. title: 新闻标题(完整或部分)
  256. threshold: 相似度阈值,0-1之间,默认0.6
  257. 注意:阈值越高匹配越严格,返回结果越少
  258. limit: 返回条数限制,默认50,最大100
  259. 注意:实际返回数量取决于相似度匹配结果,可能少于请求值
  260. include_url: 是否包含URL链接,默认False(节省token)
  261. Returns:
  262. JSON格式的相似新闻列表,包含相似度分数
  263. **重要:数据展示策略**
  264. - 本工具返回完整的相似新闻列表
  265. - **默认展示方式**:展示全部返回的新闻(包括相似度分数)
  266. - 仅在用户明确要求"总结"或"挑重点"时才进行筛选
  267. """
  268. tools = _get_tools()
  269. result = tools['analytics'].find_similar_news(
  270. reference_title=reference_title,
  271. threshold=threshold,
  272. limit=limit,
  273. include_url=include_url
  274. )
  275. return json.dumps(result, ensure_ascii=False, indent=2)
  276. @mcp.tool
  277. async def generate_summary_report(
  278. report_type: str = "daily",
  279. date_range: Optional[Dict[str, str]] = None
  280. ) -> str:
  281. """
  282. 每日/每周摘要生成器 - 自动生成热点摘要报告
  283. Args:
  284. report_type: 报告类型(daily/weekly)
  285. date_range: 自定义日期范围(可选)
  286. Returns:
  287. JSON格式的摘要报告,包含Markdown格式内容
  288. """
  289. tools = _get_tools()
  290. result = tools['analytics'].generate_summary_report(
  291. report_type=report_type,
  292. date_range=date_range
  293. )
  294. return json.dumps(result, ensure_ascii=False, indent=2)
  295. # ==================== 智能检索工具 ====================
  296. @mcp.tool
  297. async def search_news(
  298. query: str,
  299. search_mode: str = "keyword",
  300. date_range: Optional[Dict[str, str]] = None,
  301. platforms: Optional[List[str]] = None,
  302. limit: int = 50,
  303. sort_by: str = "relevance",
  304. threshold: float = 0.6,
  305. include_url: bool = False
  306. ) -> str:
  307. """
  308. 统一搜索接口,支持多种搜索模式
  309. Args:
  310. query: 搜索关键词或内容片段
  311. search_mode: 搜索模式,可选值:
  312. - "keyword": 精确关键词匹配(默认,适合搜索特定话题)
  313. - "fuzzy": 模糊内容匹配(适合搜索内容片段,会过滤相似度低于阈值的结果)
  314. - "entity": 实体名称搜索(适合搜索人物/地点/机构)
  315. threshold: 相似度阈值(仅fuzzy模式有效),0-1之间,默认0.6
  316. 注意:阈值越高匹配越严格,返回结果越少
  317. platforms: 平台ID列表,如 ['zhihu', 'weibo', 'douyin']
  318. - 不指定时:使用 config.yaml 中配置的所有平台
  319. - 支持的平台来自 config/config.yaml 的 platforms 配置
  320. - 每个平台都有对应的name字段(如"知乎"、"微博"),方便AI识别
  321. lookback_days: 回溯天数,默认7天,最大30天
  322. limit: 返回条数限制,默认50,最大1000
  323. 注意:实际返回数量取决于搜索匹配结果(特别是 fuzzy 模式下会过滤低相似度结果)
  324. include_url: 是否包含URL链接,默认False(节省token)
  325. Returns:
  326. JSON格式的搜索结果,包含标题、平台、排名等信息
  327. **重要:数据展示策略**
  328. - 本工具返回完整的搜索结果列表
  329. - **默认展示方式**:展示全部返回的新闻,无需总结或筛选
  330. - 仅在用户明确要求"总结"或"挑重点"时才进行筛选
  331. """
  332. tools = _get_tools()
  333. result = tools['search'].search_news_unified(
  334. query=query,
  335. search_mode=search_mode,
  336. date_range=date_range,
  337. platforms=platforms,
  338. limit=limit,
  339. sort_by=sort_by,
  340. threshold=threshold,
  341. include_url=include_url
  342. )
  343. return json.dumps(result, ensure_ascii=False, indent=2)
  344. @mcp.tool
  345. async def search_related_news_history(
  346. reference_text: str,
  347. time_range: str = "yesterday",
  348. threshold: float = 0.4,
  349. limit: int = 50,
  350. include_url: bool = False
  351. ) -> str:
  352. """
  353. 基于种子新闻,在历史数据中搜索相关新闻
  354. Args:
  355. seed_news_title: 种子新闻标题(完整或部分)
  356. lookback_days: 向前查找的天数范围,默认7天,最大30天
  357. threshold: 相关性阈值,0-1之间,默认0.4
  358. 注意:综合相似度计算(70%关键词重合 + 30%文本相似度)
  359. 阈值越高匹配越严格,返回结果越少
  360. platforms: 平台ID列表。不指定则搜索所有平台
  361. limit: 返回条数限制,默认50,最大100
  362. 注意:实际返回数量取决于相关性匹配结果,可能少于请求值
  363. include_url: 是否包含URL链接,默认False(节省token)
  364. Returns:
  365. JSON格式的相关新闻列表,包含相关性分数和时间分布
  366. **重要:数据展示策略**
  367. - 本工具返回完整的相关新闻列表
  368. - **默认展示方式**:展示全部返回的新闻(包括相关性分数)
  369. - 仅在用户明确要求"总结"或"挑重点"时才进行筛选
  370. """
  371. tools = _get_tools()
  372. result = tools['search'].search_related_news_history(
  373. reference_text=reference_text,
  374. time_range=time_range,
  375. threshold=threshold,
  376. limit=limit,
  377. include_url=include_url
  378. )
  379. return json.dumps(result, ensure_ascii=False, indent=2)
  380. # ==================== 配置与系统管理工具 ====================
  381. @mcp.tool
  382. async def get_current_config(
  383. section: str = "all"
  384. ) -> str:
  385. """
  386. 获取当前系统配置
  387. Args:
  388. section: 配置节,可选值:
  389. - "all": 所有配置(默认)
  390. - "crawler": 爬虫配置
  391. - "push": 推送配置
  392. - "keywords": 关键词配置
  393. - "weights": 权重配置
  394. Returns:
  395. JSON格式的配置信息
  396. """
  397. tools = _get_tools()
  398. result = tools['config'].get_current_config(section=section)
  399. return json.dumps(result, ensure_ascii=False, indent=2)
  400. @mcp.tool
  401. async def get_system_status() -> str:
  402. """
  403. 获取系统运行状态和健康检查信息
  404. 返回系统版本、数据统计、缓存状态等信息
  405. Returns:
  406. JSON格式的系统状态信息
  407. """
  408. tools = _get_tools()
  409. result = tools['system'].get_system_status()
  410. return json.dumps(result, ensure_ascii=False, indent=2)
  411. @mcp.tool
  412. async def trigger_crawl(
  413. platforms: Optional[List[str]] = None,
  414. save_to_local: bool = False,
  415. include_url: bool = False
  416. ) -> str:
  417. """
  418. 手动触发一次爬取任务(可选持久化)
  419. Args:
  420. platforms: 指定平台ID列表,如 ['zhihu', 'weibo', 'douyin']
  421. - 不指定时:使用 config.yaml 中配置的所有平台
  422. - 支持的平台来自 config/config.yaml 的 platforms 配置
  423. - 每个平台都有对应的name字段(如"知乎"、"微博"),方便AI识别
  424. - 注意:失败的平台会在返回结果的 failed_platforms 字段中列出
  425. save_to_local: 是否保存到本地 output 目录,默认 False
  426. include_url: 是否包含URL链接,默认False(节省token)
  427. Returns:
  428. JSON格式的任务状态信息,包含:
  429. - platforms: 成功爬取的平台列表
  430. - failed_platforms: 失败的平台列表(如有)
  431. - total_news: 爬取的新闻总数
  432. - data: 新闻数据
  433. Examples:
  434. - 临时爬取: trigger_crawl(platforms=['zhihu'])
  435. - 爬取并保存: trigger_crawl(platforms=['weibo'], save_to_local=True)
  436. - 使用默认平台: trigger_crawl() # 爬取config.yaml中配置的所有平台
  437. """
  438. tools = _get_tools()
  439. result = tools['system'].trigger_crawl(platforms=platforms, save_to_local=save_to_local, include_url=include_url)
  440. return json.dumps(result, ensure_ascii=False, indent=2)
  441. # ==================== 启动入口 ====================
  442. def run_server(
  443. project_root: Optional[str] = None,
  444. transport: str = 'stdio',
  445. host: str = '0.0.0.0',
  446. port: int = 3333
  447. ):
  448. """
  449. 启动 MCP 服务器
  450. Args:
  451. project_root: 项目根目录路径
  452. transport: 传输模式,'stdio' 或 'http'
  453. host: HTTP模式的监听地址,默认 0.0.0.0
  454. port: HTTP模式的监听端口,默认 3333
  455. """
  456. # 初始化工具实例
  457. _get_tools(project_root)
  458. # 打印启动信息
  459. print()
  460. print("=" * 60)
  461. print(" TrendRadar MCP Server - FastMCP 2.0")
  462. print("=" * 60)
  463. print(f" 传输模式: {transport.upper()}")
  464. if transport == 'stdio':
  465. print(" 协议: MCP over stdio (标准输入输出)")
  466. print(" 说明: 通过标准输入输出与 MCP 客户端通信")
  467. elif transport == 'http':
  468. print(f" 监听地址: http://{host}:{port}")
  469. print(f" HTTP端点: http://{host}:{port}/mcp")
  470. print(" 协议: MCP over HTTP (生产环境)")
  471. if project_root:
  472. print(f" 项目目录: {project_root}")
  473. else:
  474. print(" 项目目录: 当前目录")
  475. print()
  476. print(" 已注册的工具:")
  477. print(" === 基础数据查询(P0核心)===")
  478. print(" 1. get_latest_news - 获取最新新闻")
  479. print(" 2. get_news_by_date - 按日期查询新闻(支持自然语言)")
  480. print(" 3. get_trending_topics - 获取趋势话题")
  481. print()
  482. print(" === 智能检索工具 ===")
  483. print(" 4. search_news - 统一新闻搜索(关键词/模糊/实体)")
  484. print(" 5. search_related_news_history - 历史相关新闻检索")
  485. print()
  486. print(" === 高级数据分析 ===")
  487. print(" 6. analyze_topic_trend - 统一话题趋势分析(热度/生命周期/爆火/预测)")
  488. print(" 7. analyze_data_insights - 统一数据洞察分析(平台对比/活跃度/关键词共现)")
  489. print(" 8. analyze_sentiment - 情感倾向分析")
  490. print(" 9. find_similar_news - 相似新闻查找")
  491. print(" 10. generate_summary_report - 每日/每周摘要生成")
  492. print()
  493. print(" === 配置与系统管理 ===")
  494. print(" 11. get_current_config - 获取当前系统配置")
  495. print(" 12. get_system_status - 获取系统运行状态")
  496. print(" 13. trigger_crawl - 手动触发爬取任务")
  497. print("=" * 60)
  498. print()
  499. # 根据传输模式运行服务器
  500. if transport == 'stdio':
  501. mcp.run(transport='stdio')
  502. elif transport == 'http':
  503. # HTTP 模式(生产推荐)
  504. mcp.run(
  505. transport='http',
  506. host=host,
  507. port=port,
  508. path='/mcp' # HTTP 端点路径
  509. )
  510. else:
  511. raise ValueError(f"不支持的传输模式: {transport}")
  512. if __name__ == '__main__':
  513. import sys
  514. import argparse
  515. parser = argparse.ArgumentParser(
  516. description='TrendRadar MCP Server - 新闻热点聚合 MCP 工具服务器',
  517. formatter_class=argparse.RawDescriptionHelpFormatter,
  518. epilog="""
  519. 使用示例:
  520. # STDIO 模式(用于 Cherry Studio)
  521. uv run python mcp_server/server.py
  522. # HTTP 模式(适合远程访问)
  523. uv run python mcp_server/server.py --transport http --port 3333
  524. Cherry Studio 配置示例:
  525. 设置 > MCP Servers > 添加服务器
  526. - 名称: TrendRadar
  527. - 类型: STDIO
  528. - 命令: [UV的完整路径]
  529. - 参数: --directory [项目路径] run python mcp_server/server.py
  530. 详细配置教程请查看: README-Cherry-Studio.md
  531. """
  532. )
  533. parser.add_argument(
  534. '--transport',
  535. choices=['stdio', 'http'],
  536. default='stdio',
  537. help='传输模式:stdio (默认) 或 http (生产环境)'
  538. )
  539. parser.add_argument(
  540. '--host',
  541. default='0.0.0.0',
  542. help='HTTP模式的监听地址,默认 0.0.0.0'
  543. )
  544. parser.add_argument(
  545. '--port',
  546. type=int,
  547. default=3333,
  548. help='HTTP模式的监听端口,默认 3333'
  549. )
  550. parser.add_argument(
  551. '--project-root',
  552. help='项目根目录路径'
  553. )
  554. args = parser.parse_args()
  555. run_server(
  556. project_root=args.project_root,
  557. transport=args.transport,
  558. host=args.host,
  559. port=args.port
  560. )