This commit is contained in:
2025-07-25 17:45:41 +03:00
parent 62f7f125d3
commit 76f1180cde

View File

@@ -401,6 +401,7 @@ class AppwriteMCPServer {
properties: {
userId: { type: "string", description: "Unique user ID (optional)" },
email: { type: "string", description: "User email" },
phone: { type: "string", description: "User phone number in international format (optional, e.g., '+1234567890')" },
password: { type: "string", description: "User password" },
name: { type: "string", description: "User name (optional)" }
},
@@ -891,6 +892,7 @@ class AppwriteMCPServer {
properties: {
userId: { type: "string", description: "User ID (optional)" },
email: { type: "string", description: "User email" },
phone: { type: "string", description: "User phone number (optional)" },
password: { type: "string", description: "User password" },
name: { type: "string", description: "User name (optional)" }
},
@@ -1533,6 +1535,17 @@ class AppwriteMCPServer {
const { databaseId, collectionId, documentId, data, permissions } = args;
const docId = documentId || ID.unique();
// Validate document against collection schema
try {
const validation = await this.validateDocumentData(databaseId, collectionId, data);
if (!validation.isValid) {
throw new Error(`Document validation failed: ${validation.errors.join(', ')}`);
}
} catch (validationError) {
// If validation fails, provide helpful error message
throw new Error(`Schema validation error: ${validationError}. Use list_attributes to check collection schema.`);
}
const document = await this.databases.createDocument(
databaseId,
collectionId,
@@ -1629,10 +1642,10 @@ class AppwriteMCPServer {
private async createUser(args: any) {
if (!this.users) throw new Error("Users service not initialized");
const { userId, email, password, name } = args;
const { userId, email, phone, password, name } = args;
const uid = userId || ID.unique();
const user = await this.users.create(uid, email, password, name);
const user = await this.users.create(uid, email, phone, password, name);
return {
content: [
@@ -2371,6 +2384,71 @@ ${attributes.attributes.map((attr: any) =>
};
}
// Helper method for createDocument validation
private async validateDocumentData(databaseId: string, collectionId: string, documentData: any) {
if (!this.databases) throw new Error("Databases not initialized");
// Get collection schema
const attributes = await this.databases.listAttributes(databaseId, collectionId);
const attributeMap = new Map(attributes.attributes.map((attr: any) => [attr.key, attr]));
const errors: string[] = [];
// Check required fields
attributes.attributes.forEach((attr: any) => {
if (attr.required && !(attr.key in documentData)) {
errors.push(`Missing required field: ${attr.key} (${attr.type})`);
}
});
// Check field types and constraints
Object.keys(documentData).forEach(key => {
const attr = attributeMap.get(key);
const value = documentData[key];
if (!attr) {
errors.push(`Unknown field: ${key} (not in collection schema)`);
return;
}
// Type validation
switch (attr.type) {
case 'string':
if (typeof value !== 'string') {
errors.push(`Field ${key}: expected string, got ${typeof value}`);
} else if (attr.size && value.length > attr.size) {
errors.push(`Field ${key}: string too long (${value.length} > ${attr.size})`);
}
break;
case 'integer':
if (!Number.isInteger(value)) {
errors.push(`Field ${key}: expected integer, got ${typeof value}`);
}
break;
case 'boolean':
if (typeof value !== 'boolean') {
errors.push(`Field ${key}: expected boolean, got ${typeof value}`);
}
break;
case 'email':
if (typeof value !== 'string' || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
errors.push(`Field ${key}: invalid email format`);
}
break;
case 'datetime':
if (isNaN(Date.parse(value))) {
errors.push(`Field ${key}: invalid datetime format`);
}
break;
}
});
return {
isValid: errors.length === 0,
errors: errors
};
}
private async schemaMigration(args: any) {
if (!this.databases) throw new Error("Databases not initialized");
@@ -3608,9 +3686,9 @@ For accurate usage tracking, consider:
for (const user of users) {
try {
const { userId, email, password, name } = user;
const { userId, email, phone, password, name } = user;
const uid = userId || ID.unique();
const createdUser = await this.users.create(uid, email, password, name);
const createdUser = await this.users.create(uid, email, phone, password, name);
results.push(`${createdUser.email} (${createdUser.$id})`);
} catch (error) {
errors.push(`${user.email}: ${error}`);