Neon Integration Guide
Technology: neon · Category: database · Last reviewed: 2026-08-23
Source: https://tech-stack.codeamanilabs.org/guide/neon
Insight:
Neon is serverless Postgres whose killer feature is branching — spin up an instant copy-on-write branch per preview deploy or migration test, then discard it. It scales to zero (cheap for spiky SME traffic) and supports pgvector for in-database vector search. Now Databricks-owned (it powers Databricks Lakebase), but the free-standing Neon platform, CLI, and MCP server remain the codeAmani path.
███╗ ██╗███████╗ ██████╗ ███╗ ██╗
████╗ ██║██╔════╝██╔═══██╗████╗ ██║
██╔██╗ ██║█████╗ ██║ ██║██╔██╗ ██║
██║╚██╗██║██╔══╝ ██║ ██║██║╚██╗██║
██║ ╚████║███████╗╚██████╔╝██║ ╚████║
╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═╝ ╚═══╝
Neon Integration Guide
Focus: Managing serverless Postgres, running migrations, and using branching workflows from Claude Code via the official Neon MCP server.
Overview
Neon is a serverless Postgres platform (acquired by Databricks in 2025; it now also powers Databricks Lakebase) with scale-to-zero, database branching, and instant provisioning. Its official MCP server lets Claude Code create projects, run SQL, branch databases per feature, apply migrations safely with a two-phase commit pattern, inspect a database's health, and query slow query logs — all from natural language inside your session.
Here is the branching workflow at a glance — copy-on-write branches let you experiment freely, then discard or reset with zero risk to main:
flowchart LR
A["main branch<br/>production data"] -->|"create_branch"| B["feature branch<br/>copy-on-write"]
B --> C["run SQL · test migration"]
C --> Q1{"Looks good?"}
Q1 -->|"yes"| D["merge changes to main"]
Q1 -->|"no"| E["reset_from_parent<br/>or delete_branch"]
E --> B
Official Documentation
| Resource | URL |
|---|---|
| Neon Docs | https://neon.com/docs |
| Neon MCP Server | https://neon.com/docs/ai/neon-mcp-server |
| Branching Guide | https://neon.com/docs/introduction/branching |
| Neon CLI | https://neon.com/docs/reference/neon-cli |
| Connection Strings | https://neon.com/docs/connect/connect-from-any-app |
MCP Server Setup
Official Neon MCP Server (Remote OAuth, Recommended)
Neon's preferred approach is the hosted remote server — no API keys to manage. The
hosted server speaks Streamable HTTP at https://mcp.neon.tech/mcp (the older
/sse endpoint is deprecated and returns 410 Gone on or after 2026-10-01).
# Add via Claude Code CLI (HTTP + OAuth)
claude mcp add --transport http neon https://mcp.neon.tech/mcp
After adding, run /mcp inside Claude Code to authenticate via OAuth. (npx neon@latest init
also scaffolds the MCP config for most editors if you prefer a guided setup.)
.mcp.json Configuration (Remote)
{
"mcpServers": {
"neon": {
"type": "http",
"url": "https://mcp.neon.tech/mcp"
}
}
}
Scoping & least-privilege (recommended for codeAmani)
The MCP server is for development/testing only — never point it at a production database. Restrict scope by appending URL parameters to the MCP URL:
| Parameter | Effect |
|---|---|
?readonly=true |
SELECTs + schema inspection only; branch/migration/auth writes disabled (OAuth can also grant read-only scope at authorize time) |
?projectId=<id> |
Scope every operation to one project; cross-project search off |
?category=<name> |
Enable only named tool categories (repeatable), e.g. ?category=querying&category=schema |
Verify which tools a config exposes without authenticating:
curl "https://mcp.neon.tech/api/list-tools?readonly=true&category=querying".
Local stdio fallback (deprecated npm package → use mcp-remote)
The old local package @neondatabase/mcp-server-neon is deprecated (npm marks it
so). If your client only supports stdio servers, bridge to the hosted Streamable-HTTP
server with mcp-remote instead:
{
"mcpServers": {
"neon": {
"command": "npx",
"args": [
"-y", "mcp-remote@latest", "https://mcp.neon.tech/mcp",
"--header", "Authorization:${NEON_AUTH_HEADER}"
],
"env": { "NEON_AUTH_HEADER": "Bearer ${NEON_API_KEY}" }
}
}
}
Drop the --header/env lines to use interactive OAuth instead of an API key.
Available MCP Tools
Tools are grouped into categories (projects, branches, schema, querying,
neon_auth, data_api, observability, docs) — filter with ?category=. The
commonly used ones:
| Tool | Description |
|---|---|
list_projects / list_organizations |
List Neon projects / orgs |
create_project / delete_project |
Create or delete a Neon project |
describe_project |
Project details incl. branch list + endpoint defaults |
run_sql |
Execute a SQL query on a branch |
run_sql_transaction |
Run multiple SQL statements as a transaction |
get_database_tables |
List all tables in a database |
describe_table_schema |
Get column definitions and constraints |
create_branch |
Create a database branch (copy-on-write) |
describe_branch |
Deep view of a branch (schema objects, etc.) |
delete_branch |
Delete a branch |
reset_from_parent |
Reset a branch to match parent state |
compare_database_schema |
Diff a branch's schema against its parent |
list_branch_computes |
Per-compute suspend timeout / CU / state (cost diagnosis) |
get_connection_string |
Get psql/prisma/drizzle connection string (pooled optional) |
prepare_database_migration |
Stage a migration on a test branch |
complete_database_migration |
Apply staged migration to main branch |
inspect_database |
Run the 14 read-only health checks from neon inspect db |
list_slow_queries |
Get slow query log for analysis |
prepare_query_tuning / complete_query_tuning |
Test + apply index/query fixes on a branch |
explain_sql_statement |
Get EXPLAIN (ANALYZE) output |
list_docs_resources / get_doc_resource |
Look up Neon docs from the assistant (no OAuth) |
There is no standalone
list_branchestool — branches come back fromdescribe_project.
CLI Integration
Installation
npm i -g neon # CLI is invoked as `neon`; `neonctl` is a published alias (same binary)
The examples below use neonctl; every command works identically as neon. In
agentic/CI contexts prefer npx neon ... (or npx neonctl ...) rather than assuming a global install.
Authentication
neonctl auth # OAuth browser login
# Or use API key (CI/scripts):
export NEON_API_KEY=...
Key Commands
# Projects
neonctl projects list
neonctl projects create --name my-project
neonctl projects delete PROJECT_ID
# Branches
neonctl branches list --project-id PROJECT_ID
neonctl branches create --project-id PROJECT_ID --name feature/auth
neonctl branches delete BRANCH_ID --project-id PROJECT_ID
neonctl branches reset BRANCH_ID --project-id PROJECT_ID --parent
# Connection string
neonctl connection-string --project-id PROJECT_ID --branch main
neonctl connection-string --project-id PROJECT_ID --branch feature/auth
# SQL execution
neonctl sql --project-id PROJECT_ID --query "SELECT version();"
neonctl sql --project-id PROJECT_ID --file schema.sql
Connecting to Postgres
Get Connection String
# Via MCP tool: get_connection_string
# Or via CLI:
neonctl connection-string --project-id PROJECT_ID --branch main
Example connection string:
postgresql://user:password@ep-cool-name-123456.us-east-2.aws.neon.tech/neondb?sslmode=require
Prisma Integration
npm install prisma @prisma/client
prisma/schema.prisma:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
// Use a separate direct URL for migrations (no connection pooling)
directUrl = env("DIRECT_URL")
}
generator client {
provider = "prisma-client-js"
}
npx prisma migrate dev --name add-users
npx prisma generate
Drizzle ORM Integration
npm install drizzle-orm pg drizzle-kit
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const db = drizzle(pool);
// Query
const users = await db.select().from(usersTable).limit(10);
pgvector on Neon
Neon ships the pgvector extension, so you can store embeddings and run nearest-neighbour search inside the same Postgres branch as the rest of your data — no separate vector database to provision. This pairs naturally with the AI routing policy: generate embeddings with Anthropic/OpenAI/HuggingFace, then query them here.
Here is the end-to-end flow from raw text to a ranked similarity result:
flowchart LR
A["app text"] -->|"embeddings API"| B["vector float array"]
B --> C["INSERT into items.embedding"]
C --> D["HNSW index"]
D -->|"query vector + ORDER BY + LIMIT"| E["top-k nearest rows"]
Enable the extension, create a table + HNSW index
Run this on a branch first (use create_branch) so you can validate before touching main:
-- 1. Enable pgvector
CREATE EXTENSION IF NOT EXISTS vector;
-- 2. Table with a vector column.
-- Dimension must match your embedding model:
-- OpenAI text-embedding-3-small = 1536, Cohere embed-v3 = 1024, etc.
CREATE TABLE items (
id BIGSERIAL PRIMARY KEY,
content TEXT,
embedding VECTOR(1536)
);
-- 3. HNSW index. Pick the operator class that matches your distance metric:
-- vector_cosine_ops (cosine), vector_l2_ops (L2), vector_ip_ops (inner product).
-- Cosine is the usual choice for normalized OpenAI/Cohere embeddings.
CREATE INDEX ON items
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
Nearest-neighbour query
Use the distance operator that matches the index operator class: <=> (cosine), <-> (L2), <#> (negative inner product). The index is only used when the query has both ORDER BY on the distance operator and a LIMIT:
SELECT id, content
FROM items
ORDER BY embedding <=> '[0.012, -0.034, 0.567, ...]' -- your query embedding
LIMIT 5;
From TypeScript (Drizzle + a query embedding)
import { drizzle } from "drizzle-orm/node-postgres";
import { sql } from "drizzle-orm";
import { Pool } from "pg";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const db = drizzle(pool);
// queryEmbedding is a number[] from your embeddings provider (e.g. 1536-dim).
async function searchSimilar(queryEmbedding: number[], k = 5) {
// pgvector accepts the array as a bracketed string literal: '[0.1,0.2,...]'
const literal = `[${queryEmbedding.join(",")}]`;
const rows = await db.execute(sql`
SELECT id, content
FROM items
ORDER BY embedding <=> ${literal}
LIMIT ${k}
`);
return rows.rows;
}
Gotcha — HNSW dimension ceiling. An HNSW index on the standard
vectortype supports at most 2,000 dimensions. Models that exceed this (e.g. OpenAItext-embedding-3-largeat 3072 dims) cannot be indexed asvector— use thehalfvectype instead (16-bit floats, up to 4,000 dimensions indexed):CREATE INDEX ON items USING hnsw ((embedding::halfvec(3072)) halfvec_cosine_ops);. Without an HNSW index, large-dimension columns still work for storage and exact search, just without ANN acceleration.
See the pgvector on Neon guide for index tuning (ef_search), IVFFlat as an alternative index, and the full operator/type matrix.
Environment Variables
# Connection strings (from Neon dashboard or neonctl connection-string)
DATABASE_URL=postgresql://user:pass@ep-....neon.tech/neondb?sslmode=require
DIRECT_URL=postgresql://user:pass@ep-....neon.tech/neondb?sslmode=require
# API key (for CLI and npm MCP package)
NEON_API_KEY=...
# Project and branch (optional, for scripting)
NEON_PROJECT_ID=...
NEON_BRANCH_NAME=main
Automation Workflows
Safe Two-Phase Migration Pattern
Neon's MCP server implements a safe migration pattern that tests first on a branch:
You can apply schema changes with confidence — the migration is rehearsed on a throwaway branch before it ever touches main:
sequenceDiagram
participant CC as Claude Code
participant Neon as Neon MCP
CC->>Neon: prepare_database_migration
Neon->>Neon: create test branch · run migration
Neon-->>CC: result for review
CC->>CC: check for errors and data issues
CC->>Neon: complete_database_migration
Neon->>Neon: apply migration to main branch
Neon-->>CC: migration confirmed
- Claude Code calls
prepare_database_migration→ creates a test branch, runs migration there - Review the output — Claude Code checks for errors and data issues
- Call
complete_database_migration→ applies the migration to the main branch
This prevents irreversible migrations from running against production directly.
In practice, ask Claude Code:
"Apply this migration to the Neon database:
ALTER TABLE users ADD COLUMN avatar_url TEXT"
Claude Code will automatically use the two-phase pattern via the MCP tools.
Claude Code Slash Command: Branch per Feature
.claude/commands/neon-branch.md:
Create a Neon database branch for feature $ARGUMENTS.
1. Use the Neon MCP tool `create_branch` to create a branch named "feature/$ARGUMENTS"
2. Use `get_connection_string` to get the connection string for this branch
3. Update the `.env.local` file's DATABASE_URL to point to the new branch
4. Report the branch ID, connection string, and confirm `.env.local` was updated
Usage: /project:neon-branch user-auth
GitHub Actions: Branch per PR
# .github/workflows/neon-preview.yml
name: Neon Preview Branch
on:
pull_request:
types: [opened, synchronize]
jobs:
create-branch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Neon branch
uses: neondatabase/create-branch-action@v6
id: create-branch
with:
project_id: ${{ secrets.NEON_PROJECT_ID }}
api_key: ${{ secrets.NEON_API_KEY }}
branch_name: preview/pr-${{ github.event.pull_request.number }}
- name: Comment branch URL
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `DB branch id: \`${{ steps.create-branch.outputs.branch_id }}\`\nConnection: \`${{ steps.create-branch.outputs.db_url_pooled }}\``
})
Common Use Cases
| Use Case | Approach |
|---|---|
| Feature branch isolation | MCP create_branch per PR |
| Safe schema migrations | Two-phase: prepare → complete |
| Query analysis | MCP explain_sql_statement + list_slow_queries |
| Database health check | MCP inspect_database (14 read-only checks) |
| Guided query tuning | MCP prepare_query_tuning → complete_query_tuning |
| Instant dev environment | create_project in under 2 seconds |
| Prisma migrations | prisma migrate dev against branch URL |
| Reset dev DB | MCP reset_from_parent |
Troubleshooting
| Issue | Fix |
|---|---|
| Connection timeout | Add ?sslmode=require&connect_timeout=10 to URL |
| Branch creation fails | Check project branch limit (free tier: 10 branches) |
| Slow queries | Use MCP list_slow_queries + explain_sql_statement |
| Migration conflicts | Reset branch with MCP reset_from_parent |
| Prisma P1001 | Endpoint may be sleeping — first query wakes it (scale-to-zero) |
| API key invalid | Regenerate at console.neon.tech → Account Settings |
Official docs: