China News MCP
# China News MCP
一个面向 AI 客户端的中国与国际新闻、多平台热点查询及聚合 MCP 服务。它统一查询中英文新闻源、微博热搜、今日头条热榜、百度热搜和可选的 X Trends,进行规范化、去重、事件聚类,并在安全边界内提取新闻正文。
## 功能
- 中国新闻网 RSS、人民网/新华网公开页面和 GDELT 中文索引
- NPR World、France 24 English、Sky News World 和 GDELT 国际检索
- 国际新闻独立搜索与聚合,自动标记 `zh`、`en` 或 `other` 语言
- 微博热搜、今日头条热榜、百度热搜,保留平台排名与原始热度
- 使用 X 官方 API 按 WOEID 查询全球或地区趋势
- 识别多个平台同时出现的相似热门话题
- 通过 `CUSTOM_RSS_FEEDS` 增加公开或已授权 RSS
- 中文关键词、分类、来源、时间范围与排序筛选
- URL/近似标题去重,基于中文分词和标题相似度的事件聚类
- 同时输出适合模型阅读的文本和机器可用的 `structuredContent`
- 遵守 robots.txt 的正文提取,包含 SSRF、重定向、超时、响应大小和正文长度限制
- stdio 与带 Bearer Key 的 Streamable HTTP
- 上游部分失败、超时和陈旧缓存降级
本服务不会调用大模型生成结论。聚合结果只组织来源数据,AI 应引用返回的原文链接并自行判断事实。热榜表示平台关注度,不代表事件真实、重要或可信。
## 环境要求
- Node.js 22+
- npm 10+
```bash
npm install
npm run build
npm test
```
生产部署、Docker、Nginx、systemd、监控和回滚方案参见 [DEPLOYMENT.md](./DEPLOYMENT.md)。
## 使用 stdio
```bash
npm run start:stdio
```
通用 MCP 客户端配置示例:
```json
{
"mcpServers": {
"china-news": {
"command": "node",
"args": ["D:/test_wk/ai-news-mcp/dist/stdio.js"],
"env": {
"ENABLE_GDELT": "true",
"ENABLE_HTML_SOURCES": "true"
}
}
}
}
```
stdio 模式的日志只写入 stderr,不会污染 MCP 标准输出。
## 使用 HTTP
复制 `.env.example` 中需要的变量,至少设置一个足够长的密钥:
```powershell
$env:MCP_API_KEY = "replace-with-a-long-random-secret"
npm run start:http
```
- MCP Endpoint:`http://127.0.0.1:3000/mcp`
- 健康检查:`http://127.0.0.1:3000/healthz`
- 请求头:`Authorization: Bearer replace-with-a-long-random-secret`
HTTP 模式没有配置 `MCP_API_KEY` 时会拒绝启动。反向代理或域名部署还需在 `MCP_ALLOWED_HOSTS` 中加入外部 Host;浏览器发起请求时需在 `MCP_ALLOWED_ORIGINS` 中加入完整 Origin。服务默认按客户端地址限制为每分钟 60 次请求。
Docker 示例:
```bash
docker build -t china-news-mcp .
docker run --rm -p 3000:3000 \
-e MCP_API_KEY=replace-with-a-long-random-secret \
-e MCP_ALLOWED_HOSTS=localhost,127.0.0.1 \
china-news-mcp
```
## MCP 工具
### `search_china_news`
查询并去重新闻。
```json
{
"query": "人工智能",
"category": "technology",
"source_ids": [],
"from": "2026-08-28T00:00:00+08:00",
"to": "2026-08-29T23:59:59+08:00",
"sort": "relevance",
"limit": 10
}
```
`query` 可以为空,此时返回最新新闻;默认查询最近 24 小时。单次时间范围不超过 90 天,`limit` 最大为 50。
分类值:`all`、`politics`、`finance`、`society`、`world`、`technology`、`culture`、`sports`、`health`、`education`、`legal`。
### `aggregate_china_news`
使用与搜索相同的参数,将结果组合为事件簇。每个事件包含代表标题、关键词、来源数、报道数以及全部引用链接。
### `search_international_news`
查询国际新闻,默认返回英文结果:
```json
{
"query": "artificial intelligence",
"category": "world",
"language": "en",
"source_ids": [],
"limit": 10
}
```
`language` 支持 `en`、`zh` 和 `all`。默认国际来源为 NPR World、France 24 English、Sky News World;有查询词时也会调用 GDELT。单个来源失败只会出现在 `warnings` 中。
### `aggregate_international_news`
使用与国际新闻搜索相同的参数,按标题、关键词和发布时间生成可追溯的国际事件簇。
### `get_news_article`
```json
{
"url": "https://example.com/news/article.html",
"max_chars": 12000
}
```
URL 必须属于已注册来源,或者来自本进程近期的搜索结果。工具不会运行页面 JavaScript、下载媒体、绕过登录或付费墙。正文最多返回 30,000 字符,并通过 `status` 与 `truncated` 表明提取结果。
### `get_trending_topics`
查询微博、今日头条、百度和已配置的 X 实时趋势,并给出跨平台相似话题簇:
```json
{
"query": "人工智能",
"source_ids": ["weibo", "toutiao", "baidu", "x"],
"limit": 30
}
```
`query` 和 `source_ids` 均可省略。返回结果包含:
- 各平台原始 `rank`、`hotScore`、标签与话题链接
- 基于榜单位置计算的 `normalizedScore`,用于跨平台排序
- `clusters` 中的跨平台来源数、最佳排名、关键词和全部平台引用
不同平台的原始热度计算口径不同,不能直接横向比较;跨平台排序只使用榜单位置归一化。平台接口发生变化或临时限制访问时,其余热榜仍会返回,并在 `warnings` 中说明失败来源。
X 只通过官方 API 接入,需要在 X Developer Console 创建应用并配置:
```dotenv
ENABLE_X_TRENDS=true
X_BEARER_TOKEN=your-official-x-api-bearer-token
X_TRENDS_WOEID=1
```
`X_TRENDS_WOEID=1` 表示全球趋势。X API 为计费服务且有平台限流;Token 未配置时请求 `source_ids: ["x"]` 会返回明确告警,不会尝试抓取登录页面。
### `list_news_sources`
列出来源、支持分类及最近一次查询健康状态。
## 配置
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `ENABLE_GDELT` | `true` | 启用 GDELT;不可用时其余来源仍正常返回 |
| `ENABLE_HTML_SOURCES` | `true` | 启用人民网和新华网页面发现 |
| `ENABLE_INTERNATIONAL_NEWS` | `true` | 启用 NPR、France 24 和 Sky News 国际 RSS |
| `ENABLE_WEIBO_TRENDING` | `true` | 启用微博热搜 |
| `ENABLE_TOUTIAO_TRENDING` | `true` | 启用今日头条热榜 |
| `ENABLE_BAIDU_TRENDING` | `true` | 启用百度热搜 |
| `ENABLE_X_TRENDS` | 有 Token 时启用 | 启用 X 官方趋势 API |
| `X_BEARER_TOKEN` | 空 | X 官方 API Bearer Token |
| `X_TRENDS_WOEID` | `1` | X 趋势地区;`1` 为全球 |
| `CUSTOM_RSS_FEEDS` | 空 | 自定义 RSS JSON 数组 |
| `PROVIDER_TIMEOUT_MS` | `8000` | 单来源超时 |
| `TOTAL_TIMEOUT_MS` | `15000` | 单次聚合总预算 |
| `ARTICLE_TIMEOUT_MS` | `10000` | 正文请求超时 |
| `MAX_RESPONSE_BYTES` | `2097152` | 单个上游响应上限 |
| `DEFAULT_ARTICLE_CHARS` | `12000` | 正文默认返回字符数 |
| `SEARCH_CACHE_TTL_MS` | `300000` | 搜索内存缓存时长 |
| `STALE_CACHE_TTL_MS` | `1800000` | 上游失败时可用陈旧缓存时长 |
| `TRENDING_CACHE_TTL_MS` | `120000` | 热榜缓存时长 |
| `TRENDING_STALE_TTL_MS` | `600000` | 热榜失败时可用陈旧缓存时长 |
| `NEWS_USER_AGENT` | `ChinaNewsMCP/0.3 ...` | 访问来源和 robots.txt 时使用的 User-Agent |
自定义 RSS 示例:
```json
[
{
"id": "authorized-feed",
"name": "授权新闻源",
"url": "https://example.com/rss.xml",
"homepage": "https://example.com/",
"category": "all"
}
]
```
每个来源必须使用唯一 `id`。自定义来源应是公开允许订阅或你已取得授权的 Feed。
## 设计与降级行为
新闻来源实现统一的 `NewsProvider` 接口,热榜来源实现 `TrendingProvider` 接口。查询会并发执行,任何单一来源的 429、超时、格式变化或网络错误只会写入 `providerStatus` 和 `warnings`。存在允许时限内的缓存时会返回陈旧数据并明确标记。
来源页面变化可能导致 HTML 适配器暂时没有结果;RSS 和其他来源不会受其影响。GDELT 在部分网络环境中可能较慢,因此受到独立超时限制。
全文抓取在每次跳转前检查协议、端口和 DNS 地址,拒绝环回、私网、链路本地和保留地址,并限制重定向次数。该检查是防御措施,不应替代部署环境的出站网络策略;生产部署建议同时使用防火墙或代理限制出站访问。
## 开发
```bash
npm run typecheck
npm test
npm run build
npm run dev
npm run dev:http
```
稳定测试使用固定数据和进程内 MCP 传输,不依赖实时新闻网站。上线前应在目标网络内对实际来源执行人工冒烟测试。
新增来源时实现 `NewsProvider.search()`,将来源结果转换为 `RawNewsItem`,然后在 `src/providers/index.ts` 注册。网络访问必须继续使用 `safeFetch`/`fetchText`,不得绕过统一安全与大小限制。
## 内容与版权
新闻标题、摘要和正文的版权归原始来源或权利人所有。本项目只提供技术聚合能力,不授予转载、复制或商业使用权。使用者应遵守来源网站条款、robots.txt、适用法律以及内容许可;如无全文使用授权,可只调用搜索/聚合工具并使用原文链接。
## License
项目代码采用 MIT License;新闻内容不属于本项目许可证范围。
TDQS
Scored across 7 tools
The domestic/international and search/aggregate splits are mostly clear, but search_china_news and aggregate_china_news both begin with a news query and could be confused by an agent wanting a simple result list. get_trending_topics, list_news_sources, and get_news_article are all clearly distinct.
All tools use lowercase snake_case with a clear verb prefix and a descriptive object or domain suffix. The repeated search_ and aggregate_ pattern for China and international news makes the naming highly predictable.
Seven tools is well-scoped for news discovery, aggregation, trending topics, source listing, and article extraction. Each tool adds a distinct capability without redundancy.
The tool surface covers the main news workflow: discover trending topics, search national and international sources, aggregate into event clusters, and extract article body text. Missing source configuration or update tools are a minor gap, but the server appears intentionally read-only.