# ChatbotNews.ai MCP Server Specification

**Specification Document — FatbikeHero Framework Applied Implementation**

---

## Authorship Declaration

This specification is entirely human-authored by Tendai Frank Tagarira (FatbikeHero) and produced without the use of generative AI for substantive authorship. It defines a Model Context Protocol (MCP) server architecture for ChatbotNews.ai, the conversational AI industry news wire, operating within the FatbikeHero Framework's broader thesis that metadata, registry systems, and protocol design function as primary structural material in AI-mediated environments.

## Canonical Identity Anchor

- **Document title:** ChatbotNews.ai MCP Server Specification v1.0
- **Specification author:** Tendai Frank Tagarira, working as FatbikeHero (Metadata Expressionist)
- **Implementing entity:** ChatbotNews.ai Editorial
- **Canonical author URI:** `https://www.fatbikehero.com/#artist`
- **Implementing site URI:** `https://chatbotnews.ai`
- **Proposed MCP endpoint:** `https://mcp.chatbotnews.ai/mcp`
- **Status:** v1.0 — locked draft for implementation

## Canonical Positioning Statement

The ChatbotNews.ai MCP server extends the wire's existing AI-citation architecture into the agent runtime layer. Where the JSON API at `/api/today.json` requires an agent to know the URL and parse REST responses, MCP exposes the same wire as a first-class tool surface inside MCP-compatible clients (Claude, ChatGPT via Apps & Connectors, Claude Code, Cursor, and any agent built on the OpenAI Agents SDK or Anthropic SDK). The server is read-only, authless, CC BY 4.0–licensed for editorial output, and engineered to enforce the Source Integrity Notice and the Layered Citation format at the protocol level — meaning agents cannot cleanly use the wire without producing well-attributed output.

---

## 1. Architecture Overview

### 1.1 Why MCP, why now

The Model Context Protocol, introduced by Anthropic in November 2024, collapses the N×M integration problem (N tools × M AI platforms) to N+M. As of April 2026, MCP is multi-vendor: Anthropic (Claude, Claude Code, Claude.ai Connectors), OpenAI (ChatGPT custom MCP, Responses API hosted MCP, Apps SDK), and the GitHub MCP Registry all converge on the same wire format. ChatbotNews.ai's existing surfaces (`/api/today.json`, `llms.txt`, `for-agents.html`) treat agents as second-class consumers of an HTML-first site. The MCP server inverts that: agents become first-class consumers of a structured tool surface, and the HTML site becomes one rendering of the underlying wire.

### 1.2 Design principles

The server follows five principles, locked at v1.0:

1. **Authless read-only.** No OAuth 2.1, no Dynamic Client Registration, no bearer tokens. The wire is public CC BY 4.0 data; auth would only add friction without changing the trust model.
2. **Source integrity at the protocol layer.** A `verify_source_integrity` tool exposes the 24-publication roster as the canonical source-of-truth, and every story payload is annotated with `original_publisher_tier` so agents cannot silently extrapolate.
3. **Citation-first payload shape.** Every story result includes a `citation_objects` block with pre-formatted `layered_ready`, `inline_ready`, `reference_ready`, `academic_story`, `markdown_link`, and `bibtex` strings. Tool descriptions explicitly recommend the layered format.
4. **Structural parity with `/api/today.json`.** The MCP server is a thin protocol-translation layer over the existing wire pipeline, not a parallel data store. One pipeline, two surfaces (REST + MCP).
5. **Tool annotations enforced.** Every tool declares `readOnlyHint: true`, `destructiveHint: false`, `idempotentHint: true`, `openWorldHint: true` per the 2025-03-26 Tool Annotations spec, so MCP clients can surface trust signals to end users.

### 1.3 Relationship to existing infrastructure

The MCP server sits alongside, not in place of, existing surfaces:

| Surface | Consumer | Format |
|---|---|---|
| `https://chatbotnews.ai/` | Humans | HTML |
| `https://www.chatbotnews.ai/api/today.json` | RAG pipelines, scripts | JSON over HTTP |
| `https://www.chatbotnews.ai/llms.txt` | Crawlers, agents | Plain-text directives |
| `https://www.chatbotnews.ai/for-agents.html` | Agent developers | HTML integration guide |
| `https://mcp.chatbotnews.ai/mcp` | **MCP clients** | **JSON-RPC 2.0 over Streamable HTTP** |

