Skip to main content
Glama
README.md
<div align="center">

<img src="brand/exports/meme-logo-primary-dark.png" width="480" alt="MEME — the Internet Culture Agent" />

# MEME

**The Internet Culture Agent — trending dev discourse in, genuinely funny memes out.**

[![npm package](https://img.shields.io/badge/npm-meme--agent-7C5CFF?logo=npm&labelColor=0B0E14)](https://www.npmjs.com/package/meme-agent)
[![license: MIT](https://img.shields.io/badge/license-MIT-B8F135?labelColor=0B0E14)](LICENSE)
[![node](https://img.shields.io/badge/node-%E2%89%A520-58C4DD?labelColor=0B0E14&logo=node.js&logoColor=white)](package.json)
[![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?labelColor=0B0E14&logo=typescript&logoColor=white)](tsconfig.json)
[![tests](https://img.shields.io/badge/tests-150%20passing-B8F135?labelColor=0B0E14&logo=vitest)](#-testing)
[![version](https://img.shields.io/badge/version-0.1.0-FF8A4C?labelColor=0B0E14)](CHANGELOG.md)

An MCP server that watches what the developer internet is actually talking
about — live from **Hacker News** and **GitHub**, no API keys required — ranks
it with a transparent multi-factor engine, and turns the discourse into
original, shareable memes: moderated, fact-checked, reproducible.

`demo mode works with zero credentials — clone and run it in 60 seconds ↓`

</div>

---

## 🎬 Product demonstration

Real session, real output (run it yourself after the Quick Start):

```text
$ meme demo

[1/6] Discovering & ranking trends (demo source, 2 snapshots for acceleration)…
  #1 Team ships Friday 5pm deploy because the ticket said so
      score 0.781 · confidence 90% · 1520 pts · 640 comments
  #2 Junior developer asks what the build server does; build server retaliates
      score 0.766 · confidence 90% · 760 pts · 340 comments
  #3 AI pair programmer confidently suggests deleting the database
      score 0.739 · confidence 90% · 2190 pts · 860 comments

[2/6] Generating meme concepts (mock LLM provider, seeded)…
  ✅ ships Friday — two buttons [two-buttons]
     [buttonA] ship ships Friday right now
     [buttonB] write one more test first
     [bottom] the build was already running
     quality 0.74 · Heuristic quality signals for iteration — not a judgment of humor…

[5/6] Editing demo: retitling a caption and re-rendering…
  edited → meme-427403043f8b (v2)

[6/6] Exporting memes (SVG + manifest)…
  meme-output/ships-friday-two-buttons-meme-6ed97c3cde5a.svg
     sha256 88162574ced870389ae49988… · manifest ✔
```

An asciinema recording of this session ships at
[`docs/assets/demo.cast`](docs/assets/demo.cast) — `npx asciinema play docs/assets/demo.cast`.

| Generated memes (real renders) | Local gallery (real screenshot) |
| --- | --- |
| ![A meme generated by MEME: "BRACE YOURSELVES / THE FRIDAY DEPLOY IS COMING"](docs/assets/screenshots/meme-brace.png) | ![MEME local gallery in a browser](docs/assets/screenshots/gallery.png) |

More screenshots: [`docs/assets/screenshots/`](docs/assets/screenshots/)

## ✨ What MEME does

- **🔍 Intelligent trend discovery & ranking** — not raw popularity. Velocity,
  acceleration, engagement quality, recency, developer relevance,
  cross-platform signals, source diversity and discussion authenticity, each
  with a weight, an explanation and a confidence score. If the data is
  missing a factor, the confidence drops — visibly.
- **🌐 Live sources without keys** — Hacker News (public Firebase API) and
  GitHub (public search API, `GITHUB_TOKEN` optional) via authorized APIs
  only, with token-bucket rate limits, ETag conditional requests and 5-minute
  efficient polling. Demo mode is fully deterministic for offline/CI use.
- **🧠 Context-aware meme concepts** — an LLM provider layer (deterministic
  mock built in; OpenAI/Anthropic adapters included) that only sees external
  text inside untrusted-content delimiters, and whose output is validated
  against injection patterns before it can render.
- **🎨 Original vector memes** — six built-in templates drawn from scratch
  (no copyrighted photo memes), CJK-aware text wrapping, Unicode-safe
  rendering, PNG export via the optional `sharp` dependency.
- **🛡️ Moderation & factuality safeguards** — every concept passes a
  rules-based moderation policy; version-like technical claims are checked
  against the source text so the LLM can't invent a release for a joke.
- **📊 Meme Quality Evaluation** — technical accuracy, contextual relevance,
  originality, humor *heuristics*, readability, composition and audience fit —
  with a benchmark dataset and regression tests. Explicitly **never** claims a
  meme is objectively funny or guaranteed to go viral.
- **💸 Cost management** — token/cost tracking, daily + per-generation
  budgets, cache-efficiency metrics, graceful fallback to the free mock
  provider when a budget is exhausted.
- **⚖️ Platform Compliance Registry** — a versioned, data-driven registry of
  per-provider permissions, attribution and retention. **Reddit and X are
  disabled** — Reddit user content requires a completed legal review before
  any AI transfer, and no authorized X API is configured.
- **🔒 Security by construction** — outbound fetches only to allowlisted
  provider domains (per-hop redirect validation, private-IP blocking, size
  caps), credentials never accepted via tool arguments, credential redaction
  in all logs, localhost-only gallery with Origin/Host validation.
- **🔁 Resilient background processing** — idempotent jobs, bounded
  concurrency, exponential backoff with jitter, circuit breakers,
  Retry-After-aware rate limiting, dead-letter queue, journal durability.
- **🧾 Reproducibility metadata** — every meme records provider, model,
  prompt-template version, seed hint and asset hashes; demo mode is
  byte-identical on regeneration.
- **🌍 i18n** — configurable generation language (en + zh-CN phrasebooks
  today), script-aware typography, multilingual captions.
- **🧰 Developer UX** — history, favorites, ratings, content reporting with
  deletion records, editable memes, SVG/PNG export with attribution
  manifests, `meme doctor` readiness checks, accessible local gallery.

## ⏱️ Quick Start in 60 Seconds

```bash
git clone https://github.com/renniyy/meme.git   # or your fork
cd meme
npm install
npm run build
npm run demo
```

That's the whole demo pipeline: **discover → rank → generate → moderate →
render → edit → export**, with deterministic mock providers and zero API
credentials. You'll find exported SVG memes + manifests in `./meme-output`.

Want **live trends** instead? Nothing to configure either (HN needs no key):

```bash
MEME_MODE=live npm run demo
```

## 📦 Installation

**From source (v0.1.0 release channel):**

```bash
git clone https://github.com/renniyy/meme.git && cd meme
npm install && npm run build
node dist/cli.js doctor     # readiness check
```

**As a global CLI (after we publish — see docs/naming-review.md):**

```bash
npm install -g meme-agent
meme doctor
```

Requirements: Node.js ≥ 20. Optional: `GITHUB_TOKEN` (higher rate limits),
`OPENAI_API_KEY` or `ANTHROPIC_API_KEY` (real LLM concepts), `sharp` ships as
an optional dependency for PNG export (SVG works everywhere).

## 🔌 Using MEME with MCP clients (local stdio)

MEME is an MCP **stdio** server. Point any MCP client at the built CLI:

```json
{
  "mcpServers": {
    "meme": {
      "command": "node",
      "args": ["/absolute/path/to/meme/dist/cli.js", "serve"],
      "env": {
        "MEME_MODE": "auto",
        "MEME_DATA_DIR": "/absolute/path/to/meme/.meme-data",
        "GITHUB_TOKEN": "ghp_…optional…"
      }
    }
  }
}
```

Then ask your client: *"use the meme server: discover trends and make a meme
about the top one"*. The tool catalogue (`meme_discover_trends`,
`meme_generate_meme`, `meme_preview_meme`, `meme_edit_meme`,
`meme_export_meme`, …) is documented in [docs/mcp.md](docs/mcp.md), including
the protocol-version compatibility matrix.

**Remote MCP + OAuth:** not implemented in v0.1.0 — see
[ROADMAP.md](ROADMAP.md) (`mcp-remote-auth`). We won't publish instructions
for a transport that doesn't exist yet; local stdio is fully supported today.

## 🏗️ Architecture

```mermaid
flowchart LR
    subgraph Sources["Authorized sources"]
        HN["Hacker News API"]
        GH["GitHub Search API"]
        DEMO["Demo source\n(deterministic, fictional)"]
    end
    subgraph Core["MEME core (Node.js ≥20)"]
        REG["Compliance Registry\n(versioned, data-driven)"]
        TS["Trend store\n(snapshots, retention, deletion records)"]
        RANK["Ranking engine\n(8 factors + explanations + confidence)"]
        LLM["Concept providers\nmock / OpenAI / Anthropic"]
        MOD["Moderation +\nfactuality safeguards"]
        REN["SVG renderer\n(original templates, CJK-aware)"]
        QUAL["Quality evaluation\n+ benchmark"]
        COST["Cost tracker\n+ budgets + fallback"]
        Q["Job queue\n(backoff, breaker, DLQ)"]
    end
    subgraph Surface["Surfaces"]
        MCP["MCP stdio server\n(tools + resources)"]
        GAL["Local gallery\n(127.0.0.1, read-only)"]
        CLI["CLI\nserve/demo/gallery/doctor/report"]
    end
    HN --> REG --> TS
    GH --> REG
    DEMO --> TS
    TS --> RANK --> LLM --> MOD --> REN --> QUAL
    LLM --> COST
    Q --> LLM
    MCP --> Core
    CLI --> MCP
    GAL --> TS
```

End-to-end workflow, from trend to shareable file:

```mermaid
sequenceDiagram
    participant U as You (MCP client / CLI)
    participant S as MEME server
    participant P as Providers (HN/GitHub/LLM)
    U->>S: meme_discover_trends
    S->>P: guarded fetch (allowlist, rate limit, ETag)
    S-->>U: ranked trends + explanations + confidence + freshness
    U->>S: meme_generate_meme (trendId)
    S->>S: concept (LLM) → injection validation → moderation → factuality
    S->>S: render (original SVG template) → re-moderate → quality score
    S-->>U: meme record + reproducibility metadata
    U->>S: meme_preview_meme / meme_edit_meme
    U->>S: meme_export_meme (svg|png)
    S-->>U: file path + SHA-256 + attribution manifest
```

## 🌐 Supported provider matrix

| Provider | Live today | Auth | Compliance status | Notes |
| --- | --- | --- | --- | --- |
| **Hacker News** | ✅ | none | enabled | Titles/metadata only; links never followed; 24 h raw retention |
| **GitHub** | ✅ | optional token | enabled | Public repo search; ETag conditional requests |
| **Demo (built-in)** | ✅ | none | enabled | Fictional evergreen dev-culture trends, deterministic |
| Reddit | ❌ | OAuth (unimplemented) | **disabled — legal review required** | User content must not reach external AI providers before a recorded legal/policy review |
| X (Twitter) | ❌ | paid API (none) | disabled | No authorized access configured; will not be simulated |
| OpenAI | ✅ adapter | `OPENAI_API_KEY` | enabled | JSON-mode chat completions, untrusted-content delimiters |
| Anthropic | ✅ adapter | `ANTHROPIC_API_KEY` | enabled | Messages API |
| Mock (built-in) | ✅ | none | enabled | Deterministic; powers demo mode and CI |

The matrix mirrors `data/compliance-registry.json` — the registry is the
source of truth, and `meme_doctor` verifies it at runtime.

## ⚙️ Configuration (examples)

```bash
MEME_MODE=auto              # demo | live | auto (live sources, demo fallback)
MEME_LLM_PROVIDER=auto      # auto | mock | openai | anthropic
OPENAI_API_KEY=sk-…         # or ANTHROPIC_API_KEY
OPENAI_MODEL=gpt-4o-mini    # defaults are configurable
MEME_LANGUAGE=en            # generation language (en, zh-CN, …)
MEME_MAX_DAILY_USD=5        # budget guard; exhausted → mock fallback
MEME_MAX_PER_GEN_USD=0.25   # per-generation cost cap
MEME_DATA_DIR=./.meme-data  # workspace data (trends, profiles, memes)
MEME_EXPORT_DIR=./meme-output
MEME_SOURCE_RPM=30          # outbound rate limit per source
MEME_WORKSPACE=local        # tenant isolation scope
```

Full reference: [docs/configuration.md](docs/configuration.md) · personalization
profiles: [docs/mcp.md](docs/mcp.md) · prices: `data/price-table.json`.

## 🔒 Security & privacy

- **Local-first**: stdio server, no network listener; the gallery binds
  127.0.0.1 only and validates Origin/Host headers.
- **SSRF controls**: outbound requests are allowlist-only, with per-hop
  redirect validation, private/loopback/link-local IP blocking, response size
  caps and timeouts.
- **Prompt-injection defense**: external text is sanitized, length-capped and
  wrapped in `<<<EXTERNAL_CONTENT …>>>` data-only delimiters; LLM output is
  re-validated before rendering.
- **Secrets hygiene**: credentials only via environment/config — tool
  arguments carrying secret-like keys are rejected; logs redact token
  patterns (`ghp_…`, `sk-…`, `Bearer …`, `api_key=…`).
- **Retention & deletion**: provider TTLs enforced; deletion records contain
  ids and reasons, never content.
- Details & threat model: [docs/security.md](docs/security.md) ·
  vulnerability disclosure: [SECURITY.md](SECURITY.md)

## 🧪 Testing

150 automated tests across 17 files cover the areas the spec calls out:

```bash
npm test          # full suite (vitest)
npm run typecheck # strict TypeScript, noEmit
```

| Area | Test file |
| --- | --- |
| Authentication boundaries (credentials via tool args) | `tests/mcp.test.ts`, `tests/security.test.ts` |
| Tenant isolation (workspaces) | `tests/retention.test.ts`, `tests/demo-e2e.test.ts` |
| Content retention & deletion records | `tests/retention.test.ts` |
| Moderation decisions | `tests/moderation.test.ts` |
| Prompt-injection defenses | `tests/security.test.ts`, `tests/mcp.test.ts` |
| Provider failures & rate limits | `tests/sources.test.ts`, `tests/queue.test.ts` |
| Job retries, backoff, circuit breaker, DLQ | `tests/queue.test.ts` |
| Trend ranking & explanations | `tests/ranking.test.ts` |
| Compliance registry incl. Reddit legal gate | `tests/compliance.test.ts` |
| Cost/budget fallback | `tests/cost.test.ts` |
| Factuality safeguards | `tests/factuality.test.ts` |
| Quality benchmark regression | `tests/quality-benchmark.test.ts` |
| Renderer (CJK, escaping, overflow) | `tests/render.test.ts` |
| Gallery (headers, origin, traversal) | `tests/gallery.test.ts` |
| Log redaction | `tests/logger.test.ts` |
| End-to-end demo pipeline (Definition of Done) | `tests/demo-e2e.test.ts`, `tests/mcp.test.ts` |
| v0.1.0 audit regressions (traversal, blocked derivatives, queue config) | `tests/audit-regressions.test.ts` |
| Brand palette & assets | `tests/brand.test.ts` |

## 🧭 Roadmap

Statuses are honest: **implemented** (shipped, tested), **experimental**
(behind flags), **planned** (design exists), **unavailable** (blocked).
See [ROADMAP.md](ROADMAP.md) for the full matrix — headline items: Reddit
adapter (blocked on legal review), X adapter (blocked on API access), remote
MCP + OAuth, hosted offering, human-rating review workflow, GIF/animated
memes.

## 🤝 Contributing

PRs welcome — read [CONTRIBUTING.md](CONTRIBUTING.md) first (commit style,
test requirements, brand-change policy). Security issues: [SECURITY.md](SECURITY.md), never public issues.

## 📄 License

[MIT](LICENSE) © MEME contributors. Brand assets are original works shipped
under the same license — see [brand/BRAND-GUIDELINES.md](brand/BRAND-GUIDELINES.md).
Built on the official [Model Context Protocol TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) (MIT) — see [docs/repo-selection.md](docs/repo-selection.md).