pgvector
Similarity search, hybrid search, and index management for pgvector-backed PostgreSQL tables
Open source Open in the app JSON README (API)
About
Similarity search, hybrid search, and index management for pgvector-backed PostgreSQL tables
Details
- Kind
- MCP servers
- Topic
- Databases
- Publisher
- mittalpk
- Origin
- official
- Category
- ferramentas
- Transport
- local
- Version
- 0.1.0
- Last push
- 2026-07-21T18:35:31Z
- Repository state
- ativo
- Language
- Python
- License
- MIT
- Added
- 2026-08-29 04:00:50
- Updated
- 2026-08-29 04:00:50
- Origin id
io.github.mittalpk/pgvector
README
# mcp-server-pgvector
[](https://github.com/mittalpk/mcp-server-pgvector/actions/workflows/ci.yml)
<!-- mcp-name: io.github.mittalpk/pgvector -->
An [MCP](https://modelcontextprotocol.io/) server that gives LLM agents first-class access to
[pgvector](https://github.com/pgvector/pgvector)-backed embedding tables in PostgreSQL: similarity
search, hybrid (vector + full-text) search, upserts, and HNSW/IVFFlat index management.
Generic Postgres MCP servers expose raw SQL or schema introspection; this one speaks pgvector
specifically — nearest-neighbor search, distance metrics, and ANN index tuning are first-class
tools, not something the model has to hand-write SQL for.
## Tools
| Tool | Description |
|---|---|
| `list_vector_tables` | Discover every `vector` column in the database, with its dimensionality |
| `describe_vector_table` | Columns, indexes, and approximate row count for a table |
| `similarity_search` | k-NN search over a vector column (cosine / L2 / inner product), with structured metadata filters |
| `hybrid_search` | Weighted blend of vector similarity and Postgres full-text search (`ts_rank_cd`) |
| `upsert_embedding` | Insert or update a row's embedding + metadata |
| `create_vector_index` | Create an HNSW or IVFFlat index with tunable parameters |
| `explain_similarity_query` | `EXPLAIN ANALYZE` a similarity query to confirm the ANN index is used |
## Safety
- Every table/column name is validated against `information_schema` / `pg_catalog` before being
interpolated into SQL — an LLM can only ever reference identifiers that already exist. Values are
always bound parameters.
- Metadata filters are a closed `{column, op, value}` allowlist, not a raw SQL fragment.
- Set `MCP_PGVECTOR_READ_ONLY=true` to disable `upsert_embedding` and `create_vector_index`,
leaving only read/search tools available — useful when pointing the server at a production
database.
- Every query runs with a per-command timeout (`MCP_PGVECTOR_COMMAND_TIMEOUT_SECONDS`, default
30s) so one expensive query can't occupy a pool connection — and stall every other caller —
indefinitely. Set it to `0` to disable.
## Installation
```bash
uvx mcp-server-pgvector
```
Or with pip:
```bash
pip install mcp-server-pgvector
python -m mcp_server_pgvector
```
## Configuration
The server reads its connection string from `DATABASE_URL` (or `PGVECTOR_DATABASE_URL`):
```json
{
"mcpServers": {
"pgvector": {
"command": "uvx",
"args": ["mcp-server-pgvector"],
"env": {
"DATABASE_URL": "postgresql://user:password@localhost:5432/mydb",
"MCP_PGVECTOR_READ_ONLY": "false",
"MCP_PGVECTOR_COMMAND_TIMEOUT_SECONDS": "30"
}
}
}
}
```
## Production readiness
**Covered:**
- Identifier-safe SQL (every table/column checked against `pg_catalog` before use) and a closed
filter-operator allowlist — no path from tool arguments to raw SQL.
- Per-query timeout, so one runaway query can't monopolize the (small, 5-connection) pool.
- 60+ tests, including dimension-mismatch and injection-attempt regressions, run in CI on every
push/PR against a real pgvector container across Python 3.10–3.13. A separate CI job builds the
package and runs `twine check` on the result.
- Connection failures surface as plain `ConnectionRefusedError`/`asyncpg` exceptions — verified
these don't leak the DSN's credentials into error text.
**Known limitations, honestly:**
- No per-tool authorization — access control is whatever the Postgres role in `DATABASE_URL` can
do. If you need different agents to have different permissions, give them different
connection strings backed by different Postgres roles, not different server instances of this
same DSN.
- `hybrid_search`'s full-text side is hardcoded to Postgres's `'english'` text search
configuration; there's no parameter to change it yet.
- No structured logging — failures are exceptions surfaced through the MCP error channel, not
written to a log you can tail. Fine for a single-user desktop MCP client, a real gap if you're
running this as a shared service.
- The connection pool is fixed at 1–5 connections and isn't configurable via environment variable
yet.
## Development
```bash
uv sync --dev
# Bring up an isolated pgvector instance for local testing
docker compose -f docker-compose.dev.yml up -d
export DATABASE_URL=postgresql://postgres:postgres@localhost:5434/postgres
uv run pytest
uv run ruff check .
uv run pyright
```
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md). See [CHANGELOG.md](CHANGELOG.md) for release history.
## License
MIT — see [LICENSE](LICENSE).