Skip to content

Mastra

Dinobase integrates with Mastra via MCP. Mastra has first-class MCP support, so Dinobase’s MCP server works with zero adapter code.

Terminal window
npm install @mastra/core @mastra/mcp @ai-sdk/anthropic zod
pip install dinobase

Set up your data sources:

Terminal window
dinobase init
dinobase add stripe --api-key sk_test_...
dinobase add hubspot --api-key pat-...
dinobase sync

See Connecting Sources for the full list of 100+ supported sources, and Syncing & Scheduling for background sync options.

import { Agent } from "@mastra/core";
import { MCPClient } from "@mastra/mcp";
import { anthropic } from "@ai-sdk/anthropic";
// Connect to Dinobase MCP server
const mcp = new MCPClient({
id: "dinobase-mcp",
servers: {
dinobase: {
command: "dinobase",
args: ["serve"],
},
},
});
// All 7 Dinobase tools discovered automatically
const agent = new Agent({
id: "data-analyst",
name: "Data Analyst",
instructions: "You are a data analyst. Query business data via SQL.",
model: anthropic("claude-sonnet-4-6"),
tools: await mcp.listTools(),
});
const response = await agent.generate(
"Which customers have overdue invoices?"
);
console.log(response.text);
await mcp.disconnect();

Mastra’s MCPClient spawns the Dinobase MCP server as a subprocess (dinobase serve) and communicates via stdio. All 7 Dinobase MCP tools are discovered automatically and made available to the agent.

This is the same MCP server used by Claude Desktop and Vercel AI SDK — same tools, same data, different framework.

Via MCP, the agent gets access to:

ToolDescription
queryExecute SQL queries (DuckDB dialect)
describeGet table schema, types, and sample data
list_sourcesList connected sources with freshness status
refreshRe-sync a stale data source
confirmExecute a pending mutation (write-back)
confirm_batchExecute multiple pending mutations
cancelCancel a pending mutation

If you want more control over tool behavior, you can wrap the Dinobase CLI using createTool():

import { createTool } from "@mastra/core/tools";
import { z } from "zod";
import { execSync } from "child_process";
export const dinobaseQuery = createTool({
id: "dinobase-query",
description: "Execute SQL against Dinobase",
inputSchema: z.object({
sql: z.string().describe("SQL query to execute"),
}),
outputSchema: z.object({ result: z.string() }),
execute: async ({ sql }) => ({
result: execSync(`dinobase query ${JSON.stringify(sql)}`, {
encoding: "utf-8",
}),
}),
});

See examples/tools.ts for all four tool wrappers.

Keep data fresh while the MCP server runs:

const mcp = new MCPClient({
id: "dinobase-mcp",
servers: {
dinobase: {
command: "dinobase",
args: ["serve", "--sync", "--sync-interval", "30m"],
},
},
});