Skip to main content
Glama
mabeldata

PocketBase MCP Server

by mabeldata
README.md
# PocketBase MCP Server

[![smithery badge](https://smithery.ai/badge/@mabeldata/pocketbase-mcp)](https://smithery.ai/server/@mabeldata/pocketbase-mcp)
[![Maintained_By Mabel Data](https://img.shields.io/badge/Maintained_By-MabelData-purple)](https://github.com/mabeldata/pocketbase-mcp/blob/main/LICENSE)

This is an MCP server that interacts with a PocketBase instance. It allows you to fetch, list, create, update, and manage records and files in your PocketBase collections.

## Compatibility

| Component | Version |
|---|---|
| PocketBase server | **>= v0.23** required (`_superusers` collection model); tested against **v0.40.3** (latest stable at release time) |
| `pocketbase` JS SDK | ^0.28.1 |
| `@modelcontextprotocol/sdk` | ^1.30.0 |
| Node.js | >= 18 |

Notes for newer PocketBase servers:

-   **v0.27+**: the `geoPoint` field type and the `geoDistance()` filter function are fully supported by `list_records` / `batch_records` — see [Filter examples with geoPoint](#filter-examples-geopoint).
-   **v0.40.x**: `Log.Data` may be truncated by the server (~16KB) and marked with `"__pb_truncated__": true`; log messages are limited to 8KB. `list_logs` / `get_log` output passes this through as-is.
-   **v0.38+**: a superuser **IP whitelist** can be enabled in PocketBase Settings. When active, requests from IPs outside the whitelist (including this MCP's token) are rejected with HTTP 403 — see Troubleshooting.
-   **v0.33+**: collection/record ids may not contain `.` `/` `\` `|` `"` `'` `` ` `` `<` `>` `:` `?` `*` `%` `$` or Windows reserved names. The migration generators validate this up front.
-   **v0.28+**: the `json` field type has a default maximum size of 1MB; larger payloads fail validation on `create_record` / `update_record`.

## Installation

### Installing via Smithery

To install PocketBase MCP Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@mabeldata/pocketbase-mcp):

```bash
npx -y @smithery/cli install @mabeldata/pocketbase-mcp --client claude
```

1.  **Clone the repository (if you haven't already):**
    ```bash
    git clone <repository_url>
    cd pocketbase-mcp
    ```
2.  **Install dependencies:**
    ```bash
    npm install
    ```
3.  **Build the server:**
    ```bash
    npm run build
    ```
    This compiles the TypeScript code to JavaScript in the `build/` directory and makes the entry point executable.

## Testing

Test suite (vitest, 3 layers — full guide in [tests/TESTS.md](tests/TESTS.md)):

-   `npm test` — unit + contract tests (207: 195 passing + 12 documented known-bug markers; hermetic: no PocketBase instance or network required). The contract layer locks the `tools/list` MCP contract via snapshot (33 tools: the 22 original + 11 additive PR-3 tools, each group snapshotted separately), a real Client↔Server handshake over InMemoryTransport, and a stdio smoke of the built `build/index.js`.
-   `npm run test:integration` — integration tests against a **real** PocketBase binary (56 tests): auto-downloads/caches the binary (`POCKETBASE_VERSION` to pin, `POCKETBASE_BIN` for a local binary, `PB_BIN_DIR` for an alternative cache), boots an ephemeral instance on an OS-assigned port with a unique superuser identity, and validates generated migration files with the official `migrate up/down` runner. The PR-3 suite (`pr3-tools.test.ts`) boots its **own** dedicated instance (admin-scope endpoints — SQL, batch, backups, settings, log clear — must not race siblings on the shared server; see the file header).
-   `npm run test:all` — the full suite (263 tests).
-   `npm run typecheck` — tsc over src + tests.
-   `SKIP_KNOWN_BUG_TESTS=1 npm test` — green baseline where known-bug marker tests are skipped instead of run.

End-to-end smoke scripts (drive the built server over stdio against a real PocketBase instance, 53 checks):

-   `npm run smoke:contract` — contract-only smoke (tools/list over stdio, no PocketBase needed).
-   `npm run smoke` — full smoke: starts an ephemeral server from the binary at `$POCKETBASE_BIN` (default `/tmp/pb-bin/pocketbase`), creates a superuser, then exercises every tool category (records, collections, files, logs, crons, migrations) over the stdio JSON-RPC channel.

CI (`.github/workflows/ci.yml`) runs build + typecheck + hermetic tests + integration tests + smoke on a matrix of Node 18/20/22 × PocketBase v0.39.11/v0.40.3.

## Configuration

This server requires the following environment variables to be set:

-   `POCKETBASE_API_URL`: The URL of your PocketBase instance (e.g., `http://127.0.0.1:8090`). Defaults to `http://127.0.0.1:8090` if not set.
-   `POCKETBASE_ADMIN_TOKEN`: An admin authentication token for your PocketBase instance. **This is required.** You can generate this from your PocketBase admin UI, see [API KEYS](https://pocketbase.io/docs/authentication/#api-keys).
-   `POCKETBASE_ENABLE_SQL`: **Optional, default disabled.** Gates the `run_sql` tool (raw SQL execution). See [SQL Execution (run_sql)](#sql-execution-run_sql--security-gated) below — only set it to `true` if you understand the risks.

These variables need to be configured when adding the server to Cline (see Cline Installation section).

## Available Tools

The server provides the following tools, organized by category:

### Record Management

-   **fetch_record**: Fetch a single record from a PocketBase collection by ID.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "collection": {
              "type": "string",
              "description": "The name of the PocketBase collection."
            },
            "id": {
              "type": "string",
              "description": "The ID of the record to fetch."
            }
          },
          "required": [
            "collection",
            "id"
          ]
        }
        ```

-   **list_records**: List records from a PocketBase collection. Supports pagination, filtering, sorting, and expanding relations.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "collection": {
              "type": "string",
              "description": "The name of the PocketBase collection."
            },
            "page": {
              "type": "number",
              "description": "Page number (defaults to 1).",
              "minimum": 1
            },
            "perPage": {
              "type": "number",
              "description": "Items per page (defaults to 30, max 500).",
              "minimum": 1,
              "maximum": 500
            },
            "filter": {
              "type": "string",
              "description": "Filter string for the PocketBase query."
            },
            "sort": {
              "type": "string",
              "description": "Sort string for the PocketBase query (e.g., \\"fieldName,-otherFieldName\\")."
            },
            "expand": {
              "type": "string",
              "description": "Expand string for the PocketBase query (e.g., \\"relation1,relation2.subRelation\\")."
            }
          },
          "required": [
            "collection"
          ]
        }
        ```

-   **create_record**: Create a new record in a PocketBase collection.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "collection": {
              "type": "string",
              "description": "The name of the PocketBase collection."
            },
            "data": {
              "type": "object",
              "description": "The data for the new record.",
              "additionalProperties": true
            }
          },
          "required": [
            "collection",
            "data"
          ]
        }
        ```

-   **update_record**: Update an existing record in a PocketBase collection.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "collection": {
              "type": "string",
              "description": "The name of the PocketBase collection."
            },
            "id": {
              "type": "string",
              "description": "The ID of the record to update."
            },
            "data": {
              "type": "object",
              "description": "The data to update.",
              "additionalProperties": true
            }
          },
          "required": [
            "collection",
            "id",
            "data"
          ]
        }
        ```

-   **delete_record**: Delete a record from a PocketBase collection by ID (permanent).
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "collection": {
              "type": "string",
              "description": "The name or ID of the PocketBase collection."
            },
            "id": {
              "type": "string",
              "description": "The ID of the record to delete."
            }
          },
          "required": [
            "collection",
            "id"
          ]
        }
        ```

-   **batch_records**: Execute multiple record operations (create/update/upsert/delete) in ONE transactional batch — if any operation fails, the whole batch rolls back. **Requires server-side batch enabled**: on PocketBase >= v0.39 `/api/batch` is OFF by default; enable it via `update_settings` with `{"batch": {"enabled": true}}` (or Admin UI -> Settings), otherwise calls fail with HTTP 403 "Batch requests are not allowed".
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "requests": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "collection": { "type": "string" },
                  "action": { "enum": ["create", "update", "upsert", "delete"] },
                  "id": { "type": "string" },
                  "data": { "type": "object", "additionalProperties": true }
                },
                "required": ["collection", "action"]
              }
            }
          },
          "required": ["requests"]
        }
        ```

-   **get_collection_schema**: Get the schema of a PocketBase collection.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "collection": {
              "type": "string",
              "description": "The name of the PocketBase collection."
            }
          },
          "required": [
            "collection"
          ]
        }
        ```

-   **upload_file**: Upload a file to a specific field in a PocketBase collection record.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "collection": {
              "type": "string",
              "description": "The name of the PocketBase collection."
            },
            "recordId": {
              "type": "string",
              "description": "The ID of the record to upload the file to."
            },
            "fileField": {
              "type": "string",
              "description": "The name of the file field in the PocketBase collection."
            },
            "fileContent": {
              "type": "string",
              "description": "The content of the file to upload."
            },
            "fileName": {
              "type": "string",
              "description": "The name of the file."
            }
          },
          "required": [
            "collection",
            "recordId",
            "fileField",
            "fileContent",
            "fileName"
          ]
        }
        ```

-   **list_collections**: List all collections in the PocketBase instance.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {},
          "additionalProperties": false
        }
        ```

-   **download_file**: Get the download URL for a file stored in a PocketBase collection record.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "collection": {
              "type": "string",
              "description": "The name of the PocketBase collection."
            },
            "recordId": {
              "type": "string",
              "description": "The name of the record containing the file."
            },
            "fileField": {
              "type": "string",
              "description": "The name of the file field in the PocketBase collection."
            }
          },
          "required": [
            "collection",
            "recordId",
            "fileField"
          ]
        }
        ```
        *Note: This tool returns the file URL. The actual download needs to be performed by the client using this URL.*

### Filter examples: geoPoint

PocketBase >= v0.27 supports the `geoPoint` field type and the `geoDistance()` filter function. Both work transparently through `list_records` / `create_record` / `update_record` / `batch_records` (the filter string is passed to the server as-is):

```jsonc
// store a location: create_record data payload (location is a geoPoint field)
{ "title": "Office", "location": { "lat": -23.5505, "lon": -46.6333 } }

// geoDistance(lonA, latA, lonB, latB) returns KILOMETRES (verified on v0.40.3) —
// offices within 10 km of São Paulo center (list_records filter):
{ "collection": "places", "filter": "geoDistance(location.lon, location.lat, -46.6333, -23.5505) <= 10" }

// combine with other conditions:
{ "collection": "places", "filter": "active = true && geoDistance(location.lon, location.lat, -46.6333, -23.5505) < 5" }
```

Arguments must be plain numbers or numeric field identifiers (`location.lon` / `location.lat` for a `geoPoint` field); a geometry-literal like `{-23.55, -46.63}` is NOT valid, and `geoDistance()` is currently not supported in `sort`. Official docs: https://pocketbase.io/docs/api-rules-and-filters/ (geoDistance section).

### Collection Management

-   **list_collections**: List all collections in the PocketBase instance.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {},
          "additionalProperties": false
        }
        ```

-   **get_collection_schema**: Get the schema of a PocketBase collection.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "collection": {
              "type": "string",
              "description": "The name of the PocketBase collection."
            }
          },
          "required": [
            "collection"
          ]
        }
        ```

-   **get_collection_scaffolds**: Get example collection schema payloads (server >= v0.37) — an object keyed by collection type (`base`, `auth`, `view`) with ready-to-edit templates for building new collections.
    -   *Input Schema*: `{ "type": "object", "properties": {}, "additionalProperties": false }`

-   **dry_run_view_query**: Validate a VIEW collection SQL query without saving the collection (server >= v0.37). Returns the resulting field definitions and a sample of rows, or a validation error.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "query": { "type": "string", "description": "The SQL SELECT statement backing the view collection." }
          },
          "required": ["query"]
        }
        ```

### Log Management

> **Note:** The Logs API requires admin authentication and may not be available in all PocketBase instances or configurations. These tools interact with the PocketBase Logs API as documented at https://pocketbase.io/docs/api-logs/.

-   **list_logs**: List API request logs from PocketBase with filtering, sorting, and pagination.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "page": {
              "type": "number",
              "description": "Page number (defaults to 1).",
              "minimum": 1
            },
            "perPage": {
              "type": "number",
              "description": "Items per page (defaults to 30, max 500).",
              "minimum": 1,
              "maximum": 500
            },
            "filter": {
              "type": "string",
              "description": "PocketBase filter string (e.g., \"method='GET'\")."
            },
            "sort": {
              "type": "string",
              "description": "PocketBase sort string (e.g., \"-created,url\")."
            }
          },
          "required": []
        }
        ```
        *Note: on PocketBase >= v0.40 the server may truncate `Log.Data` (~16KB, marked with `"__pb_truncated__": true`) and limit log messages to 8KB.*

-   **get_log**: Get a single API request log by ID.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "description": "The ID of the log to fetch."
            }
          },
          "required": [
            "id"
          ]
        }
        ```

-   **get_logs_stats**: Get API request logs statistics with optional filtering.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "filter": {
              "type": "string",
              "description": "PocketBase filter string (e.g., \"method='GET'\")."
            }
          },
          "required": []
        }
        ```

-   **truncate_logs**: Delete ALL API request logs (server >= v0.40). DESTRUCTIVE and irreversible — requires `confirm: true`.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "confirm": { "type": "boolean", "description": "Must be explicitly true to delete all logs." }
          },
          "required": ["confirm"]
        }
        ```

### Cron Job Management

> **Note:** The Cron Jobs API requires admin authentication and may not be available in all PocketBase instances or configurations. These tools interact with the PocketBase Cron Jobs API.

-   **list_cron_jobs**: Returns list with all registered app level cron jobs.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "fields": {
              "type": "string",
              "description": "Comma separated string of the fields to return in the JSON response (by default returns all fields). Ex.:?fields=*,expand.relField.name"
            }
          }
        }
        ```

-   **run_cron_job**: Triggers a single cron job by its id.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "jobId": {
              "type": "string",
              "description": "The identifier of the cron job to run."
            }
          },
          "required": [
            "jobId"
          ]
        }
        ```

### Backup Management

> **Note:** The Backup API requires superuser authentication (server >= v0.22). Docs: https://pocketbase.io/docs/api-backups/.

-   **list_backups**: List all backup files available on the instance (`key`, `size`, `modified`).
    -   *Input Schema*: `{ "type": "object", "properties": {}, "additionalProperties": false }`

-   **create_backup**: Queue a new database+storage backup. Optional `name` must end in `.zip` (letters, digits, `_`, `-` only); omitted → the server generates `pb_backup_<timestamp>.zip`. Backups are processed asynchronously — poll `list_backups` for the new key.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "name": { "type": "string", "description": "Optional backup filename ending in .zip." }
          },
          "required": []
        }
        ```

-   **restore_backup**: Restore the instance from an existing backup key. DESTRUCTIVE: replaces ALL current data. Requires `confirm: true`.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "key": { "type": "string", "description": "Backup file key from list_backups." },
            "confirm": { "type": "boolean", "description": "Must be explicitly true." }
          },
          "required": ["key", "confirm"]
        }
        ```

### Settings Management

> **Note:** The Settings API requires superuser authentication. Secrets (SMTP password, S3 keys, OAuth2 client secrets) are returned by the server masked as `"******"`; `update_settings` needs the REAL new values for those fields (PATCH semantics — omitted fields keep their stored values).

-   **get_settings**: Fetch all app settings (sections: `meta`, `logs`, `smtp`, `batch`, `backups`, `s3`, `rateLimits`, ...).
    -   *Input Schema*: `{ "type": "object", "properties": {}, "additionalProperties": false }`

-   **update_settings**: Bulk-update settings with a partial payload.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "data": { "type": "object", "description": "Partial settings payload, e.g. { \"logs\": { \"maxDays\": 14 } }.", "additionalProperties": true }
          },
          "required": ["data"]
        }
        ```

### SQL Execution (run_sql — security gated)

`run_sql` executes **arbitrary raw SQL** against the PocketBase instance (server >= v0.39, endpoint `POST /api/sql`) **with superuser privileges**. Because an MCP server is typically driven by an LLM — and LLMs can be steered by prompt injection in the data they read — this tool is a much bigger blast radius than the record-level tools and is therefore:

-   **DISABLED BY DEFAULT.** The tool is always listed (stable contract), but every call returns an explanatory error unless the MCP *process* was started with `POCKETBASE_ENABLE_SQL=true`. No network request is made when the gate is closed.
-   **All-or-nothing.** There is no read-only mode: SQL statements that modify or drop data (`UPDATE`, `DELETE`, `DROP`, PRAGMAs, ...) are just as executable as `SELECT`. Only enable the gate on instances you fully trust and, ideally, on a copy of your data (PocketBase is a single file — back it up first with `create_backup`).
-   **Auditable.** SQL calls land in the PocketBase request logs (`POST /api/sql`), so `list_logs` can reconstruct what ran.

Enable explicitly, only if you accept the risks:

```bash
POCKETBASE_ENABLE_SQL=true node build/index.js
```

Typical (read-only) usage once enabled:

```json
{ "name": "run_sql", "arguments": { "query": "SELECT COUNT(*) AS n FROM posts" } }
```

### Migration Management

-   **set_migrations_directory**: Set the directory where migration files will be created and read from.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "customPath": { 
              "type": "string", 
              "description": "Custom path for migrations. If not provided, defaults to 'pb_migrations' in the current working directory." 
            }
          }
        }
        ```

-   **create_migration**: Create a new, empty PocketBase migration file with a timestamped name.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "description": { 
              "type": "string", 
              "description": "A brief description for the migration filename (e.g., 'add_user_email_index')." 
            }
          },
          "required": ["description"]
        }
        ```

-   **create_collection_migration**: Create a migration file specifically for creating a new PocketBase collection.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "description": { 
              "type": "string", 
              "description": "Optional description override for the filename." 
            },
            "collectionDefinition": {
              "type": "object",
              "description": "The full schema definition for the new collection (including name, id, fields, rules, etc.).",
              "additionalProperties": true
            }
          },
          "required": ["collectionDefinition"]
        }
        ```

-   **add_field_migration**: Create a migration file for adding a field to an existing collection.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "collectionNameOrId": { 
              "type": "string", 
              "description": "The name or ID of the collection to update." 
            },
            "fieldDefinition": {
              "type": "object",
              "description": "The schema definition for the new field.",
              "additionalProperties": true
            },
            "description": { 
              "type": "string", 
              "description": "Optional description override for the filename." 
            }
          },
          "required": ["collectionNameOrId", "fieldDefinition"]
        }
        ```

-   **list_migrations**: List all migration files found in the PocketBase migrations directory.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {},
          "additionalProperties": false
        }
        ```

-   **apply_migration**: Apply a specific migration file.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "migrationFile": { 
              "type": "string", 
              "description": "Name of the migration file to apply." 
            }
          },
          "required": ["migrationFile"]
        }
        ```

