Skip to content

Instantly share code, notes, and snippets.

@maietta
Created May 18, 2025 18:30
Show Gist options
  • Save maietta/8185d9fe687af3041bbeba234123c432 to your computer and use it in GitHub Desktop.
Save maietta/8185d9fe687af3041bbeba234123c432 to your computer and use it in GitHub Desktop.
Pocketbase MCP with Cursor IDE config example.
POCKETBASE_URL=
POCKETBASE_ADMIN_EMAIL=
POCKETBASE_ADMIN_PASSWORD=
{
"mcpServers": {
"pocketbase-mcp": {
"command": "bun",
"args": ["run", ".cursor/pocketbase.ts"]
}
}
}
{
"name": "pocketbase-mcp-server",
"version": "0.1.0",
"type": "module",
"private": true,
"scripts": {
"start": "bun run pocketbase.ts"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^0.1.0",
"dotenv": "^16.4.5",
"pocketbase": "^0.22.4"
},
"devDependencies": {
"bun-types": "latest"
}
}
#!/usr/bin/env node
import * as dotenv from 'dotenv';
dotenv.config();
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ErrorCode,
ListToolsRequestSchema,
McpError,
} from '@modelcontextprotocol/sdk/types.js';
import PocketBase from 'pocketbase';
import {
PocketBaseErrorResponse,
CreateCollectionArgs,
CreateRecordArgs,
ListRecordsArgs,
UpdateRecordArgs,
DeleteRecordArgs,
AuthenticateUserArgs,
CreateUserArgs,
GetCollectionArgs,
BackupDatabaseArgs,
ListCollectionsArgs,
PocketBaseCollectionData
} from './pocketbase.types';
class PocketBaseServer {
private server: Server;
private pb: PocketBase;
constructor() {
this.server = new Server(
{
name: 'pocketbase-server',
version: '0.1.0',
},
{
capabilities: {
tools: {},
},
}
);
// Initialize PocketBase client
const url = process.env.POCKETBASE_URL;
if (!url) {
throw new Error('POCKETBASE_URL environment variable is required');
}
this.pb = new PocketBase(url);
this.setupToolHandlers();
// Error handling
this.server.onerror = (error) => console.error('[MCP Error]', error);
process.on('SIGINT', async () => {
await this.server.close();
process.exit(0);
});
}
private setupToolHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: 'create_collection',
description: 'Create a new collection in PocketBase note never use created and updated because these are already created',
inputSchema: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'Unique collection name (used as a table name for the records table)',
},
type: {
type: 'string',
description: 'Type of the collection',
enum: ['base', 'view', 'auth'],
default: 'base',
},
fields: {
type: 'array',
description: 'List with the collection fields',
items: {
type: 'object',
properties: {
name: { type: 'string', description: 'Field name' },
type: { type: 'string', description: 'Field type', enum: ['bool', 'date', 'number', 'text', 'email', 'url', 'editor', 'autodate', 'select', 'file', 'relation', 'json'] },
required: { type: 'boolean', description: 'Is field required?' },
values: {
type: 'array',
items: { type: 'string' },
description: 'Allowed values for select type fields',
},
collectionId: { type: 'string', description: 'Collection ID for relation type fields' }
},
},
},
createRule: {
type: 'string',
description: 'API rule for creating records',
},
updateRule: {
type: 'string',
description: 'API rule for updating records',
},
deleteRule: {
type: 'string',
description: 'API rule for deleting records',
},
viewQuery: {
type: 'string',
description: 'SQL query for view collections',
},
passwordAuth: {
type: 'object',
description: 'Password authentication options',
properties: {
enabled: { type: 'boolean', description: 'Is password authentication enabled?' },
identityFields: {
type: 'array',
items: { type: 'string' },
description: 'Fields used for identity in password authentication',
},
},
},
},
required: ['name', 'fields'],
},
},
{
name: 'create_record',
description: 'Create a new record in a collection',
inputSchema: {
type: 'object',
properties: {
collection: {
type: 'string',
description: 'Collection name',
},
data: {
type: 'object',
description: 'Record data',
},
},
required: ['collection', 'data'],
},
},
{
name: 'list_records',
description: 'List records from a collection with optional filters',
inputSchema: {
type: 'object',
properties: {
collection: {
type: 'string',
description: 'Collection name',
},
filter: {
type: 'string',
description: 'Filter query',
},
sort: {
type: 'string',
description: 'Sort field and direction',
},
page: {
type: 'number',
description: 'Page number',
},
perPage: {
type: 'number',
description: 'Items per page',
},
},
required: ['collection'],
},
},
{
name: 'update_record',
description: 'Update an existing record',
inputSchema: {
type: 'object',
properties: {
collection: {
type: 'string',
description: 'Collection name',
},
id: {
type: 'string',
description: 'Record ID',
},
data: {
type: 'object',
description: 'Updated record data',
},
},
required: ['collection', 'id', 'data'],
},
},
{
name: 'delete_record',
description: 'Delete a record',
inputSchema: {
type: 'object',
properties: {
collection: {
type: 'string',
description: 'Collection name',
},
id: {
type: 'string',
description: 'Record ID',
},
},
required: ['collection', 'id'],
},
},
{
name: 'list_auth_methods',
description: 'List all available authentication methods',
inputSchema: {
type: 'object',
properties: {
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
}
}
}
},
{
name: 'authenticate_user',
description: 'Authenticate a user with email and password',
inputSchema: {
type: 'object',
properties: {
email: {
type: 'string',
description: 'User email',
},
password: {
type: 'string',
description: 'User password',
},
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
},
isAdmin: {
type: 'boolean',
description: 'Whether to authenticate as an admin (uses _superusers collection)',
default: false
}
},
required: ['email', 'password'],
},
},
{
name: 'authenticate_with_oauth2',
description: 'Authenticate a user with OAuth2',
inputSchema: {
type: 'object',
properties: {
provider: {
type: 'string',
description: 'OAuth2 provider name (e.g., google, facebook, github)',
},
code: {
type: 'string',
description: 'The authorization code returned from the OAuth2 provider',
},
codeVerifier: {
type: 'string',
description: 'PKCE code verifier',
},
redirectUrl: {
type: 'string',
description: 'The redirect URL used in the OAuth2 flow',
},
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
}
},
required: ['provider', 'code', 'codeVerifier', 'redirectUrl'],
},
},
{
name: 'authenticate_with_otp',
description: 'Authenticate a user with one-time password',
inputSchema: {
type: 'object',
properties: {
email: {
type: 'string',
description: 'User email',
},
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
}
},
required: ['email'],
},
},
{
name: 'auth_refresh',
description: 'Refresh authentication token',
inputSchema: {
type: 'object',
properties: {
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
}
}
},
},
{
name: 'request_verification',
description: 'Request email verification',
inputSchema: {
type: 'object',
properties: {
email: {
type: 'string',
description: 'User email',
},
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
}
},
required: ['email'],
},
},
{
name: 'confirm_verification',
description: 'Confirm email verification with token',
inputSchema: {
type: 'object',
properties: {
token: {
type: 'string',
description: 'Verification token',
},
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
}
},
required: ['token'],
},
},
{
name: 'request_password_reset',
description: 'Request password reset',
inputSchema: {
type: 'object',
properties: {
email: {
type: 'string',
description: 'User email',
},
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
}
},
required: ['email'],
},
},
{
name: 'confirm_password_reset',
description: 'Confirm password reset with token',
inputSchema: {
type: 'object',
properties: {
token: {
type: 'string',
description: 'Reset token',
},
password: {
type: 'string',
description: 'New password',
},
passwordConfirm: {
type: 'string',
description: 'Confirm new password',
},
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
}
},
required: ['token', 'password', 'passwordConfirm'],
},
},
{
name: 'request_email_change',
description: 'Request email change',
inputSchema: {
type: 'object',
properties: {
newEmail: {
type: 'string',
description: 'New email address',
},
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
}
},
required: ['newEmail'],
},
},
{
name: 'confirm_email_change',
description: 'Confirm email change with token',
inputSchema: {
type: 'object',
properties: {
token: {
type: 'string',
description: 'Email change token',
},
password: {
type: 'string',
description: 'Current password for confirmation',
},
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
}
},
required: ['token', 'password'],
},
},
{
name: 'impersonate_user',
description: 'Impersonate another user (admin only)',
inputSchema: {
type: 'object',
properties: {
id: {
type: 'string',
description: 'ID of the user to impersonate',
},
collectionIdOrName: {
type: 'string',
description: 'Collection name or id (default: users)',
default: 'users'
},
duration: {
type: 'number',
description: 'Token expirey time (default: 3600)',
default: 3600
}
},
required: ['id'],
},
},
{
name: 'create_user',
description: 'Create a new user account',
inputSchema: {
type: 'object',
properties: {
email: {
type: 'string',
description: 'User email',
},
password: {
type: 'string',
description: 'User password',
},
passwordConfirm: {
type: 'string',
description: 'Password confirmation',
},
name: {
type: 'string',
description: 'User name',
},
collection: {
type: 'string',
description: 'Collection name (default: users)',
default: 'users'
}
},
required: ['email', 'password', 'passwordConfirm'],
},
},
{
name: 'get_collection',
description: 'Get details for a collection',
inputSchema: {
type: 'object',
properties: {
collectionIdOrName: {
type: 'string',
description: 'ID or name of the collection to view',
},
fields: {
type: 'string',
description: 'Comma separated string of the fields to return in the JSON response',
},
},
required: ['collectionIdOrName'],
},
},
{
name: 'backup_database',
description: 'Create a backup of the PocketBase database',
inputSchema: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'backup name',
},
},
},
},
{
name: 'import_data',
description: 'Import data into a collection',
inputSchema: {
type: 'object',
properties: {
collection: {
type: 'string',
description: 'Collection name',
},
data: {
type: 'array',
description: 'Array of records to import',
items: {
type: 'object',
},
},
mode: {
type: 'string',
enum: ['create', 'update', 'upsert'],
description: 'Import mode (default: create)',
},
},
required: ['collection', 'data'],
},
},
{
name: 'list_collections',
description: 'List all collections in PocketBase',
inputSchema: {
type: 'object',
properties: {
filter: {
type: 'string',
description: 'Filter query for collections',
},
sort: {
type: 'string',
description: 'Sort order for collections',
},
},
},
},
],
}));
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
const args = request.params.arguments as Record<string, unknown>;
if (!args) {
throw new McpError(ErrorCode.InternalError, 'Arguments are required');
}
switch (request.params.name) {
case 'create_collection':
if (!this.validateArgs<CreateCollectionArgs>(args, ['name', 'fields'])) {
throw new McpError(ErrorCode.InternalError, 'Collection name and fields are required');
}
return await this.createCollection(args);
case 'create_record':
if (!this.validateArgs<CreateRecordArgs>(args, ['collection', 'data'])) {
throw new McpError(ErrorCode.InternalError, 'Collection and data are required');
}
return await this.createRecord(args);
case 'list_records':
if (!this.validateArgs<ListRecordsArgs>(args, ['collection'])) {
throw new McpError(ErrorCode.InternalError, 'Collection is required');
}
return await this.listRecords(args);
case 'update_record':
if (!this.validateArgs<UpdateRecordArgs>(args, ['collection', 'id', 'data'])) {
throw new McpError(ErrorCode.InternalError, 'Collection, id, and data are required');
}
return await this.updateRecord(args);
case 'delete_record':
if (!this.validateArgs<DeleteRecordArgs>(args, ['collection', 'id'])) {
throw new McpError(ErrorCode.InternalError, 'Collection and id are required');
}
return await this.deleteRecord(args);
case 'authenticate_user':
if (!this.validateArgs<AuthenticateUserArgs>(args, ['email', 'password'])) {
throw new McpError(ErrorCode.InternalError, 'Email and password are required');
}
return await this.authenticateUser(args);
case 'create_user':
if (!this.validateArgs<CreateUserArgs>(args, ['email', 'password', 'passwordConfirm'])) {
throw new McpError(ErrorCode.InternalError, 'Email, password, and password confirmation are required');
}
return await this.createUser(args);
case 'get_collection':
if (!this.validateArgs<GetCollectionArgs>(args, ['collectionIdOrName'])) {
throw new McpError(ErrorCode.InternalError, 'Collection ID or name is required');
}
return await this.getCollection(args);
case 'backup_database':
return await this.backupDatabase(args as BackupDatabaseArgs);
case 'list_collections':
return await this.listCollections(args as ListCollectionsArgs);
default:
throw new McpError(
ErrorCode.MethodNotFound,
`Unknown tool: ${request.params.name}`
);
}
} catch (error: unknown) {
if (error instanceof McpError) {
throw error;
}
throw new McpError(
ErrorCode.InternalError,
`PocketBase error: ${error instanceof Error ? error.message : String(error)}`
);
}
});
}
// Helper to sanitize rule strings
private sanitizeRule(rule?: string | null): string | null | undefined {
if (typeof rule !== 'string') return rule;
// Replace single quotes with double quotes for empty string checks
return rule.replace(/''/g, '""');
}
private validateArgs<T extends Record<string, unknown>>(args: Record<string, unknown>, requiredFields: (keyof T)[]): args is T {
return requiredFields.every(field => field in args);
}
private async createCollection(args: CreateCollectionArgs) {
try {
// Authenticate with PocketBase
await this.pb.collection("_superusers").authWithPassword(process.env.POCKETBASE_ADMIN_EMAIL ?? '', process.env.POCKETBASE_ADMIN_PASSWORD ?? '');
const defaultFields = [
{
hidden: false,
id: "autodate_created",
name: "created",
onCreate: true,
onUpdate: false,
presentable: false,
system: false,
type: "autodate"
},
{
hidden: false,
id: "autodate_updated",
name: "updated",
onCreate: true,
onUpdate: true,
presentable: false,
system: false,
type: "autodate"
}
];
// Sanitize rules
const collectionData = {
...args,
createRule: this.sanitizeRule(args.createRule),
updateRule: this.sanitizeRule(args.updateRule),
deleteRule: this.sanitizeRule(args.deleteRule),
listRule: this.sanitizeRule(args.listRule),
viewRule: this.sanitizeRule(args.viewRule),
viewQuery: this.sanitizeRule(args.viewQuery),
passwordAuth: args.passwordAuth,
fields: [...(args.fields || []), ...defaultFields]
};
console.error('Attempting to create collection with data:', JSON.stringify(collectionData, null, 2));
const result = await this.pb.collections.create(collectionData as PocketBaseCollectionData);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
} catch (error: unknown) {
console.error('Raw error details:', error);
if (error instanceof Error && 'response' in error) {
console.error('Error response data:', JSON.stringify((error as PocketBaseErrorResponse).response?.data, null, 2));
// Surface a user-friendly message for rule errors
const resp = (error as PocketBaseErrorResponse).response?.data;
if (resp && (resp.createRule || resp.updateRule || resp.deleteRule)) {
throw new McpError(
ErrorCode.InternalError,
`Invalid rule(s): ${[resp.createRule?.message, resp.updateRule?.message, resp.deleteRule?.message].filter(Boolean).join('; ')}`
);
}
}
throw new McpError(
ErrorCode.InternalError,
`[${error instanceof Error ? error.name : String(error)}] Failed to create collection: ${error instanceof Error ? error.message : String(error)}`
);
}
}
private async createRecord(args: CreateRecordArgs) {
try {
const result = await this.pb.collection(args.collection).create(args.data);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
} catch (error: unknown) {
throw new McpError(
ErrorCode.InternalError,
`Failed to create record: ${error instanceof Error ? error.message : String(error)}`
);
}
}
private async listRecords(args: ListRecordsArgs) {
try {
const options: {
filter?: string;
sort?: string;
page?: number;
perPage?: number;
} = {};
if (args.filter) options.filter = args.filter;
if (args.sort) options.sort = args.sort;
if (args.page) options.page = args.page;
if (args.perPage) options.perPage = args.perPage;
const result = await this.pb.collection(args.collection).getList(
options.page || 1,
options.perPage || 50,
{
filter: options.filter,
sort: options.sort,
}
);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
} catch (error: unknown) {
throw new McpError(
ErrorCode.InternalError,
`Failed to list records: ${error instanceof Error ? error.message : String(error)}`
);
}
}
private async updateRecord(args: UpdateRecordArgs) {
try {
const result = await this.pb
.collection(args.collection)
.update(args.id, args.data);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
} catch (error: unknown) {
throw new McpError(
ErrorCode.InternalError,
`Failed to update record: ${error instanceof Error ? error.message : String(error)}`
);
}
}
private async deleteRecord(args: DeleteRecordArgs) {
try {
await this.pb.collection(args.collection).delete(args.id);
return {
content: [
{
type: 'text',
text: `Successfully deleted record ${args.id} from collection ${args.collection}`,
},
],
};
} catch (error: unknown) {
throw new McpError(
ErrorCode.InternalError,
`Failed to delete record: ${error instanceof Error ? error.message : String(error)}`
);
}
}
private async authenticateUser(args: AuthenticateUserArgs) {
try {
// Use _superusers collection for admin authentication
const collection = args.isAdmin ? '_superusers' : (args.collection || 'users');
// For admin authentication, use environment variables if email/password not provided
const email = args.isAdmin && !args.email ? process.env.POCKETBASE_ADMIN_EMAIL : args.email;
const password = args.isAdmin && !args.password ? process.env.POCKETBASE_ADMIN_PASSWORD : args.password;
if (!email || !password) {
throw new Error('Email and password are required for authentication');
}
const authData = await this.pb
.collection(collection)
.authWithPassword(email, password);
return {
content: [
{
type: 'text',
text: JSON.stringify(authData, null, 2),
},
],
};
} catch (error: unknown) {
throw new McpError(
ErrorCode.InternalError,
`Authentication failed: ${error instanceof Error ? error.message : String(error)}`
);
}
}
private async createUser(args: CreateUserArgs) {
try {
const collection = args.collection || 'users';
const result = await this.pb.collection(collection).create({
email: args.email,
password: args.password,
passwordConfirm: args.passwordConfirm,
name: args.name,
});
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
} catch (error: unknown) {
throw new McpError(
ErrorCode.InternalError,
`Failed to create user: ${error instanceof Error ? error.message : String(error)}`
);
}
}
private async getCollection(args: GetCollectionArgs) {
try {
// Authenticate with PocketBase
await this.pb.collection("_superusers").authWithPassword(process.env.POCKETBASE_ADMIN_EMAIL ?? '', process.env.POCKETBASE_ADMIN_PASSWORD ?? '');
// Get collection details
const collection = await this.pb.collections.getOne(args.collectionIdOrName, {
fields: args.fields
});
return {
content: [
{
type: 'text',
text: JSON.stringify(collection, null, 2),
},
],
};
} catch (error: unknown) {
throw new McpError(
ErrorCode.InternalError,
`Failed to get collection: ${error instanceof Error ? error.message : String(error)}`
);
}
}
private async backupDatabase(args: BackupDatabaseArgs) {
try {
// Authenticate with PocketBase
await this.pb.collection("_superusers").authWithPassword(process.env.POCKETBASE_ADMIN_EMAIL ?? '', process.env.POCKETBASE_ADMIN_PASSWORD ?? '');
// Create a new backup
const backupResult = await this.pb.backups.create(args.name ?? '', {});
return {
content: [
{
type: 'text',
text: JSON.stringify(backupResult, null, 2),
},
],
};
} catch (error: unknown) {
throw new McpError(
ErrorCode.InternalError,
`Failed to backup database: ${error instanceof Error ? error.message : String(error)}`
);
}
}
private async listCollections(args: ListCollectionsArgs) {
try {
// Authenticate with PocketBase
await this.pb.collection("_superusers").authWithPassword(process.env.POCKETBASE_ADMIN_EMAIL ?? '', process.env.POCKETBASE_ADMIN_PASSWORD ?? '');
// Fetch collections based on provided arguments
let collections;
if (args.filter) {
collections = await this.pb.collections.getFirstListItem(args.filter);
} else if (args.sort) {
collections = await this.pb.collections.getFullList({ sort: args.sort });
} else {
collections = await this.pb.collections.getList(1, 100);
}
return {
content: [
{
type: 'text',
text: JSON.stringify(collections, null, 2),
},
],
};
} catch (error: unknown) {
throw new McpError(
ErrorCode.InternalError,
`Failed to list collections: ${error instanceof Error ? error.message : String(error)}`
);
}
}
async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error('PocketBase MCP server running on stdio');
}
}
const server = new PocketBaseServer();
server.run().catch(console.error);
export interface PocketBaseErrorResponse {
response?: {
data?: {
createRule?: { message: string };
updateRule?: { message: string };
deleteRule?: { message: string };
};
};
}
export interface CreateCollectionArgs extends Record<string, unknown> {
name: string;
type?: 'base' | 'view' | 'auth';
fields: Array<{
name: string;
type: string;
required?: boolean;
values?: string[];
collectionId?: string;
}>;
createRule?: string;
updateRule?: string;
deleteRule?: string;
listRule?: string;
viewRule?: string;
viewQuery?: string;
passwordAuth?: {
enabled?: boolean;
identityFields?: string[];
};
}
export interface CreateRecordArgs extends Record<string, unknown> {
collection: string;
data: Record<string, unknown>;
}
export interface ListRecordsArgs extends Record<string, unknown> {
collection: string;
filter?: string;
sort?: string;
page?: number;
perPage?: number;
}
export interface UpdateRecordArgs extends Record<string, unknown> {
collection: string;
id: string;
data: Record<string, unknown>;
}
export interface DeleteRecordArgs extends Record<string, unknown> {
collection: string;
id: string;
}
export interface AuthenticateUserArgs extends Record<string, unknown> {
email: string;
password: string;
collection?: string;
isAdmin?: boolean;
}
export interface CreateUserArgs extends Record<string, unknown> {
email: string;
password: string;
passwordConfirm: string;
name?: string;
collection?: string;
}
export interface GetCollectionArgs extends Record<string, unknown> {
collectionIdOrName: string;
fields?: string;
}
export interface BackupDatabaseArgs extends Record<string, unknown> {
name?: string;
}
export interface ListCollectionsArgs extends Record<string, unknown> {
filter?: string;
sort?: string;
}
export interface PocketBaseCollectionData {
name: string;
type?: 'base' | 'view' | 'auth';
fields: Array<{
name: string;
type: string;
required?: boolean;
values?: string[];
collectionId?: string;
hidden?: boolean;
id?: string;
onCreate?: boolean;
onUpdate?: boolean;
presentable?: boolean;
system?: boolean;
}>;
createRule?: string;
updateRule?: string;
deleteRule?: string;
listRule?: string;
viewRule?: string;
viewQuery?: string;
passwordAuth?: {
enabled?: boolean;
identityFields?: string[];
};
}
@maietta
Copy link
Author

maietta commented May 18, 2025

PocketBase MCP Server

A Model Context Protocol (MCP) server implementation for PocketBase.

Setup

  1. Install dependencies:
cd .cursor
bun install
  1. Create a .env file:
cp .env.example .env
  1. Update the .env file with your PocketBase configuration:
  • POCKETBASE_URL: Your PocketBase server URL (default: http://127.0.0.1:8090)
  • POCKETBASE_ADMIN_EMAIL: Admin email for PocketBase
  • POCKETBASE_ADMIN_PASSWORD: Admin password for PocketBase

Running the Server

bun start

Features

  • Collection Management

    • Create collections
    • List collections
    • Get collection details
    • Update collections
    • Delete collections
  • Record Management

    • Create records
    • List records
    • Update records
    • Delete records
  • Authentication

    • User authentication
    • Admin authentication
    • OAuth2 support
    • OTP support
  • Database Management

    • Database backup
    • Data import/export

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment