1. 项目概述:一个让AI“读新闻”的智能工具
最近在折腾AI应用开发,特别是想让大语言模型(LLM)能处理实时信息,比如最新的新闻、股价或者体育比分。大家可能都遇到过,问ChatGPT“今天有什么大新闻”,它大概率会告诉你它的知识截止到某个日期,无法获取最新信息。这就是所谓的“知识截止”问题。为了解决这个痛点,我深度研究并实践了pranciskus/newsmcp这个项目。简单来说,Newsmcp是一个专门为LLM设计的新闻获取服务器,它通过一个标准化的协议(MCP),让像Claude Desktop、Cursor这类AI助手能够实时、安全地查询网络新闻。
想象一下,你在写一份行业分析报告,可以直接在AI对话窗口里问:“帮我查一下过去24小时半导体行业的最新动态”,AI就能立刻返回结构化的新闻摘要和链接。这背后就是Newsmcp在起作用。它不是一个面向最终用户的新闻App,而是一个“中间件”或“后端服务”,为AI智能体提供新鲜的数据燃料。这个项目巧妙地解决了LLM的“信息时效性”短板,让静态的知识库动了起来,对于开发需要实时信息感知能力的AI应用来说,是一个非常有价值的工具。
2. 核心架构与MCP协议解析
2.1 什么是MCP(模型上下文协议)?
要理解Newsmcp,必须先搞懂MCP。MCP全称是Model Context Protocol,你可以把它理解为AI世界里的“USB协议”。在MCP出现之前,每个AI应用(如Claude Desktop)如果想接入外部工具(如日历、数据库、新闻API),都需要开发者为其编写特定的插件或集成代码,过程繁琐且不通用。
MCP的目标就是标准化AI与外部工具之间的通信。它定义了一套清晰的规则:工具(称为“服务器”)能提供哪些“资源”(比如新闻列表、搜索接口)和“工具”(比如“搜索新闻”这个函数),而AI客户端(如Claude)则知道如何发现并调用这些接口。这样一来,工具开发者只需按照MCP标准实现一次,就能被所有支持MCP的AI客户端使用。Newsmcp就是一个严格遵循MCP协议实现的“新闻工具服务器”。
2.2 Newsmcp的核心工作流程
Newsmcp的架构非常清晰,它扮演了一个“智能新闻聚合与转发器”的角色。其核心工作流程可以分解为以下几个步骤:
- 启动与注册:当你运行Newsmcp服务器时,它会向连接的AI客户端(例如配置了MCP的Claude Desktop)“宣告”自己:“嗨,我这里有‘获取新闻头条’和‘搜索新闻’这两个工具可用。”
- 接收查询:你在AI对话界面中输入“看看科技新闻”,AI客户端会理解你的意图,并将其转换为一个结构化的请求,通过MCP协议发送给Newsmcp服务器。
- 聚合与处理:Newsmcp收到请求后,并不会只有一个新闻源。它的强大之处在于,它内部整合了多个新闻源的适配器。它会根据请求的参数(如分类、关键词),并行或按优先级向这些新闻源发起查询。
- 清洗与格式化:从不同新闻源返回的数据格式五花八门。Newsmcp的核心任务之一就是进行数据清洗和标准化。它会提取标题、摘要、原文链接、发布时间、来源等关键字段,并格式化为MCP协议要求的、LLM易于理解的统一结构(通常是JSON)。
- 返回结果:处理好的结构化新闻数据被送回AI客户端。客户端将其作为“上下文”提供给LLM模型。最终,LLM利用这些新鲜、准确的上下文信息,生成对你问题的流畅、自然的回答。
这个流程的关键在于解耦:AI模型不需要知道如何抓取和解析新闻网站,它只负责理解和生成语言;Newsmcp则专精于信息的获取与标准化。两者通过MCP这个“通用接口”高效协作。
2.3 技术栈与依赖生态
Newsmcp项目本身是用TypeScript编写的,运行在Node.js环境下。选择这个技术栈非常合理:
- TypeScript:提供了强大的类型安全,这对于定义复杂的MCP协议消息格式、新闻数据接口至关重要,能极大减少开发时的低级错误。
- Node.js:非阻塞I/O模型非常适合处理高并发的网络请求(同时查询多个新闻源),并且npm生态丰富,有大量用于HTTP请求、HTML解析、缓存等的成熟库。
它的核心依赖包括:
@modelcontextprotocol/sdk:这是Anthropic官方提供的MCP协议SDK,是项目的基础,负责处理所有与MCP相关的通信、序列化、生命周期管理。axios/node-fetch:用于向各大新闻网站的RSS源或API发起HTTP请求。cheerio或rss-parser:这是新闻内容抓取的核心。很多新闻源提供RSS输出,rss-parser可以轻松解析。对于不提供标准RSS的网站,则可能需要用cheerio这样的类jQuery库来解析HTML,提取所需内容。这部分是开发中最需要定制和维护的地方。lru-cache:一个简单的LRU(最近最少使用)缓存库。这是提升性能和应对限流的关键。新闻数据虽然要求时效性,但也没必要对同一查询在秒级内反复抓取源站。合理的缓存(例如设置5-10分钟的过期时间)可以大幅降低对新闻源服务器的压力,并加快响应速度。
注意:在实际部署中,需要严格遵守目标新闻网站的
robots.txt协议,并设置合理的请求间隔(如使用setTimeout或p-limit库控制并发),避免因请求过快被对方服务器封禁IP。这是做任何网络爬虫类应用必须遵守的道德和法律底线。
3. 部署与配置实战指南
3.1 本地开发环境搭建
首先,你需要一个能运行Node.js的环境。建议使用Node.js 18或更高版本,以及npm或yarn包管理器。
# 1. 克隆项目代码 git clone https://github.com/pranciskus/newsmcp.git cd newsmcp # 2. 安装依赖 npm install # 或 yarn install # 3. 构建项目(如果是TypeScript项目) npm run build # 通常项目package.json里会有build脚本,将TS编译为JS # 4. 运行服务器 npm start # 或直接运行编译后的文件,如 node dist/index.js运行成功后,终端会输出服务器正在监听的地址(通常是stdio或某个网络端口),这表明你的Newsmcp服务器已经就绪,正在等待MCP客户端的连接。
3.2 配置AI客户端(以Claude Desktop为例)
服务器跑起来只是第一步,更重要的是让它被AI客户端识别和使用。这里以目前对MCP支持最友好的Claude Desktop为例。
找到配置文件:Claude Desktop的MCP服务器配置位于一个JSON文件中。
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
- macOS:
编辑配置文件:如果文件不存在,就创建它。你需要添加一个
mcpServers字段。以下是配置Newsmcp的示例:
{ "mcpServers": { "newsmcp": { "command": "node", "args": [ "/ABSOLUTE/PATH/TO/YOUR/newsmcp/dist/index.js" ], "env": { "NEWS_API_KEY_IF_ANY": "your_api_key_here" } } } }command: 启动服务器的命令,这里是node。args: 命令的参数,即你编译好的Newsmcp主文件绝对路径。使用绝对路径是最稳妥的方式。env: 可选。如果需要配置新闻源的API密钥(比如某些源需要认证),可以在这里以环境变量的形式传入。
重启客户端:保存配置文件后,完全退出并重启Claude Desktop。重启后,Claude会自动读取配置并启动你定义的MCP服务器。
验证连接:在Claude的对话窗口中,你可以尝试输入“/”查看可用工具。如果配置成功,你应该能看到
newsmcp相关的工具列表,例如get_top_headlines或search_news。直接使用自然语言如“用newsmcp获取今天的头条新闻”即可。
3.3 关键配置项与环境变量详解
Newsmcp的灵活性很大程度上通过配置和环境变量实现。你可以在项目根目录创建一个.env文件,或者在启动命令中传入环境变量。
| 配置项 | 示例值 | 说明 |
|---|---|---|
NEWS_SOURCES | bbc,reuters,techcrunch | 指定启用的新闻源。项目源码中通常有一个src/sources/目录,里面是各个新闻源的适配器。这里填写适配器的名称。 |
REQUEST_TIMEOUT | 10000(毫秒) | 向单个新闻源请求的超时时间。设置太短可能导致失败,太长则影响整体响应。建议在5000-15000之间。 |
CACHE_TTL | 300000(毫秒,即5分钟) | 缓存存活时间。在此时长内,相同的查询会直接返回缓存结果。对新闻来说,5-10分钟是平衡时效性与性能的合理值。 |
USER_AGENT | MyNewsAggregator/1.0 | 发送HTTP请求时的User-Agent头。务必设置一个可识别的、非爬虫的UA,这是对新闻源网站的基本尊重,也能减少被屏蔽的风险。 |
LOG_LEVEL | info/debug | 日志级别。调试时可以设为debug,查看详细的请求和响应信息;生产环境设为info或warn即可。 |
实操心得:配置的优先级通常,配置的加载顺序是:环境变量 > 配置文件 > 代码默认值。我个人的习惯是在.env文件中管理敏感信息(如API KEY)和个性化配置(如我偏好的新闻源),而将通用配置写在代码或单独的config.json中。这样既安全,也便于在不同环境(开发、生产)间切换。
4. 核心功能实现与自定义扩展
4.1 内置工具(Tools)剖析
Newsmcp通过MCP向客户端暴露的主要是“工具”。查看其源码,通常会看到类似以下的工具定义:
// 示例性代码,展示工具定义结构 server.setRequestHandler(tools.listTools, async () => { return { tools: [ { name: "get_top_headlines", description: "获取指定类别或国家的头条新闻", inputSchema: { type: "object", properties: { category: { type: "string", enum: ["business", "technology", "sports"] }, country: { type: "string", enum: ["us", "gb", "cn"] }, count: { type: "number", minimum: 1, maximum: 50 } } } }, { name: "search_news", description: "根据关键词搜索新闻", inputSchema: { type: "object", properties: { q: { type: "string" }, from: { type: "string", format: "date" }, to: { type: "string", format: "date" } }, required: ["q"] } } ] }; });get_top_headlines:这个工具封装了获取头条新闻的逻辑。AI客户端调用它时,可以传递category(分类)、country(国家/地区)等参数。服务器收到后,会根据参数筛选并聚合对应新闻源的数据。search_news:这是更通用的搜索工具。当用户问“特斯拉最近有什么新闻”时,AI客户端会调用此工具,并将“特斯拉”作为q参数传入。
关键点:inputSchema使用了JSON Schema来定义。这非常重要,因为它告诉了AI客户端这个工具需要什么格式的参数。AI模型(如Claude)可以理解这个Schema,从而在需要时自动生成符合要求的参数来调用工具。这是MCP实现“智能”调用的基础。
4.2 如何添加自定义新闻源
项目内置的新闻源可能不符合你的需求,比如你想加入某个特定行业网站或区域媒体。添加自定义新闻源是扩展Newsmcp能力的核心操作。
创建源文件:在项目的
src/sources/目录下(具体结构请参考项目源码),新建一个文件,例如my_custom_source.ts。实现源接口:你需要实现一个符合项目定义的“新闻源接口”。这个接口通常要求你提供:
name: 源的唯一标识。fetchTopHeadlines(params): 如何获取该源的头条新闻。search(query, params): 如何在该源内搜索新闻。- 这两个函数需要返回统一格式的新闻条目数组。
编写抓取逻辑:这是最具技术挑战的部分。你需要分析目标网站的页面结构或API。
- 首选RSS/Atom:如果网站提供
/rss或/feed地址,这是最规范、最稳定的方式。使用rss-parser库解析即可。 - 次选公开API:有些网站提供开发者API,需要申请API Key。这种方式最可靠,但可能有调用限制。
- 最后考虑HTML解析:如果以上都没有,则只能通过HTTP请求获取HTML页面,然后用
cheerio解析DOM,提取新闻标题、链接、摘要等。这种方式极其脆弱,网站前端一改版,你的代码就可能失效,需要持续维护。
- 首选RSS/Atom:如果网站提供
// 一个极简的示例:使用RSS的自定义源 import Parser from 'rss-parser'; import { NewsItem, NewsSource } from '../types'; // 假设的项目类型定义 const MyCustomSource: NewsSource = { name: 'my_tech_blog', async fetchTopHeadlines({ category, count }) { const parser = new Parser(); // 假设这个博客的RSS地址 const feed = await parser.parseURL('https://example-tech-blog.com/feed'); return feed.items.slice(0, count).map(item => ({ title: item.title!, link: item.link!, summary: item.contentSnippet || item.content?.substring(0, 200), publishedAt: new Date(item.pubDate!), source: this.name })); }, async search(query, { from, to }) { // 对于不支持搜索的RSS,可以在这里返回空,或尝试其他方式 return []; } }; export default MyCustomSource;注册新源:在你的源文件被创建后,需要在项目的源注册中心(可能是一个
index.ts文件)中导入并添加到源列表中。更新配置:最后,别忘了在环境变量
NEWS_SOURCES中加入你新源的名字my_tech_blog,并重启服务器。
4.3 数据处理与缓存策略优化
从各个源抓取到的原始数据需要被清洗和标准化。一个健壮的NewsItem接口应该包含:
interface NewsItem { id?: string; // 可选唯一ID,可用于去重 title: string; // 新闻标题 link: string; // 原文链接 summary: string; // 摘要 content?: string; // 全文(可选,抓取全文可能负担重且涉及版权) publishedAt: Date; // 发布时间 source: string; // 来源标识 category?: string; // 分类 author?: string; // 作者 imageUrl?: string; // 头图链接 }缓存策略是性能关键。Newsmcp通常使用内存缓存(如LRU Cache),但这在服务器重启后会丢失。对于生产环境,可以考虑:
- Redis缓存:将缓存持久化到Redis,允许多个服务器实例共享缓存,且重启不丢失。
- 分级缓存:对“头条新闻”这类通用查询使用较长TTL(如10分钟),对“搜索”这类个性化查询使用较短TTL(如1分钟)或不用缓存。
- 请求合并:在极短时间内收到多个相同请求时,可以合并为一个实际请求去抓取,然后同时返回给所有请求方。这可以用一个简单的“进行中请求”映射表来实现。
5. 生产环境部署与问题排查
5.1 从本地到服务器部署
本地开发测试没问题后,你可能希望将其部署到云服务器上,作为一个7x24小时运行的服务。
- 选择服务器:一台最基础的Linux VPS(如1核1G)就足够。选择Node.js版本管理工具(如
nvm)来安装Node.js。 - 进程守护:不能让服务运行在终端前台。必须使用进程管理工具。
- PM2(推荐):这是Node.js生态最流行的进程管理器。安装后,一个简单的
pm2 start dist/index.js --name newsmcp就能让服务在后台运行,并具备日志管理、崩溃自动重启、监控等功能。
npm install -g pm2 pm2 start dist/index.js --name "newsmcp" pm2 save pm2 startup # 设置开机自启- Systemd:对于更追求系统集成的用户,可以创建一个systemd服务单元文件,由系统直接管理。
- PM2(推荐):这是Node.js生态最流行的进程管理器。安装后,一个简单的
- 反向代理与安全:不建议直接让Node.js服务监听公网端口。应该使用Nginx或Apache作为反向代理。
- Nginx配置示例:
server { listen 80; server_name your-domain.com; # 或服务器IP location / { proxy_pass http://localhost:3000; # 假设Newsmcp运行在3000端口 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }- 配置HTTPS:使用Let‘s Encrypt的Certbot为你的域名申请免费SSL证书,在Nginx中启用HTTPS,这是生产环境的基本安全要求。
- 日志管理:使用PM2时,日志默认在
~/.pm2/logs/下。务必定期检查日志,或配置日志轮转(logrotate),避免日志文件撑满磁盘。
5.2 常见问题与排查技巧
在实际运行中,你肯定会遇到各种问题。以下是我踩过的一些坑和解决方法:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| Claude Desktop无法发现工具 | 1. 配置文件路径错误。 2. Newsmcp服务器启动失败。 3. MCP版本不兼容。 | 1.检查Claude日志:Claude Desktop通常有日志文件,查看其中是否有MCP服务器连接错误信息。 2.手动测试服务器:在终端运行 node your/path/index.js,看是否有错误输出。确保Node版本和依赖安装正确。3.简化测试:先尝试运行MCP SDK的官方示例,确保客户端配置方式正确。 |
| 获取新闻超时或返回空 | 1. 新闻源网站不可用或屏蔽了请求。 2. 网络问题(如服务器在国外)。 3. 网站结构改变,解析器失效。 | 1.直接访问源URL:用curl或浏览器测试目标新闻源的RSS地址或网页是否能正常访问。2.检查User-Agent和频率:确认配置了合理的UA,并在代码中增加了请求延迟(如 await sleep(1000))。3.开启Debug日志:将日志级别调到 debug,查看具体是哪个源的哪次请求失败了,以及失败的响应内容是什么。 |
| 返回的数据格式混乱 | 1. 网页编码问题。 2. HTML结构复杂,CSS选择器写得不准确。 | 1.指定编码:在HTTP请求或HTML解析器中明确指定编码(如utf-8)。2.更新解析逻辑:网站改版是常态。需要定期检查并更新自定义源的抓取代码。可以写一个简单的测试脚本,定期运行,验证核心字段是否能正确提取。 |
| 服务器内存占用越来越高 | 内存泄漏,常见于缓存未正确清理或异步操作未释放资源。 | 1.检查缓存策略:LRU缓存是否设置了最大条目数(max)?确保过期的条目能被自动淘汰。2.使用Node.js内存分析工具:如 node --inspect配合Chrome DevTools,或使用heapdump模块生成堆快照,分析内存中累积的对象是什么。 |
| 被新闻源网站封禁IP | 请求频率过高。 | 1.立即降低频率:大幅增加请求间隔,例如从1秒改为5秒甚至10秒。 2.使用代理IP池(高级):对于大规模抓取,这是必要手段,但对于个人使用的Newsmcp,严格遵守 robots.txt并保持礼貌的访问间隔是根本。 |
一个关键的调试技巧:你可以在Newsmcp的代码中,临时添加一个简单的HTTP端点(例如使用express),直接通过浏览器访问来测试某个新闻源的抓取是否正常工作,这比通过MCP和AI客户端层层调试要直接得多。
6. 进阶应用场景与未来展望
Newsmcp作为一个信息入口,其价值在于与AI工作流的深度结合。除了简单的问答,还可以考虑以下场景:
- 自动化日报生成:结合AI的总结和写作能力,设定一个定时任务,每天早晨自动抓取指定领域的头条新闻,生成一份简洁的邮件或Markdown日报,发送给你或你的团队。
- 舆情监控与预警:为你的品牌或关注的关键词设置搜索监控。Newsmcp定期搜索相关新闻,一旦发现高敏感度或高热度的内容,立即通过AI分析情感并触发告警(如发送Slack消息)。
- 研究助手:在学术或市场研究时,你可以让AI助手基于Newsmcp获取的最新行业动态,来辅助你完善报告框架、提供数据支撑或挑战你的既有观点。
- 多模态扩展:目前的Newsmcp主要处理文本。未来是否可以扩展?例如,识别新闻中的主要公司/人物,并自动从其他MCP服务器(如数据库服务器)中调取这些实体的背景资料,形成更立体的信息简报。
这个项目的潜力在于,它将动态信息世界接入了静态的LLM。随着MCP协议的逐步普及,会有越来越多像Newsmcp这样的“专业化工具服务器”出现,分别负责数据库、日历、邮件、项目管理工具等。届时,AI助手才能真正成为我们数字世界的全能操作中枢。而理解并会使用、甚至定制这样的MCP服务器,将成为AI应用开发者的一项重要技能。从动手部署和修改Newsmcp开始,正是踏入这个未来工作流的第一步。