Rubberband is a web chat host for analytics and visualization MCP Apps. It lets a user ask natural-language analytics questions, choose which MCP apps are available for that turn, render app previews inline, and interact with those previews without leaving the chat.
The default configuration installs Elastic MCP apps plus a Trino/Starburst visualization app. Rubberband is intentionally not tied to one backend: Elastic, Trino, Starburst, and future MCP analytics apps are treated as pluggable sources behind the same host, settings, visualization contract, and chat workflow.
Rubberband's own source code is MIT licensed. Default and optional MCP apps are third-party software with their own licenses; see THIRD_PARTY_NOTICES.md.
- React chat UI with inline MCP App rendering through
@mcp-ui/client. - Express/TypeScript backend that owns MCP stdio or HTTP connections.
- OpenAI-compatible chat completion integration.
- LangGraph Deep Agents (
deepagents) runner for bounded read-only Elastic and Trino/Starburst analysis. - Instance-level MCP app/tool exposure policy plus per-chat app selection.
- Bidirectional MCP App bridge for iframe preview interactions and tool calls.
- Final-result preview handling so the user sees one final renderable result, not intermediate tool attempts.
- Background Elastic and Trino/Starburst metadata profiling shared by all users.
- Runtime settings UI with env-locked fields, session-scoped overrides, and connection tests.
- Host-side read-only MCP guard that hides write-capable tools and blocks mutating SQL/API arguments.
- Layman error explanations with sanitized context.
- Suggested follow-up actions/questions.
- Multimodal image attachments and paste support.
- Chat export to GitHub-flavored Markdown ZIP, DOCX, and PDF with preview images preserved.
- Browser voice-to-text input where supported.
- Docker build-time MCP app installation from Git or local zip.
flowchart LR
User[User browser] --> Client[React chat UI]
Client -->|REST + SSE| Server[Express server]
Server --> Sessions[Session manager]
Server --> Settings[Settings store]
Server --> Chat[OpenAI chat orchestrator]
Server --> DeepAgent[LangGraph Deep Agents runner]
Server --> Registry[MCP registry]
Server --> Profiler[Background analytics profile service]
Server --> Errors[Error explainer]
Chat -->|OpenAI-compatible API| LLM[LLM gateway]
DeepAgent -->|ChatOpenAI| LLM
DeepAgent --> ProfilerTools[Read-only profiler tools]
Registry -->|stdio or HTTP| Apps[MCP Apps]
Apps --> ElasticApps[Elastic apps]
Apps --> TrinoApp[Trino/Starburst app]
Profiler --> Elastic[(Elasticsearch)]
Profiler --> Trino[(Trino / Starburst)]
ProfilerTools --> Elastic
ProfilerTools --> Trino
ElasticApps --> Elastic
TrinoApp --> Trino
Client --> Renderer[MCP App iframe renderer]
Renderer -->|MCP Apps bridge| Client
Client -->|tool/resource proxy| Server
| Area | Main files | Responsibility |
|---|---|---|
| Browser host | src/client/main.tsx, src/client/styles.css |
Chat state, app selection, settings UI, AppRenderer bridge, preview controls, local history. |
| API server | src/server/index.ts |
Express routes, static client hosting, SSE progress stream, request error handling. |
| Chat orchestration | src/server/openai-chat.ts |
OpenAI-compatible chat loop, MCP tool schema conversion, final-preview selection, follow-up suggestions, deep-analysis routing. |
| LangGraph Deep Agents | src/server/deep-agent-runner.ts |
deepagents runner with read-only Elastic and Trino/Starburst profiler tools backed by ChatOpenAI. |
| MCP lifecycle | src/server/mcp-registry.ts, mcp-apps.installed.json |
App manifest loading, stdio/HTTP client lifecycle, tool/resource/prompt proxies, environment passthrough. |
| Runtime settings | src/server/settings.ts, src/server/session.ts |
Env-backed locked settings, per-session overrides, reconnect behavior. |
| Analytics profiling | src/server/analytics-profile-service.ts, src/server/elastic-profiler.ts, src/server/trino-profiler.ts |
Bounded metadata cache for Elastic and Trino/Starburst. |
| Error explanation | src/server/error-explainer.ts |
Secret redaction, local fallback explanations, optional LLM-generated RCA/fix guidance. |
sequenceDiagram
participant U as User
participant C as React client
participant S as Express /api/chat
participant O as Chat orchestrator
participant L as LLM API
participant R as MCP registry
participant A as MCP app
U->>C: Submit prompt
C->>S: POST /api/chat with messages + selected app ids
S->>O: runChat(registry, settings, messages, appIds)
O->>R: list selected tools
O->>L: chat completion with tool schemas + app skills
L-->>O: assistant message or tool calls
loop Tool-call turns
O->>R: callTool(appId, toolName, args)
R->>A: MCP tool call
A-->>R: tool result
R-->>O: serialized result
O->>L: send tool result back to model
L-->>O: next tool calls or final answer
end
O-->>S: final answer + latest renderable preview only
S-->>C: JSON response
C-->>U: Render final answer and preview
Rubberband keeps only the latest renderable MCP result for a chat response. If the model or app produces multiple visual previews during a tool loop, intermediate previews are treated as implementation detail and not shown as separate final cards.
sequenceDiagram
participant I as MCP App iframe
participant C as React host
participant S as Express tool proxy
participant R as MCP registry
participant A as MCP app server
I->>C: User clicks Apply / edits preview controls
C->>S: POST /api/apps/:appId/tools/call
S->>R: registry.callTool(appId, toolName, arguments)
R->>A: MCP tool call
A-->>R: updated preview payload
R-->>S: tool result
S-->>C: JSON result
C->>C: replace current preview payload in place
C-->>I: remount renderer with refreshed result
This is the bidirectional path used by apps such as mcp-app-trino. The app owns its native preview controls, while Rubberband owns the bridge, session auth, and host-side state replacement.
Rubberband can export the current visible chat from the top bar:
- GitHub-flavored Markdown as a ZIP containing
chat.mdplus anassets/directory. - DOCX with chat text and embedded images.
- PDF with chat text and embedded images.
Exports include user image attachments, data:image/* payloads returned by tools, and browser-captured MCP preview frames where the rendered preview is available in the chat.
sequenceDiagram
participant Server as Rubberband server
participant Profile as Analytics profile service
participant Elastic as Elasticsearch
participant Trino as Trino / Starburst
participant Disk as Local profile snapshot
participant Chat as Chat request
Server->>Profile: start()
Profile->>Disk: load previous snapshot
Profile->>Elastic: bounded metadata profile
Profile->>Trino: bounded metadata profile
Profile->>Disk: save latest snapshot
Chat->>Profile: getPromptContext()
Profile-->>Chat: compact shared catalog context
alt missing/stale/error
Chat->>Profile: refreshNow(reason)
Profile-->>Chat: queue/continue background refresh
end
Profiling is intentionally read-only and bounded. It collects metadata, not full data scans. Chat uses the latest successful snapshot so users do not wait for catalog discovery during normal prompts.
Rubberband includes a LangGraph Deep Agents integration through the deepagents package. The implementation lives in src/server/deep-agent-runner.ts and uses:
createDeepAgentandStateBackendfromdeepagents.ChatOpenAIfrom@langchain/openai, pointed at the same OpenAI-compatible provider settings used by normal chat.- LangChain
tool(...)wrappers with Zod schemas for bounded read-only profiler calls.
Deep-analysis routing starts in src/server/openai-chat.ts. The chat composer includes a Deep Analysis toggle that sends the request through a LangGraph Deep Agent orchestrator with the selected MCP tools still available, so normal chart/dashboard prompts can still produce MCP Apps UI previews. Prompts containing terms such as deep analysis, profile, analyze, index catalog, table catalog, canned analytics, or suggested questions are also classified as analysis requests. Target detection maps keyword-triggered profile requests to:
elastic: Elastic / Elasticsearch index analysis.trino: Trino or Starburst catalog/table analysis.all: federated or cross-source Elastic plus Trino/Starburst analysis.
When the toggle is off, keyword-triggered analysis first uses AnalyticsProfileService so repeated analysis prompts can answer from the shared background profile snapshot without making users wait for catalog discovery. When Deep Analysis is toggled on, Rubberband uses a direct Deep Agent workflow over the selected MCP tools and instructs the agent to call visualization tools for chart, dashboard, and preview requests instead of only describing them.
The Deep Agents runner exposes two read-only tools:
profile_elastic_cluster_readonly: inspects bounded Elasticsearch metadata and field capabilities. It does not write data, create aliases, update mappings, reindex, or scan full documents.profile_trino_starburst_readonly: inspects bounded Trino/Starburst catalogs, schemas, tables, and columns through metadata queries. It does not write data or scan business table rows.
The agent system prompt requires the profiler tools before recommendations, forbids write/DDL/DML suggestions as part of the analysis, and requires caveats for bounded or inferred cross-source relationships. Domain Knowledge from settings is passed into the agent request so local context can guide recommendations without inventing unobserved tables, indices, fields, or join keys.
Deep Agent model settings:
OPENAI_BASE_URL: normalized to the provider base URL, even if the configured value includes/chat/completions.OPENAI_API_KEY: reused for the Deep AgentChatOpenAImodel.OPENAI_AUTH_SCHEME: supportsBearer,none, or custom authorization schemes.OPENAI_MODEL: model name for Deep Agent reasoning.OPENAI_TEMPERATURE,OPENAI_TOP_P,OPENAI_MAX_TOKENS: optional Deep Agent model tuning.OPENAI_TIMEOUT_MS: shared normal-chat and Deep Agent LLM timeout.OPENAI_EXTRA_HEADERS: optional JSON object merged into Deep Agent provider headers.DEEP_AGENT_LLM_TIMEOUT_MS: direct Deep Agent LLM timeout, default90000.DEEP_AGENT_RECURSION_LIMIT: maximum LangGraph Deep Agent recursion steps, default32.MAX_DEEP_AGENT_TOOL_CALLS: maximum MCP tool calls during a Deep Analysis chat turn, default24.MAX_DEEP_AGENT_RESULT_CHARS: maximum compact MCP tool-result characters returned to Deep Agents, default4000.
Rubberband can reason across selected Elastic and Trino/Starburst apps, but it keeps execution source-specific unless an app or backend can actually query both sides.
flowchart LR
Prompt[User prompt] --> Selected{Selected apps}
Selected --> ElasticPath[Elastic tools and visualizations]
Selected --> TrinoPath[Trino / Starburst tools and visualizations]
ElasticPath --> ElasticResult[Elastic result or preview]
TrinoPath --> TrinoResult[Trino result or preview]
ElasticResult --> Synthesis[LLM synthesis]
TrinoResult --> Synthesis
Synthesis --> Final[Final answer + one final renderable preview]
Synthesis -. candidate relationships .-> Plan[Safe federated query plan]
Plan -. requires actual execution engine .-> TrinoConnector[Trino connector / materialized view / MCP app support]
Recommended federated workflow:
- Profile each source with bounded metadata.
- Identify candidate relationships from names, fields, columns, and Domain Knowledge.
- Use selected MCP apps to run source-specific queries or visualizations.
- Treat cross-source joins as candidate designs until Trino, a materialized view, or a dedicated app can execute both sides.
The default mcp-apps.json installs:
elastic/example-mcp-dashbuilderelastic/example-mcp-app-securityelastic/example-mcp-app-observabilitymetalshanked/mcp-app-trinoopenai/role-specific-plugins/plugins/data-analytics
Licensing boundary:
- Rubberband source is MIT licensed.
- The Elastic MCP apps above are Elastic License 2.0 upstream projects.
- The Trino visualization app above is MIT licensed upstream.
- The OpenAI Data Analytics plugin declares MIT licensing in its plugin manifest; review upstream notices before production redistribution.
- Rubberband's MIT license does not relicense installed MCP apps.
During Docker build or npm run mcp:install, Rubberband:
- Reads
MCP_APPS_CONFIG, defaulting tomcp-apps.json. - Clones or extracts each configured app. The default config pins Git apps to commit SHAs so Docker builds do not silently float to a new upstream commit. Monorepo apps can set
source.subdirectoryso only the MCP app directory becomes the installed app root. - Runs each app's configured install/build commands.
- Downloads and verifies configured skill packs, then extracts them under the app's
skills/directory. - Scans app skills from
skills/**/SKILL.md. - Writes
mcp-apps.installed.json.
At runtime, McpRegistry reads the installed manifest and starts each app using its configured transport.
flowchart TD
Config[mcp-apps.json] --> Installer[scripts/install-mcp-apps.mjs]
Installer --> Source{Source type}
Source --> Git[Clone Git repo]
Source --> Zip[Extract local zip]
Git --> Install[Run install commands]
Zip --> Install
Install --> Build[Build app]
Build --> SkillPacks[Download configured skill packs]
SkillPacks --> Verify[Verify SHA-256]
Verify --> Skills[Scan skills]
Skills --> Manifest[mcp-apps.installed.json]
Manifest --> Runtime[MCP registry runtime]
Each app entry supports:
source:{ "type": "git", "url": "...", "ref": "<branch-or-40-char-commit-sha>", "subdirectory": "optional/path" }or{ "type": "zip", "path": "./vendor/app.zip", "subdirectory": "optional/path" }role: optional UI/routing role:source,renderer,domain,knowledge, orutility.capabilities: optional tags used for sidebar organization and prompt routing, such asui,trino,renderer,reports, orsemantic.install: command arrays run in the app directory during image build.skillPacks: optional.zipskill assets to download or copy intoskills/; each entry supportsurlorpath, plus optionalsha256.transport: stdio or HTTP runtime connection details.envPassthrough: environment variables copied into the MCP app process.skills: generated at install time from discovered skill files.
Editing mcp-apps.json does not vendor app source into this repository. Run npm run mcp:install locally, or rebuild the Docker image, to install changed apps.
Docker images built from the default Dockerfile include installed MCP app source and build output. Treat those images as Rubberband plus bundled third-party MCP apps, not as an all-MIT distribution.
Rubberband separates selected MCP apps by intent so UI apps and headless servers can be selected together without competing for the same job:
source: live data execution or metadata, such as Trino / Starburst.renderer: presentation and artifact packaging, such as Data Analytics.domain: native domain UI workflows, such as Elastic Security, Observability, or Kibana dashboard builders.knowledge: headless context or semantic servers, such as Confluence, documentation, or semantic catalog MCP servers.utility: supporting tools that do not fit the categories above.
The normal routing pattern for Trino-heavy work is:
- Query or inspect Trino / Starburst with the source app.
- Use native Trino visuals for quick SQL charts or fallback rendering.
- Use Data Analytics only after source-backed rows and runnable SQL/provenance are available, especially for polished charts, tables, reports, dashboards, and artifact validation.
- If Data Analytics validation or rendering fails, Rubberband tells the model or Deep Agent to fall back to the source app native visualization or answer from reviewed rows with SQL/provenance and caveats.
Build and run:
docker build --pull -t rubberband-mcp-chat:latest .
docker run -d --name rubberband-mcp-chat --env-file "$(Resolve-Path .env)" -p 8765:8765 rubberband-mcp-chat:latestThe default image installs the apps from mcp-apps.json at build time. Review THIRD_PARTY_NOTICES.md and each upstream app license before publishing or redistributing an image.
Replace an existing local container:
docker rm -f rubberband-mcp-chat 2>$null
docker build --pull -t rubberband-mcp-chat:latest .
docker run -d --name rubberband-mcp-chat --env-file "$(Resolve-Path .env)" -p 8765:8765 rubberband-mcp-chat:latestOpen:
http://localhost:8765
To serve the whole app and API under a subpath, set BASE_PATH:
BASE_PATH=/rubberbandThen open:
http://localhost:8765/rubberband/
Health check:
Invoke-RestMethod -Uri http://127.0.0.1:8765/api/health | ConvertTo-JsonProfile status:
Invoke-RestMethod -Uri http://127.0.0.1:8765/api/analytics-profile | ConvertTo-Json -Depth 6npm install
npm run mcp:install
npm run devFrontend:
http://localhost:5173
Backend:
http://localhost:8765
For local development without installed MCP apps, the UI still starts but app and tool lists will be empty.
npm run check
npm run build
npm run test:api
npm run test:e2e
npm test
npm run test:docker
npm run test:liveTest behavior:
npm run check: TypeScript checks server and client.npm run build: builds server and Vite client.npm run test:api: Node API smoke tests.npm run test:e2e: Playwright UI tests.npm test: build, API tests, and E2E tests.npm run test:docker: builds Docker image, starts it with.env, checks/api/healthand/api/settings, then stops it.npm run test:live: makes one real chat request using.envLLM settings and an empty MCP manifest.
Rubberband reads configuration from:
- Process environment and
.env. - Runtime settings stored per browser session.
- Built-in defaults.
Fields backed by environment variables are locked in the Settings UI. Unset fields can be edited at runtime. Saving integration settings reconnects MCP apps so child stdio processes receive updated environment values.
Settings sections are collapsed by default to keep the panel scannable.
flowchart LR
Env[.env / process env] --> Settings[Settings store]
Runtime[Runtime session overrides] --> Settings
Defaults[Built-in defaults] --> Settings
Settings --> Server[Server requests]
Settings --> Registry[MCP child process env]
Settings --> Prompt[LLM prompt contracts]
Settings --> Profilers[Background profilers]
Use the ELASTICSEARCH_* names consistently; legacy ES_* names are not read as primary Rubberband settings. The registry adds compatibility aliases for some Elastic app child processes where needed.
Use TRINO_* names for mcp-app-trino; STARBURST_* names are also passed through for compatible Trino apps.
Timeout settings have two scopes. Rubberband-owned profilers, connection tests, autocomplete helpers, and host-side read-only probes use the Rubberband settings below. Third-party source MCP apps run in their own processes; Rubberband passes relevant environment variables to them, but an app must implement support for those variables before they affect that app's internal network calls.
PORT: Express server port, defaults to8765.BASE_PATH: optional app/API mount path such as/rubberband. Leave unset or use/to serve from root. When set, app assets, API routes, SSE, and the MCP sandbox are served below this path.
OPENAI_API_KEY: enables model-driven chat.OPENAI_BASE_URL: OpenAI-compatible endpoint, defaults tohttps://api.openai.com/v1.OPENAI_AUTH_SCHEME: auth prefix for theAuthorizationheader, defaults toBearer. Set tononeif your gateway expects the raw key.OPENAI_MODEL: model name, defaults togpt-4.1-mini.OPENAI_TEMPERATURE: optional temperature for normal chat and Deep Agent calls.OPENAI_TOP_P: optional top-p value for normal chat and Deep Agent calls.OPENAI_MAX_TOKENS: optional output token limit for normal chat and Deep Agent calls.OPENAI_TIMEOUT_MS: optional normal-chat LLM timeout, also used by Deep Agent calls beforeDEEP_AGENT_LLM_TIMEOUT_MS.OPENAI_EXTRA_HEADERS: optional JSON object merged into provider request headers.OPENAI_EXTRA_BODY: optional JSON object merged into normal chat-completions request bodies.MAX_TOOL_LOOPS: maximum chat tool-call loop count.MAX_TOOL_RESULT_CHARS: maximum serialized tool result characters sent back to the model.DEEP_AGENT_LLM_TIMEOUT_MS: direct LangGraph Deep Agent LLM timeout, defaults to90000.DEEP_AGENT_RECURSION_LIMIT: maximum LangGraph Deep Agent recursion steps, defaults to32.MAX_DEEP_AGENT_TOOL_CALLS: maximum MCP tool calls during a Deep Analysis chat turn, defaults to24.MAX_DEEP_AGENT_RESULT_CHARS: maximum compact MCP tool-result characters returned to Deep Agents, defaults to4000.MAX_CONTEXT_MESSAGES: recent messages retained in model context.MAX_CONTEXT_MESSAGE_CHARS: per-message context truncation size.
MCP_ENABLED_APPS: optional comma- or newline-separated allowlist of app ids or wildcard patterns. Empty means every installed app is eligible.MCP_DISABLED_APPS: optional comma- or newline-separated denylist of app ids or wildcard patterns. Deny rules win over allow rules.MCP_ENABLED_TOOLS: optional comma- or newline-separated allowlist of tool patterns. UseappId:toolName, for exampledashbuilder:create_chartormcp-app-trino:*. Empty means every tool from enabled apps is eligible.MCP_DISABLED_TOOLS: optional comma- or newline-separated denylist of tool patterns. Deny rules win over allow rules.MCP_READ_ONLY_MODE: defaults totrue. Rubberband hides and blocks MCP tools that appear to mutate external systems, and blocks mutating SQL/API arguments at execution time.MCP_READ_ONLY_TOOL_ALLOWLIST: optional wildcard list for tool-name false positives. Allowlisted tools are still checked for mutating SQL, HTTP methods, administrative endpoints, and write-like arguments.MCP_CUSTOM_SERVERS_JSON: optional JSON array of custom non-UI Streamable HTTP MCP servers. Each entry becomes a normal selectable MCP app and uses the same app/tool allow and deny policy.MCP_CUSTOM_INSECURE_TLS: whentrue, allows insecure TLS for custom Streamable HTTP MCP servers. Prefer valid TLS outside local testing.MCP_EXPOSURE_REPORT_ON_STARTUP: whentrue, logs an audit report of installed MCP apps, exposed tools, and items hidden by the instance or read-only policy during server startup.
Patterns are case-insensitive shell-style wildcards, not regular expressions. The exposure policy controls what the UI, model tool list, and host-side MCP proxy can use. Read-only mode is a separate Rubberband host guard layered on top. For defense in depth, use upstream credentials that only have read privileges.
Example: expose only Dashbuilder's selected preview tools and all Trino tools:
MCP_ENABLED_APPS=dashbuilder,mcp-app-trino
MCP_ENABLED_TOOLS=dashbuilder:create_chart,mcp-app-trino:*Example custom Streamable HTTP MCP server:
MCP_CUSTOM_SERVERS_JSON=[{"id":"custom-search","name":"Custom Search MCP","url":"https://mcp.example.com/mcp","authType":"bearer","apiKey":"token"}]
MCP_ENABLED_APPS=custom-search
MCP_ENABLED_TOOLS=custom-search:*Supported custom auth forms include authorization, apiKey with authType, apiKeyHeader, and a headers object. OAuth is not wired yet.
MCP_APPS_CONFIG: build-time app installer config path.MCP_APPS_MANIFEST: runtime installed-app manifest path, defaults tomcp-apps.installed.json.MCP_APPS_DIR: directory used by the installer for app source.
ELASTICSEARCH_URLELASTICSEARCH_CLOUD_IDELASTICSEARCH_API_KEYELASTICSEARCH_USERNAMEELASTICSEARCH_PASSWORDELASTICSEARCH_AUTO_CREATE_API_KEY: defaults tofalse. If enabled, Rubberband can create a temporary Elasticsearch API key from username/password for child MCP apps; leave disabled for strictly read-only deployments.ELASTIC_CCS_SEARCH_BY_DEFAULT: whentrue, Rubberband tells the model and background Elastic profiler to use configured cross-cluster search targets by default.ELASTIC_CCS_INDEX_PATTERNS: comma- or newline-separated CCS targets. Usecluster:index-*for explicit targets; alias-only patterns such asremote-prod*are normalized toremote-prod*:*.ELASTIC_CCS_RESOLVE_TIMEOUT_MS: bounded_remote/infoand_resolve/clusterpreflight timeout, defaults to5000.ELASTIC_QUERY_TIMEOUT_MS: shared Rubberband Elasticsearch request timeout, defaults to300000five minutes. It is used by Rubberband's Elastic connection test, Elastic profiler/search/focus paths, and host-side CCS field/index helper calls. Rubberband also passes this value to Elastic MCP app child processes asELASTIC_QUERY_TIMEOUT_MS,ELASTIC_REQUEST_TIMEOUT_MS,ELASTICSEARCH_REQUEST_TIMEOUT_MS, andES_REQUEST_TIMEOUT_MScompatibility aliases.CLUSTERS_JSON: optional Elastic MCP cluster config override. If blank, Rubberband auto-generates the single-cluster JSON required by Elastic Security fromELASTICSEARCH_URL,KIBANA_URL,KIBANA_SPACE_ID, andELASTICSEARCH_API_KEY.CLUSTERS_FILE: optional path to the same cluster config JSON. If set, Elastic Security prefers this overCLUSTERS_JSON.KIBANA_URLKIBANA_SPACE_IDKIBANA_API_KEYKIBANA_USERNAMEKIBANA_PASSWORD
CCS patterns use Elasticsearch wildcard syntax, not regex. Rubberband resolves cluster alias wildcards case-insensitively during profiler preflight when Elasticsearch exposes matching remote aliases.
Elastic profiler controls:
ELASTIC_PROFILER_MAX_INDICESELASTIC_PROFILER_MAX_FIELD_CAPSELASTIC_PROFILER_MAX_FIELDS_PER_INDEXELASTIC_PROFILER_TIMEOUT_MS: legacy profiler request timeout fallback, defaults to8000.ELASTIC_QUERY_TIMEOUT_MStakes precedence for Rubberband-owned Elastic requests.ELASTIC_PROFILER_INCLUDED_PATTERNSELASTIC_PROFILER_EXCLUDED_PATTERNSELASTIC_PROFILER_INCLUDE_DATA_STREAMSELASTIC_PROFILER_INCLUDE_SYSTEM
Example large-cluster scope:
ELASTIC_PROFILER_INCLUDED_PATTERNS=logs-*,metrics-*,traces-*,security-*
ELASTIC_PROFILER_EXCLUDED_PATTERNS=.*,ilm-history-*,slm-history-*
ELASTIC_PROFILER_INCLUDE_DATA_STREAMS=true
ELASTIC_PROFILER_INCLUDE_SYSTEM=falseTRINO_HOSTTRINO_PORTTRINO_SCHEMETRINO_USERTRINO_PASSWORDTRINO_ACCESS_TOKENTRINO_AUTH_TYPETRINO_CATALOGTRINO_SCHEMATRINO_SOURCESTARBURST_HOSTSTARBURST_PORTSTARBURST_SCHEMESTARBURST_USERSTARBURST_PASSWORDSTARBURST_ACCESS_TOKENSTARBURST_CATALOGSTARBURST_SCHEMA
Trino profiler controls:
TRINO_PROFILER_MAX_CATALOGSTRINO_PROFILER_MAX_TABLES_PER_CATALOGTRINO_PROFILER_MAX_COLUMN_TABLES_PER_CATALOGTRINO_PROFILER_MAX_COLUMNS_PER_CATALOGTRINO_PROFILER_INCLUDED_CATALOGSTRINO_PROFILER_EXCLUDED_CATALOGSTRINO_PROFILER_CONCURRENCYTRINO_PROFILER_CACHE_TTL_MSTRINO_PROFILER_TIMEOUT_MS: per-page HTTP timeout for Rubberband-owned Trino/Starburst profiler and read-only probe requests, defaults to12000.TRINO_PROFILER_STATEMENT_TIMEOUT_MS: total statement budget for Rubberband-owned Trino/Starburst profiler and read-only probe pagination, defaults to60000.TRINO_PROFILER_MAX_PAGES_PER_STATEMENT: maximum Trino result pages Rubberband will follow for one profiler/probe statement, defaults to80.
The default Trino profiler cache TTL is one day.
These Trino timeout settings cover Rubberband's host-side Trino profiler, focused evidence, auto-probes, catalog-map path, and connection test. They do not control arbitrary SQL execution inside a selected Trino visualization MCP app unless that app implements and reads matching timeout environment variables.
For large estates, prefer a catalog whitelist:
TRINO_PROFILER_INCLUDED_CATALOGS=iceberg,hive
TRINO_PROFILER_MAX_CATALOGS=4
TRINO_PROFILER_MAX_TABLES_PER_CATALOG=30
TRINO_PROFILER_MAX_COLUMN_TABLES_PER_CATALOG=12ALLOW_INSECURE_TLS=true: master insecure TLS switch for Rubberband server-side outbound requests and child MCP app processes.TRINO_INSECURE_TLS,TRINO_CA_CERT_FILE,TRINO_CA_CERT,TRINO_CLIENT_CERT_FILE,TRINO_CLIENT_CERT,TRINO_CLIENT_KEY_FILE,TRINO_CLIENT_KEY,TRINO_CLIENT_KEY_PASSPHRASE: optional Trino TLS and mTLS settings.STARBURST_INSECURE_TLS,STARBURST_CA_CERT_FILE,STARBURST_CA_CERT,STARBURST_CLIENT_CERT_FILE,STARBURST_CLIENT_CERT,STARBURST_CLIENT_KEY_FILE,STARBURST_CLIENT_KEY,STARBURST_CLIENT_KEY_PASSPHRASE: optional Starburst TLS and mTLS settings.
Use insecure TLS only for internal/self-signed certificates. Browser certificate validation for the user's HTTPS connection to Rubberband is still controlled by the browser and OS.
RUBBERBAND_VIZ_THEMERUBBERBAND_VIZ_PALETTERUBBERBAND_VIZ_DENSITYRUBBERBAND_VIZ_LEGENDRUBBERBAND_VIZ_TOOLTIPRUBBERBAND_VIZ_TIMEZONERUBBERBAND_VIZ_NATIVE_FEATURES
These defaults are included in model guidance and passed to app processes, so Elastic and Trino visualizations can use consistent themes and behavior without losing native app functionality.
ANALYTICS_PROFILER_ENABLEDANALYTICS_PROFILER_RUN_ON_STARTUPANALYTICS_PROFILER_TARGETS:elastic,trino, orall.ANALYTICS_PROFILER_SCHEDULE_MSANALYTICS_PROFILER_STALE_AFTER_MSANALYTICS_PROFILER_STORAGE_FILE
The default snapshot path is .rubberband/analytics-profile.json. Scheduled refreshes and stale checks default to one day.
If ELASTIC_CCS_SEARCH_BY_DEFAULT=true, the Elastic background profile includes the resolved CCS targets from ELASTIC_CCS_INDEX_PATTERNS before local index candidates.
During npm run mcp:install, Rubberband downloads any configured app skill packs, verifies their SHA-256 hashes when provided, extracts them under skills/, and scans each installed MCP app for skills/**/SKILL.md. Discovered skills are written into mcp-apps.installed.json.
The default Elastic Observability app pins the app source to the v1.1.1 release commit and installs the v1.1.1 skill packs from that same upstream release:
apm-health-summaryapm-service-dependenciesk8s-blast-radiusmanage-alertsml-anomaliesobserve
The default Data Analytics app is installed from the plugins/data-analytics subdirectory of OpenAI's role-specific-plugins repository. Its bundled skills are discovered from that subdirectory and injected only when the Data Analytics app is selected for the turn.
At chat time:
- The user selects one or more apps.
- Rubberband applies the instance MCP exposure policy.
- Rubberband lists tools for the selected and enabled apps.
- Rubberband injects selected app skills into the system prompt.
- The model sees only the selected apps' exposed tools and relevant guidance.
This keeps context bounded and avoids leaking guidance from apps that are not selected for the turn.
MCP Apps can make important preview interactions visible to future chat turns by sending compact app messages through the MCP Apps bridge. Rubberband stores recent analytical events per preview and includes chat-visible events in the next model request.
Recommended event shape:
{
"type": "filter.applied",
"summary": "status = failed",
"details": { "field": "status", "value": "failed" },
"chatVisible": true
}Useful chat-visible events:
selection.changedfilter.appliedquery.reranrow.openedbrush.selecteddrilldown.requested- time-range changes
Avoid sending hover, resize, focus, debug, or heartbeat messages as chat-visible events.
Rubberband returns both technical errors and user-friendly explanations when possible.
sequenceDiagram
participant Client
participant Server
participant Explainer as Error explainer
participant LLM as LLM API
Server-->>Client: technical error path fails
Server->>Explainer: sanitized error + route metadata
alt LLM configured and available
Explainer->>LLM: sanitized explanation request
LLM-->>Explainer: layman RCA JSON
else no LLM or timeout
Explainer-->>Server: local heuristic explanation
end
Server-->>Client: safe headline, likely causes, suggested fixes
The explainer sanitizes tokens, credentials, URLs, and stack-like details before sending context to an LLM.
Common endpoints:
GET /api/health: server health.GET /api/settings: current settings snapshot.POST /api/settings: update runtime settings.GET /api/events: session progress event stream.GET /api/apps: MCP apps exposed by the instance policy.GET /api/tools: MCP tools currently exposed to the user after instance and read-only filtering.GET /api/mcp/exposure: audit report of installed apps, exposed/hidden apps, exposed/hidden tools, and active policy settings.POST /api/apps/:appId/tools/call: host-side app tool proxy.POST /api/apps/:appId/resources/read: app resource read proxy.POST /api/apps/:appId/resources/list: app resource list proxy.POST /api/apps/:appId/resources/templates/list: app resource template proxy.POST /api/apps/:appId/prompts/list: app prompt list proxy.POST /api/chat: chat orchestration.GET /api/analytics-profile: background profiler status.POST /api/analytics-profile/refresh: request profiler refresh.
When BASE_PATH is set, prefix all endpoints with that path. For example, BASE_PATH=/rubberband exposes health at /rubberband/api/health.
- Run Rubberband behind HTTPS in shared environments.
- Keep
.envout of source control. - Prefer least-privilege read-only data source credentials.
- Use
MCP_ENABLED_APPSandMCP_ENABLED_TOOLSto limit shared instances to the apps and tools users actually need. - Keep
MCP_READ_ONLY_MODE=truefor shared deployments, and keepELASTICSEARCH_AUTO_CREATE_API_KEY=falseunless you explicitly accept that write. - Keep profiler bounds conservative for large Trino and Elastic estates.
- Use include patterns/catalogs to scope profilers before increasing global limits.
- Treat
ALLOW_INSECURE_TLS=trueas a local/internal-only escape hatch. - Set
BASE_PATHwhen serving behind a reverse proxy subpath, and proxy the whole subpath to Rubberband. - Review and pin third-party MCP app refs before production builds.
- Rebuild Docker after changing MCP app source config or upstream app refs.
- Restart or reconnect MCP apps after runtime integration setting changes.
Check:
docker logs --tail 120 rubberband-mcp-chatCommon causes:
- App install failed during Docker build.
mcp-apps.installed.jsonmissing or stale.- Required app environment variables are missing.
- App child process cannot start.
- App repo ref changed and image was not rebuilt.
Use tighter bounds:
TRINO_PROFILER_INCLUDED_CATALOGS=iceberg,hive
TRINO_PROFILER_MAX_CATALOGS=4
TRINO_PROFILER_MAX_TABLES_PER_CATALOG=20
TRINO_PROFILER_MAX_COLUMN_TABLES_PER_CATALOG=8
TRINO_PROFILER_CONCURRENCY=2
TRINO_PROFILER_STATEMENT_TIMEOUT_MS=30000
TRINO_PROFILER_MAX_PAGES_PER_STATEMENT=40The profiler is backgrounded, but it should still be bounded enough to avoid tying up metadata services.
Use the timeout that matches the request owner:
ELASTIC_QUERY_TIMEOUT_MS: Rubberband-owned Elasticsearch requests and compatibility env passed to Elastic child MCP apps, default300000.ELASTIC_CCS_RESOLVE_TIMEOUT_MS: fast CCS metadata preflight and autocomplete resolution, default5000.TRINO_PROFILER_TIMEOUT_MS: Rubberband-owned Trino/Starburst per-page request timeout, default12000.TRINO_PROFILER_STATEMENT_TIMEOUT_MS: Rubberband-owned Trino/Starburst total statement budget, default60000.TRINO_PROFILER_MAX_PAGES_PER_STATEMENT: Rubberband-owned Trino/Starburst pagination bound, default80.
If the timeout happens inside a selected third-party MCP app's own query tool, Rubberband can pass environment variables but cannot force that app's internal client timeout unless the app supports it. Keep Rubberband code changes separate from mcp_apps/* source when you want to preserve upstream app code.
A 403 from Elasticsearch is usually credentials, permissions, or license/security feature state. Rubberband will surface the target as an error while still allowing other profile targets, such as Trino, to complete.
The app must implement the bidirectional tool call and return an updated MCP UI payload. Rubberband proxies onCallTool, but only renderable MCP UI results replace the current preview; background polling/data calls stay local to the iframe. If a specific app still does nothing, inspect that app's bridge/tool implementation and server logs.
Rubberband is designed to show only the final renderable tool result for chat responses. If multiple previews appear, check whether they are from older chat messages, iframe-local UI inside one preview, or a custom app returning multiple visual artifacts in one payload.
src/client/main.tsx React UI, chat state, AppRenderer bridge
src/client/styles.css Client styling
src/server/index.ts Express server and API routes
src/server/openai-chat.ts Chat orchestration and tool loop
src/server/deep-agent-runner.ts LangGraph Deep Agents analysis runner
src/server/mcp-registry.ts MCP app lifecycle, tools, resources
src/server/settings.ts Settings model and runtime overrides
src/server/session.ts Browser session isolation
src/server/progress.ts Server-sent progress events
src/server/error-explainer.ts Sanitized layman RCA/fix generation
src/server/mcp-tool-policy.ts MCP exposure policy, read-only visibility, and call guard
src/server/analytics-profile-service.ts
Shared background profile cache
src/server/elastic-ccs.ts Elastic cross-cluster search settings and prompt helpers
src/server/elastic-profiler.ts Bounded Elastic metadata profiler
src/server/trino-profiler.ts Bounded Trino/Starburst metadata profiler
scripts/install-mcp-apps.mjs Build-time MCP app installer
mcp-apps.json Default app install config
.env.example Configuration template
tests/api API smoke tests
tests/e2e Playwright UI tests
Use .env.example as the template. The checked-in .env should remain local-only.
Rubberband source code is licensed under the MIT License. See LICENSE.
Default MCP apps, optional MCP apps, npm dependencies, external services, and generated installed-app artifacts are licensed separately by their respective owners. See THIRD_PARTY_NOTICES.md.