-   **revert_migration**: Revert a specific migration file.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "migrationFile": { 
              "type": "string", 
              "description": "Name of the migration file to revert." 
            }
          },
          "required": ["migrationFile"]
        }
        ```

-   **apply_all_migrations**: Apply all pending migrations.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "appliedMigrations": { 
              "type": "array", 
              "items": { "type": "string" },
              "description": "Array of already applied migration filenames." 
            }
          }
        }
        ```

-   **revert_to_migration**: Revert migrations up to a specific target.
    -   *Input Schema*:
        ```json
        {
          "type": "object",
          "properties": {
            "targetMigration": { 
              "type": "string", 
              "description": "Name of the migration to revert to (exclusive). Use empty string to revert all." 
            },
            "appliedMigrations": { 
              "type": "array", 
              "items": { "type": "string" },
              "description": "Array of already applied migration filenames." 
            }
          },
          "required": ["targetMigration"]
        }
        ```

## Migration System

The PocketBase MCP Server includes a migration system for managing database schema changes. This system allows you to:

1. Create migration files with timestamped names
2. Generate migrations for common operations (creating collections, adding fields)
3. Apply and revert migrations individually or in batches

### How apply/revert works (and its limits)

Migration files generated by this MCP (`create_collection_migration`, `add_field_migration`) embed a machine-readable marker comment (`// mcp-migration-meta: {...}`) describing their operations as plain data. `apply_migration`, `revert_migration`, `apply_all_migrations` and `revert_to_migration` execute those operations **through the PocketBase REST API** (`pb.collections.*`), which is the only channel available to an MCP client.

Migration files **without** the marker — e.g. hand-written server-side JSVM migrations created with `./pocketbase migrate create` — use the server JSVM API (`migrate()`, `new Collection()`, `app.save()`), which does not exist in a REST client. They cannot be applied through this MCP; the apply tools return an explanatory error pointing to `./pocketbase migrate up` on the PocketBase host. (Previous versions tried to evaluate those files locally with `new Function`, which always failed at runtime.)

