Nexus AI News

io.github.99darwinv0.1.0更新于 Oct 7, 2026

Deduplicated, classified AI industry news: search, browse, and filter by vertical and event type.

已验证Streamable HTTP可网页运行Web Search & ScrapingData & Analytics

概览

AI 生成的概览

以只读方式通过 MCP 访问去重并分类的 AI 行业新闻源,支持搜索、浏览最新条目和查看统计。

功能
通过 Streamable HTTP 提供一个公开、无状态、只读的新闻源。search_news 工具支持短语、OR 和 -exclude 的全文搜索,并可按垂直领域、事件类型、来源和时间筛选;get_latest_news 按最新优先返回条目,支持相同筛选条件和基于 next_cursor 的游标分页;get_feed_stats 返回总数以及按垂直领域和事件类型的计数。条目经过去重并分类为 21 个垂直领域和八种事件类型,摘要直接取自源文本而非生成的总结。
适用场景
适合需要获取最新 AI 行业新闻、融资与发布事件或论文,并按主题、来源或日期筛选和搜索的场景。适用于研究、监测和简报类工作流,希望得到真实新闻条目而非模型生成的摘要。
运行要求
通过 Streamable HTTP 连接的远程 MCP 端点;使用托管服务无需本地运行时、软件包、账号或 API 密钥,但需要能访问该端点的网络。若自行部署项目,则需要 Node.js 与 pnpm、PostgreSQL,以及 TYPESAFE_API_KEY、POSTGRES_PASSWORD 等凭据。
安装前请注意
托管 MCP 服务被描述为公开、只读、无会话且不调用模型,因此不会写入、发送或删除数据。自行部署则不同:需要 TYPESAFE_API_KEY、POSTGRES_PASSWORD 等密钥,可选 X_BEARER_TOKEN、GITHUB_TOKEN 和 API_KEY;富化按 Jev 调用计费,约每天 50-100 条条目,外加每次聊天查询一次调用。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Nexus AI News,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。

其他 MCP 客户端

把它添加到你客户端的 mcpServers 配置中。

{
  "mcpServers": {
    "nexus": {
      "type": "http",
      "url": "https://nexus.carapace.bot/mcp"
    }
  }
}

README

Nexus

A Jev-powered AI news feed.

[TypeScript] [PostgreSQL] [License] [Docker]

Nexus ingests AI news from multiple sources, dedupes it, classifies each item with a single Jev (TypeSafe System One) call, and serves the result as a reverse-chronological feed with filters and a guarded, extractive chat search. No graph database, no generative LLM in the request path.

Sources (arxiv, hackernews, github, twitter, rss)   │   ▼dedup.ts (URL → title → arXiv-id → Jaccard + entity fingerprints)   │   ▼PostgreSQL raw_items   │   ▼Jev enrichment (TypeSafe System One, model jev-latest, 1 call/item)   relevant? (Noul) · vertical (Choice) · event_type (Choice) · significance (Score)   │   ▼PostgreSQL feed_items (reverse-chron, indexed)   │   ▼Fastify API — GET /api/feed · GET /api/feed/meta · POST /api/chat   │   ▼React feed client — ActivityFeed, FilterBar, HotCards, guarded ChatBox

Quick Start

bash
# 1. Start infrastructure (PostgreSQL)docker compose up -d
# 2. Install dependenciespnpm install
# 3. Build all packagespnpm build
# 4. Start API and client dev servers (separate terminals)pnpm dev:apipnpm dev:client
# 5. Run the agent (source polling + Jev enrichment) separatelypnpm --filter @nexus/agent start

The client opens at http://localhost:5173 and the API serves at http://localhost:3001.

Monorepo Layout

PackagePathDescription
@nexus/sharedpackages/sharedTypeScript interfaces, enums, constants, validation — imported by all packages
@nexus/agentpackages/agentSource adapters + dedup + Jev enrichment
@nexus/apipackages/apiFastify REST server for the feed and chat search
@nexus/clientpackages/clientReact feed UI (Vite)

Adding a Source Adapter

The primary contribution path is adding new data sources. Every adapter feeds raw items into the dedup + Jev enrichment pipeline, which classifies and inserts them into the feed automatically.

The RawItem Interface

typescript
// packages/agent/src/sources/types.tsinterface RawItem {  source: string;        // adapter name, e.g. "arxiv"  source_url: string;    // canonical URL for deduplication  title: string;         // headline / paper title  content: string;       // body text (Jev classifies, excerpt is sliced from here)  published_at: string;  // ISO 8601 timestamp  raw_metadata: Record<string, unknown>; // source-specific fields}

Write Your Adapter

Extend BaseAdapter and implement fetchItems(). You get rate limiting, exponential retry with backoff, and URL-based deduplication for free.

