@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.
- package/LICENSE +21 -0
- package/README.md +123 -0
- package/build/src/config/cli.d.ts +9 -0
- package/build/src/config/cli.js +31 -0
- package/build/src/config/environment.d.ts +9 -0
- package/build/src/config/environment.js +13 -0
- package/build/src/config/index.d.ts +13 -0
- package/build/src/config/index.js +20 -0
- package/build/src/index.d.ts +2 -0
- package/build/src/index.js +21 -0
- package/build/src/server.d.ts +10 -0
- package/build/src/server.js +211 -0
- package/build/src/tools/handlers/analysis.d.ts +10 -0
- package/build/src/tools/handlers/analysis.js +127 -0
- package/build/src/tools/handlers/auth.d.ts +10 -0
- package/build/src/tools/handlers/auth.js +51 -0
- package/build/src/tools/handlers/collection.d.ts +22 -0
- package/build/src/tools/handlers/collection.js +82 -0
- package/build/src/tools/handlers/file.d.ts +5 -0
- package/build/src/tools/handlers/file.js +124 -0
- package/build/src/tools/handlers/generation.d.ts +10 -0
- package/build/src/tools/handlers/generation.js +201 -0
- package/build/src/tools/handlers/index.d.ts +10 -0
- package/build/src/tools/handlers/index.js +17 -0
- package/build/src/tools/handlers/migration.d.ts +18 -0
- package/build/src/tools/handlers/migration.js +219 -0
- package/build/src/tools/handlers/record.d.ts +18 -0
- package/build/src/tools/handlers/record.js +94 -0
- package/build/src/tools/index.d.ts +5 -0
- package/build/src/tools/index.js +7 -0
- package/build/src/tools/schemas/analysis.d.ts +56 -0
- package/build/src/tools/schemas/analysis.js +54 -0
- package/build/src/tools/schemas/auth.d.ts +59 -0
- package/build/src/tools/schemas/auth.js +59 -0
- package/build/src/tools/schemas/collection.d.ts +192 -0
- package/build/src/tools/schemas/collection.js +194 -0
- package/build/src/tools/schemas/file.d.ts +70 -0
- package/build/src/tools/schemas/file.js +70 -0
- package/build/src/tools/schemas/generation.d.ts +49 -0
- package/build/src/tools/schemas/generation.js +49 -0
- package/build/src/tools/schemas/index.d.ts +10 -0
- package/build/src/tools/schemas/index.js +17 -0
- package/build/src/tools/schemas/migration.d.ts +133 -0
- package/build/src/tools/schemas/migration.js +146 -0
- package/build/src/tools/schemas/record.d.ts +103 -0
- package/build/src/tools/schemas/record.js +103 -0
- package/build/src/types/index.d.ts +188 -0
- package/build/src/types/index.js +1 -0
- package/build/src/utils/errors.d.ts +17 -0
- package/build/src/utils/errors.js +35 -0
- package/build/src/utils/response.d.ts +23 -0
- package/build/src/utils/response.js +62 -0
- package/build/src/utils/typescript.d.ts +24 -0
- package/build/src/utils/typescript.js +130 -0
- 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,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,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,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;
|