# Directory Structure ``` ├── .github │ └── workflows │ └── release.yml ├── .gitignore ├── assets │ └── og-image.png ├── eslint.config.mjs ├── LICENSE ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── README.md ├── src │ ├── index.ts │ ├── process.js │ ├── sources.json │ └── typing.ts ├── tsconfig.json └── tsup.config.ts ``` # Files -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- ``` 1 | node_modules/ 2 | dist/ 3 | .vercel 4 | .output 5 | .vinxi 6 | .cache 7 | .data 8 | .wrangler 9 | .env 10 | .env.* 11 | dev-dist 12 | *.tsbuildinfo 13 | wrangler.toml 14 | imports.app.d.ts 15 | package-lock.json ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- ```markdown 1 | # newsnow-mcp-server 2 | 3 |  4 | 5 | Official MCP Server for [NewsNow](https://github.com/ourongxing/newsnow), 40+ sources available. 6 | 7 | ## Usage 8 | 9 | ```json 10 | { 11 | "mcpServers": { 12 | "newsnow": { 13 | "command": "npx", 14 | "args": [ 15 | "-y", 16 | "newsnow-mcp-server" 17 | ], 18 | "env": { 19 | "BASE_URL": "https://newsnow.busiyi.world" 20 | } 21 | } 22 | } 23 | } 24 | ``` 25 | 26 | ## License 27 | 28 | [MIT](./LICENSE) © ourongxing 29 | ``` -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- ```yaml 1 | onlyBuiltDependencies: 2 | - esbuild 3 | - simple-git-hooks 4 | - unrs-resolver 5 | ``` -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- ``` 1 | import { ourongxing } from "@ourongxing/eslint-config" 2 | 3 | export default ourongxing({ 4 | type: "lib", 5 | ignores: ["public/", ".vscode", "**/*.json"], 6 | }) 7 | ``` -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { defineConfig } from "tsup" 2 | 3 | export default defineConfig({ 4 | entry: ["src/index.ts"], 5 | format: ["esm"], 6 | target: "node18", 7 | clean: true, 8 | sourcemap: true, 9 | dts: false, 10 | splitting: false, 11 | minify: false, 12 | shims: true, 13 | treeshake: true, 14 | outDir: "dist", 15 | }) 16 | ``` -------------------------------------------------------------------------------- /src/process.js: -------------------------------------------------------------------------------- ```javascript 1 | import sources from "./sources.json" 2 | 3 | export const description = Object.entries(sources).filter(([_, source]) => { 4 | if (source.redirect) { 5 | return false 6 | } 7 | return true 8 | }).map(([id, source]) => { 9 | return source.title ? `${source.name}-${source.title} id is ${id}` : `${source.name} id is ${id}` 10 | }).join(";") 11 | ``` -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- ```yaml 1 | name: Release 2 | 3 | on: 4 | push: 5 | branch: main 6 | tags: 7 | - 'v*' 8 | 9 | jobs: 10 | release: 11 | permissions: 12 | contents: write 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | 19 | - uses: actions/setup-node@v4 20 | with: 21 | node-version: lts/* 22 | 23 | - run: npx changelogithub 24 | env: 25 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 26 | ``` -------------------------------------------------------------------------------- /src/typing.ts: -------------------------------------------------------------------------------- ```typescript 1 | export type SourceID = string 2 | 3 | export interface NewsItem { 4 | id: string | number // unique 5 | title: string 6 | url: string 7 | mobileUrl?: string 8 | pubDate?: number | string 9 | extra?: { 10 | hover?: string 11 | date?: number | string 12 | info?: false | string 13 | diff?: number 14 | icon?: false | string | { 15 | url: string 16 | scale: number 17 | } 18 | } 19 | } 20 | 21 | export interface SourceResponse { 22 | status: "success" | "cache" 23 | id: SourceID 24 | updatedTime: number | string 25 | items: NewsItem[] 26 | } 27 | ``` -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "target": "ES2018", 5 | "moduleDetection": "force", 6 | "useDefineForClassFields": true, 7 | "module": "ESNext", 8 | "moduleResolution": "bundler", 9 | "allowImportingTsExtensions": true, 10 | "strict": true, 11 | "allowJs": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "noUnusedLocals": true, 14 | "noUnusedParameters": true, 15 | "noEmit": true, 16 | "esModuleInterop": true, 17 | "isolatedModules": true, 18 | "skipLibCheck": true, 19 | "lib": ["ES2018"], 20 | "rootDir": ".", 21 | "baseUrl": ".", 22 | }, 23 | "include": ["src/**/*.ts", "src/**/*.js"] 24 | } 25 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "newsnow-mcp-server", 3 | "version": "0.0.10", 4 | "description": "NewsNow MCP Server", 5 | "keywords": [ 6 | "mcp", 7 | "newsnow", 8 | "mcp-server", 9 | "hot-news" 10 | ], 11 | "author": "Ou RongXing<[email protected]>", 12 | "homepage": "https://github.com/ourongxing/newsnow-mcp-server#readme", 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/ourongxing/newsnow-mcp-server.git" 16 | }, 17 | "license": "MIT", 18 | "packageManager": "[email protected]", 19 | "type": "module", 20 | "bin": { 21 | "newsnow-mcp-server": "dist/index.js" 22 | }, 23 | "main": "./dist/index.js", 24 | "files": [ 25 | "dist" 26 | ], 27 | "dependencies": { 28 | "bumpp": "^10.1.0", 29 | "dotenv": "^16.5.0", 30 | "fastmcp": "^1.23.0", 31 | "ofetch": "^1.4.1", 32 | "zod": "^3.24.3" 33 | }, 34 | "scripts": { 35 | "dev": "tsup --watch --onSuccess \"node dist/index.mjs\"", 36 | "build": "tsup", 37 | "publish": "pnpm publish --access public --no-git-checks", 38 | "lint": "eslint", 39 | "release": "bumpp", 40 | "lint:fix": "eslint --fix" 41 | }, 42 | "devDependencies": { 43 | "@ourongxing/eslint-config": "3.2.3-beta.6", 44 | "@types/node": "^22.15.2", 45 | "eslint": "^9.21.0", 46 | "simple-git-hooks": "^2.11.1", 47 | "tsup": "^8.4.0", 48 | "tsx": "^4.19.3", 49 | "typescript": "^5.8.2", 50 | "typescript-eslint": "^8.25.0", 51 | "unbuild": "^3.5.0" 52 | }, 53 | "simple-git-hooks": { 54 | "pre-commit": "npx lint-staged" 55 | }, 56 | "lint-staged": { 57 | "*": "eslint --fix" 58 | } 59 | } ``` -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- ```typescript 1 | #!/usr/bin/env node 2 | import process from "node:process" 3 | import { FastMCP } from "fastmcp" 4 | import { z } from "zod" 5 | import { $fetch } from "ofetch" 6 | import { config } from "dotenv" 7 | import packageJson from "../package.json" 8 | import { description } from "./process" 9 | import type { SourceResponse } from "./typing" 10 | 11 | config() 12 | 13 | if (!process.env.BASE_URL) { 14 | console.error("BASE_URL is not set") 15 | process.exit(1) 16 | } 17 | const baseUrl = process.env.BASE_URL 18 | 19 | const server = new FastMCP({ 20 | name: "NewsNow", 21 | version: packageJson.version as `${number}.${number}.${number}`, 22 | }) 23 | 24 | server.addTool({ 25 | name: "get_hottest_latest_news", 26 | description: `get hottest or latest news from source by {id}, return {count: 10} news.`, 27 | parameters: z.object({ 28 | id: z.string().describe(`source id. e.g. ${description}`), 29 | count: z.any().default(10).describe("count of news to return."), 30 | }), 31 | execute: async ({ id, count }) => { 32 | let n = Number(count) 33 | if (Number.isNaN(n) || n < 1) { 34 | n = 10 35 | } 36 | const res: SourceResponse = await $fetch(`${baseUrl}/api/s?id=${id}`, { 37 | headers: { 38 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36", 39 | }, 40 | }) 41 | return { 42 | content: res.items.slice(0, count).map(item => ({ 43 | text: `[${item.title}](${item.url})`, 44 | type: "text", 45 | })), 46 | } 47 | }, 48 | }) 49 | 50 | server.start({ 51 | transportType: "stdio", 52 | }) 53 | ``` -------------------------------------------------------------------------------- /src/sources.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "v2ex": { 3 | "redirect": "v2ex-share", 4 | "name": "V2EX", 5 | "column": "tech", 6 | "home": "https://v2ex.com/", 7 | "color": "slate", 8 | "interval": 600000, 9 | "title": "最新分享" 10 | }, 11 | "v2ex-share": { 12 | "name": "V2EX", 13 | "column": "tech", 14 | "home": "https://v2ex.com/", 15 | "color": "slate", 16 | "interval": 600000, 17 | "title": "最新分享" 18 | }, 19 | "zhihu": { 20 | "name": "知乎", 21 | "type": "hottest", 22 | "column": "china", 23 | "home": "https://www.zhihu.com", 24 | "color": "blue", 25 | "interval": 600000 26 | }, 27 | "weibo": { 28 | "title": "实时热搜", 29 | "name": "微博", 30 | "type": "hottest", 31 | "column": "china", 32 | "home": "https://weibo.com", 33 | "color": "red", 34 | "interval": 120000 35 | }, 36 | "zaobao": { 37 | "name": "联合早报", 38 | "type": "realtime", 39 | "desc": "来自第三方网站: 早晨报", 40 | "column": "world", 41 | "home": "https://www.zaobao.com", 42 | "color": "red", 43 | "interval": 1800000 44 | }, 45 | "coolapk": { 46 | "title": "今日最热", 47 | "name": "酷安", 48 | "type": "hottest", 49 | "column": "tech", 50 | "home": "https://coolapk.com", 51 | "color": "green", 52 | "interval": 600000 53 | }, 54 | "mktnews": { 55 | "redirect": "mktnews-flash", 56 | "name": "MKTNews", 57 | "column": "finance", 58 | "home": "https://mktnews.net", 59 | "color": "indigo", 60 | "interval": 120000, 61 | "title": "快讯" 62 | }, 63 | "mktnews-flash": { 64 | "name": "MKTNews", 65 | "column": "finance", 66 | "home": "https://mktnews.net", 67 | "color": "indigo", 68 | "interval": 120000, 69 | "title": "快讯" 70 | }, 71 | "wallstreetcn": { 72 | "redirect": "wallstreetcn-quick", 73 | "name": "华尔街见闻", 74 | "type": "realtime", 75 | "column": "finance", 76 | "home": "https://wallstreetcn.com/", 77 | "color": "blue", 78 | "interval": 300000, 79 | "title": "实时快讯" 80 | }, 81 | "wallstreetcn-quick": { 82 | "name": "华尔街见闻", 83 | "type": "realtime", 84 | "column": "finance", 85 | "home": "https://wallstreetcn.com/", 86 | "color": "blue", 87 | "interval": 300000, 88 | "title": "实时快讯" 89 | }, 90 | "wallstreetcn-news": { 91 | "name": "华尔街见闻", 92 | "column": "finance", 93 | "home": "https://wallstreetcn.com/", 94 | "color": "blue", 95 | "interval": 1800000, 96 | "title": "最新资讯" 97 | }, 98 | "wallstreetcn-hot": { 99 | "name": "华尔街见闻", 100 | "type": "hottest", 101 | "column": "finance", 102 | "home": "https://wallstreetcn.com/", 103 | "color": "blue", 104 | "interval": 1800000, 105 | "title": "最热文章" 106 | }, 107 | "36kr": { 108 | "redirect": "36kr-quick", 109 | "name": "36氪", 110 | "type": "realtime", 111 | "disable": "cf", 112 | "column": "tech", 113 | "home": "https://36kr.com", 114 | "color": "blue", 115 | "interval": 600000, 116 | "title": "快讯" 117 | }, 118 | "36kr-quick": { 119 | "name": "36氪", 120 | "type": "realtime", 121 | "disable": "cf", 122 | "column": "tech", 123 | "home": "https://36kr.com", 124 | "color": "blue", 125 | "interval": 600000, 126 | "title": "快讯" 127 | }, 128 | "douyin": { 129 | "name": "抖音", 130 | "type": "hottest", 131 | "column": "china", 132 | "home": "https://www.douyin.com", 133 | "color": "gray", 134 | "interval": 600000 135 | }, 136 | "hupu": { 137 | "title": "主干道热帖", 138 | "name": "虎扑", 139 | "type": "hottest", 140 | "column": "china", 141 | "home": "https://hupu.com", 142 | "color": "red", 143 | "interval": 600000 144 | }, 145 | "tieba": { 146 | "title": "热议", 147 | "name": "百度贴吧", 148 | "type": "hottest", 149 | "column": "china", 150 | "home": "https://tieba.baidu.com", 151 | "color": "blue", 152 | "interval": 600000 153 | }, 154 | "toutiao": { 155 | "name": "今日头条", 156 | "type": "hottest", 157 | "column": "china", 158 | "home": "https://www.toutiao.com", 159 | "color": "red", 160 | "interval": 600000 161 | }, 162 | "ithome": { 163 | "name": "IT之家", 164 | "type": "realtime", 165 | "column": "tech", 166 | "home": "https://www.ithome.com", 167 | "color": "red", 168 | "interval": 600000 169 | }, 170 | "thepaper": { 171 | "title": "热榜", 172 | "name": "澎湃新闻", 173 | "type": "hottest", 174 | "column": "china", 175 | "home": "https://www.thepaper.cn", 176 | "color": "gray", 177 | "interval": 1800000 178 | }, 179 | "sputniknewscn": { 180 | "name": "卫星通讯社", 181 | "column": "world", 182 | "home": "https://sputniknews.cn", 183 | "color": "orange", 184 | "interval": 600000 185 | }, 186 | "cankaoxiaoxi": { 187 | "name": "参考消息", 188 | "column": "world", 189 | "home": "https://china.cankaoxiaoxi.com", 190 | "color": "red", 191 | "interval": 1800000 192 | }, 193 | "pcbeta": { 194 | "redirect": "pcbeta-windows11", 195 | "name": "远景论坛", 196 | "type": "realtime", 197 | "column": "tech", 198 | "home": "https://bbs.pcbeta.com", 199 | "color": "blue", 200 | "interval": 300000, 201 | "title": "Windows 11" 202 | }, 203 | "pcbeta-windows11": { 204 | "name": "远景论坛", 205 | "type": "realtime", 206 | "column": "tech", 207 | "home": "https://bbs.pcbeta.com", 208 | "color": "blue", 209 | "interval": 300000, 210 | "title": "Windows 11" 211 | }, 212 | "cls": { 213 | "redirect": "cls-telegraph", 214 | "name": "财联社", 215 | "type": "realtime", 216 | "column": "finance", 217 | "home": "https://www.cls.cn", 218 | "color": "red", 219 | "interval": 300000, 220 | "title": "电报" 221 | }, 222 | "cls-telegraph": { 223 | "name": "财联社", 224 | "type": "realtime", 225 | "column": "finance", 226 | "home": "https://www.cls.cn", 227 | "color": "red", 228 | "interval": 300000, 229 | "title": "电报" 230 | }, 231 | "cls-depth": { 232 | "name": "财联社", 233 | "column": "finance", 234 | "home": "https://www.cls.cn", 235 | "color": "red", 236 | "interval": 600000, 237 | "title": "深度" 238 | }, 239 | "cls-hot": { 240 | "name": "财联社", 241 | "type": "hottest", 242 | "column": "finance", 243 | "home": "https://www.cls.cn", 244 | "color": "red", 245 | "interval": 600000, 246 | "title": "热门" 247 | }, 248 | "xueqiu": { 249 | "redirect": "xueqiu-hotstock", 250 | "name": "雪球", 251 | "type": "hottest", 252 | "column": "finance", 253 | "home": "https://xueqiu.com", 254 | "color": "blue", 255 | "interval": 120000, 256 | "title": "热门股票" 257 | }, 258 | "xueqiu-hotstock": { 259 | "name": "雪球", 260 | "type": "hottest", 261 | "column": "finance", 262 | "home": "https://xueqiu.com", 263 | "color": "blue", 264 | "interval": 120000, 265 | "title": "热门股票" 266 | }, 267 | "gelonghui": { 268 | "title": "事件", 269 | "name": "格隆汇", 270 | "type": "realtime", 271 | "column": "finance", 272 | "home": "https://www.gelonghui.com", 273 | "color": "blue", 274 | "interval": 120000 275 | }, 276 | "fastbull": { 277 | "redirect": "fastbull-express", 278 | "name": "法布财经", 279 | "type": "realtime", 280 | "column": "finance", 281 | "home": "https://www.fastbull.cn", 282 | "color": "emerald", 283 | "interval": 120000, 284 | "title": "快讯" 285 | }, 286 | "fastbull-express": { 287 | "name": "法布财经", 288 | "type": "realtime", 289 | "column": "finance", 290 | "home": "https://www.fastbull.cn", 291 | "color": "emerald", 292 | "interval": 120000, 293 | "title": "快讯" 294 | }, 295 | "fastbull-news": { 296 | "name": "法布财经", 297 | "column": "finance", 298 | "home": "https://www.fastbull.cn", 299 | "color": "emerald", 300 | "interval": 1800000, 301 | "title": "头条" 302 | }, 303 | "solidot": { 304 | "name": "Solidot", 305 | "column": "tech", 306 | "home": "https://solidot.org", 307 | "color": "teal", 308 | "interval": 3600000 309 | }, 310 | "hackernews": { 311 | "name": "Hacker News", 312 | "type": "hottest", 313 | "column": "tech", 314 | "home": "https://news.ycombinator.com/", 315 | "color": "orange", 316 | "interval": 600000 317 | }, 318 | "producthunt": { 319 | "name": "Product Hunt", 320 | "type": "hottest", 321 | "column": "tech", 322 | "home": "https://www.producthunt.com/", 323 | "color": "red", 324 | "interval": 600000 325 | }, 326 | "github": { 327 | "redirect": "github-trending-today", 328 | "name": "Github", 329 | "type": "hottest", 330 | "column": "tech", 331 | "home": "https://github.com/", 332 | "color": "gray", 333 | "interval": 600000, 334 | "title": "Today" 335 | }, 336 | "github-trending-today": { 337 | "name": "Github", 338 | "type": "hottest", 339 | "column": "tech", 340 | "home": "https://github.com/", 341 | "color": "gray", 342 | "interval": 600000, 343 | "title": "Today" 344 | }, 345 | "bilibili": { 346 | "redirect": "bilibili-hot-search", 347 | "name": "哔哩哔哩", 348 | "type": "hottest", 349 | "column": "china", 350 | "home": "https://www.bilibili.com", 351 | "color": "blue", 352 | "interval": 600000, 353 | "title": "热搜" 354 | }, 355 | "bilibili-hot-search": { 356 | "name": "哔哩哔哩", 357 | "type": "hottest", 358 | "column": "china", 359 | "home": "https://www.bilibili.com", 360 | "color": "blue", 361 | "interval": 600000, 362 | "title": "热搜" 363 | }, 364 | "bilibili-hot-video": { 365 | "name": "哔哩哔哩", 366 | "type": "hottest", 367 | "disable": "cf", 368 | "column": "china", 369 | "home": "https://www.bilibili.com", 370 | "color": "blue", 371 | "interval": 600000, 372 | "title": "热门视频" 373 | }, 374 | "bilibili-ranking": { 375 | "name": "哔哩哔哩", 376 | "type": "hottest", 377 | "disable": "cf", 378 | "column": "china", 379 | "home": "https://www.bilibili.com", 380 | "color": "blue", 381 | "interval": 1800000, 382 | "title": "排行榜" 383 | }, 384 | "kuaishou": { 385 | "name": "快手", 386 | "type": "hottest", 387 | "disable": "cf", 388 | "column": "china", 389 | "home": "https://www.kuaishou.com", 390 | "color": "orange", 391 | "interval": 600000 392 | }, 393 | "kaopu": { 394 | "name": "靠谱新闻", 395 | "desc": "不一定靠谱,多看多思考", 396 | "column": "world", 397 | "home": "https://kaopu.news/", 398 | "color": "gray", 399 | "interval": 1800000 400 | }, 401 | "jin10": { 402 | "name": "金十数据", 403 | "type": "realtime", 404 | "column": "finance", 405 | "home": "https://www.jin10.com", 406 | "color": "blue", 407 | "interval": 600000 408 | }, 409 | "baidu": { 410 | "name": "百度热搜", 411 | "type": "hottest", 412 | "column": "china", 413 | "home": "https://www.baidu.com", 414 | "color": "blue", 415 | "interval": 600000 416 | }, 417 | "nowcoder": { 418 | "name": "牛客", 419 | "type": "hottest", 420 | "column": "china", 421 | "home": "https://www.nowcoder.com", 422 | "color": "blue", 423 | "interval": 600000 424 | }, 425 | "sspai": { 426 | "name": "少数派", 427 | "type": "hottest", 428 | "column": "tech", 429 | "home": "https://sspai.com", 430 | "color": "red", 431 | "interval": 600000 432 | }, 433 | "juejin": { 434 | "name": "稀土掘金", 435 | "type": "hottest", 436 | "column": "tech", 437 | "home": "https://juejin.cn", 438 | "color": "blue", 439 | "interval": 600000 440 | }, 441 | "ifeng": { 442 | "title": "热点资讯", 443 | "name": "凤凰网", 444 | "type": "hottest", 445 | "column": "china", 446 | "home": "https://www.ifeng.com", 447 | "color": "red", 448 | "interval": 600000 449 | }, 450 | "chongbuluo": { 451 | "redirect": "chongbuluo-latest", 452 | "name": "虫部落", 453 | "column": "china", 454 | "home": "https://www.chongbuluo.com/forum.php?mod=guide&view=newthread", 455 | "color": "green", 456 | "interval": 1800000, 457 | "title": "最新" 458 | }, 459 | "chongbuluo-latest": { 460 | "name": "虫部落", 461 | "column": "china", 462 | "home": "https://www.chongbuluo.com/forum.php?mod=guide&view=newthread", 463 | "color": "green", 464 | "interval": 1800000, 465 | "title": "最新" 466 | }, 467 | "chongbuluo-hot": { 468 | "name": "虫部落", 469 | "type": "hottest", 470 | "column": "china", 471 | "home": "https://www.chongbuluo.com/forum.php?mod=guide&view=hot", 472 | "color": "green", 473 | "interval": 1800000, 474 | "title": "最热" 475 | } 476 | } ```