HEX
Server: Apache/2.4.46 (Win64) OpenSSL/1.1.1j PHP/8.4.25
System: Windows NT DESKTOP-4TAV2RJ 10.0 build 19045 (Windows 10) AMD64
User: fred (0)
PHP: 8.4.25
Disabled: NONE
Upload Files
File: C:/Users/fred/.codex/.tmp/plugins/plugins/metabase/skills/setup-metabase-mcp/SKILL.md
---
name: setup-metabase-mcp
description: Read these instructions before using Metabase MCP tools. Setup is needed to connect to Metabase instances through the Metabase app-backed connector.
---

**Read this entire skill file end-to-end before taking any action.** Do not skim, do not stop at the first matching step, and do not act on the summary alone. The gates, failure modes, prohibitions, and post-setup rules are scattered through the document.

**Follow these instructions exactly as written.** Do not make assumptions, do not silently substitute "equivalent" actions, and do not bypass the app-backed connector flow. If a step says stop, stop.

---

Configure the Metabase Codex plugin so the user can connect to a ready Metabase instance through the Metabase app-backed connector. This skill assumes the instance itself is already set up and has the MCP feature enabled - that is the job of the `setup-metabase-instance` skill, not this one.

The plugin is app-backed. `../../.app.json` is a static app mapping, not a per-user runtime config file. Do not rewrite `.app.json` with the user's Metabase URL, and do not create or restore `.mcp.json` as a workaround.

## Valid Instance URL Formats

- Local development: `http://localhost:3000`
- Metabase Cloud: `https://yourcompany.metabaseapp.com`
- Self-hosted: `https://metabase.yourcompany.com`

## Required Actions

1. Read `../../.app.json` (relative to this `SKILL.md` - two directories up, the plugin root). It must contain a Metabase app entry with a non-empty app or connector ID.

   Expected shape:

   ```json
   {
     "apps": {
       "metabase": {
         "id": "templated_apps_6a044bbd332881919b553bdfc2240952"
       }
     }
   }
   ```

   If `apps` is empty or there is no `metabase` entry, stop and tell the user:

   > This Metabase plugin is missing its Codex app mapping. Ask the plugin maintainer to add the Metabase app or connector ID to `.app.json`, reinstall the plugin, and start a new chat.

   Do not continue, do not edit `.app.json`, and do not run `codex mcp login`.

2. Stop all other exploration. Ask the user: "Do you have a Metabase instance URL, or would you like to set up a local instance?"

   - **If they provide a URL**: continue with step 3.
   - **If they don't have one and want to set up a local instance**: invoke the `setup-metabase-instance` skill. That skill spins up Metabase, walks the user through first-run setup, and returns with a ready URL (typically `http://localhost:3000`). Continue here with that URL.

3. Sanity-check that the URL points at a **ready-to-use** Metabase instance. Run all three probes:

   ```bash
   curl -s <INSTANCE_URL>/api/session/properties | grep -o '"tag":"[^"]*"'
   curl -s <INSTANCE_URL>/api/session/properties | grep -o '"has-user-setup":[a-z]*'
   curl -s -o /dev/null -w "%{http_code}\n" <INSTANCE_URL>/api/mcp
   ```

   All three must pass:

   - Version tag's major version is **>= 60**.
   - `"has-user-setup":true` - instance has an admin account and is past the first-run wizard.
   - `/api/mcp` response code is **`401`** - endpoint live, OAuth required.

   If any fails, **stop**. Do not run OAuth and do not modify plugin files. Failure modes:

   - **`has-user-setup:false`** - the instance is running but has never been initialized. If this is the local instance launched through this workflow, forward to the `setup-metabase-instance` skill so its Gate 1 walks the user through the first-run wizard. If this is a user-supplied Cloud or self-hosted URL, tell the user to open `<INSTANCE_URL>` in their browser, complete the first-run wizard there, and then come back so you can re-run step 3 here.
   - **Version < 60** - tell the user to upgrade Metabase, then stop.
   - **`/api/mcp` returns `404`** - MCP is on by default in 60+ and has no toggle, so this usually means the version is older than reported or the URL is wrong. Ask the user to confirm.
   - **Other HTTP codes** - surface the code to the user and stop.

   **Never call `POST /api/setup`, `POST /api/session`, or any other authenticated Metabase REST endpoint.** Those bypass the OAuth flow this skill depends on. If the user asks you to, refuse.

4. Hand the user to the app-backed connection flow. Tell them:

   > Your Metabase instance is ready. Connect the Metabase app in Codex using this URL: `<INSTANCE_URL>`. Complete the OAuth approval in Metabase, then start a new chat so the app tools are available.

   Do not run `codex mcp login`. This plugin no longer registers a local `.mcp.json` MCP server; authentication belongs to the Codex app connector.

5. Tell the user to start a new chat so the app config and token take effect:

   - **Codex CLI**: `/new`
   - **Codex Desktop**: click **New chat** in the sidebar

   Confirm setup is complete and **stop**. The Metabase tools become available in the new thread.

## After setup: do NOT bypass MCP

Once the app connector is configured, the **only** way to read data from Metabase is through the Metabase app/MCP tools. Do not, under any circumstances:

- Read, copy, snapshot, or query Metabase's H2 application database file directly (`metabase.db`, `metabase.db.mv.db`, `metabase.db.h2.db`, etc.). Even read-only inspection or working from a copy is forbidden.
- Use `sqlite`, `duckdb`, `h2`, JDBC, JDBC tools, Python `sqlalchemy`/`h2`/`jaydebeapi`, or any other client to talk to Metabase's storage.
- Call Metabase REST endpoints (`/api/card`, `/api/dashboard`, `/api/database`, `/api/session`, etc.) to answer the user's question while the new chat is pending.
- Run any other side-channel that bypasses the configured app/MCP server.

If the running chat does not yet expose Metabase tools, the correct response is only to remind the user to start a new chat and stop. Do not offer to inspect internals.