Hacking Model Context Protocol (MCP): Connecting Any Local Database and API to Your AI Agent
Why MCP Matters for Power Users
Before MCP, every IDE bolted on its own plugin format. Anthropic's Model Context Protocol standardizes how an AI client discovers capabilities: list tools → call tool with JSON args → return structured results. That means one Postgres read-only server can serve Claude Desktop, Cursor, and other MCP hosts without rewriting integrations.
Hardcore developers care because:
- Databases become queryable context without pasting schema dumps into every chat
- Internal APIs (billing, feature flags, deploy status) surface as typed tools instead of fragile copy-paste
- IDE + agent stacks share the same toolchain when you also run Claude Code alternatives or OpenClaw on a remote Mac
Official reference: Model Context Protocol specification and Anthropic MCP documentation.
MCP Architecture in 60 Seconds
┌─────────────┐ JSON-RPC ┌──────────────────┐
│ MCP Host │ ◄──────────────► │ MCP Server │
│ (Claude / │ tools/resources │ (your custom code)│
│ Cursor) │ │ → DB / API / CLI │
└─────────────┘ └──────────────────┘
| Role | Examples | Responsibility |
|---|---|---|
| Host | Claude Desktop, Cursor, Claude Code | Spawns server, sends tools/call, renders results |
| Server | Your Node/Python binary | Implements list_tools, call_tool, optional resources/read |
| Transport | stdio, SSE | Carries JSON-RPC messages between host and server |
Depth rule: One server per trust boundary. Do not put production write access and experimental shell tools in the same server binary — split processes so you can revoke one config block without touching the other.
Transport Decision Matrix
| Transport | Latency | Best for | Config file (typical) |
|---|---|---|---|
| stdio | Lowest | Local DB on laptop, single-user | claude_desktop_config.json, Cursor mcp.json |
| SSE (HTTP) | +1 hop | Server on NAS, remote Mac, Docker sidecar | Host URL http://host:port/sse |
| Streamable HTTP (newer hosts) | Similar to SSE | Same as SSE; check host version | Per host docs |
| Scenario | Recommended transport |
|---|---|
| SQLite file on same machine as Claude Desktop | stdio |
| PostgreSQL on office LAN | SSE server on jump host OR stdio via SSH wrapper |
| 5 internal REST microservices | One gateway MCP server exposing namespaced tools |
| Team-shared tool catalog | Central MCP server on always-on host (see remote Mac setup) |
Pattern 1 — Database MCP Server
Goal: Let the model run read-only SQL (or predefined queries) against PostgreSQL, MySQL, or SQLite.
Design constraints:
- Expose named tools (
query_sales_summary,list_tables) instead of raw arbitrary SQL when possible - Enforce row limits (e.g. max 200 rows) and statement timeouts (e.g. 5 s)
- Never pass connection strings through the model — load from
DATABASE_URLin the server environment
Example tool surface:
| Tool name | Input | Output |
|---|---|---|
postgres_query_readonly |
{ "sql": "SELECT ..." } |
JSON rows + column names |
describe_table |
{ "table": "orders" } |
Column types from information_schema |
Use a read-only DB role: GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_reader;
Pattern 2 — Local REST API Gateway
Goal: Wrap existing HTTP endpoints as MCP tools so Claude never holds long-lived API keys in the chat window.
Gateway pattern:
Claude → MCP tool "deploy_status" → your server → GET https://internal/api/v1/deployments
Implementation tips:
- Map each tool to one HTTP method + path template
- Validate inputs with a schema (Zod, Pydantic) before calling fetch
- Return truncated JSON (first 8 KB) plus a
truncated: trueflag when responses are huge - Log correlation IDs server-side; do not echo secrets in tool results
This pairs well with multi-agent orchestration when OpenClaw workers call the same internal APIs via MCP instead of ad-hoc curl.
Pattern 3 — IDE and Repo Bridge
Cursor and Claude Code already ship MCP client support. Your custom server can expose:
- Repo tools:
git_diff_summary,run_linter(sandboxed) - Doc resources:
file://orresources/readforAGENTS.md, OpenAPI specs - ECC / plugin hooks: after ECC install, add MCP tools that wrap your team's
eccscripts
Keep IDE bridges stdio-local unless the whole team shares one remote dev box.
Eight-Step Runbook
Step 1 — Install the official SDK
Node (recommended for most hosts):
mkdir mcp-company-gateway && cd mcp-company-gateway
npm init -y
npm install @modelcontextprotocol/sdk zod pg
Python alternative: pip install mcp (see MCP Python SDK).
Step 2 — Scaffold a minimal server
Create src/index.ts:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new McpServer({ name: "company-gateway", version: "1.0.0" });
server.tool("ping", {}, async () => ({
content: [{ type: "text", text: "pong" }],
}));
const transport = new StdioServerTransport();
await server.connect(transport);
Run once: npx tsx src/index.ts — it should block waiting for stdio (no output is normal).
Step 3 — Add a read-only Postgres tool
export DATABASE_URL="postgresql://mcp_reader:****@127.0.0.1:5432/app"
Register postgres_query_readonly with Zod-validated SQL that must start with SELECT (reject ; and DDL keywords server-side).
Step 4 — Register in Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"company-gateway": {
"command": "npx",
"args": ["tsx", "/absolute/path/mcp-company-gateway/src/index.ts"],
"env": { "DATABASE_URL": "postgresql://mcp_reader@127.0.0.1:5432/app" }
}
}
}
Restart Claude Desktop. In a new chat, confirm the hammer/tools icon lists ping and postgres_query_readonly.
Step 5 — Register in Cursor
Project or global .cursor/mcp.json:
{
"mcpServers": {
"company-gateway": {
"command": "npx",
"args": ["tsx", "/absolute/path/mcp-company-gateway/src/index.ts"]
}
}
}
Reload Cursor window. Test the same ping tool from the agent panel.
Step 6 — Expose SSE for a remote host (optional)
When the MCP server runs on a remote Mac (team bastion or rented M4):
# Example: SDK HTTP/SSE transport on port 8787 — bind localhost only unless behind VPN
node dist/sse-server.js --port 8787 --host 127.0.0.1
Point the host config at url: "http://127.0.0.1:8787/sse" via SSH tunnel:
ssh -L 8787:127.0.0.1:8787 user@remote-mac
Never expose an unauthenticated MCP SSE port to the public internet.
Step 7 — Secrets and sandboxing
| Rule | Why |
|---|---|
Secrets only in server env, never in tool arguments |
Prevents prompt injection exfiltration |
| Separate servers for prod vs staging | Stops accidental cross-environment queries |
Cap subprocess tools with timeout and allowlists |
Blocks rm -rf class mistakes |
Step 8 — Verify with the MCP Inspector
npx @modelcontextprotocol/inspector npx tsx src/index.ts
Call tools/list and tools/call manually before trusting the host UI. Log every tool invocation with timestamp + user OS user (not chat content) for audit.
Security and Sandbox Checklist
- Read-only DB roles for analytics tools; use a second server with write tools only on dev machines
- Input validation on every tool; reject nested objects over 32 KB
- Network egress allowlist from the server process (iptables or macOS firewall) when wrapping internal APIs
- OAuth for SaaS — implement token refresh inside the server; expose only opaque
tool_okto the model
When to Run MCP on a Dedicated Mac
Laptop-sleep kills stdio servers. Teams that want shared MCP catalogs (same Postgres tools for 8 engineers) often run the server on an always-on Apple Silicon Mac — local desk or a small remote node — then reach it via SSH tunnel or VPN.
That is an infrastructure choice, not an MCP requirement. A 16 GB M4 comfortably runs 3–5 lightweight MCP server processes (~80–150 MB each) plus Node tooling; add RAM if you also run Docker databases on the same box.
Troubleshooting
Error: Connection closed immediately after spawn
Pattern: Claude Desktop log shows server exit code 1.
Fix: Run the same command + args in Terminal; fix missing tsx, wrong absolute path, or thrown exception on startup. MCP hosts do not surface stderr in the UI.
Error: Tool not found / empty tool list
Pattern: Config JSON typo in server name or host did not reload.
Fix: Validate JSON with jq . claude_desktop_config.json; fully quit and reopen the host app (not just close the window).
Error: SSE 404 or CORS failures
Pattern: Remote URL wrong path (/sse vs /mcp).
Fix: Match the path your SDK HTTP transport documents; tunnel with ssh -L and use 127.0.0.1 in config.
Recommended Path
| Your situation | Do this |
|---|---|
| Solo dev, DB on laptop | stdio + Claude Desktop + Cursor mcp.json |
| Team internal APIs | One gateway MCP server with namespaced tools |
| DB on LAN, laptop elsewhere | MCP server on jump host + SSH tunnel to SSE/stdio |
| Heavy agents + MCP on one box | 24 GB RAM if Docker DB + OpenClaw fan-out share the host |
| Greenfield | Start with Inspector + ping tool before any production SQL |
If X → Y: If the data lives on another machine, put the MCP server next to the data and tunnel to the host — do not give Claude a raw database port on the public internet.
FAQ
What is the difference between MCP and ChatGPT plugins?
MCP is an open, host-agnostic JSON-RPC protocol with SDKs in multiple languages. Plugins were platform-specific. MCP servers run as local or remote processes you control; the host only spawns or connects to them.
Can I connect MySQL or SQLite the same way as PostgreSQL?
Yes. The server implementation changes (driver + SQL dialect); the MCP surface (list_tools, call_tool) stays identical. Use read-only connections and dialect-specific guards (SELECT only).
Does Claude Code support MCP custom servers?
As of 2026, Claude Code and Cursor both support MCP client configuration similar to Claude Desktop. Paths differ by product — check the current Anthropic and Cursor docs for mcpServers location. The server code you write is reusable across hosts.
How many tools should one server expose?
Stay under ~20 tools per server for reliable model routing. Split into billing-gateway, data-gateway, ops-gateway servers when catalogs grow. Each appears as a separate block in host config.
Is it safe to expose write tools (DELETE, deploy)?
Only on non-production servers with explicit human confirmation flows. Prefer read tools in shared configs; gate writes behind a second MCP server that only senior developers enable in their personal config.
Run MCP Servers on Apple Silicon
Rent a KuzCloud M4 Mac for always-on MCP gateways, Postgres read-only tools, and SSE tunnels over SSH — no hardware purchase, pay only for the time you use.