Skip to main content

AGE MCP Server

License Python

An MCP server for querying Apache AGE graphs in PostgreSQL.

Version 0.3.0 makes read-only operation the secure default, adds asynchronous connection pooling, safe Cypher parameters and bounded cursor pagination, and returns MCP structured content from every tool.

Requirements

  • Python 3.13 or later
  • PostgreSQL with the Apache AGE extension installed and loaded
  • A database role restricted to the graphs and operations the MCP client needs

Enable AGE in the target database:

CREATE EXTENSION IF NOT EXISTS age CASCADE;

Install

With uv:

uv init your_project
cd your_project
uv add age_mcp_server

With a Python virtual environment:

python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install age_mcp_server

With Homebrew:

brew install rioriost/tap/age_mcp_server

Configure an MCP client

Avoid placing a database password in command-line arguments. Supply a connection string through PG_CONNECTION_STRING and use one of libpq's credential mechanisms, such as PGPASSWORD or a protected PostgreSQL password file.

{
  "mcpServers": {
    "age_manager": {
      "command": "age_mcp_server",
      "env": {
        "PG_CONNECTION_STRING": "host=db.example port=5432 dbname=postgres user=age_reader sslmode=require",
        "PGPASSWORD": "replace-with-a-secret"
      }
    }
  }
}

Treat the MCP client configuration as a secret if it contains PGPASSWORD. A PostgreSQL password file or the client's secret store is preferable.

The connection string can still be supplied explicitly when necessary:

age_mcp_server --pg-con-str "host=db.example dbname=postgres user=age_reader sslmode=require"

For Microsoft Entra authentication to Azure Database for PostgreSQL, first sign in with the Azure CLI, then opt in to token acquisition:

age_mcp_server \
  --pg-con-str "host=server.postgres.database.azure.com dbname=postgres user=identity sslmode=require" \
  --azure-identity

Tools

Read-only mode is the default:

Tool Purpose
read-age-cypher Run a validated, parameterized, paginated read-only Cypher query
list-age-graphs List Apache AGE graphs
get-age-schema Inspect counts, directions, and sampled property types

Write tools are only advertised and accepted when the server starts with --allow-write:

Tool Purpose
write-age-cypher Run Cypher containing a mutating clause
create-age-graph Create a graph
drop-age-graph Permanently drop a graph
age_mcp_server --allow-write

Use a separate, least-privileged database role for write mode. Enabling the flag does not grant PostgreSQL privileges that the configured role does not already have.

Safety limits

  • Cypher, graph names, return aliases, and graph-management arguments are safely quoted or parameterized before reaching PostgreSQL.
  • Read tools run inside PostgreSQL read-only transactions.
  • CALL is considered side-effecting and requires write mode.
  • Read pages contain at most 50 rows. Opaque HMAC-authenticated cursors are bound to the graph, query, and parameters, with a maximum offset of 100,000.
  • Cypher $parameters are accepted only when placeholder names exactly match a JSON parameter object. The object is capped at 100,000 bytes and passed to AGE through a prepared statement.
  • Write queries execute fully and return an affected-row count instead of result rows.
  • Statements time out after 30 seconds by default.
  • Queries are limited to 100,000 characters and must contain one explicit RETURN clause per query branch.
  • Raw database errors, query contents, and connection credentials are not returned to MCP clients or written to normal logs.

Change the timeout when needed:

age_mcp_server --statement-timeout-ms 60000

The timeout must be between 1 millisecond and 1 hour.

Tune the asynchronous connection pool or load the AGE library for every newly opened pooled connection:

age_mcp_server --pool-min-size 2 --pool-max-size 8 --load-age

The pool must satisfy 1 <= min <= max <= 64. RETURN * remains unsupported; list return values explicitly so Apache AGE's SQL result types can be declared.

Example tool input with parameters and pagination:

{
  "graph_name": "people",
  "query": "MATCH (n:Person) WHERE n.age >= $minimum RETURN n.name AS name ORDER BY name",
  "parameters": {"minimum": 18},
  "page_size": 25
}

Pass the returned nextCursor as cursor to fetch the next page.

OpenTelemetry

Install the optional exporter dependencies and enable OTLP export:

python3 -m pip install "age_mcp_server[telemetry]"
age_mcp_server --enable-telemetry --otel-service-name age-production

The exporter follows standard OTEL_EXPORTER_OTLP_* environment variables. Traces and metrics record operation latency, counts, and failures. Connection details, Cypher text, parameter values, and raw database errors are excluded.

Development

Install all development dependencies and run the release gate:

make sync
make check

make check runs Ruff, the 80% coverage gate, Bandit, the locked dependency audit, and package builds. The test suite includes a live Apache AGE integration test:

AGE_TEST_CONNECTION_STRING="host=127.0.0.1 dbname=postgres user=postgres password=postgres" \
  make integration

CI runs this test against the official Apache AGE PostgreSQL container. See the 0.3.0 review for the completed security and feature review.

License

MIT

Release files for age_mcp_server 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for age_mcp_server 0.3.0
File Size Uploaded
age_mcp_server-0.3.0.tar.gz 18.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for age_mcp_server 0.3.0
File Interpreter ABI Platform
age_mcp_server-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size:39.4 kB

Release files / age_mcp_server-0.3.0.tar.gz

Download URL age_mcp_server-0.3.0.tar.gz
Size 18.5 kB
Tags Source
SHA-256 checksum
How to use checksums
77077d3efea4bf5051b64e43f61c2fba244d17365e8ff34ad59c25bf8aa5e464
BLAKE2b-256 checksum
How to use checksums
5acea5e849cb94844ae0af269b3dd1ca516e54656da88831fea2497ff1c82fd6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / age_mcp_server-0.3.0-py3-none-any.whl

Download URL age_mcp_server-0.3.0-py3-none-any.whl
Size 20.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
855ce3343345334fcb16b4acfb640f51406577099623ba094879830955f88849
BLAKE2b-256 checksum
How to use checksums
8d794d13fab70178be97940921075faba88fc1c81b64109bb2e32df08a9074be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.50

2 release files

0.2.49

2 release files

0.2.47

2 release files

0.2.46

2 release files

0.2.45

2 release files

0.2.44

2 release files

0.2.43

2 release files

0.2.42

2 release files

0.2.40

2 release files

0.2.39

2 release files

0.2.38

2 release files

0.2.37

2 release files

0.2.34

2 release files

0.2.33

2 release files

0.2.32

2 release files

0.2.30

2 release files

0.2.29

2 release files

0.2.28

2 release files

0.2.26

2 release files

0.2.25

2 release files

0.2.23

2 release files

0.2.20

2 release files

0.2.19

2 release files

0.2.17

2 release files

0.2.16

2 release files

0.2.13

2 release files

0.2.12

2 release files

0.2.11

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page