diff --git a/src/index.ts b/src/index.ts index 52f3cd6..5023e9c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -171,6 +171,20 @@ class AppwriteMCPServer { required: ["databaseId"] } }, + { + name: "update_collection", + description: "Update collection name and permissions", + inputSchema: { + type: "object", + properties: { + databaseId: { type: "string", description: "ID of the database" }, + collectionId: { type: "string", description: "ID of the collection" }, + name: { type: "string", description: "New collection name" }, + permissions: { type: "array", description: "Collection permissions (optional)", items: { type: "string" } } + }, + required: ["databaseId", "collectionId", "name"] + } + }, { name: "delete_collection", description: "Delete a collection from a database", @@ -449,13 +463,15 @@ class AppwriteMCPServer { }, { name: "list_documents", - description: "List documents in a collection with optional queries", + description: "List documents in a collection with optional queries, limit, and offset", inputSchema: { type: "object", properties: { databaseId: { type: "string", description: "ID of the database" }, collectionId: { type: "string", description: "ID of the collection" }, - queries: { type: "array", description: "Query filters (optional)", items: { type: "string" } } + queries: { type: "array", description: "Query filters (optional)", items: { type: "string" } }, + limit: { type: "number", description: "Maximum number of documents to return (default 25, max 5000)" }, + offset: { type: "number", description: "Number of documents to skip for pagination (default 0)" } }, required: ["databaseId", "collectionId"] } @@ -507,11 +523,13 @@ class AppwriteMCPServer { }, { name: "list_users", - description: "List all users", + description: "List all users with pagination", inputSchema: { type: "object", properties: { - queries: { type: "array", description: "Query filters (optional)", items: { type: "string" } } + queries: { type: "array", description: "Query filters (optional)", items: { type: "string" } }, + limit: { type: "number", description: "Maximum number of users to return (default 25, max 5000)" }, + offset: { type: "number", description: "Number of users to skip for pagination (default 0)" } } } }, @@ -1910,6 +1928,8 @@ class AppwriteMCPServer { return await this.createCollection(request.params.arguments); case "list_collections": return await this.listCollections(request.params.arguments); + case "update_collection": + return await this.updateCollection(request.params.arguments); case "delete_collection": return await this.deleteCollection(request.params.arguments); @@ -2311,6 +2331,28 @@ class AppwriteMCPServer { }; } + private async updateCollection(args: any) { + if (!this.databases) throw new Error("Databases not initialized"); + + const { databaseId, collectionId, name, permissions } = args; + + const collection = await this.databases.updateCollection( + databaseId, + collectionId, + name, + permissions + ) as any; + + return { + content: [ + { + type: "text", + text: `Collection updated:\n- ID: ${collection.$id}\n- Name: ${collection.name}\n- Documents: ${collection.total}\n- Permissions: ${collection.$permissions?.join(', ') || 'None'}` + } + ] + }; + } + private async deleteCollection(args: any) { if (!this.databases) throw new Error("Databases not initialized"); @@ -2800,15 +2842,29 @@ ${attribute.default !== undefined ? `- Default: ${attribute.default}` : ''}` private async listDocuments(args: any) { if (!this.databases) throw new Error("Databases not initialized"); - const { databaseId, collectionId, queries } = args; + const { databaseId, collectionId, queries, limit, offset } = args; - const documents = await this.databases.listDocuments(databaseId, collectionId, queries || []); + // Build query array with limit and offset + const allQueries = [...(queries || [])]; + if (limit !== undefined) { + allQueries.push(Query.limit(limit)); + } + if (offset !== undefined) { + allQueries.push(Query.offset(offset)); + } + + const documents = await this.databases.listDocuments(databaseId, collectionId, allQueries) as any; + + const currentLimit = limit || 25; + const currentOffset = offset || 0; + const showing = Math.min(documents.documents.length, currentLimit); + const totalDocs = documents.total; return { content: [ { type: "text", - text: `Documents in collection ${collectionId} (${documents.total}):\n${JSON.stringify(documents.documents, null, 2)}` + text: `Documents in collection ${collectionId}:\n- Total: ${totalDocs}\n- Showing: ${showing} (offset: ${currentOffset}, limit: ${currentLimit})\n- Has more: ${currentOffset + showing < totalDocs}\n\n${JSON.stringify(documents.documents, null, 2)}` } ] }; @@ -2876,9 +2932,18 @@ ${attribute.default !== undefined ? `- Default: ${attribute.default}` : ''}` private async listUsers(args: any) { if (!this.users) throw new Error("Users service not initialized"); - const { queries } = args; + const { queries, limit, offset } = args; - const users = await this.users.list(queries || []); + // Build query array with limit and offset + const allQueries = [...(queries || [])]; + if (limit !== undefined) { + allQueries.push(Query.limit(limit)); + } + if (offset !== undefined) { + allQueries.push(Query.offset(offset)); + } + + const users = await this.users.list(allQueries) as any; const header = `${'Name'.padEnd(20)} ${'Email'.padEnd(30)} ${'Phone'.padEnd(15)} ${'Email Ver'.padEnd(10)} ${'Phone Ver'.padEnd(10)} ID`; const separator = '-'.repeat(100); @@ -2892,11 +2957,16 @@ ${attribute.default !== undefined ? `- Default: ${attribute.default}` : ''}` return `${name} ${email} ${phone} ${emailVer} ${phoneVer} ${user.$id}`; }).join('\n'); + const currentLimit = limit || 25; + const currentOffset = offset || 0; + const showing = users.users.length; + const totalUsers = users.total; + return { content: [ { type: "text", - text: `Users (${users.total}):\n\n${header}\n${separator}\n${userList}` + text: `Users:\n- Total: ${totalUsers}\n- Showing: ${showing} (offset: ${currentOffset}, limit: ${currentLimit})\n- Has more: ${currentOffset + showing < totalUsers}\n\n${header}\n${separator}\n${userList}` } ] };