Skip to main content
Glama
Sa3fa

pg-analytics-mcp

by Sa3fa

pg-analytics-mcp

Конфигурационный read-only Postgres MCP-сервер для Claude. Открывает схему Postgres для Claude через Streamable HTTP; схема и значения enum интроспектируются из работающей базы данных при запуске, а всё клиент-специфичное хранится в одном YAML-файле.

Спроектирован для работы за Cloudflare Access на стеке cloudflared → reverse-proxy (в комплекте идёт полный playbook по развёртыванию), но сам сервер не зависит от Cloudflare и работает где угодно.

Не зависит от клиента. Внутри server/ нет ничего, что знало бы о конкретном клиенте. Чтобы обслужить нового клиента: скопируйте репозиторий, напишите конфигурационный файл, задайте .env.

Зачем это существует

Предыдущее решение нагромождало три процесса, чтобы обойти сторонний пакет:

supergateway  →  enrich.py  →  postgres-mcp  →  Postgres

postgres-mcp поддерживает только stdio/SSE (Cloudflare требует Streamable HTTP), у него нет ни поверхности конфигурации, а, supergateway порождал по дочернему процессу на каждую MCP-сессию, которые никогда не завершались, — измерено 23 дочерних процесса / 15 соединений при лимите роли 20, что проявлялось как «работает около 9 вызовов, а затем всё падает, включая SELECT 1».

Этот сервер — это один процесс с одним общим пулом. Измерено: 1 процесс после 30 вызовов инструментов.

Related MCP server: Brand MCP Server

Архитектура

Claude → portal.<zone>          Cloudflare MCP Server Portal (OAuth)
       → mcp-origin.<zone>      Access app + Managed OAuth
       → cloudflared            tunnel
       → traefik                Host-header routing
       → this container         uvicorn, Streamable HTTP at /mcp
       → Postgres               read-only role → analytics.* views

Граница безопасности — роль базы данных, а не этот сервер.

Быстрый старт

cp .env.example .env      # set DATABASE_URI + the deployment vars
$EDITOR config/example.yaml   # domain prose for this client
docker compose up -d --build

curl -s localhost:8000/healthz        # ok
curl -s localhost:8000/introspection  # what the server decided at boot

Затем следуйте docs/PLAYBOOK-NEW-CLIENT.md для части, связанной с Cloudflare.

Конфигурация

.env — специфичное для хоста, единственное, что меняется между VPS:

Переменная

Назначение

DATABASE_URI

Роль только для чтения. В Supavisor pooler имя пользователя обязано содержать .PROJECT_REF.

MCP_CONTAINER_NAME

Контейнер, тег образа и имя роутера traefik

MCP_HOSTNAME

Публичное имя хоста; автоматически добавляется в allowlist транспортной безопасности

TRAEFIK_NETWORK

Внешняя docker-сеть, за которой следит traefik

MCP_CONFIG

Путь к клиентскому YAML внутри образа

MCP_LOCAL_PORT

Публикуемый порт на стороне хоста (по умолчанию 8000)

config/<client>.yaml — предметная область. Не перечисляйте здесь колонки или значения enum: они интроспектируются из живой базы при запуске и поэтому не могут устареть. Пишите только то, что интроспекция не может узнать, — бизнес-смысл и ловушки.

Инструменты

Встроенные:

  • execute_sql(sql) — сырой SQL только для чтения. Его описание собирается при запуске из вашего авторского текста плюс сгенерированного списка схемы и enum.

  • list_views() — все доступные для чтения объекты с колонками, количеством строк и enum.

  • describe_view(name) — колонки одного объекта.

Определяемые конфигурацией: каждая запись в tools.queries становится настоящим MCP-инструментом с типизированными параметрами. Параметры привязываются через именованные плейсхолдеры psycopg — никогда через строковую интерполяцию, — а min/max проверяются до привязки.

