npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@seungje.jun/redash-mcp

v0.2.1

Published

Redash MCP server with schema caching and column exploration

Readme

redash-mcp

npm version license node

Expose the Redash API as an MCP (Model Context Protocol) server. Schema, column values, and code-to-label mappings are cached — in memory for schema and persistently on disk for metadata — so repeated lookups skip redundant Redash calls and the model can compose queries without re-exploring the database every time.

한국어 문서 / Korean README

Installation & Setup

npx (no installation required)

Add the following to ~/.mcp.json.

{
  "mcpServers": {
    "redash": {
      "command": "npx",
      "args": ["@seungje.jun/redash-mcp"],
      "env": {
        "REDASH_URL": "https://redash.example.com",
        "REDASH_API_KEY": "your-key"
      }
    }
  }
}

Build from source

git clone https://github.com/ninanung/redash-mcp.git
cd redash-mcp
npm install
npm run build

Add the following to ~/.mcp.json.

{
  "mcpServers": {
    "redash": {
      "command": "node",
      "args": ["/path/to/redash-mcp/dist/cli.js"],
      "env": {
        "REDASH_URL": "https://redash.example.com",
        "REDASH_API_KEY": "your-key"
      }
    }
  }
}

Restart Claude Code to activate the MCP tools.

Environment Variables

| Variable | Description | |----------|-------------| | REDASH_URL | Redash server URL (single-instance mode, required when REDASH_INSTANCES is unset) | | REDASH_API_KEY | Redash API Key (single-instance mode) | | REDASH_INSTANCES | (optional) JSON array for multi-instance mode. Example: [{"name":"prod","url":"...","api_key":"...","allowed_data_sources":[1,2]},{"name":"dev","url":"...","api_key":"..."}]. When set, pass instance: "prod" on any tool call to pick the target. Falls back to the first entry if instance is omitted. | | REDASH_ALLOWED_DS | (optional) Comma-separated list of allowed data source IDs (e.g. 1,3,7). When set, all other IDs are blocked and list_data_sources only returns allowed ones. | | REDASH_MCP_LOG | (optional) Log level: debug, info (default), warn, error, silent. Logs go to stderr to avoid corrupting the MCP stdio channel. | | REDASH_MCP_AUDIT_LOG | (optional) Audit log file path. Defaults to ~/.redash-mcp/audit.log. Set to off to disable. Each line is a JSON record with tool name, args, duration, status. | | REDASH_QUERY_TIMEOUT_MS | (optional) Default query timeout in ms (default 120000). Override per-call via execute_query's timeout_ms argument. | | REDASH_SUMMARIZE_THRESHOLD | (optional) Row count above which execute_query auto-summarizes results (per-column min/max/distinct/null + 10 sample rows). Default 500. save_csv disables auto mode. Override per call with summarize:"never". | | REDASH_MASK_COLUMNS | (optional) Column-name patterns to mask in result rows (comma-separated, * wildcard supported). Include builtin to also mask common PII columns (email, phone, SSN/RRN, password, token, card). Example: builtin,user_name,addr* | | REDASH_DEFAULT_FORMAT | (optional) Default result encoding for execute_query / execute_saved_query: json (default) or compact. A per-call format argument overrides it. | | REDASH_DEFAULT_MAX_ROWS | (optional) Default row cap for execute_query / execute_saved_query when the call passes no max_rows (default 1000). | | REDASH_RESULT_HINTS | (optional) Set to off to drop the trailing LLM guidance from query results ("IMPORTANT: include the executed SQL verbatim…", "To save this query, use save_query…"). Default: on. Useful when your own prompt governs presentation or save_query is not exposed. | | REDASH_METADATA_TTL_DAYS | (optional) Metadata cache TTL in days. When set, entries older than this are treated as cache misses by explore_column / find_mapping / get_schema and are re-fetched; get_cache output tags them [stale]. Unset = keep forever. |

Tools

| Tool | Description | |------|-------------| | list_data_sources | List available data sources | | self_test | Diagnostic check — verifies env vars, Redash connectivity, and schema access | | get_schema | Fetch table/column schema (keyword filter, cached) | | execute_query | Run SQL (only SELECT/WITH allowed; job polling handled automatically; auto-injects LIMIT max_rows — default 1000 — when the query has none; format: "compact" returns rows as arrays at about a quarter of the size) | | explain_query | Run EXPLAIN for a query without executing it — inspect cost / scan plan before a heavy run (engine-specific support) | | explore_column | Inspect unique values/counts and infer column types (supports multiple columns at once) | | sample_rows | Return a few raw rows from a table (default 5) to inspect real column values at a glance | | describe_table | Combined schema + sample rows for a single table | | find_table | Find tables by column name and/or table-name keyword (useful when locating join targets) | | join_hints | List other tables that share column names with the given table — candidate join keys | | find_mapping | Automatically find mapping tables for numeric code columns | | save_query | Save a SQL query to Redash (supports description and tags) | | update_query | Update name/query/description/tags of an existing saved query | | list_saved_queries | List queries already saved in Redash (supports search + data source filter) | | get_saved_query | Fetch SQL and metadata of a saved query by ID, including declared parameters (name, type, stored default, enum choices) and who last saved it | | execute_saved_query | Run a saved query by ID with optional parameters; omitted parameters fall back to the stored defaults, a p_ URL-style prefix is stripped, values are converted to the declared parameter type (text / number), unknown names are rejected with the accepted list, and the result echoes the parameter values actually used | | list_dashboards | List Redash dashboards (search supported) | | get_dashboard | Fetch widgets of a dashboard and the query IDs they reference | | get_cache | Read the metadata cache (column types/values, mapping tables, recommended tables) | | export_metadata_cache | Export the metadata cache to a JSON file (share across a team or back up) | | import_metadata_cache | Import a metadata cache from a JSON file (merge/replace modes) |

Usage Example

A typical natural-language flow, as orchestrated by the MCP client:

  1. User: "Find me the orders table and show yesterday's revenue."
  2. list_data_sources → pick the target data_source_id.
  3. get_schema with keyword order → locate candidate tables/columns.
  4. explore_column on status/type columns → understand enum values and infer types.
  5. find_mapping on code columns (e.g. status_cd) → resolve numeric codes to labels.
  6. execute_query → run the final SELECT and return rows.
  7. (Optional) save_query → persist the SQL back to Redash.

Subsequent runs reuse the metadata cache, so step 4–5 often short-circuits via get_cache.

Safety & Constraints

  • Read-only SQL: only statements starting with SELECT or WITH are allowed. DML/DDL keywords (INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE, MERGE, GRANT, REVOKE, CALL, EXEC, ...) are rejected even if buried inside a CTE. Multiple statements separated by semicolons are also blocked. Comments and string literals are stripped before the scan to prevent keyword-smuggling.
  • Row-limit guardrail: execute_query auto-injects LIMIT max_rows (default 1000) when the query has no LIMIT, preventing accidental full-table scans from blowing up the model context. Override with the max_rows argument or include an explicit LIMIT in the SQL.
  • CSV export: pass save_csv: "/path/to/out.csv" to execute_query to write the full result to disk instead of (or in addition to) returning it through the model context.
  • Automatic schema recovery: if a query fails with a "table/column not found" style error, the schema cache for that data source is invalidated and refreshed. For a missing column, the actual columns of the tables referenced in FROM/JOIN are returned; for a missing table, up to 50 similarly named tables are suggested. Either way the model can fix the query in one retry.
  • Compact output: format: "compact" (or REDASH_DEFAULT_FORMAT=compact) encodes columns/column_types as arrays and rows as arrays of values with no indentation. Row caps are announced in the notes ("Returned the first M rows" / "Returned the first M of N rows").
  • Job polling: Redash async jobs are polled until completion; only the final result is returned to the client.
  • No write API: the server does not expose any endpoint that mutates Redash state other than save_query (creating a new saved query).

Data Source Selection

  • data_source_id is a required argument on every query-related tool (execute_query, get_schema, explore_column, find_mapping, save_query).
  • Call list_data_sources first to discover available IDs; the MCP client is expected to pass the chosen ID explicitly.
  • There is no implicit "default data source" — this is intentional, to avoid accidentally querying the wrong database when multiple sources are configured.
  • Set REDASH_ALLOWED_DS=1,3,7 to restrict the server to specific data source IDs. Any other ID is rejected before hitting Redash, and list_data_sources / list_saved_queries return only the allowed subset.

Cache

  • Schema cache: in-memory, kept alive while the server runs. Refreshed automatically when a query execution hits a table/column error. Manual refresh is available via refresh: true on get_schema, which also asks Redash to rebuild its own server-side schema cache (this is what picks up newly created tables). Every get_schema response starts with a status line: cached/fresh, table count, and fetch time.
  • Metadata cache: persisted to ~/.redash-mcp/metadata-cache.json. Results from explore_column and find_mapping are stored automatically and reused on subsequent lookups. Keys are prefixed with ds<id>: so the same table name in different data sources never collides.

Cache Location & Reset

| Cache | Location | Reset | |-------|----------|-------| | Schema | in-memory (per server process) | restart the MCP server, or call get_schema with refresh: true | | Metadata | ~/.redash-mcp/metadata-cache.json | delete the file (rm ~/.redash-mcp/metadata-cache.json) — it will be recreated on the next write |

The metadata cache file is a plain JSON document — safe to inspect, edit, or back up manually.

License

MIT