ZeroDB MCP Server vs PostgreSQL MCP Server

A side-by-side look at the ZeroDB MCP Server and PostgreSQL MCP Server MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.

ZeroDB MCP Server logoZeroDB MCP ServerDatabases · Local subprocess (stdio)AINative ZeroDB tools for vector search, NoSQL tables, managed PostgreSQL, files, events and knowledge graphs. Local stdio server.63GoodAuth: not declaredPostgreSQL MCP Server logoPostgreSQL MCP ServerDatabases · Local subprocess (stdio)PostgreSQL MCP server - query, schema introspection, explain, and health checks for AI assistants64GoodAuth: not declared

Verdict: choose ZeroDB MCP Server for databases work as a local process; choose PostgreSQL MCP Server for databases as a local process. You can also run both side by side in one mcpServers block.

Which MCP server should you choose?

ZeroDB MCP Server logoChoose ZeroDB MCP Server when

  • You need dedicated capabilities in the Databases domain.
  • You prefer a local stdio subprocess transport.
  • You have the keys it needs: ZERODB_API_URL, ZERODB_PROJECT_ID, ZERODB_API_KEY.
  • You want tools like zerodb_generate_embeddings, zerodb_embed_and_store, zerodb_semantic_search.
Explore ZeroDB MCP Server

PostgreSQL MCP Server logoChoose PostgreSQL MCP Server when

  • You need dedicated capabilities in the Databases domain.
  • You prefer a local stdio subprocess transport.
  • You have the keys it needs: DATABASE_URL.
  • You want tools like pg_readonly, pg_query, pg_list_schemas.
Explore PostgreSQL MCP Server

Feature & specification comparison

Rows where the two servers differ are marked.

SpecZeroDB MCP Server logoZeroDB MCP ServerPostgreSQL MCP Server logoPostgreSQL MCP Server
CategoryDatabasesDatabases
Quality signal63/100 · Good64/100 · Good
Install commandConfirmedConfirmed
TransportLocal subprocess (stdio)Local subprocess (stdio)
AuthNot declaredNot declared
PricingNot declaredNot declared
Required env varsZERODB_API_URLZERODB_PROJECT_IDZERODB_API_KEYDATABASE_URL
Verified ownerCommunity listingCommunity listing
GitHub stars08
Directory activity 1 views 0 installs 0 upvotes 1 views 0 installs 0 upvotes
Tools8523

Tools & capabilities

ZeroDB MCP Server tools 85

  • zerodb_generate_embeddingsGenerate embeddings using specified model (384/768/1024 dimensions). Supports BAAI/bge-small-en-v1.5 (384-dim, default), BAAI/bge-base-en-v1.5 (768-dim), BAAI/bge-large-en-v1.5 (1024-dim). Use when you need raw embedding vectors without storing them. Does not persist data — for embed + store in one step, use zerodb_embed_and_store instead.
  • zerodb_embed_and_storeGenerate embeddings and store in ZeroDB in one step. Auto-detects dimension based on model and routes to correct storage. Use when you want to embed text and persist the vectors in a single call. Combines zerodb_generate_embeddings + zerodb_upsert_vector.
  • zerodb_semantic_searchSemantic search using text query (auto-embeds query text). Searches vectors in the same dimension as the model used. Use when searching vectors using a text query (auto-embeds the text). Unlike zerodb_search_vectors which requires a raw vector, this accepts plain text. Unlike zerodb_search_memory which searches agent conversation memory, this searches the general vector store.
  • zerodb_store_memoryStore agent memory in ZeroDB for persistent context. Use when the agent needs to persist conversation turns, decisions, or observations for later recall. Stores with role, session, and agent metadata for filtered retrieval.
  • zerodb_search_memorySearch agent memory using semantic similarity. Use when searching agent conversation memory by natural language. Unlike zerodb_search_vectors which requires a raw vector, and zerodb_semantic_search which searches the general vector store, this searches agent-specific memory entries filtered by session/agent/role.
  • zerodb_get_contextGet agent context window for current session. Use when the agent needs to retrieve its recent conversation context within token limits. Returns the most recent memories for a session, bounded by max_tokens.
  • zerodb_upsert_vectorStore or update a vector embedding with metadata. Supports 384, 768, 1024, or 1536 dimensions. Dimension is auto-detected and validated. Use when you have a pre-computed embedding vector to store or update. For embedding text and storing in one step, use zerodb_embed_and_store instead.
  • zerodb_batch_upsert_vectorsBatch upsert multiple vectors for efficiency. Use when storing many vectors at once to reduce API round-trips. Accepts an array of vector objects and processes them in a single request.
  • zerodb_search_vectorsSearch vectors using semantic similarity. Supports 384, 768, 1024, or 1536 dimension query vectors. Auto-detects dimension. Use when searching raw vector embeddings by similarity with a query vector. Unlike zerodb_semantic_search which accepts text (auto-embeds), this requires a pre-computed vector. Unlike zerodb_search_memory which searches agent memory, this searches the general vector store.
  • zerodb_delete_vectorDelete a specific vector by ID. Use when removing a single vector embedding from the store. WARNING: This operation is irreversible.
  • zerodb_get_vectorRetrieve a specific vector by ID. Use when you need to inspect a particular vector's metadata or embedding values. Optionally includes the full embedding array.
  • zerodb_list_vectorsList vectors in a project/namespace with pagination. Use when the agent needs to browse or enumerate stored vectors, or answer "what vectors exist?". Supports filtering by namespace and metadata.
  • +73 more on the listing page

