#!/usr/bin/env node
/**
* This is an MCP server to manage PocketBase via LLMs.
*/
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import PocketBase from 'pocketbase';
/**
* PocketBase configuration options obtained from command line args.
*/
interface PocketBaseConfig {
url: string;
adminEmail: string;
adminPassword: string;
}
/**
* Parse configuration from command line arguments and environment variables.
* Command line arguments take precedence over environment variables.
*/
function getPocketBaseConfig(): PocketBaseConfig {
const args = process.argv.slice(2);
const url = args.find((arg) => arg.startsWith('--pb-url='))?.split('=')[1] || process.env.PB_URL;
const adminEmail =
args.find((arg) => arg.startsWith('--pb-admin-email='))?.split('=')[1] || process.env.PB_ADMIN_EMAIL;
const adminPassword =
args.find((arg) => arg.startsWith('--pb-admin-password='))?.split('=')[1] || process.env.PB_ADMIN_PASSWORD;
if (!url || !adminEmail || !adminPassword) {
console.error(
'PocketBase configuration is required. Please provide --pb-url, --pb-admin-email, and --pb-admin-password as command line arguments or set PB_URL, PB_ADMIN_EMAIL, and PB_ADMIN_PASSWORD as environment variables.',
);
process.exit(1);
}
return { url, adminEmail, adminPassword };
}
// Load PocketBase configuration from command line args or environment variables
const pocketBaseConfig = getPocketBaseConfig();
/**
* Create an MCP server with capabilities for resources,
* tools, and prompts.
*/
const server = new Server(
{
name: 'pocketbase-mcp-server',
version: '0.1.0',
},
{
capabilities: {
resources: {},
tools: {},
prompts: {},
},
},
);
/**
* Handler that lists available tools.
* Exposes tools for creating notes and listing PocketBase collections (if configured).
*/
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'pocketbase_list_collections',
description: 'List PocketBase Collections',
inputSchema: {
type: 'object',
properties: {},
required: [],
},
},
],
};
});
/**
* Handler for tool calls.
* Handles:
* - pocketbase_list_collections: Connects to PocketBase and lists all collections
*/
server.setRequestHandler(CallToolRequestSchema, async (request) => {
switch (request.params.name) {
case 'pocketbase_list_collections': {
if (!pocketBaseConfig) {
throw new Error(
'PocketBase configuration is not available. Please start the server with --pb-url, --pb-admin-email, and --pb-admin-password arguments.',
);
}
try {
// Connect to PocketBase
const pb = new PocketBase(pocketBaseConfig.url);
// Authenticate as admin
await pb
.collection('_superusers')
.authWithPassword(pocketBaseConfig.adminEmail, pocketBaseConfig.adminPassword);
// Fetch all collections
const collections = await pb.collections.getFullList();
return {
content: [
{
type: 'text',
text: JSON.stringify(collections, null, 2),
},
],
};
} catch (error) {
throw new Error(
`Failed to list PocketBase collections: ${error instanceof Error ? error.message : String(error)}`,
);
}
}
default:
throw new Error('Unknown tool');
}
});
/**
* Start the server using stdio transport.
* This allows the server to communicate via standard input/output streams.
*/
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch((error) => {
console.error('Server error:', error);
process.exit(1);
});