Skip to content
Conduit

mcp server

rdt-gateway

Headless, read-only gateway for public Reddit data with HTTP, CLI, and MCP interfaces. No Reddit account, API key, or HTML scraping required.

yutakobayashidev/rdt-gatewaycommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 26, 2026

rdt-gateway

A headless, read-only gateway for public Reddit data, with a standalone HTTP server, CLI, and self-contained MCP server. Uses transport code adapted from Redlib; no Reddit account, API key, or HTML scraping is required.

  • rdt-request owns anonymous Reddit authentication and upstream transport.
  • rdt-gateway provides a shared request service with caching and rate limits, an Axum router, and a standalone HTTP executable.
  • rdt provides JSON or readable text from the terminal.
  • rdt-mcp bundles the request service and exposes public posts, comments, communities, and user activity over stdio.

The CLI and MCP server share a Rust SDK that maps requests and normalizes responses. The SDK also offers raw_get() for unmodified JSON structure. Existing Reddit SDK compatibility is not guaranteed.

Package layout

Inspired by twitter_api_safe_relay: a reusable request package, a server library with its own executable, and an MCP package that composes them.

CrateResponsibility
rdt-requestDirect Reddit transport, independent of HTTP serving
rdt-gatewayShared request state/cache, HTTP router, and daemon
rdt-gateway-typesShared responses and errors
rdt-gateway-clientTransport-independent request mapping and normalization, plus the HTTP client
rdt-clirdt CLI using the HTTP client
rdt-mcpMCP library and executable, with an embedded request service

In embedded mode, MCP calls the shared service directly. When HTTP is enabled, both interfaces share authentication, cache, and rate-limit state. Normalization stays in the client library; the gateway returns Reddit JSON.

Quick start

From a checkout, with Nix flakes enabled (gateway and MCP: x86_64 Linux):

nix run .#rdt-gateway

In another terminal:

nix run .#rdt-cli -- search 'nixos flakes' --limit 5
nix run .#rdt-cli -- posts rust --sort new
nix run .#rdt-cli -- post POST_ID
nix run .#rdt-cli -- comments POST_ID --depth 3 --limit 50

The gateway listens on 127.0.0.1:8787. Set RDT_GATEWAY_LISTEN to change it, or RDT_GATEWAY_URL to point either client at another gateway. The HTTP endpoint has no authentication.

CLI

The rdt-cli Nix package and app are available for x86_64 Linux, aarch64 Linux, and Apple Silicon macOS. They provide the rdt executable, which connects to a gateway over HTTP.

