Server data from the Official MCP Registry
Deduplicated, classified AI industry news: search, browse, and filter by vertical and event type.
About
Deduplicated, classified AI industry news: search, browse, and filter by vertical and event type.
Remote endpoints: streamable-http: https://nexus.carapace.bot/mcp
Security Report
Nexus is a well-architected TypeScript monorepo for an AI news feed with proper authentication, careful input validation, and appropriate permission scoping. The MCP server is read-only and stateless. Minor code quality observations exist around error handling breadth and env var validation, but no security vulnerabilities were identified. The server's permissions (network_http for public APIs, env_vars for credentials, database access) align with its purpose as a news aggregation and classification tool. Supply chain analysis found 4 known vulnerabilities in dependencies (2 critical, 0 high severity).
5 files analyzed · 8 issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
Permissions Required
This plugin requests these system permissions. Most are normal for its category.
How to Install & Connect
Available as Local & Remote
This plugin can run on your machine or connect to a hosted endpoint. during install.
Documentation
View on GitHubFrom the project's GitHub README.
Nexus
A Jev-powered AI news feed.
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
# 1. Start infrastructure (PostgreSQL)
docker compose up -d
# 2. Install dependencies
pnpm install
# 3. Build all packages
pnpm build
# 4. Start API and client dev servers (separate terminals)
pnpm dev:api
pnpm dev:client
# 5. Run the agent (source polling + Jev enrichment) separately
pnpm --filter @nexus/agent start
The client opens at http://localhost:5173 and the API serves at http://localhost:3001.
Monorepo Layout
| Package | Path | Description |
|---|---|---|
@nexus/shared | packages/shared | TypeScript interfaces, enums, constants, validation — imported by all packages |
@nexus/agent | packages/agent | Source adapters + dedup + Jev enrichment |
@nexus/api | packages/api | Fastify REST server for the feed and chat search |
@nexus/client | packages/client | React 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
// packages/agent/src/sources/types.ts
interface 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.
// packages/agent/src/sources/my-source.ts
import 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
| Adapter | Source | Priority | Poll Interval | Auth |
|---|---|---|---|---|
ArxivAdapter | arXiv RSS (cs.AI, cs.CL, cs.LG) | P0 | 30 min | None |
HackerNewsAdapter | HN Algolia API | P0 | 15 min | None |
GitHubTrendingAdapter | GitHub Search API | P0 | 60 min | Optional GITHUB_TOKEN |
TwitterAdapter | X/Twitter API v2 | P1 | 15 min | X_BEARER_TOKEN required |
RssAdapter | Company blogs, TechCrunch AI, The Verge AI, Simon Willison | P1 | 2h (default) | None |
Register Your Adapter
- Add your adapter to the adapter list in
packages/agent/src/start.ts:
import { MySourceAdapter } from "./sources/my-source.js";
const adapters: SourceAdapter[] = [
new HackerNewsAdapter(),
new ArxivAdapter(),
new GitHubTrendingAdapter(),
new MySourceAdapter(), // add here
];
-
Write a test in
packages/agent/src/sources/__tests__/following existing patterns. -
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.6vertical(Choice) — one of the 21Verticalvalues, ornoneevent_type(Choice) —launch | funding | release | acquisition | paper | update | shutdown | othersignificance(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
| Tool | What it does |
|---|---|
search_news | Full-text search (phrases, OR, -exclude), filterable by vertical / event_type / source / since |
get_latest_news | Newest items first, same filters, cursor-paginated via next_cursor |
get_feed_stats | Total 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
- Fork the repo and create a branch:
feat/my-feature,fix/some-bug, orchore/cleanup - Write conventional commit messages:
feat: add devto adapter,fix: handle empty RSS feed - Run checks before opening a PR:
pnpm test # run all tests
pnpm lint # eslint
pnpm typecheck # tsc --noEmit
- Keep PRs focused — one adapter or feature per PR.
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
TYPESAFE_API_KEY | Yes | — | TypeSafe API key for Jev (System One) enrichment and chat classification |
POSTGRES_HOST | No | localhost | PostgreSQL host |
POSTGRES_PORT | No | 5432 | PostgreSQL port |
POSTGRES_DB | No | nexus | PostgreSQL database name |
POSTGRES_USER | No | nexus | PostgreSQL user |
POSTGRES_PASSWORD | Yes | — | PostgreSQL password |
X_BEARER_TOKEN | No | — | X/Twitter API bearer token (enables Twitter adapter) |
GITHUB_TOKEN | No | — | GitHub PAT (raises rate limits for GitHub adapter) |
API_KEY | No | — | API key for write/admin endpoints |
API_PORT | No | 3001 | API server port |
API_HOST | No | 0.0.0.0 | API server bind address |
CLIENT_PORT | No | 5173 | Client 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
Reviews
No reviews yet
Be the first to review this server!
More Developer Tools MCP Servers
Git
Freeby Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
Fetch
Freeby Modelcontextprotocol · Developer Tools
Web content fetching and conversion for efficient LLM usage
Worldmonitor
Freeby Koala73 · Developer Tools
Live markets, conflicts, country risk, chokepoints, energy, and China decision signals. 89 tools.
Paperclip
Freeby Paperclipai · Developer Tools
Trending hip-hop artist momentum scores across four cultural dimensions.
Toleno
Freeby Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
mcp-creator-python
Freeby mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
