WrongBot
by jasperkooij
README.md
# WrongBot š
A chat bot ā and a real [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server ā that answers every question confidently and incorrectly.
Live at **https://wrongbot.jasperkooij.com**
[](https://buymeacoffee.com/jasperkooij)
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").
## 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](https://specification.website)'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
```bash
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](https://playground.ai.cloudflare.com/) at `http://localhost:8787/mcp`, or use `mcp-remote`:
```bash
npx mcp-remote http://localhost:8787/mcp
```
## Deploying
### 1. First deploy (to a `*.workers.dev` URL)
```bash
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`:
```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):
```json
{
"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`):
```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](./LICENSE). Be confidently wrong responsibly.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues