Skip to content

bborn/blazer-mcp

Repository files navigation

blazer-mcp

Let Claude operate Blazer — explore data sources, write and run SQL, and build dashboards

blazer-mcp adds an authenticated Model Context Protocol (MCP) endpoint to a Rails app running Blazer. Claude (Claude Code, Claude Desktop, claude.ai) connects to it and does anything a person can do in the Blazer web UI — every tool maps 1:1 to a Blazer UI action and runs through Blazer's own API, so an MCP action and the equivalent click are identical, audit rows included.

Installation

Add this line to your application's Gemfile:

gem "blazer-mcp"

Run:

rails generate blazer:mcp:install

This creates config/initializers/blazer_mcp.rb. Then mount the engine in config/routes.rb:

mount Blazer::Mcp::Engine, at: "/mcp/blazer"

The endpoint will not work until you configure authentication.

Tools

Claude gets twelve tools, each mapping to a Blazer UI action.

Read:

  • list_data_sources — list the data sources available to query
  • get_schema — tables and columns for a data source
  • list_queries — list saved queries (optional search)
  • get_query — a saved query's SQL and variables
  • run_query — run a saved query or draft SQL and return rows
  • list_dashboards — list dashboards
  • get_dashboard — a dashboard and its ordered queries
  • list_checks — list checks (alerts)

Write:

  • create_query — save a new query
  • update_query — update a query
  • create_dashboard — create a dashboard from a list of queries
  • update_dashboard — rename a dashboard or replace its queries

Set read_only to drop the write tools.

Authentication

The gem ships no OAuth server and no role model. Authentication and authorization are two callables you supply — the host app owns identity and policy. Set them in config/initializers/blazer_mcp.rb.

authenticate turns a request into a user, or nil (which returns a 401):

Blazer::Mcp.authenticate = ->(request) { ... return a user or nil ... }

authorize decides whether that user may use the endpoint (a falsey return returns a 403). It defaults to allowing any authenticated user:

Blazer::Mcp.authorize = ->(user) { user.admin? }

Three recipes follow. None ship as gem code — they touch host models.

Doorkeeper

If your app is already an OAuth Authorization Server via Doorkeeper, reuse its opaque-token lookup:

Blazer::Mcp.authenticate = ->(request) do
  token = request.authorization.to_s.delete_prefix("Bearer ")
  access_token = Doorkeeper::AccessToken.by_token(token)
  next nil unless access_token&.accessible?
  User.find_by(id: access_token.resource_owner_id)
end

Managed provider (JWT / JWKS)

If a managed provider (Auth0, WorkOS, Stytch) issues JWT access tokens, verify the signature against its JWKS endpoint:

Blazer::Mcp.authenticate = ->(request) do
  token = request.authorization.to_s.delete_prefix("Bearer ")
  next nil if token.empty?
  payload, = JWT.decode(token, nil, true, algorithms: ["RS256"], jwks: JWKS_LOADER)
  User.find_by(external_id: payload["sub"])
rescue JWT::DecodeError
  nil
end

Static token (development)

For local development and CI, the gem ships a generic static-token helper:

Blazer::Mcp.authenticate = Blazer::Mcp::Auth.static_token(ENV.fetch("BLAZER_MCP_TOKEN"))

Do not use this in production. The claude.ai and Claude Desktop connector UIs cannot send a static token — only OAuth credentials — so a production server must sit behind OAuth.

The 401 response carries a WWW-Authenticate header advertising resource_metadata_url so MCP clients can discover your Authorization Server. The gem does not serve .well-known documents — your host app does.

Security

run_query runs whatever SQL it is given, exactly like the Blazer query editor's Run button. The gem adds no SQL filtering.

Use a read-only database user for your Blazer data sources, as Blazer recommends. This is the real guardrail against destructive queries.

max_rows is a presentation cap on the MCP payload, not a query-cost guard — the data source timeout and a read-only DB user are the real protection against expensive queries.

Set read_only to remove the four write tools entirely:

Blazer::Mcp.read_only = true

Query results can contain PII. Serve the endpoint over TLS and rotate tokens.

Configuration

# Callable -> (request) { user_or_nil }. Required, no default.
Blazer::Mcp.authenticate = ->(request) { ... }

# Callable -> (user) { bool }. Default: allow any authenticated user.
Blazer::Mcp.authorize = ->(user) { user.admin? }

# OAuth protected-resource metadata URL, advertised on a 401. Default: nil.
Blazer::Mcp.resource_metadata_url = "https://api.example.com/.well-known/oauth-protected-resource"

# Remove the four write tools. Default: false.
Blazer::Mcp.read_only = false

# Maximum rows returned by run_query. Default: 500.
Blazer::Mcp.max_rows = 500

# Allowlist of Blazer data source ids. Default: nil (all).
Blazer::Mcp.data_sources = ["main", "replica"]

# Base URL of your mounted Blazer UI — write tools return deep links. Default: nil.
Blazer::Mcp.blazer_url = "https://app.example.com/blazer"

# MCP server identity. Defaults are usually fine.
Blazer::Mcp.server_name = "blazer-mcp"
Blazer::Mcp.server_version = Blazer::Mcp::VERSION

Claude client setup

For Claude Code, add the endpoint to .mcp.json:

{
  "mcpServers": {
    "blazer": {
      "type": "http",
      "url": "https://app.example.com/mcp/blazer"
    }
  }
}

For Claude Desktop and claude.ai, add it as a custom connector using the same URL. The connector flow uses OAuth, so the host app must run an OAuth Authorization Server.

Compatibility

  • Ruby 3.3+
  • Blazer 3.x
  • Rails 7.2+

Tested against Blazer 3.2, 3.3, and 3.4, and against mcp 0.8 and 0.17. The mcp gem is pre-1.0 and has shipped breaking changes in minor releases, so only those two versions are proven. A host running multiple MCP servers should pin mcp to a single consistent version across them.

License

The gem is available as open source under the terms of the MIT License.

About

Model Context Protocol server for ankane/blazer — let Claude run, save, and build Blazer SQL queries and dashboards

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages