@fadlee/pocketbase-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +123 -0
  3. package/build/src/config/cli.d.ts +9 -0
  4. package/build/src/config/cli.js +31 -0
  5. package/build/src/config/environment.d.ts +9 -0
  6. package/build/src/config/environment.js +13 -0
  7. package/build/src/config/index.d.ts +13 -0
  8. package/build/src/config/index.js +20 -0
  9. package/build/src/index.d.ts +2 -0
  10. package/build/src/index.js +21 -0
  11. package/build/src/server.d.ts +10 -0
  12. package/build/src/server.js +211 -0
  13. package/build/src/tools/handlers/analysis.d.ts +10 -0
  14. package/build/src/tools/handlers/analysis.js +127 -0
  15. package/build/src/tools/handlers/auth.d.ts +10 -0
  16. package/build/src/tools/handlers/auth.js +51 -0
  17. package/build/src/tools/handlers/collection.d.ts +22 -0
  18. package/build/src/tools/handlers/collection.js +82 -0
  19. package/build/src/tools/handlers/file.d.ts +5 -0
  20. package/build/src/tools/handlers/file.js +124 -0
  21. package/build/src/tools/handlers/generation.d.ts +10 -0
  22. package/build/src/tools/handlers/generation.js +201 -0
  23. package/build/src/tools/handlers/index.d.ts +10 -0
  24. package/build/src/tools/handlers/index.js +17 -0
  25. package/build/src/tools/handlers/migration.d.ts +18 -0
  26. package/build/src/tools/handlers/migration.js +219 -0
  27. package/build/src/tools/handlers/record.d.ts +18 -0
  28. package/build/src/tools/handlers/record.js +94 -0
  29. package/build/src/tools/index.d.ts +5 -0
  30. package/build/src/tools/index.js +7 -0
  31. package/build/src/tools/schemas/analysis.d.ts +56 -0
  32. package/build/src/tools/schemas/analysis.js +54 -0
  33. package/build/src/tools/schemas/auth.d.ts +59 -0
  34. package/build/src/tools/schemas/auth.js +59 -0
  35. package/build/src/tools/schemas/collection.d.ts +192 -0
  36. package/build/src/tools/schemas/collection.js +194 -0
  37. package/build/src/tools/schemas/file.d.ts +70 -0
  38. package/build/src/tools/schemas/file.js +70 -0
  39. package/build/src/tools/schemas/generation.d.ts +49 -0
  40. package/build/src/tools/schemas/generation.js +49 -0
  41. package/build/src/tools/schemas/index.d.ts +10 -0
  42. package/build/src/tools/schemas/index.js +17 -0
  43. package/build/src/tools/schemas/migration.d.ts +133 -0
  44. package/build/src/tools/schemas/migration.js +146 -0
  45. package/build/src/tools/schemas/record.d.ts +103 -0
  46. package/build/src/tools/schemas/record.js +103 -0
  47. package/build/src/types/index.d.ts +188 -0
  48. package/build/src/types/index.js +1 -0
  49. package/build/src/utils/errors.d.ts +17 -0
  50. package/build/src/utils/errors.js +35 -0
  51. package/build/src/utils/response.d.ts +23 -0
  52. package/build/src/utils/response.js +62 -0
  53. package/build/src/utils/typescript.d.ts +24 -0
  54. package/build/src/utils/typescript.js +130 -0
  55. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 DynamicEndpoints
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # PocketBase MCP Server
2
+
3
+ Seamless integration between PocketBase and MCP clients through the Model Context Protocol (MCP). This server enables MCP-compatible applications to directly interact with PocketBase databases for collection management, record operations, schema generation, and data analysis.
4
+
5
+ ## ✨ Key Features
6
+
7
+ - **🗄️ Collection Management**: Create, migrate, and manage collections with custom schemas
8
+ - **📝 Record Operations**: Full CRUD operations with advanced querying and filtering
9
+ - **🔄 Schema Generation**: Bidirectional conversion between TypeScript interfaces and PocketBase schemas
10
+ - **📊 Data Analysis**: Intelligent insights and analytics for your collections
11
+ - **🔐 Authentication**: User management and authentication workflows
12
+ - **⚡ Performance**: Optimized for speed with built-in caching and connection pooling
13
+
14
+ ## 🚀 Quick Start
15
+
16
+ ### Installation
17
+
18
+ ```bash
19
+ npm install -g @fadlee/pocketbase-mcp
20
+ ```
21
+
22
+ ### MCP Client Setup
23
+
24
+ #### For Cursor AI
25
+ 1. Open Cursor AI Settings (`Cmd+,` / `Ctrl+,`)
26
+ 2. Navigate to **AI** → **Model Context Protocol Servers**
27
+ 3. Add new server:
28
+ - **Name**: `pocketbase`
29
+ - **Command**: `npx`
30
+ - **Args**: `@fadlee/pocketbase-mcp --url=http://127.0.0.1:8090`
31
+
32
+ #### For Other MCP Clients
33
+ Refer to your MCP client's documentation for server configuration. Use:
34
+ - **Server Command**: `npx @fadlee/pocketbase-mcp`
35
+ - **Arguments**: `--url=http://127.0.0.1:8090`
36
+
37
+ ### Basic Configuration
38
+
39
+ ```bash
40
+ # Using command line
41
+ npx @fadlee/pocketbase-mcp --url=http://127.0.0.1:8090
42
+
43
+ # Using environment variables
44
+ export POCKETBASE_URL=http://127.0.0.1:8090
45
+ npx @fadlee/pocketbase-mcp
46
+ ```
47
+
48
+ ## 💡 Usage Examples
49
+
50
+ ### Create Collections from TypeScript
51
+ ```typescript
52
+ // Describe your interface to your MCP client
53
+ interface User {
54
+ username: string;
55
+ email: string;
56
+ isActive: boolean;
57
+ profile: UserProfile;
58
+ }
59
+ ```
60
+
61
+ ### Generate TypeScript from PocketBase
62
+ ```
63
+ Generate TypeScript interfaces from my PocketBase collections
64
+ ```
65
+
66
+ ### Data Analysis
67
+ ```
68
+ Analyze the "products" collection and provide insights
69
+ ```
70
+
71
+ ## 🛠️ Available Tools
72
+
73
+ **Collection Management**: `create_collection`, `list_collections`, `delete_collection`, `get_collection_schema`, `update_collection`, `truncate_collection`, `migrate_collection`
74
+
75
+ **Record Operations**: `create_record`, `list_records`, `update_record`, `delete_record`, `query_collection`
76
+
77
+ **Authentication**: `authenticate_user`, `create_user`
78
+
79
+ **Code Generation**: `generate_pb_schema`, `generate_typescript_interfaces`
80
+
81
+ **Analysis**: `analyze_collection_data`, `backup_database`, `import_data`
82
+
83
+ **File Management**: `upload_file`, `download_file`, `upload_file_from_url`
84
+
85
+ **Advanced**: `manage_indexes`
86
+
87
+ > 📖 **[Complete API Reference →](./docs/api-reference.md)**
88
+
89
+ ## 📚 Documentation
90
+
91
+ - **[Getting Started](./docs/getting-started.md)** - Installation and configuration guide
92
+ - **[Developer Guide](./docs/developer-guide.md)** - How to extend the server with new tools
93
+ - **[API Reference](./docs/api-reference.md)** - Complete tool reference and examples
94
+ - **[Architecture](./docs/architecture.md)** - System design and architectural decisions
95
+ - **[Contributing](./docs/contributing.md)** - Guidelines for contributors
96
+
97
+ ## 🏗️ Architecture
98
+
99
+ Built with a modular, extensible architecture:
100
+
101
+ ```
102
+ src/
103
+ ├── tools/ # Modular tool system
104
+ │ ├── schemas/ # Input validation
105
+ │ └── handlers/ # Business logic
106
+ ├── utils/ # Shared utilities
107
+ ├── types/ # TypeScript definitions
108
+ └── config/ # Configuration management
109
+ ```
110
+
111
+ **Key Benefits**:
112
+ - 🔧 **Extensible**: Easy to add new tools
113
+ - 🛡️ **Type-Safe**: Full TypeScript coverage
114
+ - ⚡ **Performance**: Optimized for speed
115
+ - 🧪 **Testable**: Comprehensive test coverage
116
+
117
+ ## Contributing
118
+
119
+ Contributions are always welcome! Please create an issue or pull request.
120
+
121
+ ## License
122
+
123
+ MIT
@@ -0,0 +1,9 @@
1
+ export interface CLIConfig {
2
+ url?: string;
3
+ adminEmail?: string;
4
+ adminPassword?: string;
5
+ }
6
+ /**
7
+ * Parse command line arguments for PocketBase MCP Server
8
+ */
9
+ export declare function parseCliArgs(): CLIConfig;
@@ -0,0 +1,31 @@
1
+ import yargs from "yargs";
2
+ import { hideBin } from "yargs/helpers";
3
+ /**
4
+ * Parse command line arguments for PocketBase MCP Server
5
+ */
6
+ export function parseCliArgs() {
7
+ const argv = yargs(hideBin(process.argv))
8
+ .option("url", {
9
+ alias: "u",
10
+ type: "string",
11
+ description: "PocketBase URL",
12
+ })
13
+ .option("admin-email", {
14
+ alias: "e",
15
+ type: "string",
16
+ description: "Admin email for authentication",
17
+ })
18
+ .option("admin-password", {
19
+ alias: "p",
20
+ type: "string",
21
+ description: "Admin password for authentication",
22
+ })
23
+ .help()
24
+ .alias("help", "h")
25
+ .parseSync();
26
+ return {
27
+ url: argv.url,
28
+ adminEmail: argv["admin-email"],
29
+ adminPassword: argv["admin-password"],
30
+ };
31
+ }
@@ -0,0 +1,9 @@
1
+ export interface EnvironmentConfig {
2
+ pocketbaseUrl?: string;
3
+ adminEmail?: string;
4
+ adminPassword?: string;
5
+ }
6
+ /**
7
+ * Load and parse environment variables for PocketBase MCP Server
8
+ */
9
+ export declare function loadEnvironmentConfig(): EnvironmentConfig;
@@ -0,0 +1,13 @@
1
+ import dotenv from "dotenv";
2
+ /**
3
+ * Load and parse environment variables for PocketBase MCP Server
4
+ */
5
+ export function loadEnvironmentConfig() {
6
+ // Load environment variables from .env file
7
+ dotenv.config();
8
+ return {
9
+ pocketbaseUrl: process.env.POCKETBASE_URL,
10
+ adminEmail: process.env.POCKETBASE_ADMIN_EMAIL,
11
+ adminPassword: process.env.POCKETBASE_ADMIN_PASSWORD,
12
+ };
13
+ }
@@ -0,0 +1,13 @@
1
+ import { CLIConfig } from "./cli.js";
2
+ import { EnvironmentConfig } from "./environment.js";
3
+ export interface ServerConfig {
4
+ url: string;
5
+ adminEmail?: string;
6
+ adminPassword?: string;
7
+ }
8
+ /**
9
+ * Create unified server configuration by merging CLI args and environment variables
10
+ * CLI arguments take precedence over environment variables
11
+ */
12
+ export declare function createServerConfig(): ServerConfig;
13
+ export { CLIConfig, EnvironmentConfig };
@@ -0,0 +1,20 @@
1
+ import { parseCliArgs } from "./cli.js";
2
+ import { loadEnvironmentConfig } from "./environment.js";
3
+ /**
4
+ * Create unified server configuration by merging CLI args and environment variables
5
+ * CLI arguments take precedence over environment variables
6
+ */
7
+ export function createServerConfig() {
8
+ const cliConfig = parseCliArgs();
9
+ const envConfig = loadEnvironmentConfig();
10
+ // Prioritize CLI args over environment variables
11
+ const url = cliConfig.url || envConfig.pocketbaseUrl;
12
+ if (!url) {
13
+ throw new Error("PocketBase URL is required. Provide it via --url parameter or POCKETBASE_URL environment variable.");
14
+ }
15
+ return {
16
+ url,
17
+ adminEmail: cliConfig.adminEmail || envConfig.adminEmail,
18
+ adminPassword: cliConfig.adminPassword || envConfig.adminPassword,
19
+ };
20
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ import { createServerConfig } from "./config/index.js";
3
+ import { startServer } from "./server.js";
4
+ // Main entry point
5
+ async function main() {
6
+ try {
7
+ // Create server configuration from CLI args and environment
8
+ const config = createServerConfig();
9
+ // Start the MCP server
10
+ await startServer(config);
11
+ }
12
+ catch (error) {
13
+ console.error("Failed to start PocketBase MCP Server:", error);
14
+ process.exit(1);
15
+ }
16
+ }
17
+ // Start the server
18
+ main().catch((error) => {
19
+ console.error("Unhandled error:", error);
20
+ process.exit(1);
21
+ });
@@ -0,0 +1,10 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import type { ServerConfig } from "./config/index.js";
3
+ /**
4
+ * Create and configure the MCP server
5
+ */
6
+ export declare function createServer(config: ServerConfig): Server;
7
+ /**
8
+ * Start the MCP server
9
+ */
10
+ export declare function startServer(config: ServerConfig): Promise<void>;
@@ -0,0 +1,211 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
4
+ import PocketBase from "pocketbase";
5
+ import { handlePocketBaseError } from "./utils/errors.js";
6
+ // Import all schemas
7
+ import { createCollectionSchema, deleteCollectionSchema, getCollectionSchemaSchema, listCollectionsSchema, truncateCollectionSchema, createRecordSchema, listRecordsSchema, updateRecordSchema, deleteRecordSchema, authenticateUserSchema, createUserSchema, analyzeCollectionDataSchema, queryCollectionSchema, migrateCollectionSchema, backupDatabaseSchema, importDataSchema, manageIndexesSchema, generatePbSchemaSchema, generateTypescriptInterfacesSchema, uploadFileSchema, downloadFileSchema, uploadFileFromUrlSchema, } from "./tools/index.js";
8
+ // Import all handlers
9
+ import { createCreateCollectionHandler, createDeleteCollectionHandler, createGetCollectionSchemaHandler, createListCollectionsHandler, createTruncateCollectionHandler, createCreateRecordHandler, createListRecordsHandler, createUpdateRecordHandler, createDeleteRecordHandler, createAuthenticateUserHandler, createCreateUserHandler, createAnalyzeCollectionDataHandler, createQueryCollectionHandler, createMigrateCollectionHandler, createBackupDatabaseHandler, createImportDataHandler, createManageIndexesHandler, createGeneratePbSchemaHandler, createGenerateTypescriptInterfacesHandler, createUploadFileHandler, createDownloadFileHandler, createUploadFileFromUrlHandler, } from "./tools/index.js";
10
+ /**
11
+ * Create and configure the MCP server
12
+ */
13
+ export function createServer(config) {
14
+ const server = new Server({
15
+ name: "@fadlee/pocketbase-mcp",
16
+ version: "1.0.0",
17
+ }, {
18
+ capabilities: {
19
+ tools: {},
20
+ },
21
+ });
22
+ // Initialize PocketBase client
23
+ const pb = new PocketBase(config.url);
24
+ // Authenticate admin if credentials provided
25
+ if (config.adminEmail && config.adminPassword) {
26
+ pb.collection("_superusers").authWithPassword(config.adminEmail, config.adminPassword)
27
+ .catch((error) => {
28
+ console.error("Failed to authenticate admin:", error);
29
+ });
30
+ }
31
+ // Tool definitions with their schemas and handlers
32
+ const tools = [
33
+ // Collection tools
34
+ {
35
+ name: "create_collection",
36
+ description: "Create a new collection in PocketBase",
37
+ inputSchema: createCollectionSchema,
38
+ handler: createCreateCollectionHandler(pb),
39
+ },
40
+ {
41
+ name: "delete_collection",
42
+ description: "Delete a collection from PocketBase",
43
+ inputSchema: deleteCollectionSchema,
44
+ handler: createDeleteCollectionHandler(pb),
45
+ },
46
+ {
47
+ name: "get_collection_schema",
48
+ description: "Get schema details for a collection",
49
+ inputSchema: getCollectionSchemaSchema,
50
+ handler: createGetCollectionSchemaHandler(pb),
51
+ },
52
+ {
53
+ name: "list_collections",
54
+ description: "List all collections with optional sorting",
55
+ inputSchema: listCollectionsSchema,
56
+ handler: createListCollectionsHandler(pb),
57
+ },
58
+ {
59
+ name: "truncate_collection",
60
+ description: "Delete all records associated with the specified collection",
61
+ inputSchema: truncateCollectionSchema,
62
+ handler: createTruncateCollectionHandler(pb),
63
+ },
64
+ // Record tools
65
+ {
66
+ name: "create_record",
67
+ description: "Create a new record in a collection",
68
+ inputSchema: createRecordSchema,
69
+ handler: createCreateRecordHandler(pb),
70
+ },
71
+ {
72
+ name: "list_records",
73
+ description: "List records from a collection with optional filters",
74
+ inputSchema: listRecordsSchema,
75
+ handler: createListRecordsHandler(pb),
76
+ },
77
+ {
78
+ name: "update_record",
79
+ description: "Update an existing record",
80
+ inputSchema: updateRecordSchema,
81
+ handler: createUpdateRecordHandler(pb),
82
+ },
83
+ {
84
+ name: "delete_record",
85
+ description: "Delete a record",
86
+ inputSchema: deleteRecordSchema,
87
+ handler: createDeleteRecordHandler(pb),
88
+ },
89
+ // Auth tools
90
+ {
91
+ name: "authenticate_user",
92
+ description: "Authenticate a user and get auth token",
93
+ inputSchema: authenticateUserSchema,
94
+ handler: createAuthenticateUserHandler(pb),
95
+ },
96
+ {
97
+ name: "create_user",
98
+ description: "Create a new user account",
99
+ inputSchema: createUserSchema,
100
+ handler: createCreateUserHandler(pb),
101
+ },
102
+ // Analysis tools
103
+ {
104
+ name: "analyze_collection_data",
105
+ description: "Analyze data patterns and provide insights about a collection",
106
+ inputSchema: analyzeCollectionDataSchema,
107
+ handler: createAnalyzeCollectionDataHandler(pb),
108
+ },
109
+ {
110
+ name: "query_collection",
111
+ description: "Advanced query with filtering, sorting, and aggregation",
112
+ inputSchema: queryCollectionSchema,
113
+ handler: createQueryCollectionHandler(pb),
114
+ },
115
+ // Migration tools
116
+ {
117
+ name: "migrate_collection",
118
+ description: "Add, remove, or modify fields from a collection",
119
+ inputSchema: migrateCollectionSchema,
120
+ handler: createMigrateCollectionHandler(pb),
121
+ },
122
+ {
123
+ name: "backup_database",
124
+ description: "Create a backup of the PocketBase database",
125
+ inputSchema: backupDatabaseSchema,
126
+ handler: createBackupDatabaseHandler(pb),
127
+ },
128
+ {
129
+ name: "import_data",
130
+ description: "Import data into a collection",
131
+ inputSchema: importDataSchema,
132
+ handler: createImportDataHandler(pb),
133
+ },
134
+ {
135
+ name: "manage_indexes",
136
+ description: "Manage collection indexes",
137
+ inputSchema: manageIndexesSchema,
138
+ handler: createManageIndexesHandler(pb),
139
+ },
140
+ // Generation tools
141
+ {
142
+ name: "generate_pb_schema",
143
+ description: "Generate a PocketBase schema based on TypeScript interfaces or database diagram",
144
+ inputSchema: generatePbSchemaSchema,
145
+ handler: createGeneratePbSchemaHandler(pb),
146
+ },
147
+ {
148
+ name: "generate_typescript_interfaces",
149
+ description: "Generate TypeScript interfaces from PocketBase collections",
150
+ inputSchema: generateTypescriptInterfacesSchema,
151
+ handler: createGenerateTypescriptInterfacesHandler(pb),
152
+ },
153
+ // File tools
154
+ {
155
+ name: "upload_file",
156
+ description: "Upload a file to a record in PocketBase",
157
+ inputSchema: uploadFileSchema,
158
+ handler: createUploadFileHandler(pb),
159
+ },
160
+ {
161
+ name: "download_file",
162
+ description: "Download a file from a record in PocketBase",
163
+ inputSchema: downloadFileSchema,
164
+ handler: createDownloadFileHandler(pb),
165
+ },
166
+ {
167
+ name: "upload_file_from_url",
168
+ description: "Upload a file from URL to a record in PocketBase",
169
+ inputSchema: uploadFileFromUrlSchema,
170
+ handler: createUploadFileFromUrlHandler(pb),
171
+ },
172
+ ];
173
+ // Register list_tools handler
174
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
175
+ return {
176
+ tools: tools.map(tool => ({
177
+ name: tool.name,
178
+ description: tool.description,
179
+ inputSchema: tool.inputSchema,
180
+ })),
181
+ };
182
+ });
183
+ // Register call_tool handler
184
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
185
+ const { name, arguments: args } = request.params;
186
+ const tool = tools.find(t => t.name === name);
187
+ if (!tool) {
188
+ throw new Error(`Unknown tool: ${name}`);
189
+ }
190
+ try {
191
+ const result = await tool.handler(args || {});
192
+ return {
193
+ content: result.content,
194
+ };
195
+ }
196
+ catch (error) {
197
+ throw handlePocketBaseError(`tool ${name}`, error);
198
+ }
199
+ });
200
+ return server;
201
+ }
202
+ /**
203
+ * Start the MCP server
204
+ */
205
+ export async function startServer(config) {
206
+ const server = createServer(config);
207
+ const transport = new StdioServerTransport();
208
+ await server.connect(transport);
209
+ console.error("PocketBase MCP Server started successfully");
210
+ console.error(`Connected to PocketBase at: ${config.url}`);
211
+ }
@@ -0,0 +1,10 @@
1
+ import type PocketBase from "pocketbase";
2
+ import type { ToolHandler } from "../../types/index.js";
3
+ /**
4
+ * Analyze data patterns and provide insights about a collection
5
+ */
6
+ export declare function createAnalyzeCollectionDataHandler(pb: PocketBase): ToolHandler;
7
+ /**
8
+ * Advanced query with filtering, sorting, and aggregation
9
+ */
10
+ export declare function createQueryCollectionHandler(pb: PocketBase): ToolHandler;
@@ -0,0 +1,127 @@
1
+ import { handlePocketBaseError } from "../../utils/errors.js";
2
+ import { createJsonResponse } from "../../utils/response.js";
3
+ import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
4
+ /**
5
+ * Analyze data patterns and provide insights about a collection
6
+ */
7
+ export function createAnalyzeCollectionDataHandler(pb) {
8
+ return async (args) => {
9
+ try {
10
+ const { collection, options = {} } = args;
11
+ const sampleSize = options.sampleSize || 100;
12
+ // Get collection info and records
13
+ const collectionInfo = await pb.collections.getOne(collection);
14
+ const records = await pb
15
+ .collection(collection)
16
+ .getList(1, sampleSize);
17
+ // Initialize analysis structure
18
+ const analysis = {
19
+ collectionName: collection,
20
+ recordCount: records.totalItems,
21
+ fields: [],
22
+ insights: [],
23
+ };
24
+ if (records.items.length === 0) {
25
+ analysis.insights.push("No records available for analysis");
26
+ return createJsonResponse(analysis);
27
+ }
28
+ // Analyze each field
29
+ const fields = collectionInfo.fields || [];
30
+ for (const field of fields) {
31
+ if (options.fields && !options.fields.includes(field.name)) {
32
+ continue;
33
+ }
34
+ const fieldAnalysis = {
35
+ name: field.name,
36
+ type: field.type,
37
+ nonNullValues: 0,
38
+ uniqueValues: new Set(),
39
+ min: null,
40
+ max: null,
41
+ };
42
+ // Analyze field values
43
+ for (const record of records.items) {
44
+ const value = record[field.name];
45
+ if (value !== null && value !== undefined) {
46
+ fieldAnalysis.nonNullValues++;
47
+ fieldAnalysis.uniqueValues.add(JSON.stringify(value));
48
+ // For numeric fields, track min/max
49
+ if (field.type === "number") {
50
+ if (fieldAnalysis.min === null || value < fieldAnalysis.min) {
51
+ fieldAnalysis.min = value;
52
+ }
53
+ if (fieldAnalysis.max === null || value > fieldAnalysis.max) {
54
+ fieldAnalysis.max = value;
55
+ }
56
+ }
57
+ }
58
+ }
59
+ // Process analysis results
60
+ const processedAnalysis = {
61
+ ...fieldAnalysis,
62
+ uniqueValueCount: fieldAnalysis.uniqueValues.size,
63
+ fillRate: `${((fieldAnalysis.nonNullValues / records.items.length) * 100).toFixed(2)}%`,
64
+ uniqueValues: undefined, // Remove the Set before serializing
65
+ };
66
+ analysis.fields.push(processedAnalysis);
67
+ // Generate insights
68
+ if (processedAnalysis.uniqueValueCount === records.items.length &&
69
+ records.items.length > 5) {
70
+ analysis.insights.push(`Field '${field.name}' contains all unique values, consider using it as an identifier.`);
71
+ }
72
+ if (processedAnalysis.nonNullValues === 0) {
73
+ analysis.insights.push(`Field '${field.name}' has no values. Consider removing it or ensuring it's populated.`);
74
+ }
75
+ }
76
+ return createJsonResponse(analysis);
77
+ }
78
+ catch (error) {
79
+ throw handlePocketBaseError("analyze collection data", error);
80
+ }
81
+ };
82
+ }
83
+ /**
84
+ * Advanced query with filtering, sorting, and aggregation
85
+ */
86
+ export function createQueryCollectionHandler(pb) {
87
+ return async (args) => {
88
+ try {
89
+ const collection = pb.collection(args.collection);
90
+ const options = {};
91
+ if (args.filter)
92
+ options.filter = args.filter;
93
+ if (args.sort)
94
+ options.sort = args.sort;
95
+ if (args.expand)
96
+ options.expand = args.expand;
97
+ const records = await collection.getList(1, 100, options);
98
+ const result = { items: records.items };
99
+ if (args.aggregate) {
100
+ const aggregations = {};
101
+ for (const [name, expr] of Object.entries(args.aggregate)) {
102
+ const [func, field] = expr.split("(");
103
+ const cleanField = field.replace(")", "");
104
+ switch (func) {
105
+ case "sum":
106
+ aggregations[name] = records.items.reduce((sum, record) => sum + (record[cleanField] || 0), 0);
107
+ break;
108
+ case "avg":
109
+ aggregations[name] =
110
+ records.items.reduce((sum, record) => sum + (record[cleanField] || 0), 0) / records.items.length;
111
+ break;
112
+ case "count":
113
+ aggregations[name] = records.items.length;
114
+ break;
115
+ default:
116
+ throw new McpError(ErrorCode.InvalidParams, `Unsupported aggregation function: ${func}`);
117
+ }
118
+ }
119
+ result.aggregations = aggregations;
120
+ }
121
+ return createJsonResponse(result);
122
+ }
123
+ catch (error) {
124
+ throw handlePocketBaseError("query collection", error);
125
+ }
126
+ };
127
+ }
@@ -0,0 +1,10 @@
1
+ import type PocketBase from "pocketbase";
2
+ import type { ToolHandler } from "../../types/index.js";
3
+ /**
4
+ * Authenticate a user and get auth token
5
+ */
6
+ export declare function createAuthenticateUserHandler(pb: PocketBase): ToolHandler;
7
+ /**
8
+ * Create a new user account
9
+ */
10
+ export declare function createCreateUserHandler(pb: PocketBase): ToolHandler;