PostgreSQL MCP Server tools 23

  • pg_readonlyRun a SQL statement with no persistent data changes. Always executes inside a `BEGIN READ ONLY` transaction regardless of `ALLOW_WRITES`, so postgres itself rejects any INSERT/UPDATE/DELETE/DDL and the transaction is always rolled back. Use this whenever the goal is to read - SELECT, EXPLAIN, SHOW, VALUES, WITH ... SELECT, etc. Scope caveat for hosts that auto-allow this tool: `READ ONLY` constrains writes to the DATABASE, not every side effect. Functions whose effect is outside the table data - `pg_cancel_backend` / `pg_terminate_backend`, `pg_read_file`, `lo_export`, `COPY ... TO PROGRAM` - are NOT blocked here and are NOT behind the `ALLOW_WRITES` gate that `pg_kill` sits behind. They still require the privileges the `DATABASE_URL` role holds, so a least-privileged role (e.g. `pg_read_all_data`) is what actually bounds this tool. Use `params` for parameterized queries to avoid SQL injection. Params can be strings, numbers, booleans, null, arrays (for postgres arrays / ANY), or objects (for json/jsonb columns). Large result sets are truncated to POSTGRES_MAX_ROWS (default 1000) with a `truncated: true` flag.
  • pg_queryRun a SQL query against the configured PostgreSQL database. Postgres itself is the primary safety gate: the role in `DATABASE_URL` enforces what queries can succeed. The recommended posture is a least-privileged role (e.g. one granted `pg_read_all_data`), which makes writes server-rejected regardless of any env var. `ALLOW_WRITES=1` is a secondary belt-and-braces gate - it lifts the in-server `BEGIN READ ONLY` wrapper, but it cannot grant privileges the role lacks. Useful for managed databases where creating a second role is awkward. For read-only access where you want the guarantee in the tool name, prefer `pg_readonly`. Use `params` for parameterized queries to avoid SQL injection. Params can be strings, numbers, booleans, null, arrays (for postgres arrays / ANY), or objects (for json/jsonb columns). Dates and UUIDs can be passed as ISO strings. Large result sets are truncated to POSTGRES_MAX_ROWS (default 1000) with a `truncated: true` flag.
  • pg_list_schemasList non-system schemas in the database. Excludes `pg_catalog`, `information_schema`, and other `pg_*` internals.
  • pg_list_tablesList tables (and optionally views) in a schema. Returns name, type (table/view/materialized view/foreign), and estimated row count (from `reltuples`; null = no ANALYZE yet on PG 14+; 0 may mean empty or unanalyzed on PG <= 13). Paginate via `limit`/`offset` on very large schemas.
  • pg_describe_tableDescribe a relation: kind (table / view / materialized_view / partitioned_table / foreign_table), columns (name, type, nullable, default, `generated`, `identity`), primary key, foreign keys (outgoing), `referenced_by` (other tables whose FKs point at this one), `constraints` (CHECK / UNIQUE non-PK / EXCLUDE), indexes, and partition info (`partition_of` parent, `partitions` children). Works on views and materialized views too -- PK/FK/constraint/index lists will simply be empty for a plain view. Use `kind` to disambiguate before assuming you can write to the relation. Generated columns (`generated`: 'stored' / 'virtual') and `identity`: 'always' columns are NOT writable -- omit them from INSERT/UPDATE column lists; a generated column's expression is reported as `generation_expression`, never as `default_value`. On PostgreSQL 18+ constraints also report `validated` / `enforced` / `has_period`, and columns report `not_null_validated` -- a NOT VALID not-null constraint means `nullable: false` can still hide NULLs.
  • pg_list_viewsList views and materialized views in a schema with their SQL definitions. Use this over `pg_list_tables` with `includeViews: true` when you want the view body, not just names.
  • pg_list_functionsList functions, procedures, and aggregates in a schema. Returns name, arguments, return type, kind (function/procedure/aggregate/window), and implementation language.
  • pg_list_extensionsList installed PostgreSQL extensions. Returns name, version, schema, and description. Useful to check for pgvector, postgis, pg_stat_statements, uuid-ossp, etc. before writing queries that rely on them.
  • pg_search_columnsSearch for columns by name across all user schemas. Supports SQL LIKE patterns (`%` matches any substring, `_` matches one character). Case-insensitive. Use this instead of iterating `pg_describe_table` when the user asks 'which tables have X'.
  • pg_explainGet the query plan for a SQL statement. By default, this uses plain EXPLAIN (no execution). Set `analyze: true` to run the query with EXPLAIN ANALYZE - for non-SELECT statements, ALLOW_WRITES=1 is required (since ANALYZE actually executes the statement). Writes executed during EXPLAIN ANALYZE are rolled back, so you can inspect a plan for an INSERT/UPDATE/DELETE without persisting the rows -- but only what Postgres rolls back is undone: a sequence the statement advanced (nextval, a serial or identity column) stays advanced, and any side effect of a function the statement called that lands outside table data (pg_terminate_backend, an advisory lock) persists. Format is `text` (default) or `json`. Pass the raw SQL (not an EXPLAIN-prefixed statement). Planner options (all optional): `buffers` reports shared/local/temp block hits and is the fastest way to tell a bad plan from a cold cache - it defaults to TRUE whenever `analyze` is true (matching PostgreSQL 18, which turns it on for you), pass `buffers: false` to suppress it; requesting it WITHOUT `analyze` needs PostgreSQL 13+. `verbose` adds output columns and schema-qualified names. `settings` (PostgreSQL 12+) lists planner GUCs set away from their defaults - the usual explanation for a plan that looks impossible. `wal` (PostgreSQL 13+) reports WAL generated and `serialize` (`none`|`text`|`binary`, PostgreSQL 17+) charges the cost of building the result rows; both require `analyze`. `memory` (PostgreSQL 17+) reports memory used by the PLANNER, so it works with or without `analyze` - use it alone to ask why planning a statement is expensive. `generic_plan` (PostgreSQL 16+) plans a parameterized statement WITHOUT values for its $1/$2 placeholders and cannot be combined with `analyze` or `params`. `costs` and `timing` default to true (as in postgres); set either to false to drop those columns, and note `timing` only applies with `analyze`. Options that need a newer server than the one connected are rejected with an explicit error naming the required version instead of a confusing parse failure. Set `hypothetical_indexes` to a list of `{table, columns, using?}` to ask the planner 'what would the plan be if these indexes existed?' -- requires the HypoPG extension (`CREATE EXTENSION hypopg`). The hypothetical indexes are torn down at the end of the call, never touching real disk.
  • pg_index_advisorRecommend indexes for a workload, and prove each one pays for itself before recommending it. Give it `statements` (the SQL you care about) or let it take the top N from `pg_stat_statements`; it plans each statement, generates candidate indexes, costs them with HypoPG hypothetical indexes, and returns only the ones that measurably cut estimated cost. How candidates are generated, and the honest limit: this tool has NO SQL parser and does not read your SQL text. It EXPLAINs each statement and harvests the columns the PLANNER reports as filters, join keys, and sort keys, then intersects those tokens with the real column list from `pg_attribute` -- so a candidate can never name a column that does not exist. The extraction is deliberately loose (a token matching a real column name on a different table can slip through); HypoPG is the arbiter, and anything that does not lower cost is discarded. Column ORDER within each candidate is equality columns first (most selective first, from `pg_stats`), then at most one range column, then sort columns. The search is greedy and BOUNDED. Each accepted index stays in place while the rest are re-costed on top of it, so later picks account for what earlier ones already fixed. `max_candidates` caps how many candidates are considered and `max_explains` caps total EXPLAIN round trips; when a cap stops the search early, `budget_exhausted` is true and the result is a truncated search, not a converged one. PostgreSQL 18 note, and it reverses a rule you have probably internalized: PG18 added B-tree SKIP SCAN, so a multi-column index whose LEADING column the query never constrains CAN now be used. The classic 'leading column never filtered means the index is useless' heuristic is wrong on PG18+. This tool gates that prune on the server version -- on PG18+ such candidates are kept and costed (`skip_scan_available: true`, and an accepted one carries `requires_skip_scan`), below PG18 they are pruned as unusable and counted in `candidates_pruned_leading_column`. Requires the HypoPG extension (`CREATE EXTENSION hypopg;`). Hypothetical indexes are session-scoped and are reset before the call returns, on the success and the failure path alike, so they never touch disk and never leak into a later query plan. Statements are only ever EXPLAINed, never executed, inside a `BEGIN READ ONLY` transaction. Costs are PLANNER ESTIMATES, not measurements: they are the right way to compare two plans for the same statement and the wrong way to predict wall-clock time. They are weighted by `calls` when the workload came from pg_stat_statements, so a query run a million times outranks an identical one run twice. Validate a recommendation with `pg_explain` before creating it, and create it with CONCURRENTLY in production (`create_statement_concurrently`).
  • pg_healthQuick health snapshot: server version, database size, connection counts measured against `max_connections`, active queries with their wait events, a pg_stat_database rollup, and table count. Useful as a connection sanity check and to spot runaway queries, connection-cap pressure, and lock/IO waits. - connections: `total` for the CURRENT database, broken down into `active` / `idle` / `idle_in_transaction` / `idle_in_transaction_aborted` / `other` (starting, fastpath function call, disabled) / `state_unavailable` -- those six sum to `total`. `idle_in_transaction_aborted` is called out separately because it holds locks and blocks vacuum while doing no work and will never commit. `state_unavailable` counts sessions whose `state` reads NULL because the role lacks pg_read_all_stats / pg_monitor membership; a non-zero value means every other bucket is under-counted by at least that much, so do NOT read `active: 0` next to it as an idle database. Plus `cluster_client_backends` (client backends across ALL databases -- those are what actually consume connection slots), `max_connections`, `superuser_reserved_connections`, and `used_fraction` (cluster_client_backends / max_connections). A raw connection count means nothing without the cap; read `used_fraction` first. - active_queries: `pid`, `state`, `query`, `application_name`, `backend_type`, `wait_event_type` / `wait_event` (both NULL when the backend is running rather than waiting -- the single most diagnostic pair in pg_stat_activity). Both are reported verbatim as the server spells them, and that spelling changes between majors: a backend waiting on a buffer pin reports `wait_event_type` 'BufferPin' through PostgreSQL 18 and 'Buffer' from 19 on, with the `wait_event` names beneath it changing to match. Read them against the reported `version` rather than hard-coding a literal. `duration_seconds` (since query_start) and `transaction_age_seconds` (since xact_start). A large transaction_age_seconds next to a small duration_seconds is a long-open transaction, the usual root cause behind lock waits, bloat, and stalled autovacuum. - database_stats: pg_stat_database for the current database -- `deadlocks`, `temp_files` / `temp_bytes` (work_mem spills), `conflicts` (recovery conflicts, only ever non-zero on a replica), `blks_hit` / `blks_read` / `cache_hit_ratio`, and `stats_reset`. Every counter is CUMULATIVE since stats_reset, not a rate -- interpret them against that timestamp. Sub-queries that fail (several of these are permission-gated on managed providers) append to `_warnings` and leave their field null; the rest of the snapshot still returns.
  • +11 more on the listing page

Ready-to-paste client configs

Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.

ZeroDB MCP Server

mcpServers (Claude Desktop / Cursor)
{
  "mcpServers": {
    "ainative-zerodb-mcp-server": {
      "command": "npx",
      "args": [
        "ainative-zerodb-mcp-server"
      ],
      "env": {
        "ZERODB_API_URL": "YOUR_ZERODB_API_URL_HERE",
        "ZERODB_PROJECT_ID": "YOUR_ZERODB_PROJECT_ID_HERE",
        "ZERODB_API_KEY": "YOUR_ZERODB_API_KEY_HERE"
      }
    }
  }
}

PostgreSQL MCP Server

mcpServers (Claude Desktop / Cursor)
{
  "mcpServers": {
    "postgresql-mcp-server-4": {
      "command": "npx",
      "args": [
        "-y",
        "@yawlabs/postgres-mcp@latest"
      ],
      "env": {
        "DATABASE_URL": "YOUR_DATABASE_URL_HERE"
      }
    }
  }
}

Frequently asked questions

ZeroDB MCP Server is categorized under Databases and uses a local stdio subprocess. PostgreSQL MCP Server belongs to Databases and uses a local stdio subprocess. Pick ZeroDB MCP Server for databases work and PostgreSQL MCP Server for databases.

Copy the mcpServers block from the config section on this page into your client's config (for example claude_desktop_config.json or ~/.cursor/mcp.json), then fully restart the client.

ZeroDB MCP Server has no declared pricing — check the project's own site. PostgreSQL MCP Server has no declared pricing — check the project's own site. If a server needs environment variables such as API keys, define them under the env key in your client's MCP config.

Yes. MCP clients support multiple servers: add ainative-zerodb-mcp-server and postgresql-mcp-server-4 as separate keys in the same mcpServers object, and your assistant will call tools from either one.

On AllMCPs, ZeroDB MCP Server has a quality signal of 63/100 (Good) with 1 views, 0 installs and 0 GitHub stars. PostgreSQL MCP Server has 64/100 (Good) with 1 views, 0 installs and 8 GitHub stars.