Skip to main content
Glama
sourav2024

reddit-radar-mcp

by sourav2024

reddit-radar-mcp

Find Reddit threads where your product genuinely fits, reconstruct the conversation, and gate every drafted reply against a claim boundary you define.

Read-only by design. There is no code path that posts, votes, or acts as an account, and a test asserts there never will be. Drafts are for a human to review, edit, and post.

CI npm node license

npx reddit-radar-mcp          # run as an MCP server
npm install reddit-radar-mcp  # or use the scoring/gate functions directly

Requires Node 20.10+. No build step, no native dependencies.

Why this exists

The usual "social listening" tool finds mentions. That is the easy half. The hard half is everything after: is this thread actually relevant, what is the person really asking, and is the reply you are about to post true?

This package is built around three claims that came out of running it in production:

  1. Keyword matching produces mostly garbage. A recency + question-form + "any recommendations" heuristic scores 50/100 on literally any recent Reddit post. The fix is the anchor rule (below), and it is the most important thing here.

  2. Where a thread lives changes what you should say. The same question in a buyer subreddit and an engineering subreddit warrant different comments, so subreddit tiers set behaviour, not just ranking.

  3. A model writing promotional copy is the worst possible judge of whether it overclaimed. So the claim gate is deterministic, rule-based, and runs server-side. It refuses to hand back a blocked draft.

Quick start

Write a config:

Name it .mjs unless your project already sets "type": "module" — otherwise Node parses it as CommonJS and the import fails.

// radar.config.mjs
import { defineConfig, packs, composePacks } from 'reddit-radar-mcp';

export default defineConfig({
  product: {
    name: 'Acme',
    what: 'CI/CD pipeline observability.',
    claims: ['flaky test detection', 'build timing breakdowns'],
  },

  queries: ['flaky tests', 'CI pipeline slow', 'build times'],

  // REQUIRED. Without it, every recent question looks like an opportunity.
  domainTerms: ['ci', 'pipeline', 'flaky', 'github actions', 'test suite'],

  // Words that mean something else outside your niche.
  ambiguousTerms: ['build', 'runner'],

  tiers: {
    tier1: { mode: 'PROMOTE',        weight: 20, subreddits: ['devops'] },
    tier2: { mode: 'PROMOTE_SOFT',   weight: 15, subreddits: ['sre', 'kubernetes'] },
    tier3: { mode: 'CONTRIBUTE',     weight: 8,  subreddits: ['ExperiencedDevs'] },
    tier4: { mode: 'TECHNICAL_ONLY', weight: 3,  subreddits: ['programming'] },
  },

  gate: {
    ...composePacks(packs.noPricing, packs.noFabricatedMetrics, packs.noCustomerNames),
    productPattern: /\bAcme\b/i,
    unsupported: [
      { term: /\bJenkins\b/i, why: 'No Jenkins integration exists.' },
    ],
  },
});

Register it as an MCP server:

claude mcp add radar --scope user \
  -e RADAR_CONFIG=/abs/path/radar.config.mjs \
  -- npx reddit-radar-mcp

Then just talk to your agent: "run a sweep and show me what's worth replying to."

The anchor rule

The single most useful idea in this package.

A post is anchored only if something ties it to your domain: real domain vocabulary, an unambiguous query match, or a configured subreddit. Signals that describe the shape of a post — it is recent, it is a question, it says "recommendations" — can never carry a post on their own.

Without this gate, those shape signals sum to 40+ and pass anything. With it, a post in r/podcasts asking about a "POD episode" stops outranking a genuine buying question.

Two related behaviours fall out of the same idea:

  • Ambiguous terms ("build", "POD", "detention") only count when a second domain signal is present — or when the post is in one of your subreddits, since the subreddit is itself domain context.

  • Venting is penalized hard (-35). Rants out-engage buying questions, so without this the ranking inverts and you get "opportunities" that are people complaining about their coworkers.

Engagement modes

Tiers attach a mode to every result, and the sweep output repeats it next to each thread:

Mode

Meaning

PROMOTE

Name the product, describe the fitting capability, disclose affiliation.

PROMOTE_SOFT

Answer first. Mention the product only if they are asking for tooling.

CONTRIBUTE

Share insight. Product only as context for who you are.

TECHNICAL_ONLY

Do not pitch. Nobody there is buying; promo gets removed.

The draft gate

check_draft runs two independent checks and refuses to return a blocked draft.

Claim gate (factCheck) — deterministic rules over your claim boundary. Starter packs cover the four common failure modes:

Pack

Blocks

noPricing

Dollar figures, per-unit rates, price-tier comparisons

noFabricatedMetrics

Invented percentages, uptime/SLA claims, unverifiable scale

noCustomerNames

Client references (even anonymous), case studies with measured outcomes

noMarketingSpeak

"leverage", "seamless", "robust", "game-changing" (WARN)

requireDisclosure

Naming your product without disclosing affiliation

Two behaviours worth knowing:

  • Denials are always allowed. "We do not support Jenkins" passes. An early version blocked it, which pushed drafts toward silence about gaps — the opposite of the intent. Conceding a real limitation is the cheapest credibility available.

  • Capability checks are assertion-scoped. "Jenkins is a solid choice if you need self-hosting" does not trip the gate, because it is not a claim about your product.

Quality gate (styleCheck) — catches text that reads as unedited generated filler: em dashes, semicolons, curly quotes, negation framing ("not just X, it's Y"), marketing vocabulary, flat sentence rhythm, and thin substance.

This is not AI-detection evasion. It cannot be and does not try to be. Many subreddits ban low-effort content, and moderators read comments rather than running classifiers. So the gate enforces what that rule actually asks for: real substance, no filler. The human still edits and posts, and disclosure is always present.

Pass your domain vocabulary so the substance check knows what a specific noun looks like:

styleCheck(draft, { anchorTerms: [...config.domainTerms, ...config.featureTerms] });

MCP tools

Tool

Does

LLM cost

plan_sweep

Returns search URLs + the page extractor to run on each

none

ingest_sweep

Dedupes, scores, ranks swept results into an opportunity list

none

score_thread

0–100 score for one post with per-point reasoning

none

analyze_thread

Reconstructs a thread + returns binding claim constraints

none

parse_thread_html

Same, from client-side browser extraction

none

check_draft

The enforcement point. APPROVED or BLOCKED

none

get_claim_boundary

What may and may not be claimed

none

Every tool is deterministic. The model supplies the writing; the server supplies the facts and the veto.

Reddit access

Three interchangeable adapters behind one interface:

  • BrowserRedditClient — reads the same public pages a person reads, from your own browser tool. No credentials. This is the default path today.

  • RedditApiClient — OAuth against the official Data API. Access is approval-gated; see docs/REDDIT-ACCESS.md.

  • FixtureRedditClient — local JSON fixtures for tests and development.

Fixtures run through the same normalizers as live responses, so parsers are genuinely exercised rather than first meeting real data in production.

A caveat worth stating plainly: browser mode depends on Reddit's DOM, and Reddit ships redesigns. The extractors are written to fail loudly rather than silently return empty threads that look like "no discussion found."

Programmatic use

import { scoreRelevance, factCheck, styleCheck, packs, composePacks } from 'reddit-radar-mcp';
import config from './radar.config.js';

const result = scoreRelevance(post, config, { matchedQueries: ['flaky tests'] });
if (result.passed) console.log(result.score, result.reasons);

const gate = factCheck(draft, config.gate);
if (!gate.allowed) console.log(gate.findings);

Ethics and policy

This tool exists to help you find conversations you can genuinely contribute to. It will not help you astroturf.

  • No posting automation. Not implemented, and enforced by test.

  • Disclose affiliation. requireDisclosure is on by default. Undisclosed vendor comments get removed and can earn a permanent ban, which ends the channel entirely.

  • One account. Reddit's Responsible Builder Policy prohibits registering multiple accounts for the same use case. Do not use this to run a sockpuppet network.

  • Threads are scored, never people. Nothing here profiles an author, in line with Reddit's prohibition on inferring user characteristics.

  • Respect subreddit rules. TECHNICAL_ONLY exists because pitching in the wrong place is both rude and counterproductive.

Environment variables

Variable

Default

Purpose

RADAR_CONFIG

Required. Absolute path to your config (.js ESM with a default export, or .json).

REDDIT_MODE

browser

browser, live, or fixture. See docs/REDDIT-ACCESS.md.

REDDIT_CLIENT_ID

live mode only.

REDDIT_CLIENT_SECRET

live mode only.

REDDIT_USER_AGENT

live mode only. Must be <platform>:<appid>:<version> (by /u/<user>).

REDDIT_QPM

60

Rate limit for live mode. Lower than Reddit's advertised 100 on purpose.

RADAR_LOG_LEVEL

info

silent, error, warn, info, debug.

RADAR_LOG_FORMAT

json

json or text.

Full annotated list in .env.example.

Logs go to stderr only. On stdio transport stdout carries the JSON-RPC protocol, so anything written there corrupts the stream. Credentials in URLs and sensitive keys are redacted before logging.

Troubleshooting

Everything scores as an opportunity. Your domainTerms are too generic or missing. That list is what anchors a post to your domain, and without it the shape signals carry posts on their own. Config validation treats an empty list as an error for this reason.

Nothing scores at all. Check that domainTerms uses words that actually appear in post titles. Terms of 5+ characters match simple inflections (pipelinepipelines); shorter ones match exactly, so app will not match apps.

A good draft is blocked as thin substance. Pass your vocabulary as anchorTerms — the MCP server does this from your config automatically, but a direct styleCheck() call needs it explicitly.

An honest limitation is blocked. It should not be; denials are explicitly allowed. Please report it.

Reddit shows "Prove your humanity". A cold search can hit a JS challenge. Loading any subreddit page first usually clears it for the session.

"Cannot use import statement outside a module". Your config is a .js file in a project without "type": "module", so Node parses it as CommonJS. Either name it radar.config.mjs or add "type": "module" to the nearest package.json. A .json config avoids the question entirely, at the cost of regex literals and composePacks.

More in SUPPORT.md.

Tests

npm test       # 33 unit tests
npm run smoke  # 14 checks over the real MCP wire protocol
npm run verify # everything, including the metadata consistency guard

The safety suite asserts that no client exposes a write method, no source file references a Reddit write endpoint, and the package exports no posting function.

Contributing

Issues and PRs welcome — see CONTRIBUTING.md. Note the permanent exclusions listed there: posting automation, multi-account support, and AI-detection evasion are deliberate non-goals rather than missing features.

Support this project

If this saves you time, sponsoring on GitHub helps keep it maintained. Entirely optional — the package is MIT and always will be.

Non-financial contributions are just as useful: a bug report with a reproducing config, a rule pack that generalizes, or a note about a scoring case that surprised you.

License

MIT — see LICENSE.

-
license - not tested
Not graded
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
2Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Agentic Reddit/HN buying-signal detection for Claude Code, Cursor, and Windsurf via MCP.

  • A personal RAG database you build from chat, so AI creates work that sounds like you.

  • Reddit & X data for AI agents over MCP. Semantic search, hosted, no Reddit API.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sourav2024/reddit-radar-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server