Supabase MCP lets Claude Code query your Postgres database directly using natural language. Combined with search enrichment, your AI agent can answer questions like 'which customers match companies recently funded?' by joining internal data with live web results. This tutorial sets up Supabase MCP, configures read-only access for safety, and adds a search enrichment step that augments query results with fresh web data. Cost: $0.005 per search enrichment query.
Prerequisites
- A Supabase project with data
- Supabase service role key or read-only key
- Claude Code installed
- Python 3.9+ and requests library
Walkthrough
Step 1: Configure Supabase MCP in Claude Code
Add the Supabase MCP server to your .mcp.json. Use a read-only key to prevent accidental writes.
import json
from pathlib import Path
mcp_config = {
'mcpServers': {
'supabase': {
'command': 'npx',
'args': ['-y', '@supabase/mcp-server'],
'env': {
'SUPABASE_URL': 'https://your-project.supabase.co',
'SUPABASE_KEY': 'your-read-only-key-here'
}
}
}
}
mcp_path = Path('.mcp.json')
if mcp_path.exists():
existing = json.loads(mcp_path.read_text())
existing['mcpServers']['supabase'] = mcp_config['mcpServers']['supabase']
mcp_config = existing
mcp_path.write_text(json.dumps(mcp_config, indent=2))
print('Supabase MCP configured in .mcp.json')
print('Restart Claude Code to connect.')Step 2: Query Supabase from Python for enrichment
Use the Supabase Python client to pull data that you want to enrich with search results. This example pulls customer companies to research.
import os
from supabase import create_client
SUPABASE_URL = os.environ['SUPABASE_URL']
SUPABASE_KEY = os.environ['SUPABASE_KEY']
supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
# Pull companies to research
result = supabase.table('customers').select('id, company_name, domain').limit(10).execute()
companies = result.data
print(f'Loaded {len(companies)} companies to enrich')
for c in companies[:5]:
print(f' {c["company_name"]}: {c["domain"]}')Step 3: Enrich database records with live search
For each company from Supabase, search the web for recent news, funding, or hiring signals and write the enrichment back.
import requests
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
def enrich_company(company: dict) -> dict:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
json={'query': f'{company["company_name"]} funding news 2026',
'country_code': 'us', 'num_results': 3})
results = resp.json().get('organic_results', [])
signals = []
for r in results:
snippet = r.get('snippet', '').lower()
if any(w in snippet for w in ['funding', 'raised', 'series', 'acquisition']):
signals.append('funding_news')
if any(w in snippet for w in ['hiring', 'job', 'careers', 'open role']):
signals.append('actively_hiring')
return {
'company_id': company['id'],
'top_result': results[0]['title'] if results else '',
'signals': list(set(signals)),
'results_count': len(results)
}
enriched = [enrich_company(c) for c in companies[:5]]
for e in enriched:
print(f' Company {e["company_id"]}: {e["signals"] or ["no signals"]} -- {e["top_result"][:50]}')
print(f'Cost: {len(enriched)} searches = ${len(enriched) * 0.005:.3f}')Python Example
import os, requests
from supabase import create_client
supabase = create_client(os.environ['SUPABASE_URL'], os.environ['SUPABASE_KEY'])
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
companies = supabase.table('customers').select('id, company_name').limit(5).execute().data
for c in companies:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
json={'query': f'{c["company_name"]} news 2026', 'country_code': 'us', 'num_results': 3})
top = resp.json().get('organic_results', [{}])[0].get('title', 'N/A')
print(f'{c["company_name"]}: {top}')JavaScript Example
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY);
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
async function enrichCompanies() {
const { data: companies } = await supabase.from('customers').select('id, company_name').limit(5);
for (const c of companies) {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: `${c.company_name} news 2026`, country_code: 'us', num_results: 3 })
});
const top = (await resp.json()).organic_results?.[0]?.title || 'N/A';
console.log(`${c.company_name}: ${top}`);
}
}
enrichCompanies();Expected Output
Loaded 10 companies to enrich
Acme Corp: acme.io
TechFlow: techflow.dev
Company 1: ['funding_news'] -- Acme Corp Raises $15M Series A
Company 2: ['actively_hiring'] -- TechFlow Careers - 12 Open Roles
Company 3: ['funding_news', 'actively_hiring'] -- DataSync Acquir
Cost: 5 searches = $0.025