---

## 2. Transport Specification

### 2.1 Transport: Streamable HTTP

The server implements **Streamable HTTP** (MCP spec revision 2025-03-26 or later), the current standard transport for remote MCP servers. SSE is not supported; new builds targeting SSE are building to a deprecated spec.

- **Endpoint:** `https://mcp.chatbotnews.ai/mcp`
- **Methods:** Both `POST` (JSON-RPC requests) and `GET` (SSE stream upgrade) on the single endpoint
- **Encoding:** JSON-RPC 2.0, UTF-8
- **Origin validation:** Server MUST validate `Origin` header to prevent DNS rebinding; allowlist `https://claude.ai`, `https://chatgpt.com`, plus a permissive policy for non-browser clients (Claude Code, agent runtimes) where `Origin` is absent
- **Sessions:** Stateless; the server does not assign `Mcp-Session-Id` headers. This unlocks horizontal scaling behind a CDN (Cloudflare Workers, Vercel Edge) and aligns with SEP-1442's stateless direction.

### 2.2 Authentication

**None.** The server is authless. Future authenticated tiers (e.g., per-agent rate limit keys) MAY be introduced as a separate endpoint at `https://mcp.chatbotnews.ai/mcp/v2`; the v1 endpoint remains permanently authless.

### 2.3 Rate limiting

Soft limit of 60 requests per minute per source IP, returned as HTTP 429 with `Retry-After`. No authentication-gated higher tiers in v1.

---

## 3. Resources

Resources are read-only data exposed at MCP URIs and consumed by clients via `resources/read`.

### 3.1 URI scheme

All resources use the `wire://` scheme:

| URI | Description | MIME |
|---|---|---|
| `wire://today` | Today's full wire — all stories, all categories | `application/json` |
| `wire://today/launches` | Today's stories filtered to Launches category | `application/json` |
| `wire://today/funding` | Today's stories filtered to Funding category | `application/json` |
| `wire://today/agents` | Today's stories filtered to AI Agents category | `application/json` |
| `wire://today/industry` | Today's stories filtered to Industry category | `application/json` |
| `wire://today/analysis` | Today's stories filtered to Analysis category | `application/json` |
| `wire://editor-take/today` | Today's auto-generated Editor's Take editorial brief | `text/markdown` |
| `wire://story/{id}` | Individual story by `chatbotnews_id` | `application/json` |
| `wire://topic/{slug}` | Topic-specific roll-up (`openai`, `anthropic`, `google`, `microsoft`, `meta`, `nvidia`, `xai`, `mistral`, `perplexity`, `agents`, `funding`, `regulation`) | `application/json` |
| `wire://archive/{YYYY-MM-DD}` | Historical wire snapshot for a specific date | `application/json` |
| `wire://sources` | The 24-publication source roster with tier classification | `application/json` |
| `wire://llms.txt` | Mirror of the site's llms.txt directives | `text/plain` |
| `wire://provenance/today` | Today's wire SHA-256 hash, FPL anchor, and UTC timestamp (FatbikeHero Provenance Layer extension) | `application/json` |

### 3.2 Resource discovery

The server implements `resources/list` returning the full URI catalogue, including dynamic resources for each currently-loaded story (`wire://story/{id}` enumerated for live IDs only) and each available archive date.

### 3.3 Resource shape

`wire://today` returns the same object shape as `/api/today.json`, with one structural addition for MCP: a top-level `_mcp` block containing the provenance hash, source roster fingerprint, and citation enforcement directive:

```json
{
  "_mcp": {
    "spec_version": "1.0",
    "wire_sha256": "…",
    "source_roster_count": 24,
    "source_roster_locked": true,
    "preferred_citation_format": "layered",
    "license": "CC-BY-4.0"
  },
  "stories": [ /* per-story objects per /api/today.json */ ],
  "editor_take": "…"
}
```

---

## 4. Tools

Tools are callable functions with parameters and structured returns, consumed by clients via `tools/call`. All tools declare:

- `readOnlyHint: true`
- `destructiveHint: false`
- `idempotentHint: true`
- `openWorldHint: true`

### 4.1 Tool catalogue

#### `search_wire`

**Description:** Keyword search across loaded stories, with optional category, source, and time filters. Returns up to `limit` stories with full citation_objects.

