فهرست منبع

fix: 支持 date_range 参数的 JSON 字符串输入

sansan 4 ماه پیش
والد
کامیت
97e050459c

+ 1 - 1
README-EN.md

@@ -14,7 +14,7 @@
 [![GitHub Forks](https://img.shields.io/github/forks/sansan0/TrendRadar?style=flat-square&logo=github&color=blue)](https://github.com/sansan0/TrendRadar/network/members)
 [![License](https://img.shields.io/badge/license-GPL--3.0-blue.svg?style=flat-square)](LICENSE)
 [![Version](https://img.shields.io/badge/version-v4.0.3-blue.svg)](https://github.com/sansan0/TrendRadar)
-[![MCP](https://img.shields.io/badge/MCP-v1.1.0-green.svg)](https://github.com/sansan0/TrendRadar)
+[![MCP](https://img.shields.io/badge/MCP-v1.1.1-green.svg)](https://github.com/sansan0/TrendRadar)
 
 [![WeWork](https://img.shields.io/badge/WeWork-Notification-00D4AA?style=flat-square)](https://work.weixin.qq.com/)
 [![WeChat](https://img.shields.io/badge/WeChat-Notification-00D4AA?style=flat-square)](https://weixin.qq.com/)

+ 1 - 1
README.md

@@ -14,7 +14,7 @@
 [![GitHub Forks](https://img.shields.io/github/forks/sansan0/TrendRadar?style=flat-square&logo=github&color=blue)](https://github.com/sansan0/TrendRadar/network/members)
 [![License](https://img.shields.io/badge/license-GPL--3.0-blue.svg?style=flat-square)](LICENSE)
 [![Version](https://img.shields.io/badge/version-v4.0.3-blue.svg)](https://github.com/sansan0/TrendRadar)
-[![MCP](https://img.shields.io/badge/MCP-v1.1.0-green.svg)](https://github.com/sansan0/TrendRadar)
+[![MCP](https://img.shields.io/badge/MCP-v1.1.1-green.svg)](https://github.com/sansan0/TrendRadar)
 
 [![企业微信通知](https://img.shields.io/badge/企业微信-通知-00D4AA?style=flat-square)](https://work.weixin.qq.com/)
 [![个人微信通知](https://img.shields.io/badge/个人微信-通知-00D4AA?style=flat-square)](https://weixin.qq.com/)

+ 1 - 1
mcp_server/__init__.py

@@ -4,4 +4,4 @@ TrendRadar MCP Server
 提供基于MCP协议的新闻聚合数据查询和系统管理接口。
 """
 
-__version__ = "1.1.0"
+__version__ = "1.1.1"

+ 6 - 6
mcp_server/server.py

@@ -6,7 +6,7 @@ TrendRadar MCP Server - FastMCP 2.0 实现
 """
 
 import json
-from typing import List, Optional, Dict
+from typing import List, Optional, Dict, Union
 
 from fastmcp import FastMCP
 
@@ -230,7 +230,7 @@ async def get_news_by_date(
 async def analyze_topic_trend(
     topic: str,
     analysis_type: str = "trend",
-    date_range: Optional[Dict[str, str]] = None,
+    date_range: Optional[Union[Dict[str, str], str]] = None,
     granularity: str = "day",
     threshold: float = 3.0,
     time_window: int = 24,
@@ -294,7 +294,7 @@ async def analyze_topic_trend(
 async def analyze_data_insights(
     insight_type: str = "platform_compare",
     topic: Optional[str] = None,
-    date_range: Optional[Dict[str, str]] = None,
+    date_range: Optional[Union[Dict[str, str], str]] = None,
     min_frequency: int = 3,
     top_n: int = 20
 ) -> str:
@@ -337,7 +337,7 @@ async def analyze_data_insights(
 async def analyze_sentiment(
     topic: Optional[str] = None,
     platforms: Optional[List[str]] = None,
-    date_range: Optional[Dict[str, str]] = None,
+    date_range: Optional[Union[Dict[str, str], str]] = None,
     limit: int = 50,
     sort_by_weight: bool = True,
     include_url: bool = False
@@ -436,7 +436,7 @@ async def find_similar_news(
 @mcp.tool
 async def generate_summary_report(
     report_type: str = "daily",
-    date_range: Optional[Dict[str, str]] = None
+    date_range: Optional[Union[Dict[str, str], str]] = None
 ) -> str:
     """
     每日/每周摘要生成器 - 自动生成热点摘要报告
@@ -465,7 +465,7 @@ async def generate_summary_report(
 async def search_news(
     query: str,
     search_mode: str = "keyword",
-    date_range: Optional[Dict[str, str]] = None,
+    date_range: Optional[Union[Dict[str, str], str]] = None,
     platforms: Optional[List[str]] = None,
     limit: int = 50,
     sort_by: str = "relevance",

+ 9 - 9
mcp_server/tools/analytics.py

@@ -7,7 +7,7 @@
 import re
 from collections import Counter, defaultdict
 from datetime import datetime, timedelta
-from typing import Dict, List, Optional
+from typing import Dict, List, Optional, Union
 from difflib import SequenceMatcher
 
 from ..services.data_service import DataService
@@ -89,7 +89,7 @@ class AnalyticsTools:
         self,
         insight_type: str = "platform_compare",
         topic: Optional[str] = None,
-        date_range: Optional[Dict[str, str]] = None,
+        date_range: Optional[Union[Dict[str, str], str]] = None,
         min_frequency: int = 3,
         top_n: int = 20
     ) -> Dict:
@@ -156,7 +156,7 @@ class AnalyticsTools:
         self,
         topic: str,
         analysis_type: str = "trend",
-        date_range: Optional[Dict[str, str]] = None,
+        date_range: Optional[Union[Dict[str, str], str]] = None,
         granularity: str = "day",
         threshold: float = 3.0,
         time_window: int = 24,
@@ -243,7 +243,7 @@ class AnalyticsTools:
     def get_topic_trend_analysis(
         self,
         topic: str,
-        date_range: Optional[Dict[str, str]] = None,
+        date_range: Optional[Union[Dict[str, str], str]] = None,
         granularity: str = "day"
     ) -> Dict:
         """
@@ -401,7 +401,7 @@ class AnalyticsTools:
     def compare_platforms(
         self,
         topic: Optional[str] = None,
-        date_range: Optional[Dict[str, str]] = None
+        date_range: Optional[Union[Dict[str, str], str]] = None
     ) -> Dict:
         """
         平台对比分析 - 对比不同平台对同一话题的关注度
@@ -631,7 +631,7 @@ class AnalyticsTools:
         self,
         topic: Optional[str] = None,
         platforms: Optional[List[str]] = None,
-        date_range: Optional[Dict[str, str]] = None,
+        date_range: Optional[Union[Dict[str, str], str]] = None,
         limit: int = 50,
         sort_by_weight: bool = True,
         include_url: bool = False
@@ -1157,7 +1157,7 @@ class AnalyticsTools:
     def generate_summary_report(
         self,
         report_type: str = "daily",
-        date_range: Optional[Dict[str, str]] = None
+        date_range: Optional[Union[Dict[str, str], str]] = None
     ) -> Dict:
         """
         每日/每周摘要生成器 - 自动生成热点摘要报告
@@ -1336,7 +1336,7 @@ class AnalyticsTools:
 
     def get_platform_activity_stats(
         self,
-        date_range: Optional[Dict[str, str]] = None
+        date_range: Optional[Union[Dict[str, str], str]] = None
     ) -> Dict:
         """
         平台活跃度统计 - 统计各平台的发布频率和活跃时间段
@@ -1464,7 +1464,7 @@ class AnalyticsTools:
     def analyze_topic_lifecycle(
         self,
         topic: str,
-        date_range: Optional[Dict[str, str]] = None
+        date_range: Optional[Union[Dict[str, str], str]] = None
     ) -> Dict:
         """
         话题生命周期分析 - 追踪话题从出现到消失的完整周期

+ 2 - 2
mcp_server/tools/data_query.py

@@ -4,7 +4,7 @@
 实现P0核心的数据查询工具。
 """
 
-from typing import Dict, List, Optional
+from typing import Dict, List, Optional, Union
 
 from ..services.data_service import DataService
 from ..utils.validators import (
@@ -90,7 +90,7 @@ class DataQueryTools:
     def search_news_by_keyword(
         self,
         keyword: str,
-        date_range: Optional[Dict] = None,
+        date_range: Optional[Union[Dict, str]] = None,
         platforms: Optional[List[str]] = None,
         limit: Optional[int] = None
     ) -> Dict:

+ 2 - 2
mcp_server/tools/search_tools.py

@@ -8,7 +8,7 @@ import re
 from collections import Counter
 from datetime import datetime, timedelta
 from difflib import SequenceMatcher
-from typing import Dict, List, Optional, Tuple
+from typing import Dict, List, Optional, Tuple, Union
 
 from ..services.data_service import DataService
 from ..utils.validators import validate_keyword, validate_limit
@@ -39,7 +39,7 @@ class SearchTools:
         self,
         query: str,
         search_mode: str = "keyword",
-        date_range: Optional[Dict[str, str]] = None,
+        date_range: Optional[Union[Dict[str, str], str]] = None,
         platforms: Optional[List[str]] = None,
         limit: int = 50,
         sort_by: str = "relevance",

+ 18 - 4
mcp_server/utils/validators.py

@@ -5,8 +5,9 @@
 """
 
 from datetime import datetime
-from typing import List, Optional
+from typing import List, Optional, Union
 import os
+import json
 import yaml
 
 from .errors import InvalidParameterError
@@ -142,12 +143,12 @@ def validate_date(date_str: str) -> datetime:
         )
 
 
-def validate_date_range(date_range: Optional[dict]) -> Optional[tuple]:
+def validate_date_range(date_range: Optional[Union[dict, str]]) -> Optional[tuple]:
     """
     验证日期范围
 
     Args:
-        date_range: 日期范围字典 {"start": "YYYY-MM-DD", "end": "YYYY-MM-DD"}
+        date_range: 日期范围字典或JSON字符串 {"start": "YYYY-MM-DD", "end": "YYYY-MM-DD"}
 
     Returns:
         (start_date, end_date) 元组,或 None
@@ -158,8 +159,21 @@ def validate_date_range(date_range: Optional[dict]) -> Optional[tuple]:
     if date_range is None:
         return None
 
+    # 支持字符串形式的JSON输入(某些MCP客户端会将JSON对象序列化为字符串)
+    if isinstance(date_range, str):
+        try:
+            date_range = json.loads(date_range)
+        except json.JSONDecodeError as e:
+            raise InvalidParameterError(
+                f"date_range JSON 解析失败: {e}",
+                suggestion='请使用正确的JSON格式: {"start": "YYYY-MM-DD", "end": "YYYY-MM-DD"}'
+            )
+
     if not isinstance(date_range, dict):
-        raise InvalidParameterError("date_range 必须是字典类型")
+        raise InvalidParameterError(
+            "date_range 必须是字典类型或有效的JSON字符串",
+            suggestion='例如: {"start": "2025-10-01", "end": "2025-10-11"}'
+        )
 
     start_str = date_range.get("start")
     end_str = date_range.get("end")