With rdt installed (or using nix run .#rdt-cli --):

rdt [--url URL] [--json | --text] [--verbose] COMMAND
  search QUERY [--subreddit NAME]
  posts NAME
  post POST
  read POST
  comments POST
  subreddit search QUERY
  subreddit info NAME
  subreddit wiki NAME [--page index]
  subreddit rules NAME
  user info NAME
  user posts NAME
  user comments NAME
  completions bash|zsh|fish

Names accept r/name or u/name as appropriate. POST accepts a post ID, t3_ID, or Reddit post URL; - reads one value from stdin. Wiki pages can contain nested paths such as faq/install.

rdt subreddit search 'self hosting' --limit 5
rdt posts popular --sort top --time week
rdt user comments USERNAME --sort new
rdt read POST_URL --expand-more --max-requests 3 --limit 100 --text
rdt search 'nixos flakes' --limit 1 | jq -r '.data[0].id' | rdt read -
rdt completions zsh > _rdt

Search and listing commands accept --limit (default 20, maximum 100) and --cursor from meta.next_cursor; they do not automatically fetch subsequent pages. Post search defaults to relevance, subreddit posts to hot, and user history to new. Use --help for supported --sort values. --time hour|day|week|month|year|all filters searches or top/controversial listings.

read returns the post and comments together; comments returns only comments. Both accept --depth (default 3, maximum 8; top-level comments are depth 1) and a total comment --limit (default 50, maximum 200). --expand-more fetches omitted comments using /api/morechildren.json. Its --max-requests budget defaults to 3, maximum 10, and includes the initial post/comment request but excludes authentication. Without expansion, only the initial request is made.

JSON is the default, independent of TTY; --json makes it explicit and --text renders readable text. Results go to stdout and diagnostics to stderr. --verbose reports the gateway origin and elapsed time. Output is uncolored (--no-color and NO_COLOR are supported); commands never prompt. Gateway selection is --url > RDT_GATEWAY_URL > http://127.0.0.1:8787.

Responses use {data, meta} with citation URLs and fetch time. meta.requests counts SDK transport calls, including cache hits, not physical Reddit requests. meta.truncated and truncation_reasons describe omitted content. A failed comment expansion preserves the available result and adds meta.partial_error; the CLI exits 1. Exit codes are 0 for success (including empty results and requested limits), 1 for retrieval failures, 2 for invalid arguments, and 130 for interruption.

MCP

nix build .#rdt-mcp --out-link result-mcp

Configure your MCP client to launch the absolute path to result-mcp/bin/rdt-mcp using stdio. It runs on its own; no separate gateway or CLI is required.

To also serve the HTTP gateway from the same process, pass --listen 127.0.0.1:8787. To use an existing gateway instead, pass --gateway-url http://127.0.0.1:8787 or set RDT_GATEWAY_URL. Remote mode and --listen are mutually exclusive. Unset RDT_GATEWAY_URL when using embedded mode.

Diagnostics go to stderr. Closing the MCP session or sending SIGINT/SIGTERM stops the process and its optional HTTP listener.

The 12 tools share the CLI's SDK, limits, normalized responses, and partial-result metadata:

  • Posts: reddit_search, reddit_list_posts, reddit_get_post, reddit_read, reddit_get_comments.
  • Communities: reddit_search_subreddits, reddit_get_subreddit, reddit_get_wiki, reddit_get_rules.
  • Users: reddit_get_user, reddit_list_user_posts, reddit_list_user_comments.

MCP uses typed arguments such as expand_more and max_requests; no CLI subprocess or raw-query tool is involved. Partial retrieval failures return the available data with the MCP error flag set.

Raw HTTP

curl 'http://127.0.0.1:8787/r/rust/hot.json?limit=5&raw_json=1'

GET /{path} forwards relative .json paths and query parameters to Reddit, including /api/*.json. Upstream requests use GET with anonymous authentication and a fixed Reddit origin; write methods and invalid paths are rejected. Successful responses preserve Reddit's JSON structure; x-reddit-fetched-at records the original fetch time. GET /health returns 200 with { "ok": true } when the gateway is running; it does not contact Reddit or report upstream availability. The gateway does not strip a /reddit prefix; update HTTP clients and the gateway together when migrating from prefixed URLs.

NixOS

Add this repository as a flake input named rdt-gateway, then:

{
  imports = [ inputs.rdt-gateway.nixosModules.default ];
  services.rdt-gateway.enable = true;
}

OpenAI Secure MCP Tunnel

Add openai-secure-tunnel-nix to your flake inputs:

inputs.rdt-gateway.url = "github:yutakobayashidev/rdt-gateway";
inputs.openai-secure-tunnel-nix = {
  url = "github:nakasyou/openai-secure-tunnel-nix";
  inputs.nixpkgs.follows = "nixpkgs";
};

This module runs the self-contained MCP server through the tunnel. Pass inputs through specialArgs:

{ inputs, pkgs, ... }:
let
  packages = inputs.rdt-gateway.packages.${pkgs.stdenv.hostPlatform.system};
  tunnelService = "tunnel-client-rdt-gateway";
in
{
  imports = [
    inputs.openai-secure-tunnel-nix.nixosModules.tunnel-client
  ];

  services = {
    openai-tunnel-client.instances.rdt-gateway = {
      enable = true;
      settings = {
        config_version = 1;
        control_plane = {
          tunnel_id = "tunnel_YOUR_ID";
          api_key = "file:/run/credentials/${tunnelService}.service/api-key";
        };
        health.listen_addr = "127.0.0.1:18792";
        admin_ui.open_browser = false;
        mcp.commands = [{
          channel = "main";
          command = "${packages.rdt-mcp}/bin/rdt-mcp";
        }];
      };
    };
  };

  systemd.services.${tunnelService} = {
    serviceConfig.LoadCredential = [
      "api-key:/run/secrets/openai-tunnel-api-key"
    ];
  };
}

Replace tunnel_YOUR_ID with your tunnel ID. Provision the API key at /run/secrets/openai-tunnel-api-key using your secret manager; never put the key in a Nix expression. The tunnel launches the self-contained stdio MCP server; no separate gateway service or public listener is needed. See the OpenAI guide for tunnel creation and ChatGPT setup.

Updating app versions

From the checkout, run bash scripts/update_oauth_resources.sh with Bash, curl, ripgrep, and coreutils available (also included in nix develop). It fetches Android app versions from APKCombo and regenerates crates/rdt-request/src/oauth_resources.rs. Review the diff before committing. HTTP errors or unexpected page markup leave the existing file untouched.

Use --output /tmp/oauth_resources.rs to preview without replacing the checked-in file. Updater tests run with python3 -m unittest discover -s scripts/tests.

The Update OAuth resources workflow runs every Monday at 03:17 UTC (12:17 JST), or manually from Actions on main. It fetches versions, compiles the generated Rust file, and creates or updates a PR on automation/update-oauth-resources only when there is a diff. Fetch or validation failures stop the run without publishing changes.

Enable Allow GitHub Actions to create and approve pull requests in Settings → Actions → General → Workflow permissions. No extra secret is needed. PRs created with GITHUB_TOKEN do not trigger pull-request CI automatically; run CI manually on automation/update-oauth-resources before merging. Updates are never automatically merged.

CI

GitHub Actions runs on pull requests and pushes to main. It runs the updater’s Python tests, workspace Rust tests, and a NixOS service smoke test, and builds all three executables. Dependencies come from the locked nixpkgs input; actions are pinned to commit SHAs.

Run nix flake check -L for workspace tests and the NixOS service smoke test (requires Linux with KVM), then nix build --no-link .#rdt-gateway .#rdt-cli .#rdt-mcp for the packages.

License

AGPL-3.0-only. See NOTICE for Redlib attribution and source provenance.

↑↓ navigate openesc close