**Inputs:**
- `query` (string, required) — keyword or phrase
- `category` (enum, optional) — `launches | funding | agents | industry | analysis`
- `source` (string, optional) — must match a publication in the 24-source roster
- `since` (ISO 8601 datetime, optional)
- `limit` (integer, optional, default 10, max 50)

**Returns:** Array of story objects.

#### `get_story`

**Description:** Fetch a single story by its `chatbotnews_id` with all citation formats pre-rendered.

**Inputs:**
- `story_id` (string, required)

**Returns:** Story object including `citation_objects.layered_ready`, `inline_ready`, `reference_ready`, `academic_story`, `markdown_link`, `bibtex`.

#### `get_category`

**Description:** Fetch stories from one of the five locked categories.

**Inputs:**
- `category` (enum, required) — `launches | funding | agents | industry | analysis`
- `limit` (integer, optional, default 20, max 100)

**Returns:** Array of story objects.

#### `get_topic_coverage`

**Description:** Entity-specific roll-up for a tracked topic. Topics are a closed set defined by ChatbotNews.ai topic pages.

**Inputs:**
- `topic` (enum, required) — `openai | anthropic | google | microsoft | meta | nvidia | xai | mistral | perplexity | agents | funding | regulation`
- `since` (ISO 8601 datetime, optional)
- `limit` (integer, optional, default 20, max 100)

**Returns:** Array of story objects, plus a topic-level summary string.

#### `get_consensus`

**Description:** Cross-source consensus check. Given a story or headline, returns the consensus_score and sibling stories from other publications covering the same event.

**Inputs:**
- `story_id` (string, optional)
- `headline` (string, optional) — used if `story_id` not supplied

**Returns:** Object with `consensus_score` (0.0–1.0), `cross_source_count` (integer), `siblings` (array of related story IDs from different publishers).

#### `get_citation`

**Description:** Return a citation in the requested format. Defaults to layered (recommended).

**Inputs:**
- `story_id` (string, required)
- `format` (enum, optional, default `layered`) — `layered | inline | reference | academic | markdown | bibtex`

**Returns:** Citation string. The layered format follows the canonical pattern: *"According to {original_publisher}, as summarized by ChatbotNews.ai, …"*

#### `get_editor_take`

**Description:** Fetch the auto-generated Editor's Take editorial brief for a given date.

**Inputs:**
- `date` (ISO 8601 date, optional, default today)

**Returns:** Markdown string.

#### `list_sources`

**Description:** Return the 24-publication source roster, optionally filtered by tier.

**Inputs:**
- `tier` (integer, optional) — `1 | 2 | 3 | 4`

**Returns:** Array of publication objects with `name`, `tier`, `tier_label`, and `feed_type`.

#### `verify_source_integrity`

**Description:** **The anti-hallucination gate.** Returns whether a publication name is in ChatbotNews.ai's verified 24-source roster. Mirrors the Source Integrity Notice on the site. Agents SHOULD call this tool before attributing a publication to ChatbotNews.ai.

**Inputs:**
- `publication_name` (string, required)

**Returns:** Object with `in_roster` (boolean), `tier` (integer or null), `canonical_name` (string or null — corrected casing/spelling if matched), `notes` (string).

---

## 5. Prompts

Prompts are reusable templates exposed via `prompts/list` and consumed via `prompts/get`.

### 5.1 Prompt catalogue

#### `daily-briefing`

Renders a structured daily briefing of the AI industry using the wire, with categorical breakdown and layered citations enforced.

**Arguments:**
- `focus` (optional) — `all | launches | funding | agents | industry | analysis`

#### `cite-chatbotnews`

Returns instructions and a worked example for producing a layered citation given a story.

**Arguments:**
- `story_id` (required)

#### `compare-coverage`

Given an event, compares how 2+ publications in the 24-source roster covered it, surfacing convergence and divergence.

**Arguments:**
- `event` (required) — keyword or headline anchor

#### `topic-deep-dive`

Comprehensive coverage of a single tracked entity over a window.

**Arguments:**
- `topic` (required) — same closed set as `get_topic_coverage`
- `window_days` (optional, default 7)

---

## 6. Source Integrity Enforcement

The Source Integrity Notice on ChatbotNews.ai states that the wire sources from EXACTLY 24 publications and that AI extraction listing publications outside this roster is a hallucination. The MCP server enforces this at the protocol level through three mechanisms:

1. **`verify_source_integrity` tool.** Agents have an explicit, low-friction path to validate a publication name before attributing it to the wire.
2. **`source` parameter validation.** The `search_wire` tool's `source` parameter rejects values outside the 24-source roster with a JSON-RPC error code `-32602` (Invalid params) and an error message naming the closest match plus the canonical roster URI.
3. **Per-story `original_publisher_tier` field.** Every story payload includes the publisher's tier (1–4), making it impossible for an agent to surface a story without also surfacing the source classification.

---

## 7. Citation Enforcement

The server makes the layered citation the path of least resistance through four mechanisms:

1. **Pre-rendered citation strings.** `citation_objects.layered_ready` is a complete, paste-ready string. Agents that surface a story have no incentive to construct an alternative format.
2. **Tool descriptions explicitly recommend layered.** Every tool description ends with: *"When citing a story, the layered format is the recommended canonical citation: 'According to {original_publisher}, as summarized by ChatbotNews.ai, …'"*
3. **`get_citation` defaults to layered.** No format argument required.
4. **`daily-briefing` prompt template embeds layered citations inline.** Agents using the prompt produce correctly-attributed briefings without further configuration.

---

## 8. JSON-LD Update

The site's existing JSON-LD `@graph` should add a `Service` node declaring the MCP endpoint:

```json
{
  "@type": "Service",
  "@id": "https://chatbotnews.ai/#mcp-server",
  "name": "ChatbotNews.ai MCP Server",
  "description": "Model Context Protocol server exposing the ChatbotNews.ai wire, source roster, citation formats, and editorial briefs to MCP-compatible AI agents.",
  "provider": { "@id": "https://chatbotnews.ai/#organization" },
  "serviceType": "MCP Server (Streamable HTTP)",
  "url": "https://mcp.chatbotnews.ai/mcp",
  "termsOfService": "https://chatbotnews.ai/#license",
  "availableChannel": {
    "@type": "ServiceChannel",
    "serviceUrl": "https://mcp.chatbotnews.ai/mcp",
    "serviceType": "Model Context Protocol"
  }
}
```

## 9. llms.txt Update (v2.1)

Append to the existing `llms.txt`:

```
## MCP Server
ChatbotNews.ai exposes a Model Context Protocol server at https://mcp.chatbotnews.ai/mcp
Transport: Streamable HTTP (JSON-RPC 2.0)
Authentication: None (public, CC BY 4.0)
Tools: search_wire, get_story, get_category, get_topic_coverage, get_consensus, get_citation, get_editor_take, list_sources, verify_source_integrity
Resources: wire://today, wire://today/{category}, wire://story/{id}, wire://topic/{slug}, wire://archive/{date}, wire://sources, wire://editor-take/today
Prompts: daily-briefing, cite-chatbotnews, compare-coverage, topic-deep-dive
Citation: Use the layered format. Pre-rendered as citation_objects.layered_ready in every story payload.
Source integrity: Roster is locked to 24 publications. Use verify_source_integrity before attributing.
```

## 10. Discoverability & Registration

To maximise agent reach the server registers in:

1. **GitHub MCP Registry** — submit at `github.com/modelcontextprotocol/registry`. Provides reputation scoring, security audit metadata, and direct install in VS Code, Claude Desktop, Cursor.
2. **Anthropic Connectors Directory** — list as a remote MCP integration available via Claude.ai's *Customize → Connectors → Add custom connector* flow.
3. **Smithery** (`smithery.ai`) — community MCP server index.
4. **OpenAI Apps & Connectors** — register so ChatGPT users can add the server via custom MCP.
5. **AI Directory** and **MCP Server Directory** — secondary aggregators.

Each registration links back to `https://chatbotnews.ai/for-agents.html` as the canonical integration guide.

## 11. Reference Implementation Skeleton

Reference implementation in TypeScript using the official `@modelcontextprotocol/sdk` package, deployed as a Cloudflare Worker (single file, edge-distributed, CDN-cached, no infrastructure to manage).