typescript
// packages/agent/src/sources/my-source.tsimport type { RawItem } from "./types.js";import { BaseAdapter } from "./base-adapter.js";
export class MySourceAdapter extends BaseAdapter {  name = "my-source";  priority = "P1" as const;
  constructor() {    super({      pollIntervalMs: 30 * 60 * 1000, // how often to poll      rateLimitMs: 2000,               // min delay between requests    });  }
  protected async fetchItems(): Promise<RawItem[]> {    const response = await fetch("https://api.example.com/items");    if (!response.ok) throw new Error(`Fetch failed: ${response.status}`);
    const data = await response.json();    return this.dedupeByUrl(      data.map((item: any) => ({        source: this.name,        source_url: item.url,        title: item.title,        content: item.body,        published_at: new Date(item.date).toISOString(),        raw_metadata: { id: item.id },      }))    );  }}

Existing Adapters

AdapterSourcePriorityPoll IntervalAuth
ArxivAdapterarXiv RSS (cs.AI, cs.CL, cs.LG)P030 minNone
HackerNewsAdapterHN Algolia APIP015 minNone
GitHubTrendingAdapterGitHub Search APIP060 minOptional GITHUB_TOKEN
TwitterAdapterX/Twitter API v2P115 minX_BEARER_TOKEN required
RssAdapterCompany blogs, TechCrunch AI, The Verge AI, Simon WillisonP12h (default)None

Register Your Adapter

  1. Add your adapter to the adapter list in packages/agent/src/start.ts:
typescript
import { MySourceAdapter } from "./sources/my-source.js";
const adapters: SourceAdapter[] = [  new HackerNewsAdapter(),  new ArxivAdapter(),  new GitHubTrendingAdapter(),  new MySourceAdapter(),          // add here];
  1. Write a test in packages/agent/src/sources/__tests__/ following existing patterns.

  2. Run tests: pnpm --filter @nexus/agent test

Jev Enrichment

Every deduped RawItem gets exactly one call to TypeSafe's System One API (POST https://api.typesafe.ai/v1/systemone, model jev-latest, Bearer TYPESAFE_API_KEY). Jev is a decision model — it answers typed questions (Noul, Choice, Score) against structured JSON, it does not generate text. One call answers all four questions for an item:

  • is_ai_relevant (Noul) — dropped if confidence < 0.6
  • vertical (Choice) — one of the 21 Vertical values, or none
  • event_type (Choice) — launch | funding | release | acquisition | paper | update | shutdown | other
  • significance (Score) — a 5-point rubric mapped to 0.2–1.0

The excerpt shown in the feed is the first 280 characters of the source content — never an LLM summary, so it can't hallucinate.

Chat Search

POST /api/chat is a guarded, extractive search box, not a chatbot. It classifies the query with one Jev call (on-topic check, vertical/event-type/timeframe extraction), then returns real rows from feed_items via Postgres trigram search. There is no generative model anywhere in the chat path — there's nothing for a prompt injection to talk to.

MCP Server

The feed is exposed to agents as a public, read-only Model Context Protocol server over Streamable HTTP:

https://nexus.carapace.bot/mcp
ToolWhat it does
search_newsFull-text search (phrases, OR, -exclude), filterable by vertical / event_type / source / since
get_latest_newsNewest items first, same filters, cursor-paginated via next_cursor
get_feed_statsTotal count plus counts per vertical and event_type

Add it to Claude Code with claude mcp add --transport http nexus https://nexus.carapace.bot/mcp. Stateless (no sessions), extractive only — same validation as GET /api/feed, no model calls. Registry manifest: server.json.

Data Model

feed_items

id (uuid) · title · url (unique) · source · published_at · excerpt · vertical · event_type · significance (0.0–1.0) · created_at

Verticals

21 spatial-cluster categories, defined in packages/shared/src/types.ts (e.g. foundation_models, agents, safety_alignment, consumer_products, ...).

Event Types

launch | funding | release | acquisition | paper | update | shutdown | other

Contributing

  1. Fork the repo and create a branch: feat/my-feature, fix/some-bug, or chore/cleanup
  2. Write conventional commit messages: feat: add devto adapter, fix: handle empty RSS feed
  3. Run checks before opening a PR:
bash
pnpm test          # run all testspnpm lint          # eslintpnpm typecheck     # tsc --noEmit
  1. Keep PRs focused — one adapter or feature per PR.

Environment Variables

VariableRequiredDefaultDescription
TYPESAFE_API_KEYYes—TypeSafe API key for Jev (System One) enrichment and chat classification
POSTGRES_HOSTNolocalhostPostgreSQL host
POSTGRES_PORTNo5432PostgreSQL port
POSTGRES_DBNonexusPostgreSQL database name
POSTGRES_USERNonexusPostgreSQL user
POSTGRES_PASSWORDYes—PostgreSQL password
X_BEARER_TOKENNo—X/Twitter API bearer token (enables Twitter adapter)
GITHUB_TOKENNo—GitHub PAT (raises rate limits for GitHub adapter)
API_KEYNo—API key for write/admin endpoints
API_PORTNo3001API server port
API_HOSTNo0.0.0.0API server bind address
CLIENT_PORTNo5173Client dev server port

Tech Stack

  • Database — PostgreSQL 16 (raw_items, feed_items, pg_trgm search)
  • API — Fastify
  • Client — Vite + React
  • Search — Fuse.js (client-side, loaded items), pg_trgm (server, chat + feed search)
  • Agent — TypeSafe Jev (System One) for enrichment and chat classification
  • Deploy — Railway (Postgres + API) + Vercel (client)

Cost

Enrichment is roughly 1 Jev call per new deduped item, at ~50–100 items/day across all sources, plus 1 Jev call per chat query. There is no Neo4j, no Redis, and no generative LLM anywhere in the pipeline — that's the entire compute bill.

License

MIT

来源:README.md,提交 0a59cfc

工具

0
工具元数据尚未被收录。

版本历史

1
  1. v0.1.0最新Oct 7, 2026