Skip to main content
Glama
Touexe
by Touexe

pocketbase-mcp

An MCP server that exposes PocketBase through 13 intent-first tools rather than ~50 endpoint wrappers.

Install

Requires Python >=3.11 and uv.

uv sync

uv sync installs the pypocketbase client from its Git repository.

Related MCP server: PocketBase MCP Server

Environment Variables

Variable

Default

Description

POCKETBASE_URL

http://127.0.0.1:8090

PocketBase instance URL

POCKETBASE_ADMIN_EMAIL

(none)

Superuser email for startup auth

POCKETBASE_ADMIN_PASSWORD

(none)

Superuser password for startup auth

POCKETBASE_ENABLE_DESTRUCTIVE

(unset)

Set any truthy value to register delete_records and destroy_collection

POCKETBASE_MCP_HOST

127.0.0.1

HTTP transport bind host

POCKETBASE_MCP_PORT

8000

HTTP transport bind port

POCKETBASE_LOG_PAGE_SIZE_MAX

500

Max page size for read_logs

POCKETBASE_BATCH_LIMIT

200

Max operations per bulk_write call

Tools

13 intent-first tools. Each one returns {"ok": true, "data": …, "hint"?: …} on success or {"ok": false, "error_type": …, "message": …, "hint": …} on failure. The hint names the next tool to call or the step that fixes the error. The Kind column marks each tool R read-only, I idempotent, or D destructive.

Always registered (11)

Tool

Kind

Purpose

Key parameters

describe_schema

R

Inventory every collection (name, id, type, field count)

refresh

describe_collection

R

Full field defs, types, required, relation targets, select values, API rules, indexes for one collection

collection

find_records

R

Query/look up records — by id, or filter_template + filter_params; paged by default

collection, record_id, filter_template, filter_params, expand, fields, sort, page, per_page, fetch_all

write_record

I

Create or update one record; the server validates the payload against the cached schema first

collection, action (create/update), data, record_id, expand

bulk_write

Many writes as one atomic transaction

operations[] ({collection, action: create/update/upsert/delete, data?, record_id?}) — cap POCKETBASE_BATCH_LIMIT

manage_collection

I

Create or alter a collection (base / auth / view)

action, name, collection_type, fields, view_query, api_rules, indexes

connect

Check or switch the process identity

as_ (status/superuser/user/impersonate), collection, email, password, user_id

manage_auth

Auth lifecycle: password reset, verification, email change, token refresh

action, collection, email, token, new_email, password, password_confirm

manage_files

File on a record: get URL, download bytes, upload local file

action (url/download/upload), collection, record_id, field, filename, local_path, thumb

inspect_server

R

Health, settings summary, cron list, log stats (non-health sections need superuser)

(none)

read_logs

R

Request log entries (superuser only)

log_id, filter_template, filter_params, page, per_page

Destructive — opt-in only (2)

The server registers these two only when POCKETBASE_ENABLE_DESTRUCTIVE is set. Each one requires a confirmation argument that must match the current state, so you cannot run the call without first checking what it will affect.

Tool

Kind

Purpose

Key parameters

delete_records

D

Permanently delete records. IRREVERSIBLE

collection, confirm_count (must equal resolved count), record_ids or filter_template + filter_params

destroy_collection

D

delete drops the collection + data; truncate keeps schema, drops rows

action, name, confirm_name (must equal name)

Resource & prompts

  • Resource pocketbase://schema — all collections (id, name, type, field_count).

  • Prompts: inspect_then_query, safe_delete, create_with_validation.

Skills

skills/pocketbase-mcp-tools/SKILL.md is an agent skill that teaches an MCP client to use these tools correctly. It covers the inspect-then-act order, filter templates instead of string interpolation, pagination limits, the complex-query grammar (relation traversal, ?= any-of, API-rule shapes), and the confirmation steps for destructive tools. Point your agent at the file, or copy it into the client's skills directory. It gives better tool use than the tool docstrings alone.

Docker

The image runs the HTTP transport (pocketbase-mcp --http). This is the only transport that works in a container, because the stdio transport needs the MCP client to start the process itself. The image binds 0.0.0.0:8000, runs as a non-root user, and contains no build tools.

Pull the published image. Every GitHub release triggers .github/workflows/docker-release.yml, which builds linux/amd64 and linux/arm64 and pushes to GHCR:

docker run -d --name pocketbase-mcp -p 8000:8000 --env-file .env \
  ghcr.io/touexe/pocketbase-mcp:latest

Tags: latest, the full version (1.0.0), 1.0, and 1.

Read the logs with docker logs -f pocketbase-mcp. Stop and remove the container with docker rm -f pocketbase-mcp.

Build it yourself:

docker build -t pocketbase-mcp .
docker run -d --name pocketbase-mcp -p 8000:8000 --env-file .env pocketbase-mcp

docker-compose has two profiles:

docker compose --profile local up --build      # build from the local Dockerfile
docker compose --profile registry up           # pull ghcr.io/touexe/pocketbase-mcp:latest

Both services read the variables from .env (POCKETBASE_URL, POCKETBASE_ADMIN_EMAIL, POCKETBASE_ADMIN_PASSWORD, POCKETBASE_ENABLE_DESTRUCTIVE, and the rest) and set POCKETBASE_MCP_HOST=0.0.0.0 and POCKETBASE_MCP_PORT=8000.

To reach a PocketBase server on the host: inside the container, 127.0.0.1 points at the container itself, not the host. Set POCKETBASE_URL=http://host.docker.internal:8090. On Linux, also add --add-host=host.docker.internal:host-gateway to docker run. Or run PocketBase in the same compose network and use its service name.

To override the default flag (for example, to bind a different port), append the arguments:

docker run -d --name pocketbase-mcp-9000 -p 9000:9000 -e POCKETBASE_MCP_PORT=9000 \
  --env-file .env ghcr.io/touexe/pocketbase-mcp:latest --http

One Identity Per Process

This server carries exactly one PocketBase identity. The pypocketbase client writes the auth token into a single shared aiohttp session. Calling connect(as_='user', ...) changes the identity for all subsequent calls in the session.

For multi-tenant use (different identities in parallel), run one server process per identity.

Destructive Tools Opt-In

delete_records and destroy_collection are not registered by default. Set POCKETBASE_ENABLE_DESTRUCTIVE=1 to make them available. The opt-in stops a deployment that must never delete data from doing so by accident, whatever the agent requests.

Running

stdio (default, for Claude Desktop / MCP clients):

uv run pocketbase-mcp

HTTP transport:

uv run pocketbase-mcp --http

Client Config Snippet

For Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "pocketbase": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/mcp", "pocketbase-mcp"],
      "env": {
        "POCKETBASE_URL": "http://127.0.0.1:8090",
        "POCKETBASE_ADMIN_EMAIL": "admin@example.com",
        "POCKETBASE_ADMIN_PASSWORD": "your-password"
      }
    }
  }
}

Testing

The default suite is hermetic: no network, no credentials.

uv run python -m pytest

Live integration suite

tests/live/ drives the in-memory FastMCP client (the surface an agent sees) against a real PocketBase server. It is marked live and excluded from the default run; opt in with:

uv run python -m pytest -m live

Required environment (names only; never commit a value):

Variable

Purpose

POCKETBASE_URL