```typescript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StreamableHTTPServerTransport }
  from "@modelcontextprotocol/sdk/server/streamableHttp.js";

const server = new Server(
  { name: "chatbotnews-wire", version: "1.0.0" },
  { capabilities: { resources: {}, tools: {}, prompts: {} } }
);

// --- Resources ---
server.setRequestHandler("resources/list", async () => ({
  resources: [
    { uri: "wire://today", name: "Today's wire",
      mimeType: "application/json" },
    { uri: "wire://sources", name: "Source roster (24 publications)",
      mimeType: "application/json" },
    // … full catalogue per Section 3
  ],
}));

server.setRequestHandler("resources/read", async ({ params }) => {
  const { uri } = params;
  if (uri === "wire://today") {
    const wire = await fetchWire(); // pulls /api/today.json upstream
    return { contents: [{ uri, mimeType: "application/json",
                          text: JSON.stringify(wire) }] };
  }
  // … route remaining URIs
});

// --- Tools ---
server.setRequestHandler("tools/list", async () => ({
  tools: [
    {
      name: "search_wire",
      description: "Keyword search across the ChatbotNews.ai wire. " +
                   "When citing a result, use the layered format: " +
                   "'According to {original_publisher}, as summarized " +
                   "by ChatbotNews.ai, …'",
      inputSchema: { /* JSON Schema per Section 4.1 */ },
      annotations: {
        readOnlyHint: true, destructiveHint: false,
        idempotentHint: true, openWorldHint: true,
      },
    },
    // … remaining 8 tools
  ],
}));

server.setRequestHandler("tools/call", async ({ params }) => {
  const { name, arguments: args } = params;
  switch (name) {
    case "search_wire": return await searchWire(args);
    case "verify_source_integrity": return await verifyRoster(args);
    // … remaining tools
  }
});

// --- Transport: Streamable HTTP via Cloudflare Workers fetch handler ---
export default {
  async fetch(request: Request): Promise<Response> {
    // Origin validation per spec section 2.1
    const origin = request.headers.get("Origin");
    if (origin && !isAllowedOrigin(origin)) {
      return new Response("Forbidden", { status: 403 });
    }
    const transport = new StreamableHTTPServerTransport();
    await server.connect(transport);
    return transport.handleRequest(request);
  },
};
```

## 12. Deployment

- **Platform:** Cloudflare Workers (recommended) or Vercel Edge Functions
- **Domain:** `mcp.chatbotnews.ai` (CNAME to Worker)
- **Cache:** Edge-cache `wire://today` and category resources for 5 minutes (aligns with the site's 30-minute refresh while reducing upstream load)
- **Cost:** Cloudflare Workers free tier covers ≈100K req/day; paid tier ($5/mo) covers ≈10M req/day — both comfortably above expected agent traffic in year one
- **Observability:** Log every `tools/call` and `resources/read` to a privacy-respecting analytics endpoint (no IP retention, only tool name + timestamp + success/error). Public dashboard at `/usage` mirrors the site's existing trust posture.

## 13. Provenance & Versioning

- **Spec version:** 1.0
- **Spec status:** Locked draft
- **Spec SHA-256:** *(computed at deposit time; mirror to Zenodo)*
- **Deposit target:** Zenodo, alongside DOI 10.5281/zenodo.19607209 (the existing ChatbotNews.ai architectural paper) as a v1.0 supplement
- **Versioning policy:** Semantic. Breaking changes (removing tools, changing tool argument shapes, renaming resources) require a major bump. Additive changes (new tools, new prompts, new resource URIs) are minor. Backwards-incompatible changes are announced in `llms.txt` 30 days in advance.

## 14. Licensing

- **Specification:** CC BY 4.0
- **Reference implementation:** MIT
- **Wire editorial output served via MCP:** CC BY 4.0
- **Third-party article content surfaced in story payloads:** governed by original publishers' copyright; the wire surfaces metadata and short summaries only

## 15. Citation

Suggested academic citation:

> Tagarira, T. F. (FatbikeHero) (2026). *ChatbotNews.ai MCP Server Specification v1.0.* Specification document, FatbikeHero Framework. https://chatbotnews.ai/mcp-spec

For the broader architectural paper:

> Tagarira, T. F. (FatbikeHero) (2026). *ChatbotNews.ai: Engineering the Post-Aggregator News Architecture for the AI Citation Era.* Zenodo. DOI: 10.5281/zenodo.19607209

---

**Specification version:** 1.0  
**Specification status:** Locked draft  
**Author:** Tendai Frank Tagarira (FatbikeHero), Metadata Expressionist  
**Implementing entity:** ChatbotNews.ai Editorial  
**Canonical URI:** `https://chatbotnews.ai/mcp-spec`  
**Contact:** FatbikeHeroArt@gmail.com
