Thank you for your interest in contributing to postgres-mcp! This project is built by developers, for developers, and we welcome contributions that make the PostgreSQL MCP experience better for everyone.
- Fork the repository on GitHub
- Clone your fork locally
- Create a feature branch from
main - Make your changes and test thoroughly
- Submit a pull request with a clear description
- Node.js 24+ (see
enginesinpackage.json) - npm (comes with Node.js)
- Git (for version control)
- PostgreSQL (local instance or Docker)
- Docker (optional, for container testing)
# Clone your fork
git clone https://github.com/YOUR_USERNAME/postgres-mcp.git
cd postgres-mcp
# Install dependencies
npm install
# Build TypeScript
npm run build
# Run the test suite
npm test
# Run the full quality check
npm run check # Runs ESLint + TypeScript strict-mode type checking# Connect to a local PostgreSQL instance via stdio
node dist/cli.js --transport stdio --postgres "postgresql://user:pass@localhost:5432/mydb"
# HTTP transport (for testing with an MCP client)
node dist/cli.js --transport http --port 3000 --postgres "postgresql://user:pass@localhost:5432/mydb"Connection string required. The server requires a valid PostgreSQL connection string. For local testing, you can use a
.envfile or pass the string directly. Never commit credentials to version control.
# Build the Docker image locally
docker build -f Dockerfile -t postgres-mcp-dev .
# Run with a connection string
docker run --rm -i postgres-mcp-dev --transport stdio --postgres "postgresql://user:pass@host:5432/mydb"We especially welcome contributions in these areas:
- Bug fixes and stability improvements
- Performance improvements (faster tool dispatch, reduced overhead, connection pool tuning)
- New tools that extend PostgreSQL capabilities within existing groups
- Better error messages with actionable remediation hints
- Enhanced Code Mode worker-thread operations and sandbox capabilities
- Additional PostGIS / pgvector advanced spatial/math tool coverage
- New PostgreSQL extensions integrations (e.g., TimescaleDB)
- Documentation improvements and Playwright end-to-end examples
- New tool groups for specialized PostgreSQL workflows
- Additional PostgreSQL extension integrations
- Performance benchmarks for new hot paths
- IDE-specific integrations beyond MCP
# Run all tests
npm test
# Run tests with coverage
npm run test:coverage
# Run a specific test file
npx vitest run src/__tests__/your-test-file.test.ts
# Run benchmarks
npm run bench# Lint + type check (required before submitting)
npm run check # ESLint + TypeScript strict-mode
# Or individually
npm run lint # ESLint only
npm run typecheck # TypeScript strict-mode type checkingThe Playwright E2E suite validates HTTP and SSE transport parity:
npm run test:e2eAdd your local build to ~/.cursor/mcp.json:
{
"mcpServers": {
"postgres-mcp-dev": {
"command": "node",
"args": [
"path/to/your/postgres-mcp/dist/cli.js",
"--transport",
"stdio",
"--postgres",
"postgresql://user:pass@localhost:5432/mydb"
]
}
}
}# Build and run locally
docker build -f Dockerfile -t postgres-mcp-dev .
docker run --rm -i postgres-mcp-dev --transport stdio --postgres "postgresql://user:pass@host:5432/mydb"- Strict mode —
tsconfig.jsonenforces strict TypeScript - ESLint — Run
npm run lintto check,npm run lint:fixto auto-fix (when available) - Prettier — Formatting is handled automatically during the release workflow
- Type safety — Avoid
any; use proper types and Zod schemas - Modularity — Keep files under ~500 lines; split into sub-modules when approaching the limit
- Error handling — Use structured
{success, error, code, category, suggestion, recoverable}responses in tool handlers
All files and directories use kebab-case (lowercase with dashes):
- ✅
database-adapter.ts,tool-filter.ts,pool-manager/ - ❌
DatabaseAdapter.ts,toolFilter.ts
Every tool must return structured error responses — never raw exceptions:
{
"success": false,
"error": "Descriptive message with context",
"code": "MODULE_ERROR_CODE",
"category": "VALIDATION_ERROR",
"suggestion": "Actionable remediation hint",
"recoverable": true
}Error logic should leverage the PostgresMcpError hierarchy (e.g., ValidationError, QueryError). Our Auto-refinement system automatically maps generic codes to specific ones (e.g., QUERY_ERROR → TABLE_NOT_FOUND) and populates suggestions. Catch at the handler boundary and return formatHandlerError(error) to ensure a highly-compliant JSON payload. Always propagate stack traces — don't swallow errors.
- All parameters are validated via Zod schemas with explicit coercion controls (e.g.,
z.preprocess(coerceNumber, z.number().optional())instead of aggressivez.coerce.number()) - Output schemas are strictly defined to guarantee AI agents receive deterministic P154-compliant structures (using
openWorldHint: false) - Invalid inputs must return structured errors, automatically handled by
formatHandlerError()without raw Zod validation messages - SQL injection is prevented via parameter binding — never interpolate user input into SQL strings
Use the centralized logger with structured payloads. Include: module, operation, entityId, context, and stack (for errors). Severity levels: error, warning, info, debug.
- Multi-stage builds — Keep images lean
- Security — Run as non-root user, minimal privileges
- Multi-platform — Test on both amd64 and arm64 when possible
- Documentation — Update Docker guides if needed
postgres-mcp organizes tools into groups covering: core, schema, introspection, migration, monitoring, performance, stats, text, jsonb, vector, admin, transactions, partitioning, backup, codemode, and PostgreSQL extensions (postgis, ltree, citext, pgcrypto, partman, cron, kcache). When adding a new tool:
- Define the tool input and output schemas using Zod in the appropriate group under
src/adapters/postgresql/schemas/ - Implement the handler in the corresponding adapter directory under
src/adapters/postgresql/tools/ - Add structured error handling by letting the handler return
formatHandlerError()when exceptions are caught - Write meaningful Vitest tests and update E2E spec files if making systemic changes
- Add the tool to the group's help resource (the markdown file under
src/constants/server-instructions/) - Verify OAuth Scope — ensure the new tool aligns with its group's defined OAuth 2.1 scope (
read,write, oradmin) - Update
UNRELEASED.mdwith your change (see Changelog below)
When reporting bugs, please include:
- Environment details (OS, Node.js version, npm version)
- Steps to reproduce the issue
- Expected vs actual behavior
- PostgreSQL version and relevant extensions enabled
- MCP client details (Cursor version, Claude Desktop, configuration)
- Relevant logs or error messages
Use our Bug Report template for consistency.
For new features, please provide:
- Use case description — What problem does this solve?
- Proposed solution — How should it work?
- Tool group fit — Which group does this belong to, or does it need a new one?
- Alternatives considered — What other approaches did you think about?
- Implementation notes — Any technical considerations
Use our Feature Request template.
- Fork the repository and create a feature branch
- Test your changes (
npm run check && npm test) - Update documentation if you changed APIs or behavior
- Add examples for new features
- Update
UNRELEASED.mdwith your change - Check that existing functionality still works
- Summary of changes made
- Testing performed (how did you verify it works?)
- Breaking changes (if any)
- Related issues (fixes #123)
- Automated checks must pass (lint, typecheck, tests)
- Maintainer review — we'll provide feedback
- Address feedback — make requested changes
- Merge — once approved, we'll merge your PR
| Workflow | What It Does |
|---|---|
| Lint & Test | ESLint, TypeScript strict-mode, Vitest suite |
| CodeQL | Static analysis for security vulnerabilities |
| E2E | Playwright end-to-end transport parity tests |
All checks must pass before merge. Security steps hard-fail on fixable issues — this is intentional.
Log all changes in UNRELEASED.md at the project root using Keep a Changelog format. Use the appropriate header:
### Added— new features or tools### Changed— changes to existing functionality### Fixed— bug fixes### Removed— removed features### Security— vulnerability fixes
Do not edit
CHANGELOG.mddirectly — it is assembled automatically during the release process.
- Test with a real PostgreSQL instance — behaviour varies across versions and extension states
- Check tool responses — Ensure JSON responses are well-formed
- Output schemas — All tools have Zod output schemas; error responses must pass validation
- Dual-schema pattern — Relaxed schemas for SDK validation, strict schemas inside handlers
src/
├── adapters/ # PostgreSQL queries, handlers, Zod schemas, prompts, and resources
├── audit/ # JSONL audit trail with session token estimates, pre-mutation snapshots, interceptor
├── auth/ # Transport-agnostic OAuth 2.1, scopes, RFC 6750 enforcement
├── cli/ # CLI argument parsing and server bootstrap
├── cli.ts # Entry point
├── codemode/ # Sandboxed JavaScript execution (Code Mode — VM & Worker Isolate)
├── constants/ # Help content generation and dynamic server instructions
├── filtering/ # Tool filter parsing, group resolution
├── pool/ # Connection pool management
├── server/ # MCP server setup, handler registration
├── transports/ # HTTP/SSE/stdio transport layer
├── types/ # Core TypeScript types (errors, schema, mcp, oauth)
├── utils/ # Logging, sanitization, validation, errors helpers
└── index.ts # Public API exports
| Script | Purpose |
|---|---|
npm run build |
Production build via tsc |
npm run dev |
Watch mode (incremental builds) |
npm run check |
Quality gate — lint + typecheck (run before PRs) |
npm run lint |
ESLint only |
npm run typecheck |
TypeScript strict-mode type checking |
npm test |
Run all unit tests (Vitest) |
npm run test:coverage |
Tests with V8 coverage report |
npm run test:e2e |
Playwright end-to-end tests (HTTP/SSE transport) |
npm run bench |
Performance benchmarks (tinybench via Vitest) |
npm run bench:verbose |
Benchmarks with detailed timings |
If your change touches a hot path (tool dispatch, schema parsing, auth, Code Mode, connection pool), run benchmarks to verify you haven't introduced a regression:
npm run benchIf you discover a security vulnerability, do not open a public issue. Please follow our Security Policy and report it to admin@adamic.tech.
When contributing code, follow these security practices:
- Parameter binding for all SQL — never string interpolation
- Input validation via Zod schemas at tool boundaries
- No secrets in code — use environment variables (
.envfiles are gitignored) - Typed error classes with descriptive messages — don't expose internal details to end users
- Transport Security — preserve DNS rebinding protection and Slowloris DoS timeouts in HTTP layers
- Be respectful — Follow our Code of Conduct
- Ask questions — Use GitHub Issues for discussion
- Share ideas — Feature requests and feedback welcome
- Help others — Answer questions and review PRs
- GitHub Issues — Bug reports and feature requests
- Documentation — Check README.md, Wiki, and Docker guides first
- Email — admin@adamic.tech
Contributors are recognized in:
- Release notes — Major contributions highlighted
- README — Contributor acknowledgments
- Git history — Your commits are permanent record
Thank you for helping make postgres-mcp better for the developer community! 🚀