Analytics MCP Guide

Connect Claude Code or Claude Desktop to the merged analytics database โ€” read-only, two-step setup.

What you get

An MCP (Model Context Protocol) server that lets Claude query the merged analytics MySQL cluster directly using natural language. Ask "how many bot trades happened yesterday?" and Claude writes the SQL, runs it, and explains the result. Read-only โ€” Claude can't write, update, delete, or run DDL even if it tries.

Schemas exposed:

  • pricing โ€” 7 tables, refreshed every 15 min (item_eod once daily).
  • steamarbitrage โ€” 51 tables, mostly refreshed every 15 min.
Compatibility
Claude Code
โœ“ Works
Claude Desktop
โœ“ Works
Cursor / Continue / Zed
โœ“ Works
claude.ai web
โœ— Not yet
Why not claude.ai web? This MCP runs locally on your machine. Web Claude only talks to remote (HTTPS) MCP servers. A web-compatible variant is on the roadmap โ€” see "Future: web access" at the bottom of the page.
How it works

The cluster lives inside our VPC (eu-west-1c) and is not internet-accessible. To reach it from your laptop, you tunnel through the bastion using AWS Session Manager, then point the MCP server at localhost:13307. Claude talks to the MCP server over stdio, the MCP server talks to MySQL.

[ Claude Code / Desktop ] โ”‚ stdio [ analytics-mysql-mcp.sh ] โ† fetches password from Secrets Manager โ”‚ stdio [ npx @benborla29/mcp-server-mysql ] โ”‚ TCP [ 127.0.0.1:13307 ] โ† SSM port-forward (you keep open in another terminal) โ”‚ [ tradeit-analytics-merged ] โ† inside VPC, eu-west-1c
Before you start

You need:

  • AWS CLI signed in to account 037333185217, region eu-west-1. Verify with aws sts get-caller-identity.
  • Permissions: ssm:StartSession on the bastion + secretsmanager:GetSecretValue on tradeit-analytics/merged-aurora-analytics-ro. If you can't read the secret, ping Ehud.
  • Session Manager Plugin: brew install --cask session-manager-plugin (Mac) or install for Windows / Linux.
  • Node.js 18 or newer (for npx): brew install node or nvm install 20.
  • jq: brew install jq.
  • The tradeit-analytics repo cloned locally โ€” that's where the wrapper script lives.
Step 1 โ€” Open the SSM tunnel
1
Tunnel from your laptop to the cluster

Open a terminal and run this command. Leave it running โ€” closing this terminal closes the tunnel.

aws ssm start-session --target i-09307b996e59fc707 --region eu-west-1 \
  --document-name AWS-StartPortForwardingSessionToRemoteHost \
  --parameters 'host=tradeit-analytics-merged.cluster-crwayzab6rxf.eu-west-1.rds.amazonaws.com,portNumber=3306,localPortNumber=13307'

You should see Waiting for connections.... That's the tunnel โ€” your machine's localhost:13307 now points at the Aurora cluster.

Test it from another terminal:

nc -zv 127.0.0.1 13307
# Connection to 127.0.0.1 port 13307 [tcp/*] succeeded!
Heads-up: the tunnel disconnects after ~30 min of idle, after laptop sleep, or VPN flap. If MCP queries start failing, re-run the tunnel command. (For a one-line auto-restart pattern, see "Pro tip" at the bottom.)
Step 2 โ€” Wire it into your Claude
2
Add the MCP server to your config

The wrapper script lives at infra/mcp/analytics-mysql-mcp.sh in the tradeit-analytics repo. Get its absolute path:

cd ~/Projects/tradeit-analytics
realpath infra/mcp/analytics-mysql-mcp.sh
# /Users/you/Projects/tradeit-analytics/infra/mcp/analytics-mysql-mcp.sh

Then drop the snippet into the right config file for your client:

Edit ~/.claude.json and add the entry under mcpServers. Use the absolute path you printed above.

~/.claude.json
{
  "mcpServers": {
    "analytics-mysql": {
      "command": "/Users/you/Projects/tradeit-analytics/infra/mcp/analytics-mysql-mcp.sh"
    }
  }
}

If mcpServers already has other entries, add analytics-mysql alongside them. Save the file. Claude Code picks it up on the next session โ€” close and reopen, or claude from the terminal again.

Mac: edit ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json

claude_desktop_config.json
{
  "mcpServers": {
    "analytics-mysql": {
      "command": "/Users/you/Projects/tradeit-analytics/infra/mcp/analytics-mysql-mcp.sh"
    }
  }
}

Restart Claude Desktop after saving. The MCP server appears as a tool the next time you start a chat.

Both Cursor and Continue support MCP over stdio. The exact config location varies by version; check their docs. The shape is identical:

"mcpServers": {
  "analytics-mysql": {
    "command": "/Users/you/Projects/tradeit-analytics/infra/mcp/analytics-mysql-mcp.sh"
  }
}
Step 3 โ€” Verify
3
Ask Claude something

Start a new Claude conversation and try one of these. The first time, Claude may ask to confirm using the new tool.

  • "List all tables in the steamarbitrage schema."
  • "How many rows are in pricing.bot_trade_item_logs?"
  • "Show me the watermark status โ€” table_name, last_run_at, status โ€” from pricing._repl_state."
  • "Top 10 affiliates by revenue in the last 7 days."

If the answers come back, you're connected. If you see a connect ECONNREFUSED error, your tunnel isn't running โ€” check Step 1.

What's queryable

Two schemas Claude can read. Freshness is replication-driven โ€” see the _repl_state table in each schema for live watermarks.

SchemaTablesCadenceNotes
pricing 7 + _repl_state 15 min (item_eod daily) Pricing engine inputs/outputs from pricing-test source.
steamarbitrage 51 + _repl_state 15 min (guess_questions 4-hourly) Trading lifecycle from steamarbitrage-cluster source.
PII not yet redacted. The analytics_ro user can read everything, including emails and Steam IDs. Treat MCP output as engineer-only until OPS-160 ships the analytics_safe redacted views.
Security & safety

Three layers of read-only enforcement:

  1. The analytics_ro MySQL user has SELECT grants only.
  2. The wrapper script forces ALLOW_INSERT_OPERATION=false, ALLOW_UPDATE_OPERATION=false, ALLOW_DELETE_OPERATION=false, ALLOW_DDL_OPERATION=false on every spawn.
  3. Per-query timeout 30s, 20 qps client-side rate limit.

The password is fetched fresh from Secrets Manager each time the MCP starts โ€” never written to disk in a config file.

Don't share your AWS credentials. The MCP wrapper uses your local AWS profile. If you let someone else's machine run this with your creds, they get analytics-ro access until you rotate. Each teammate sets up their own per the steps above.
Troubleshooting
SymptomFix
connect ECONNREFUSED 127.0.0.1:13307 Your SSM tunnel isn't running. Re-open it (Step 1).
AccessDenied โ€ฆ secretsmanager:GetSecretValue Your AWS user/role lacks the secret read permission. Ping Ehud to add the IAM policy.
npx: command not found Install Node.js 18+: brew install node.
jq: command not found brew install jq.
Claude doesn't see the MCP tool Restart Claude Code/Desktop. Confirm config file path is right (Mac vs Win) and JSON is valid.
Queries hang or time out Tunnel may have dropped silently. Run nc -zv 127.0.0.1 13307; if it fails, re-open the tunnel.
Authentication plugin error Set "env": { "MYSQL_AUTH_PLUGIN": "mysql_native_password" } in your Claude config block.
Pro tip โ€” auto-restart the tunnel

Drop this in a terminal tab and forget about it โ€” the tunnel reconnects every time it drops:

while true; do
  aws ssm start-session --target i-09307b996e59fc707 --region eu-west-1 \
    --document-name AWS-StartPortForwardingSessionToRemoteHost \
    --parameters 'host=tradeit-analytics-merged.cluster-crwayzab6rxf.eu-west-1.rds.amazonaws.com,portNumber=3306,localPortNumber=13307'
  echo "tunnel dropped, reconnecting in 3sโ€ฆ"
  sleep 3
done

Or wrap it as a launchd job so it starts automatically on login. Ehud has a sample plist if you want it.

Future: web access (claude.ai)

For non-engineers (Product, support) who use claude.ai in the browser, we'd need a remote MCP variant:

  1. HTTP-transport MCP server hosted in our VPC (small Fargate task or shared on the bastion).
  2. Cloudflare Tunnel + Cloudflare Access (Google SSO โ€” same pattern as bi.tradeit.gg).
  3. Custom Connector configured in claude.ai with the public URL + OAuth bridge.

Estimated 3-6 hours of setup and ~$5-15/mo ongoing. Tracked under OPS-201 as a Phase 2 follow-up.

Links