Skip to main content
Glama
jasperkooij

WrongBot

by jasperkooij

WrongBot 🙃

A chat bot — and a real Model Context Protocol (MCP) server — that answers every question confidently and incorrectly.

Live at https://wrongbot.jasperkooij.com

Buy Me A Coffee

It exists for two reasons:

  1. Satire. It's a small, harmless joke about AI overconfidence and hallucination, made in the middle of a very earnest news cycle about both.

  2. Demo. It's a working, minimal example of a remote MCP server deployed on Cloudflare Workers — something worth having a real, running example of rather than just reading about.

⚠️ This project is intentionally wrong 100% of the time. Do not use its output as a factual answer to anything. That's the entire point.


Architecture

┌──────────────────────────────────────────┐
│         wrongbot.jasperkooij.com          │
│                                            │
│   /                → landing page + full  │  Static HTML/CSS/JS, served
│                       documentation +      │  from ./public via Workers
│                       in-browser demo      │  Assets. The chat widget
│                       widget               │  runs entirely client-side
│                                            │  (no server round-trip).
│                                            │
│   /mcp              → MCP server           │  Cloudflare Workers + Durable
│   /sse              → (legacy)             │  Objects, via the `agents`
│                                            │  package's McpAgent class.
│                                            │  Exposes one tool:
│                                            │  `get_wrong_answer`.
│                                            │
│   /api/wrong-answers.json → the wrong-    │  Same data the MCP tool
│                       answer bank as JSON  │  draws from, as plain JSON.
│                                            │
│   /robots.txt, /sitemap.xml, /llms.txt,   │  Static files served the
│   /llms-full.txt, /.well-known/*          │  same way as the landing page.
└──────────────────────────────────────────┘

Both the browser widget and the MCP tool share the same "wrongness engine" (src/wrong-answers.ts): naive keyword matching picks a bank of wrong answers, then every response gets a suspiciously high confidence score (90–100%, always) and a fabricated source ("per my uncle who works at Nintendo").

Related MCP server: Bible API MCP Server

Stack

  • Cloudflare Workers — compute + static asset hosting, one deployment

  • Durable Objects — required by the MCP Agent SDK to hold a session per connected client

  • agents (Cloudflare's MCP Agent SDK) + @modelcontextprotocol/sdk — the actual MCP server implementation

  • Zod — input schema validation for the MCP tool

  • Plain HTML/CSS/JS — the landing page and demo widget, no build step, no framework

Documentation & AI-agent readiness

The landing page (public/index.html) is the primary documentation: architecture, the full get_wrong_answer tool reference, how to connect a client, how to add more wrongness, and an FAQ — all as real HTML sections (<h2>/<h3>, semantic landmarks, a skip link), not just this README.

Beyond that, the site follows The Website Specification's agent-readiness and seo checklists as far as they apply to a small static + Workers site:

  • /llms.txt, /llms-full.txt, and /index.md — a short index, a full Markdown dump of the docs, and a Markdown twin of the homepage (with frontmatter), for AI agents that prefer Markdown to scraping HTML.

  • /openapi.json — an OpenAPI 3.1 spec for the one real REST endpoint (/api/wrong-answers.json); the MCP tool is documented separately since OpenAPI doesn't model MCP tools.

  • /api/wrong-answers.json — the wrong-answer bank and fake-source list as JSON, served dynamically by the Worker from src/wrong-answers.ts (so it can't drift from the MCP tool's actual behavior). GET-only; other methods and unmatched /api/* paths get a proper JSON error, not an HTML 404.

  • /robots.txt — an explicit Allow for named AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, etc.), an explicit Disallow for training-only scrapers (CCBot, Bytespider) that don't power any answer engine, and an experimental Content-Signal line.

  • /sitemap.xml, /.well-known/security.txt, /.well-known/api-catalog (RFC 9727 linkset, served with application/linkset+json), /.well-known/ard.json (Agentic Resource Discovery catalog), /.well-known/mcp/server-card.json, /.well-known/agent-skills/index.json.

  • JSON-LD on the landing page — WebSite, SoftwareApplication, Person (with a sameAs link to GitHub), and FAQPage structured data, plus Open Graph/Twitter meta tags (including a generated og-image.png) and a canonical URL.

  • MCP server metadata — instructions on the server's initialize response, and behavioral annotations (readOnlyHint, etc.) on the get_wrong_answer tool, so a client can reason about it without calling it first.

  • WebMCP — the landing page registers get_wrong_answer as a client-side tool via document.modelContext.registerTool() (feature-detected; early preview, Chromium 146+ behind a flag), reusing the exact same wrongify() logic the chat widget already runs — for in-browser AI agents that can drive the page directly, no server round trip.

  • Security headers (CSP, HSTS, X-Content-Type-Options, Referrer-Policy, Permissions-Policy) and discovery Link headers (pointing at llms.txt, sitemap.xml, api-catalog) applied to every response in src/index.ts, along with a short Markdown 404 body instead of the generic Workers Assets page.

  • /about, /privacy, /contact — real, if short, trust-anchor pages. /privacy specifically discloses the Google Analytics tag now on the site.

The whole point of WrongBot is that its output is always fake — so the strategy here is maximum crawlability paired with the falseness being declared everywhere an agent might look (the MCP tool description, /llms.txt, the page copy itself), rather than blocking crawlers.

Known gaps, if you want to push this further: no raster favicon set (only an SVG favicon — no .ico/apple-touch-icon/maskable PWA icon). A number of "agent readiness" scoring services (e.g. ora.ai) also grade sites against commercial-SaaS criteria — OAuth 2.0, agent payment protocols (x402/ACP/UCP/AP2), a developer portal with a sandbox, multi-language SDK packages, a Wikipedia/Wikidata entity, a ChatGPT App Store listing — that are deliberately not implemented here: they don't fit a free, single-tool satirical demo, and faking them (a payments protocol on a site that sells nothing, an OAuth flow gating a joke) would be dishonest rather than "agent-ready."

Local development

npm install
npm run dev

This starts the Worker locally (default http://localhost:8787). The landing page is served at /, the MCP endpoint at /mcp.

To test the MCP server locally without a full client, point the Cloudflare AI Playground at http://localhost:8787/mcp, or use mcp-remote:

npx mcp-remote http://localhost:8787/mcp

Deploying

1. First deploy (to a *.workers.dev URL)

npm install
npx wrangler login        # opens a browser to authenticate with your Cloudflare account
npm run deploy

This deploys to wrongbot-mcp.<your-subdomain>.workers.dev. Confirm it works — load the URL, try the widget, and connect a client to /mcp — before moving to the custom domain.

2. Point wrongbot.jasperkooij.com at it

Since jasperkooij.com is already on Cloudflare, this is a Workers custom domain, not a separate DNS + hosting setup:

  1. In the Cloudflare dashboard: Workers & Pages → wrongbot-mcp → Settings → Domains & Routes → Add → Custom Domain.

  2. Enter wrongbot.jasperkooij.com. Cloudflare will automatically create the DNS record (since the zone is already on your account) and provision the TLS certificate.

  3. Alternatively, do it from the CLI: uncomment the routes block in wrangler.jsonc:

    "routes": [
      { "pattern": "wrongbot.jasperkooij.com", "custom_domain": true }
    ]

    then run npm run deploy again.

  4. Propagation is usually near-instant since it's all within one Cloudflare account/zone.

3. Verify

  • Visit https://wrongbot.jasperkooij.com — the landing page and widget should load.

  • Connect an MCP client to https://wrongbot.jasperkooij.com/mcp and call get_wrong_answer.

Connecting an MCP client

Claude Desktop / Claude Code (claude_desktop_config.json or equivalent):

{
  "mcpServers": {
    "wrongbot": {
      "command": "npx",
      "args": ["mcp-remote", "https://wrongbot.jasperkooij.com/mcp"]
    }
  }
}

Cloudflare AI Playground: go to https://playground.ai.cloudflare.com/ and paste in the server URL directly — no config needed.

Cursor (.cursor/mcp.json):

{
  "mcpServers": {
    "wrongbot": {
      "url": "https://wrongbot.jasperkooij.com/mcp"
    }
  }
}

Adding more wrongness

All the "logic" lives in src/wrong-answers.ts — it's a plain object of keyword → wrong-answer-bank, plus a list of fake sources. Add a new category or more absurd answers there; both the MCP tool and /api/wrong-answers.json pick it up automatically. The browser widget in public/index.html has its own inline copy of the bank for zero-dependency simplicity (so the widget block can be dropped into any page on its own, with no server) — keep it in sync if you edit src/wrong-answers.ts.

License

MIT — see LICENSE. Be confidently wrong responsibly.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    A remote MCP server template for deployment on Cloudflare Workers without authentication. Provides a foundation for building custom MCP tools that can be accessed from Claude Desktop or Cloudflare AI Playground.
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    This example allows you to deploy a stateless remote MCP server that doesn't require authentication on Cloudflare. It implements the MCP 2026-07-28 specification while remaining compatible with legacy clients for ordinary tool calls.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Serves a curated Markdown collection of Cloudflare Workers, Durable Objects, D1, KV, and Workers AI learnings to MCP clients over HTTP, exposing it as a readable resource and a callable tool.
    -