# Connect Mastra to Axiom

**Transport:** stdio (Mastra MCP client also supports HTTP/SSE)
**Auth:** local-stdio (Phase 0)
**Status:** Untested — recipe inferred from upstream docs

Mastra is a TypeScript-first agent framework. It ships its own MCP
client (`@mastra/mcp`) that pulls Axiom's MCP tools into a Mastra
`Agent` as native tools.

## Install prerequisites

```bash
npm install @mastra/core @mastra/mcp @ai-sdk/anthropic
```

(Use `pnpm` or `yarn` if those are your conventions.) Same Axiom
prerequisites — Python venv with the Axiom package importable.

## Configure the connection

```typescript
// agent.ts
import { Mastra } from "@mastra/core";
import { Agent } from "@mastra/core/agent";
import { MCPClient } from "@mastra/mcp";
import { anthropic } from "@ai-sdk/anthropic";

const mcp = new MCPClient({
  servers: {
    "axiom-root": {
      command: "/absolute/path/to/.venv/bin/axi",
      args: ["mcp", "serve"],
      // env: { PYTHONPATH: "..." },  // worktree variant
    },
  },
});

const tools = await mcp.getTools();
console.log("Loaded Axiom tools:", Object.keys(tools));

const diagnostician = new Agent({
  name: "axiom_diagnostician",
  instructions:
    "You inspect the local Axiom node via its MCP tools. " +
    "Always show the raw JSON result of any tool call.",
  model: anthropic("claude-sonnet-4-5"),
  tools,
});

const result = await diagnostician.generate(
  "Call axiom_node__hooks_list with no arguments and show the JSON."
);
console.log(result.text);
```

Worktree variant:

```typescript
const mcp = new MCPClient({
  servers: {
    "axiom-root": {
      command: "/absolute/path/to/.venv/bin/python3",
      args: ["-m", "axiom.extensions.builtins.mcp.server"],
      env: { PYTHONPATH: "/absolute/path/to/axiom-checkout/src" },
    },
  },
});
```

## Verify

The script above prints the tool list and the agent's response. A
direct check (no model call):

```typescript
import { MCPClient } from "@mastra/mcp";

const mcp = new MCPClient({
  servers: { "axiom-root": { command: "axi", args: ["mcp", "serve"] } },
});

const tools = await mcp.getTools();
const result = await tools["axiom-root_axiom_node__hooks_list"].execute({
  context: {},
});
console.log(result);
```

Expected:

```json
{
  "node": "/Users/<you>/.axiom",
  "hooks_total": 0,
  "events_observed": [],
  "by_event": {}
}
```

## Notes

- Mastra prefixes tool names with the server key (`axiom-root_<name>`)
  to avoid collisions across servers in `getTools()` output. The MCP
  protocol-level name is unchanged.
- Mastra's `MCPClient` opens the subprocess on first `getTools()` call
  and reuses it for the lifetime of the client object. Call
  `mcp.disconnect()` for clean shutdown.
- For HTTP/SSE: `url: "https://..."` instead of `command`/`args`; needs
  Axiom Phase 5 auth.
- Mastra runs on Node 18+ — check your runtime if you hit
  `fetch is not defined` or similar.

## Troubleshooting

| Symptom | Likely cause | Fix |
|---|---|---|
| `Error: ENOENT axi` | Node `spawn` PATH issue | Use absolute path |
| Tools missing | server crashed on init | Run `axi mcp serve` in a terminal first |
| `getTools()` hangs | stdio deadlock | Confirm `axi` writes to stdout and not stdin; pipe stderr separately |

## References

- ADR-038 §D7
- Mastra MCP docs: https://mastra.ai/en/docs/tools-mcp/mcp-overview

_Copyright (c) 2026 B-Tree Ventures, LLC. Apache-2.0 licensed._
