DEV Community

Vivek Kumar
Vivek Kumar

Posted on

Local vs. Remote MCP Servers for Your Database: Which One Should You Actually Use?

You wired up an AI assistant to your database last week. It reads your schema, writes surprisingly good SQL, and answers questions like "what was MRR by plan last month?" in seconds. It works great — on your laptop.

Then a teammate asks for the same thing. Or you want it running in CI. Or your security lead asks where, exactly, the production database password is stored. Suddenly the setup that felt magical raises a real architecture question: should the MCP server that connects the AI to your database run locally on each machine, or remotely as a shared service?

This is the fork in the road most teams hit once "AI can talk to our database" stops being a demo and starts being infrastructure. The two options behave very differently in terms of speed, security, and who can use them. Let's break down how each works, when each makes sense, and the hybrid pattern that tends to win in practice.

Quick refresher: what an MCP server does for a database

The Model Context Protocol (MCP) is an open standard that lets AI clients — Claude, Cursor, ChatGPT, VS Code, and others — call tools through a consistent interface. An MCP server for a database typically exposes a handful of tools like list_tables, get_schema, and run_query. The AI doesn't hold your credentials or speak Postgres wire protocol; it calls a tool, and the server does the actual database work behind the credentials it holds.

That indirection is the whole point. But where that server runs — and how the client talks to it — is exactly what "local vs. remote" decides.

The two transports: stdio and Streamable HTTP

MCP defines two standard transports, and they map almost one-to-one onto local vs. remote.

stdio is for local servers. The client launches the server as a child process and talks to it over standard input/output — JSON-RPC messages in, JSON-RPC messages out. No network, no ports. It's the natural fit when the server and client live on the same machine.

Streamable HTTP is for remote servers. The server runs as an independent, long-lived process that clients reach over HTTP (optionally streaming responses via Server-Sent Events). It's built for network access, multiple concurrent clients, and central hosting. It replaced the older HTTP+SSE transport.

Here's the practical contrast:

Property stdio (local) Streamable HTTP (remote)
Where it runs Same machine as the AI client A shared host or cloud service
Concurrent users One client, one process Many clients at once
Auth model Reads credentials from the local environment OAuth 2.1 at the transport layer
Audit / central control None built in Single point to log and revoke
Latency Near-zero (no network hop) Network round-trip
Best for Solo dev work, local/dev databases Teams, customers, production data

The spec's own guidance: clients should support stdio whenever possible, but you switch to Streamable HTTP the moment the server needs to be reachable by more than one machine.

Local MCP servers: fast, private, single-player

A local server runs on your box and connects to a database it can reach directly. Configuration usually looks like a small block in your AI client's settings that tells it how to launch the process:

{
  "mcpServers": {
    "analytics-db": {
      "command": "npx",
      "args": ["-y", "some-postgres-mcp-server"],
      "env": {
        "DATABASE_URL": "postgres://readonly:***@localhost:5432/appdb"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now you can ask questions in plain English and the server turns them into SQL against your schema:

You: How many trial users converted to paid last month?

SELECT COUNT(DISTINCT u.id) AS converted_users
FROM users u
JOIN subscriptions s ON s.user_id = u.id
WHERE u.trial_started_at >= '2026-08-01'
  AND s.status = 'active'
  AND s.started_at >= '2026-08-01'
  AND s.started_at <  '2026-09-01';
Enter fullscreen mode Exit fullscreen mode
 converted_users
-----------------
             418
Enter fullscreen mode Exit fullscreen mode

This is a great developer experience: zero network latency, nothing leaves your machine, and it's dead simple to spin up against a local or dev database. For solo exploration and building queries, local is hard to beat.

The catch shows up when you try to scale it to people. stdio has no transport-layer authentication, so it inherits whatever credentials sit in your local environment. Every teammate who wants the same capability copies a config file with a connection string in it. There's no central audit log, no shared query cache, and no single place to rotate a leaked password. It's single-player by design.

Remote MCP servers: shared, governed, multi-player

A remote server flips the model. It runs once, as a service, and every AI client connects to the same endpoint over HTTP — authenticating with OAuth instead of a pasted connection string.

{
  "mcpServers": {
    "analytics-db": {
      "type": "http",
      "url": "https://mcp.internal.example.com/mcp"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The first time a client connects, it runs an OAuth flow and receives a short-lived token. The database credentials never touch the client, the prompt, or anyone's config file — they live only on the server. Because there's one gateway, you also get the things stdio can't offer: a shared connection pool, centralized audit logs of every query the AI ran, per-user or per-tenant scoping, and one-click revocation when someone leaves the team.

Managed options exist here too. Draxlr, for example, runs a hosted MCP server you connect as a read-only OAuth custom connector — one implementation of the remote pattern where the server holds the credentials and only SELECT gets through. Whether you self-host or buy, the defining trait of the remote model is the same: the database stops being directly exposed to every developer's laptop, which shrinks your attack surface considerably.

The trade-off is operational weight. Someone has to run that service, keep OAuth configured correctly, and monitor it. There's a real network hop. And a misconfigured public endpoint is a much bigger deal than a stdio process that only you can launch.

A decision framework

If you… Lean toward
Are one developer exploring a local or dev database Local (stdio)
Need the lowest possible latency and full privacy Local (stdio)
Want several teammates to share the same access Remote (HTTP)
Must keep production credentials off end-user machines Remote (HTTP)
Need audit logs, revocation, or per-tenant scoping Remote (HTTP)
Are exposing data to customers or non-technical staff Remote (HTTP)

The pattern is simple: local optimizes for one developer's speed and privacy; remote optimizes for a team's governance and reach. The more people and the more sensitive the data, the further you slide toward remote.

The hybrid setup most teams land on

You don't have to pick one forever. A very common progression:

  1. Develop locally. Run a stdio server against a dev or read-replica database while you build and test queries. Fast feedback, no infrastructure.
  2. Promote to remote. Once a workflow is worth sharing, put it behind a remote HTTP server with OAuth so the whole team — and their various AI clients — hit the same governed endpoint.
  3. Keep production remote-only. Never let a stdio config with production credentials float around laptops. Production data lives behind the shared, audited gateway.

This gives you the local dev loop and the centralized control, without forcing everyone through a network hop while they're just iterating on a query.

Common mistakes and gotchas

Putting production credentials in a stdio config. The single most common footgun. A DATABASE_URL in a local config is fine for a dev database and dangerous for production — it's a plaintext secret that gets copied, committed, and forgotten. Keep production behind a remote server.

Assuming stdio is "secure" because it's local. Local means private to that machine, not governed. There's no audit trail and no way to revoke access short of changing the database password for everyone.

Standing up a remote server without OAuth. A remote MCP endpoint without proper authorization is just an unauthenticated database proxy on the internet. If you go remote, OAuth 2.1 (short-lived tokens, central revocation) is table stakes, not a nice-to-have.

Forgetting read-only. Whichever model you choose, scope the database role the server uses to SELECT only. An AI exploring your data should never be one hallucinated DELETE away from a bad day. Enforce it at the database and the server layer.

Ignoring multi-tenancy. If customers or different teams share one remote server, a single missing WHERE tenant_id = ... leaks everyone's data. Push tenant isolation into row-level security or scoped credentials — don't rely on the AI to remember it.

Key takeaways

  • MCP's two transports map cleanly onto the choice: stdio for local, Streamable HTTP for remote.
  • Local wins for a single developer: fast, private, trivial to set up against dev databases.
  • Remote wins for teams and production: OAuth instead of pasted credentials, central audit and revocation, one endpoint for many AI clients, and a database that isn't exposed to every laptop.
  • Most teams use both — build locally, share and ship remotely, keep production strictly behind the gateway.
  • Regardless of model: read-only roles, OAuth for anything networked, and real tenant isolation.

Your turn

How are you running MCP against your database today — a local stdio server per developer, a shared remote one, or some hybrid? What tipped you from one to the other? Drop your setup (and your favorite gotcha) in the comments — I'd love to hear what's working for other teams.

Top comments (0)