Applied-state tracking is **not** stored server-side: `apply_all_migrations` / `revert_to_migration` take an `appliedMigrations` array parameter (the server's `_migrations` table is not exposed to REST clients). Keep that list in your own tooling, or apply/revert individual files.

Generated files remain valid JSVM migrations, so the same file can also be applied on the host with `./pocketbase migrate up` (in which case PocketBase tracks the state in its own `_migrations` table — do not mix both execution paths for the same file).

### Migration File Format

Migration files are JavaScript files with a timestamp prefix and descriptive name:

```javascript
// 1744005374_update_transactions_add_debt_link.js
/// <reference path="../pb_data/types.d.ts" />
// mcp-migration-meta: {"ops":{"up":[...],"down":[...]}}   <- only in MCP-generated files
migrate((app) => {
  // Up migration code here
  return app.save();
}, (app) => {
  // Down migration code here
  return app.save();
});
```

Each migration has an "up" function for applying changes and a "down" function for reverting them.

### Usage Examples

**Setting a custom migrations directory:**
```javascript
await setMigrationsDirectory("./my_migrations");
```

**Creating a basic migration:**
```javascript
await createNewMigration("add_user_email_index");
```

**Creating a collection migration:**
```javascript
await createCollectionMigration({
  id: "users",
  name: "users",
  fields: [
    { name: "email", type: "email", required: true }
  ]
});
```

**Adding a field to a collection:**
```javascript
await createAddFieldMigration("users", {
  name: "address",
  type: "text"
});
```

**Applying migrations:**
```javascript
// Apply a specific migration
await applyMigration("1744005374_update_transactions_add_debt_link.js", pocketbaseInstance);

// Apply all pending migrations
await applyAllMigrations(pocketbaseInstance);
```

**Reverting migrations:**
```javascript
// Revert a specific migration
await revertMigration("1744005374_update_transactions_add_debt_link.js", pocketbaseInstance);

// Revert to a specific point (exclusive)
await revertToMigration("1743958155_update_transactions_add_relation_to_itself.js", pocketbaseInstance);

// Revert all migrations
await revertToMigration("", pocketbaseInstance);
```

## Cline Installation

To use this server with Cline, you need to add it to your MCP settings file (`cline_mcp_settings.json`).

1.  **Locate your Cline MCP settings file:**
    *   Typically found at `~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` on Linux/macOS.
    *   Or `~/Library/Application Support/Claude/claude_desktop_config.json` if using the Claude desktop app on macOS.

2.  **Edit the file and add the following configuration under the `mcpServers` key.** Replace `/path/to/pocketbase-mcp` with the actual absolute path to this project directory on your system. Also, replace `<YOUR_POCKETBASE_API_URL>` and `<YOUR_POCKETBASE_ADMIN_TOKEN>` with your actual PocketBase URL and admin token.

    ```json
    {
      "mcpServers": {
        // ... other servers might be listed here ...

        "pocketbase-mcp": {
          "command": "node",
          "args": ["/path/to/pocketbase-mcp/build/index.js"],
          "env": {
            "POCKETBASE_API_URL": "<YOUR_POCKETBASE_API_URL>", // e.g., "http://127.0.0.1:8090"
            "POCKETBASE_ADMIN_TOKEN": "<YOUR_POCKETBASE_ADMIN_TOKEN>"
          },
          "disabled": false, // Ensure it's enabled
          "autoApprove": [
            "fetch_record",
            "list_collections",
            "get_collection_schema",
            "list_logs",
            "get_log",
            "get_logs_stats",
            "list_cron_jobs",
            "run_cron_job"
          ] // Suggested auto-approve settings
        }

        // ... other servers might be listed here ...
      }
    }
    ```

3.  **Save the settings file.** Cline should automatically detect the changes and connect to the server. You can then use the tools listed above.

## Troubleshooting

-   **HTTP 403 on every request**: since PocketBase v0.38 you can enable a superuser **IP whitelist** (Admin UI -> Settings). If enabled, add the IP of the machine running this MCP server (or disable the whitelist).
-   **`FATAL: POCKETBASE_ADMIN_TOKEN environment variable is required`**: the token env var is not set; generate an API key in the PocketBase admin UI (superuser -> API keys) and set `POCKETBASE_ADMIN_TOKEN`.
-   **Health-check warning on stderr at startup**: the configured `POCKETBASE_API_URL` is unreachable (instance down or wrong URL). The MCP still starts so `tools/list` works, but tool calls will fail until the instance is reachable.
-   **`Cannot apply ...: This migration file does not contain MCP metadata`**: the file is a server-side JSVM migration; run `./pocketbase migrate up` on the PocketBase host instead (see Migration System).

## Dependencies

-   `@modelcontextprotocol/sdk` (^1.30.0)
-   `pocketbase` (^0.28.1)
-   `typescript` (dev dependency)
-   `@types/node` (dev dependency)

TDQS

A3.5/5.0

Scored across 22 tools

Disambiguation5/5

Each tool targets a distinct operation on a specific resource (collections, records, migrations, logs, cron, files). No two tools have overlapping purposes; descriptions clearly differentiate them.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (e.g., create_record, list_collections, apply_migration). No mixing of conventions or vague verbs.

Tool Count5/5

22 tools is appropriate for a PocketBase server, covering collections, records, migrations, logs, cron, and file handling. Each tool serves a clear purpose without redundancy.

Completeness2/5

Significant gaps: no tool to delete a record or collection, and no direct create/update/delete for collections (only migration-based). This will likely cause agent failures when cleanup is needed.

Maintenance

ActivityMaintained
ResponsivenessNo issues