tools:
  queries:
    monthly_trend:
      description: |
        Donations per month. The most recent month is PARTIAL.
      params:
        months: {type: integer, default: 6, min: 1, max: 36}
      sql: |
        select ... where donated_at >= date_trunc('month', now())
                                     - make_interval(months => %(months)s - 1)

Именно это закрывает разрыв с n8n: добавление инструмента — это текст + SQL, а не Python.

Почему описания живут здесь

Описания инструментов — это единственный контекст, который модель видит всякий раз, когда инструмент доступен, — для каждого клиентаи каждого разговора, без загрузки навыков и без инструкций проекта. Знание предметной области, хранящееся во внешнем документе, — это знание, которого у модели часто нет.

Половина каждого описания — авторская (суждения), половина — сгенерированная (факты). Сгенерированная половина — причина, по которой платформа/процессор boxy и частота daily больше не могут пропасть так, как они пропали в написанном вручную промпте, который был раньше.

Эксплуатация

curl -s localhost:8000/introspection | python3 -m json.tool   # objects, enums, tools, limits
docker top <container>                                        # must stay at 1 process
docker compose up -d --build                                  # after a config edit

Изменение конфигурации или схемы требует перезапуска: интроспекция намеренно кэшируется на всё время жизни процесса, чтобы поведение не могло изменяться посреди работы.

Пять граничных тестов

Перезапустите после любого изменения представлений, грантов или конфигурации. Все пять обязаны упасть:

update donations set amount = 0 where false;   -- permission denied for view
select count(*) from public.donations;         -- permission denied for table
select count(*) from public.website_orders;    -- permission denied for table
create table analytics.t (id int);             -- read-only transaction
select phone_number from customers limit 1;    -- column does not exist

limits.select_only существует, но по умолчанию выключен: роль — это граница, а SQL-валидатор поверх неё блокирует корректные read-only конструкции без всякой выгоды — именно поэтому ограниченный режим postgres-mcp был и abandoned.

Грабли, оплаченные кровью

  • Ключи labels в Compose не подставляют переменные. Labels должны быть в же списке (- "traefik...=value"), иначе вы получите роутер, буквально названный ${MCP_CONTAINER_NAME}, и traefik отдаёт 404.

  • Защита от DNS-rebinding включена по умолчанию в MCP SDK. Проброшенный Host за прокси должен быть разрешён; MCP_HOSTNAME и MCP_LOCAL_PORT добавляются автоматически.

  • Монтирование MCP-приложения под ваше Starlette-приложение заменяет его жизненный цикл. Менеджер сессий нужно запускать явно (server.session_manager.run()), иначе каждый запрос падает коду 500 «Task group is not initialized».

  • set_read_only / set_autocommit должны предшествовать любому execute() на соединении, иначе пул падает с ошибкой «connection in transaction status INTRANS».

  • pg_class.reltuples бессмысленна для представлений, поэтому оценка количества строк при запуске переходит на ограниченный count(*).

  • Supavisor переписывает application_name в «Supavisor», поэтому атрибуция соединения по клиентам через коллектор невозможна.

  • MCP SDK 2.0 переименовал FastMCP в MCPServer и вынес его из mcp.server.fastmcp. Именно поэтому requirements.txt — это полный lock-файл.

Лицензия

MIT — см. LICENSE.

A
license - permissive license
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude to interact with PostgreSQL databases by executing SQL queries, exploring schemas, and monitoring database health. It provides tools for data manipulation and schema management via a secure SSE connection.
    287
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude Desktop to query a PostgreSQL brand database through MCP. Supports local stdio and remote HTTP/SSE deployments with API key authentication for secure database access.
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables natural language querying of PostgreSQL databases through the Model Context Protocol. It translates user questions into validated SQL, executes read-only queries safely, and returns results to MCP-compatible clients like Claude Desktop.
  • A
    license
    A
    quality
    A
    maintenance
    Query and manage PostgreSQL databases from Claude Code, Cursor, and any MCP client, with read-only by default and built-in schema introspection, EXPLAIN, and performance diagnostics.
    21
    1,809
    3
    MIT

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Sa3fa/pg-analytics-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server