Local-first architecture
Isthmus runs entirely on your machine. By default, it communicates with your AI client over stdio (standard input/output) — no network ports are opened, no data leaves your machine, and no cloud service is involved. When using the HTTP transport, Isthmus opens a network port. Bind to127.0.0.1 to restrict access to your machine, or use a reverse proxy for TLS and authentication if remote access is needed.
Defense in depth
1. SQL AST validation
Every query is parsed using PostgreSQL’s actual parser (pg_query) and validated at the AST level. Only SELECT and EXPLAIN statements are allowed. This is not regex matching — it uses the same parser that PostgreSQL itself runs.
See SQL Validation for details.
2. Read-only transactions
All queries execute inside read-only transactions (SET TRANSACTION READ ONLY). Even if a write query somehow passed AST validation, PostgreSQL would reject it.
3. Row limits
Results are capped atMAX_ROWS (default: 100). This prevents accidental data dumps from SELECT * on large tables.
4. Query timeout
Queries are cancelled afterQUERY_TIMEOUT (default: 10s). This prevents runaway queries from consuming database resources.
5. Schema filtering
TheSCHEMAS environment variable restricts which schemas the AI can discover. Only listed schemas appear in discover and describe_table results.
See Schema Filtering for details.
6. Column masking
The policy file supports per-column masking rules (redact, hash, partial, null) that protect PII in both query results and describe_table sample rows. Masking is enforced server-side — the AI cannot bypass it regardless of what SQL it generates.
See Column Masking for details.
7. Policy engine
The policy file enriches responses with business context but also acts as a documentation layer — operators can describe exactly what data means, reducing the chance of AI misinterpretation. See Policy Engine for details.8. Explain-only mode
The--explain-only flag forces all query calls to return EXPLAIN plans instead of actual data. Useful for environments where you want the AI to help with query writing without accessing the data.
9. Audit logging
The--audit-log flag writes every executed query to an NDJSON file with timestamps, row counts, and execution times. Use this for compliance and monitoring.
See Audit Logging for details.
10. Bearer authentication (HTTP transport)
When using the HTTP transport, Isthmus requires a bearer token on every request to the/mcp endpoint. Isthmus refuses to start in HTTP mode without a token configured, preventing accidental unauthenticated exposure.
Key implementation details:
- Constant-time comparison — tokens are compared using
crypto/subtle.ConstantTimeCompare, which prevents timing attacks that could leak the token byte-by-byte - Mandatory token — the server refuses to start if
HTTP_BEARER_TOKENis empty whenTRANSPORT=http - Health endpoints excluded —
/healthand/readyare unauthenticated so container orchestrators can probe them without credentials
11. Error sanitization
Isthmus wraps all database errors before returning them to the AI model. Raw PostgreSQL error messages — which can contain table names, constraint definitions, internal IP addresses, or schema details — are never exposed directly. Instead, errors are wrapped with a generic context prefix:| Error source | What the AI sees |
|---|---|
| Query validation failure | "query failed: only SELECT queries are allowed" |
| Query execution error | "query failed: ..." (wrapped, not raw PG error) |
| Table not found | "failed to describe table: ..." |
| Schema listing failure | "failed to list schemas: ..." |
12. Credential redaction
Database credentials are never logged or displayed in plaintext:- Structured logs — the
DATABASE_URLis never included insloglog output - Dry-run output — when
--dry-runprints the resolved configuration, the password in the connection string is replaced with***using Go’snet/urlparser (e.g.postgres://user:***@localhost:5432/mydb) - Error messages — connection failures do not include the full DSN
13. Observability
OpenTelemetry tracing and metrics (--otel) let you monitor query latency, error rates, and tool usage in production. Traces include the full SQL statement, row counts, and error details.
See OpenTelemetry for details.
Recommended Postgres role
For production use, create a dedicated read-only database role:Security checklist
Database
- Use a dedicated read-only Postgres role with minimal privileges
- Set
SCHEMASto limit schema discovery to only the schemas the AI needs - Set
MAX_ROWSto a reasonable limit for your use case - Set
QUERY_TIMEOUTappropriate for your database workload
Data protection
- Mask all PII columns (
email,ssn,phone, etc.) in your policy YAML - Consider
--explain-onlyif the AI should analyze queries without accessing actual data - Use
redactmask for highly sensitive columns,hashfor columns needed in JOINs/GROUP BY
Monitoring
- Enable
--audit-login production for query forensics - Review the audit log periodically for unexpected queries
- Consider
--otelfor real-time monitoring of query latency and error rates
Network (HTTP transport only)
- Set a strong, randomly generated
HTTP_BEARER_TOKEN(at least 32 bytes) - Bind to
127.0.0.1unless remote access is specifically required - Use TLS (via reverse proxy) to protect the bearer token in transit
- Never commit bearer tokens to version control