Skip to main content

MCP Database Access

Use the Sqlite component to let Claude query databases.

Code

#!/usr/bin/env bun

import {
  createSmithersRoot,
  createSmithersDB,
  SmithersProvider,
  Claude,
  Sqlite,
} from "smithers-orchestrator";

async function main() {
  const db = await createSmithersDB({ path: ".smithers/data-analysis" });
  const executionId = await db.execution.start("Data Analysis", "data-analysis.tsx");

  function DataAnalysis() {
    return (
      <SmithersProvider db={db} executionId={executionId}>
        <Claude
          model="sonnet"
          maxTurns={10}
          onFinished={(result) => {
            console.log("Analysis complete!");
            console.log(result.output);
          }}
        >
          <Sqlite path="./ecommerce.db" readOnly>
            E-commerce database with the following schema:

            users(id, name, email, created_at, country)
            orders(id, user_id, total, status, created_at)
            order_items(id, order_id, product_id, quantity, price)
            products(id, name, category, price, stock)
          </Sqlite>

          Generate a comprehensive business report:

          1. Revenue Analysis
             - Total revenue by month (last 12 months)
             - Revenue by product category
             - Average order value trends

          2. Customer Analysis
             - Top 10 customers by lifetime value
             - Customer acquisition by country
             - Repeat customer rate

          3. Product Performance
             - Best selling products
             - Products with low stock
             - Category performance comparison

          Save the report as a markdown file: reports/business-report.md
        </Claude>
      </SmithersProvider>
    );
  }

  try {
    const root = createSmithersRoot();
    await root.mount(DataAnalysis);

    await db.execution.complete(executionId, {
      summary: "Data analysis complete",
    });
  } catch (err) {
    const error = err instanceof Error ? err : new Error(String(err));
    await db.execution.fail(executionId, error.message);
    throw error;
  } finally {
    await db.close();
  }
}

main();
If you restrict allowedTools, include any MCP tools you need (for Sqlite, allow sqlite), or omit allowedTools to avoid blocking DB access.

Multiple Databases

<Claude model="sonnet" maxTurns={15}>
  <Sqlite path="./users.db" readOnly>
    User database: users, profiles, preferences
  </Sqlite>

  <Sqlite path="./analytics.db" readOnly>
    Analytics database: events, sessions, pageviews
  </Sqlite>

  Cross-reference data between the two databases:

  1. Find users who signed up but never logged an event
  2. Identify most active users by session count
  3. Correlate user preferences with behavior patterns
</Claude>

Read-Only for Safety

<Sqlite path="./production.db" readOnly>
  Production database - read-only access for safety.
</Sqlite>

Workflow with Database

Excerpt: render DataWorkflow inside a SmithersProvider that supplies db and executionId.
import { Claude, If, Sqlite, useSmithers } from "smithers-orchestrator";
import { useQueryValue } from "smithers-orchestrator/reactive-sqlite";

function DataWorkflow() {
  const { db, reactiveDb } = useSmithers();

  const { data: phase } = useQueryValue<string>(
    reactiveDb,
    "SELECT value FROM state WHERE key = 'phase'"
  );
  const currentPhase = phase ?? "analyze";

  const setPhase = (newPhase: string) => {
    db.state.set("phase", newPhase);
  };

  return (
    <>
      <If condition={currentPhase === "analyze"}>
        <Claude
          model="sonnet"
          onFinished={(result) => {
            db.state.set("findings", result.output);
            setPhase("report");
          }}
        >
          <Sqlite path="./data.db" readOnly>
            Sales database.
          </Sqlite>
          Analyze Q4 sales performance.
        </Claude>
      </If>

      <If condition={currentPhase === "report"}>
        <Claude
          allowedTools={["Write"]}
          onFinished={() => setPhase("done")}
        >
          Create a formatted report from these findings:
          {db.state.get("findings")}

          Save to reports/q4-analysis.md
        </Claude>
      </If>
    </>
  );
}