instance the suite runs against (defaults to http://127.0.0.1:8090)

POCKETBASE_ADMIN_EMAIL

superuser identity, established through the connect tool

POCKETBASE_ADMIN_PASSWORD

superuser password

The suite sets settings.enable_destructive for its own session, so delete_records and destroy_collection are exercised; you do not need to set POCKETBASE_ENABLE_DESTRUCTIVE yourself.

When the server is unreachable or either credential is missing, every live test skips with a stated reason; it never errors.

⚠️ Development instances only. The live suite creates and deletes collections. Never point POCKETBASE_URL at production or any instance whose data you care about.

The mcptest_ prefix rule: the safety contract

Every collection a live test touches must be one it created itself, named mcptest_<area>_<hex8> via the live_collection factory. Teardown (both the per-test finalizer and the session-end sweep) deletes only mcptest_* names and raises rather than deletes anything else. This, plus the rule that no test names a collection it did not create, keeps a mis-pointed POCKETBASE_URL from destroying real data. Anyone adding a live test must honor it: draw collections from the factory, never hard-code a bare name.

Resolved design questions

  • Session-end sweep is always on (no --no-live-sweep). The sweep runs at the start and end of the next session and removes a crashed run's mcptest_* leftovers, so a fresh run is always clean; diagnose a failure by rerunning the single test.

  • File-upload fixture is a generated temp file, not a committed binary asset. No thumbnail behaviour is exercised, so no real image is needed.

Smoke-testing over HTTP

tests/ and tests/live/ both run in-process; neither builds an HTTP request. scripts/curl_smoke.sh closes that gap: it drives an already-running HTTP server with nothing but curl, jq, and sed, completing the MCP Streamable HTTP handshake, then issuing one real tools/call against every registered tool. It is an operator/developer command; it is not collected by pytest and not wired into CI.

⚠️ It writes to a real instance. Point it only at a development PocketBase. Every collection and record it creates lives under an ephemeral mcpsmoke_-prefixed collection that it drops again on exit.

1. Start the server (a second terminal), against a development instance, with the destructive tools registered so all 13 are covered:

POCKETBASE_URL=http://127.0.0.1:8090 \
POCKETBASE_ADMIN_EMAIL=admin@example.com \
POCKETBASE_ADMIN_PASSWORD=your-password \
POCKETBASE_ENABLE_DESTRUCTIVE=1 \
uv run pocketbase-mcp --http

Without POCKETBASE_ENABLE_DESTRUCTIVE=1 the server registers only 11 tools and the harness prints a SKIP: line saying the flag is required for full coverage.

2. Run the harness:

POCKETBASE_ADMIN_EMAIL=admin@example.com \
POCKETBASE_ADMIN_PASSWORD=your-password \
bash scripts/curl_smoke.sh

It reads POCKETBASE_MCP_HOST / POCKETBASE_MCP_PORT (default 127.0.0.1:8000) to find the server. POCKETBASE_ADMIN_EMAIL / POCKETBASE_ADMIN_PASSWORD are the superuser credentials it authenticates and tears down with; the same names the server itself uses.

Prerequisites: bash, curl, jq, and sed on PATH. Missing any of them, missing a credential, or an unreachable MCP port each produce a SKIP: line and exit 0, never a failure. A genuine assertion failure prints the request and the full response body, still runs the remaining cases, tears down, and exits 1.

Cleanup. A clean run, a failed run, and a Ctrl-C all trigger an EXIT trap that reconnects as superuser and drops every mcpsmoke_ collection the run created. A hard kill (SIGKILL) can still strand mcpsmoke_* collections; they are safe to drop by hand. If teardown's own superuser reconnect fails (the process may be left holding an ephemeral user identity), restart the server process before retrying.

Design Decisions (Open Questions Resolved)

Should find_records fall back to get_full_list automatically?

Decision: Explicit fetch_all=True required.

An accidental full-table read floods the context window. An agent that asks for "all records" from a 100,000-row table would silently exhaust its context budget if the fallback were automatic. Passing fetch_all=True is a deliberate signal; the default paged behavior is safe.

Expose the schema as an MCP resource in addition to describe_schema?

Decision: Deferred. Tools only for v1.

Resources require the client to know when to re-fetch them (cache invalidation). Tools give the agent explicit control: call describe_schema(refresh=True) after a schema change. Once real usage shows the schema being re-read every turn, a resource is the right fix. Adding it later is cheap; it doesn't change any tool contracts.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A comprehensive server that enables advanced database operations with PocketBase, providing tools for collection management, record operations, user management, and database administration through the Model Context Protocol.
    502
    MIT
  • A
    license
    Not graded
    quality
    F
    maintenance
    Enables AI assistants and MCP clients to interact with PocketBase databases for authentication, data management, and administrative operations.
    12
    65
    MIT

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/Touexe/pocketbase-mcp'

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