Home/Work/Case 02

MCP Hub

An air-traffic controller for data. Every app talks to the Hub, the Hub talks to the database, and no app holds a credential.

RoleArchitect & builder
WhenFeb–Aug 2026 · Decasonic
StackNext.js 14 · Supabase · SSE
ModelsAnthropic → OpenAI → xAI
35+codebases that no longer hold DB keys
87tables behind one gateway
11×signal throughput after the audit
Minto onboard an app, down from days
01 / The problem

Every app had
the keys to everything.

Before the Hub, database credentials sat in 35+ codebases. There was no central visibility, no least privilege, and a schema change could break an app without anyone hearing about it. Onboarding a new app was a manual, multi-day job.

I had already designed the shared 87-table schema. The Hub is what made it safe to share.

Credentials copied into every codebase.
No record of who wrote what, or when.
Schema changes break apps silently.
New integrations take days by hand.
One gateway, strict per-app rules, and generated clients.
02 / One request, start to finish

Follow a
single write.

POST /api/gateway with an API key and a payload. Here is what happens to it.

Step 01 · Authenticate

Who is asking?

The key is validated and the app's status checked. Apps move from pending to configured to active, and promote themselves on their first successful request.

Step 02 · Authorize

What are they allowed to touch?

Rate limits and timeouts first, then permissions at the level of the table and the column. An app can be allowed to read a table and still be blocked from one field in it.

Step 03 · Execute and log

Do it, and write it down.

The query runs against Supabase, the request is logged with sensitive values stripped, and raw database errors come back as friendly 400 and 409 messages.

Step 04 · Onboard the next app

An AI handshake between apps.

Paste a new app's discovery file. The model recommends permissions, you review them, and the Hub generates a complete integration client in JS, TS or Python, plus a prompt to paste back into the app's builder.

03 / Before and after

Drag the
line.

A database health audit across the connected apps. Left: what I found. Right: after the fixes.

Before the audit
Signals flowing78
Signals linked to their source run0
Agent runs recorded0
Apps fixed0

~400 CHECK failures from 'prod' vs 'PROD'. Zero rows in every junction table. '[object Object]' saved as a UUID.

After the fixes
Signals flowing864
Signals linked to their source run777
Agent runs recorded72
Apps fixed9

Five failure classes, a four-section fix-prompt template, and permission gaps closed in four apps.

Two lessons I carry everywhere: a gateway 200 doesn't mean the data is useful, and regressions happen during redeploys.

Beforeevery app holds every key
const db = createClient(URL, SERVICE_ROLE_KEY);await db.from('signals').insert(row);// no permissions, no log, no warning
Afterone gateway, least privilege
await fetch(HUB + '/api/gateway', { method: 'POST', headers: { 'x-api-key': process.env.HUB_KEY }, body: JSON.stringify({ operation: 'insert', table: 'signals', data: row })});// checked, rate limited, permitted, logged
04 / Decisions worth explaining
01When do you go around your own gateway?

Twice, on purpose. Bulk sync writes directly: without upsert, a 150-record sync would take 395+ round trips and hit the rate limit, so it writes straight to the database and still logs to the audit table. Analytics reads go direct with a read-only key, because a dashboard needs joins and window functions the gateway doesn't do.

02What did the first integration teach you?

It hit foreign-key violations, because the generator wasn't passing relationship information into the prompt. I fixed it in the generator, once, and every later integration inherited the fix.

03Why write meanings into the schema?

Human-written table and column descriptions feed the code generator. That's the difference between knowing a status column is a varchar and knowing it's a deal pipeline stage.

04What if a model fails halfway through generating a client?

Generation streams over server-sent events with automatic fallback from Anthropic to OpenAI to xAI if a provider fails or truncates.

Next.js 14Supabase AuthPostgreSQLServer-sent eventsSchema introspection3 LLM providers

Need something like this? I build these end to end, as a full-time engineer, on contract, or with SKAI Group.

Book a 30-min call
Next case · 03Context Engine
Contact

Let's build

Credentials in every repo? I can map it, gate it and audit it.