Sooner or later, someone on your team wants to point an AI assistant at the production database. Maybe it’s a support engineer who wants to answer “why is this customer’s invoice stuck?” without writing SQL. Maybe it’s you, wanting Claude or Cursor to draft a gnarly multi-join query against real tables instead of guessing at column names.
The moment you decide to do this, you hit a fork in the road. You can give the AI tool a direct database connection — hand it a connection string and let it talk straight to Postgres or MySQL. Or you can put a broker in between using something like the Model Context Protocol (MCP), so the AI never touches your credentials and only ever sees what you allow.
Both work. They feel similar from the developer’s chair — you type a question, SQL comes back. But under the hood they make very different trade-offs on security, blast radius, and workflow. Here’s how they compare, with concrete examples, so you can pick deliberately instead of by accident.
The two setups, side by side
A direct connection is exactly what it sounds like. The AI tool (or an agent you wrote) holds a connection string like this:
postgresql://app_user:[email protected]:5432/production
Enter fullscreen mode Exit fullscreen mode
It opens a socket to the database and runs whatever SQL the model produces. Simple, fast, and dangerous in ways that aren’t obvious on day one.
A brokered connection puts a server in the middle. The AI client talks to the broker over a standard protocol; the broker holds the actual database credentials and decides what to do with each request. The AI never sees s3cr3t. MCP is the emerging open standard for this pattern — the host acts as a security broker that mediates every AI-to-resource interaction, and it typically authenticates with OAuth rather than a static secret.
Here’s the shape of the difference:
Concern Direct connection Brokered (MCP-style) Who holds DB credentials The AI tool / every client machine The broker only What the AI can run Any SQL, including writes and DDL Whatever the broker permits (often SELECT-only) Auth style Long-lived connection string OAuth token, centrally revocable Network exposure DB reachable from each client Only the broker reaches the DB Audit trail Scattered, per-client Centralized at the broker Setup effort Minimal — paste a string Stand up / connect a broker onceSecurity: where the credentials live
The single biggest difference is who knows the password.
With a direct connection, the connection string ends up in a config file, an environment variable, a chat log, or — if you’re unlucky — pasted into a prompt window that gets stored on someone else’s server. Connection strings are notoriously hard to keep secret: they get hardcoded, committed, disassembled out of compiled binaries, and leaked in client-side code. Once one leaks, an attacker has privileged, unauthenticated access to your data, and rotating the secret means chasing down every place it was copied.
A broker flips this around. The AI tool authenticates to the broker with a token; the broker holds the real credentials in one controlled place. If a laptop is compromised or an employee leaves, you revoke one token instead of rotating a database password everywhere. This is the same reasoning behind putting an API in front of a database instead of letting every client connect directly — the high-value credentials live in a controlled environment you manage, not on every user’s machine.
There’s a catch worth naming: a broker that aggregates access becomes a high-value target itself. If it’s compromised, it can expose everything behind it. That’s why brokers lean hard on least-privilege roles, short-lived tokens, and audit logging — the mitigations matter as much as the pattern.
Blast radius: what can go wrong when the AI is wrong
LLMs hallucinate. That’s tolerable when the worst case is a SELECT that returns nothing. It’s a very different story when the model confidently generates:
-- The model "cleaning up test data"
DELETE FROM users WHERE created_at < '2020-01-01';
Enter fullscreen mode Exit fullscreen mode
With a direct connection using a read-write role, that query runs. With a read-only broker, it’s rejected before it ever reaches the database, because writes and DDL simply aren’t in the set of allowed operations.
You can get read-only safety on a direct connection — by creating a dedicated role and granting it carefully:
-- Direct-connection approach: a read-only role you must maintain yourself
CREATE ROLE ai_readonly LOGIN PASSWORD 'another-secret';
GRANT CONNECT ON DATABASE production TO ai_readonly;
GRANT USAGE ON SCHEMA public TO ai_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO ai_readonly;
-- ...and remember to re-grant for every new table, forever
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO ai_readonly;
Enter fullscreen mode Exit fullscreen mode
This is the right instinct. But notice it’s now your job to keep that role correct as the schema evolves, manage yet another secret, and make sure nobody accidentally hands the AI the read-write role instead. A read-only-by-design broker makes that guarantee structural rather than something you have to remember.
Workflow: schema awareness and the day-to-day loop
Security aside, the two setups feel different to use.
The most common failure mode with AI-generated SQL is invented tables and columns. The fix is giving the model the real schema. With a direct connection you can do this — the AI can introspect information_schema if its role has access:
SELECT table_name, column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'public'
ORDER BY table_name, ordinal_position;
Enter fullscreen mode Exit fullscreen mode
Brokers typically expose this as a first-class capability: “fetch the schema” is a dedicated command, so the model gets accurate table and column names before it writes a line of SQL, which cuts down hallucinated columns. Either way, the lesson is the same — share schema, not credentials — but the broker makes it the default path.
A typical brokered loop looks like this from the user’s side:
You: "How many active subscriptions did we add last month, by plan?"
AI (via broker):
1. fetch schema -> sees subscriptions(plan, status, created_at)
2. draft SQL:
Enter fullscreen mode Exit fullscreen mode
SELECT plan, COUNT(*) AS new_subs
FROM subscriptions
WHERE status = 'active'
AND created_at >= date_trunc('month', now()) - interval '1 month'
AND created_at < date_trunc('month', now())
GROUP BY plan
ORDER BY new_subs DESC;
Enter fullscreen mode Exit fullscreen mode
3. run (read-only) -> returns rows
4. optionally save the query or drop it on a dashboard
Enter fullscreen mode Exit fullscreen mode
That last step hints at the other workflow win: brokers built for analytics often let you save a query or pin it to a dashboard, so a one-off question becomes reusable reporting. Managed MCP servers such as Draxlr implement this shape — read-only, OAuth, schema-aware, with commands to run, save, and chart queries — but the pattern is what matters, and you can assemble it from open-source pieces too.
Direct connections keep it lean: no extra service, no OAuth dance, just a string and a socket. For a throwaway script on a local dev database, that simplicity is genuinely the right call.
Common mistakes
A few gotchas trip people up regardless of which path they choose:
- Reusing your app’s database user for the AI. That role usually has write access and broad grants. Make a separate, minimal role — or let the broker enforce read-only for you.
-
Assuming read-only means safe. A read-only role can still run a
SELECTthat scans a billion rows and pins your CPU, or reads PII it shouldn’t. Scope grants to specific schemas and consider statement timeouts. - Exposing the database to the whole network. With direct connections, every client that queries needs a network path to the DB. A broker shrinks that to one host and keeps the database off the open network.
- Pasting connection strings into prompts. If the tool sends context to a model provider, your credentials may be logged. This is the failure a broker exists to prevent — don’t recreate it by hand.
- No audit trail. With scattered direct connections you often can’t answer “who asked the AI what, and when?” Centralized logging at a broker gives you one place to look.
Key takeaways
Direct connections win on simplicity: minimal setup, no moving parts, perfect for local experiments and throwaway scripts. The cost is that credentials spread out, the AI can run anything its role allows, and your database sits closer to the open network.
Brokered / MCP-style connections win on safety and governance: credentials stay in one place, access is read-only by design and revocable with a single token, the schema is shared without the secrets, and every query is auditable. The cost is standing up or connecting a broker, plus the responsibility of protecting that broker as a high-value target.
The rough rule of thumb: for a database with anything real in it — customers, revenue, PII — or any setup more than one person touches, put a broker in the middle. For a local sandbox you’d happily drop and recreate, a direct connection is fine. The mistake isn’t picking one; it’s picking by default without noticing there was a choice.
How are you connecting AI tools to your databases today — raw connection strings, a custom API layer, or an MCP server? I’d love to hear what’s worked and what’s bitten you in the comments.
Sources: Anthropic — Introducing MCP, Model Context Protocol — Architecture, SentinelOne — MCP Security Guide, Microsoft — Protecting connection information, Microsoft Security — Least privilege for AI agents, datamcp — PostgreSQL permissions for AI tools.