UNPKG

frappe-mcp-server

Version:

Enhanced Model Context Protocol server for Frappe Framework with comprehensive API instructions and helper tools

617 lines (569 loc) 19.8 kB
/** * This file contains detailed instructions and examples for using the Frappe API * through the MCP server. It provides guidance on common operations and best practices. */ /** * Common Frappe DocTypes * * These are some of the standard DocTypes in Frappe that you might want to interact with: * * - User: User accounts in the system * - Role: User roles for permission management * - DocType: Metadata about document types * - DocField: Field definitions for DocTypes * - DocPerm: Permission rules for DocTypes * - Custom Field: Custom fields added to DocTypes * - Custom Script: Client-side scripts for DocTypes * - Server Script: Server-side scripts for automation * - Workflow: Workflow definitions * - Workflow State: States in a workflow * - Workflow Action: Actions that transition between workflow states */ export const COMMON_DOCTYPES = { SYSTEM: [ 'User', 'Role', 'DocType', 'DocField', 'DocPerm', 'Module Def', 'Custom Field', 'Custom Script', 'Server Script', 'Client Script', 'Property Setter', 'Print Format', 'Report', 'Page', 'Workflow', 'Workflow State', 'Workflow Action' ], CORE: [ 'File', 'Note', 'ToDo', 'Tag', 'Email Queue', 'Email Template', 'Notification', 'Event', 'Comment', 'Activity Log' ] }; /** * Frappe API Usage Instructions * * This object contains detailed instructions for common Frappe operations. * Each instruction includes a description, example usage, and tips. */ export const FRAPPE_INSTRUCTIONS = { // Document Operations DOCUMENT_OPERATIONS: { CREATE: { description: "Create a new document in Frappe", usage: ` To create a new document, use the create_document tool with the DocType name and field values: Example: { "doctype": "ToDo", "values": { "description": "Complete the project", "priority": "Medium", "status": "Open" } } Tips: - Required fields must be included in the values - For Link fields, provide the exact document name as the value - For Table fields, provide an array of row objects. **Do not create child documents separately before adding them to the parent document's table field.** - Child table rows should include all required fields. - The system will automatically set owner, creation, and modified fields. - For documents with a naming series (autoname is "naming_series"), do not include the "name" field in the values. The system will generate the name automatically. `, }, GET: { description: "Retrieve a document from Frappe", usage: ` To get a document, use the get_document tool with the DocType name and document name: Example: { "doctype": "ToDo", "name": "TODO-0001", "fields": ["description", "status", "priority"] // Optional: specific fields to retrieve } Tips: - If fields are not specified, all fields will be returned - The document name is case-sensitive - For standard naming, use the format [DocType]-[Number] (e.g., TODO-0001) - For documents with custom naming, use the exact document name `, }, UPDATE: { description: "Update an existing document in Frappe", usage: ` To update a document, use the update_document tool with the DocType name, document name, and values to update: Example: { "doctype": "ToDo", "name": "TODO-0001", "values": { "status": "Completed", "priority": "High" } } Tips: - Only include fields that need to be updated. - For Table fields, you need to provide the entire table data, not just the changed rows. **When updating child documents, include the 'name' field for existing rows. Do not attempt to update child documents by creating them separately.** - The system will automatically update the modified and modified_by fields. - Some fields may be read-only and cannot be updated. `, }, DELETE: { description: "Delete a document from Frappe", usage: ` To delete a document, use the delete_document tool with the DocType name and document name: Example: { "doctype": "ToDo", "name": "TODO-0001" } Tips: - Deletion may fail if there are dependent documents - Some documents may be set as not deletable in their DocType configuration - Deletion permissions are controlled by DocPerm records `, }, LIST: { description: "List documents from Frappe with filters", usage: ` To list documents, use the list_documents tool with the DocType name and optional filters: Example: { "doctype": "ToDo", "filters": { "status": "Open", "priority": "High" }, "fields": ["name", "description", "status"], "limit": 10, "limit_start": 0, "order_by": "creation desc" } Filter Formats: 1. Simple equality: { "status": "Open" } 2. Operators: { "creation": [">=", "2023-01-01"] } 3. Multiple conditions: { "status": "Open", "priority": "High" } 4. OR conditions: [ ["status", "=", "Open"], ["status", "=", "In Progress"] ] Available operators: - "=", "!=", "<", ">", "<=", ">=", "like", "not like" - "in", "not in" (for arrays) - "is", "is not" (for null values) - "between" (for date ranges) Tips: - Before using the \`list_documents\` tool with filters, the schema for the target doctype **must** be retrieved (e.g., using a \`get_doctype_schema\` tool or equivalent functionality). This step is crucial to identify the correct field names for the filter conditions, preventing errors due to invalid field references. - Use limit and limit_start for pagination - order_by accepts field name with optional "asc" or "desc" direction - If fields are not specified, standard fields will be returned - Complex filters can be created using arrays for OR conditions `, }, }, // Schema Operations SCHEMA_OPERATIONS: { GET_DOCTYPE_SCHEMA: { description: "Get the complete schema for a DocType", usage: ` To get a DocType schema, use the get_doctype_schema tool with the DocType name: Example: { "doctype": "ToDo" } The response includes: - Field definitions with types, labels, and validation rules - Permissions information - Naming configuration - Workflow information (if applicable) Tips: - Use this to understand the structure of a DocType before creating or updating documents - Check required fields, field types, and validation rules - Examine linked DocTypes for reference fields - Review permissions to ensure operations will succeed `, }, GET_FIELD_OPTIONS: { description: "Get available options for a Link or Select field", usage: ` To get field options, use the get_field_options tool with the DocType name and field name: Example: { "doctype": "ToDo", "fieldname": "priority", "filters": { "enabled": 1 } } Tips: - For Link fields, this returns documents from the linked DocType - For Select fields, this returns the predefined options - Use filters to narrow down the options for Link fields - The response includes both value and label for each option `, }, FIND_DOCTYPE: { description: "Find DocTypes in the system", usage: ` To find DocTypes, use the list_documents tool with DocType as the doctype: Example: { "doctype": "DocType", "filters": { "istable": 0, "issingle": 0 }, "fields": ["name", "module", "description"], "limit": 20 } Common filters for DocTypes: - istable: 0/1 (whether it's a child table) - issingle: 0/1 (whether it's a single document) - module: "Core" (filter by module) - custom: 0/1 (whether it's a custom DocType) - name: ["like", "%User%"] (search by name) Tips: - Use this to discover available DocTypes in the system - Filter by module to find related DocTypes - Check istable=0 and issingle=0 for regular DocTypes - Check custom=1 for custom DocTypes `, }, }, // Advanced Operations ADVANCED_OPERATIONS: { WORKING_WITH_CHILD_TABLES: { description: "Working with child tables (Table fields)", usage: ` Child tables are handled as arrays of row objects when creating or updating documents: Example (Creating a document with child table): { "doctype": "Sales Order", "values": { "customer": "Customer Name", "delivery_date": "2023-12-31", "items": [ { "item_code": "ITEM-001", "qty": 5, "rate": 100 }, { "item_code": "ITEM-002", "qty": 2, "rate": 200 } ] } } Example (Updating a child table): { "doctype": "Sales Order", "name": "SO-0001", "values": { "items": [ { "name": "existing-row-id-1", // Include row ID for existing rows "qty": 10 // Updated quantity }, { "item_code": "ITEM-003", // New row without name field "qty": 3, "rate": 150 } ] } } Tips: - When updating, include the row "name" for existing rows - Rows without a "name" field will be added as new rows - Rows in the database but not in the update will be deleted - Always include all required fields for new rows `, }, HANDLING_FILE_ATTACHMENTS: { description: "Handling file attachments", usage: ` Files in Frappe are stored as File documents. To attach a file to a document: 1. First, create a File document: { "doctype": "File", "values": { "file_name": "document.pdf", "is_private": 1, "content": "[base64 encoded content]", "attached_to_doctype": "ToDo", "attached_to_name": "TODO-0001" } } 2. The file will automatically be attached to the specified document Tips: - Use base64 encoding for the file content - Set is_private to 1 for private files, 0 for public files - The attached_to_doctype and attached_to_name fields link the file to a document - To get attached files, list File documents with filters for attached_to_doctype and attached_to_name `, }, WORKING_WITH_WORKFLOWS: { description: "Working with workflows", usage: ` Documents with workflows have additional fields for tracking the workflow state: 1. Check if a DocType has a workflow: { "doctype": "DocType", "name": "ToDo", "fields": ["name", "workflow_state"] } 2. Get available workflow states: { "doctype": "Workflow", "filters": { "document_type": "ToDo" } } 3. Update a document's workflow state: { "doctype": "ToDo", "name": "TODO-0001", "values": { "workflow_state": "Approved" } } Tips: - Workflow transitions may have permission requirements - Some states may require additional fields to be filled - Workflow actions may trigger notifications or other automations - Check the Workflow DocType for the complete workflow definition `, }, }, // Common Patterns and Best Practices BEST_PRACTICES: { HANDLING_ERRORS: { description: "Handling common errors", usage: ` Common Frappe API errors and how to handle them: 1. Document not found: - Check if the document exists - Verify the document name is correct (case-sensitive) - Ensure you have permission to access the document 2. Permission denied: - Check if you have the required permissions - Verify the API key has sufficient privileges - Check if the document is restricted by user permissions 3. Validation errors: - Required fields are missing - Field value doesn't match validation rules - Linked document doesn't exist - Unique constraint violation 4. Workflow errors: - Invalid workflow state transition - Missing workflow transition permission Tips: - Always check the error message for specific details - Use get_doctype_schema to understand field requirements - Test operations with minimal data first - Handle errors gracefully in your application `, }, EFFICIENT_QUERYING: { description: "Efficient querying patterns", usage: ` Tips for efficient querying in Frappe: 1. Always specify only the fields you need: { "doctype": "ToDo", "fields": ["name", "description", "status"], "limit": 10 } 2. Use appropriate filters to reduce result set: { "doctype": "ToDo", "filters": { "status": "Open", "owner": "current_user" } } 3. Use pagination for large result sets: { "doctype": "ToDo", "limit": 20, "limit_start": 0, "order_by": "modified desc" } Then increment limit_start by limit for each page. 4. Use indexed fields in filters when possible: - name - modified - creation - owner - docstatus - Fields marked as "in_standard_filter" or "in_list_view" 5. Avoid complex OR conditions when possible 6. For reporting, consider using Frappe Reports instead of raw queries `, }, NAMING_CONVENTIONS: { description: "Understanding Frappe naming conventions", usage: ` Frappe uses several naming conventions for documents: 1. Standard naming: [DocType]-[Number] (e.g., TODO-0001) - Automatically generated when autoname is "naming_series" 2. Field-based naming: Uses a field value as the name - When autoname is "field:[fieldname]" 3. Format-based naming: Uses a pattern with fields - When autoname is like "HR-EMP-.YYYY.-.#####" - Supports date formatting (YYYY, MM, DD) and sequences (#) 4. Prompt naming: User provides the name - When autoname is "prompt" 5. Custom naming: Programmatically generated - When autoname is "custom" Tips: - Check the DocType's autoname field to understand its naming convention - Names are case-sensitive and must be unique within a DocType - When creating documents, you can often omit the name for auto-named DocTypes - For manually named DocTypes, always provide a unique name `, }, USER_FRIENDLY_DISPLAY_NAMES: { description: "Using user-friendly names vs. internal IDs", usage: ` When presenting information to the user, generating summaries, or updating descriptive documentation (such as markdown files): * Prioritize using user-friendly display names for Frappe documents (e.g., the \`account_name\` for an Account, \`item_name\` for an Item, \`full_name\` for a User) instead of their internal \`name\` (ID). * If you only have the document's internal \`name\` (ID), and need its display name for descriptive purposes, attempt to fetch the document to retrieve the appropriate display field. * **Important Distinction:** For all direct API interactions with Frappe (e.g., creating documents, updating documents, setting link fields, applying filters via \`list_documents\`), you **must** continue to use the internal Frappe \`name\` (ID) of the document in the relevant data fields to ensure correct system operation. Example: If you have an Account with \`name\` = "001-ACC" and \`account_name\` = "Sales Revenue Account". - When showing this account in a report: Display "Sales Revenue Account". - When setting this account in a Journal Entry's \`account\` field (a Link field): Use "001-ACC". `, }, } }; /** * Helper function to get instructions for a specific operation */ export function getInstructions(category, operation) { const categoryData = FRAPPE_INSTRUCTIONS[category]; if (!categoryData) { return `Category '${category}' not found in instructions.`; } const operationData = categoryData[operation]; if (!operationData) { return `Operation '${operation}' not found in category '${category}'.`; } return `${operationData.description}\n\n${operationData.usage}`; } /** * Helper function to get a list of common DocTypes */ export function getCommonDocTypes(category) { return COMMON_DOCTYPES[category] || []; } // Define helper tools export const HELPER_TOOLS = [ { name: "find_doctypes", description: "Find DocTypes in the system matching a search term", inputSchema: { type: "object", properties: { search_term: { type: "string", description: "Search term to look for in DocType names" }, module: { type: "string", description: "Filter by module name (optional)" }, is_table: { type: "boolean", description: "Filter by table DocTypes (optional)" }, is_single: { type: "boolean", description: "Filter by single DocTypes (optional)" }, is_custom: { type: "boolean", description: "Filter by custom DocTypes (optional)" }, limit: { type: "number", description: "Maximum number of results (optional, default 20)" } }, required: [] } }, { name: "get_module_list", description: "Get a list of all modules in the system", inputSchema: { type: "object", properties: {}, required: [] } }, { name: "get_doctypes_in_module", description: "Get a list of DocTypes in a specific module", inputSchema: { type: "object", properties: { module: { type: "string", description: "Module name" } }, required: ["module"] } }, { name: "check_doctype_exists", description: "Check if a DocType exists in the system", inputSchema: { type: "object", properties: { doctype: { type: "string", description: "DocType name to check" } }, required: ["doctype"] } }, { name: "check_document_exists", description: "Check if a document exists", inputSchema: { type: "object", properties: { doctype: { type: "string", description: "DocType name" }, name: { type: "string", description: "Document name to check" } }, required: ["doctype", "name"] } }, { name: "get_document_count", description: "Get a count of documents matching filters", inputSchema: { type: "object", properties: { doctype: { type: "string", description: "DocType name" }, filters: { type: "object", description: "Filters to apply (optional)", additionalProperties: true } }, required: ["doctype"] } }, { name: "get_naming_info", description: "Get the naming series information for a DocType", inputSchema: { type: "object", properties: { doctype: { type: "string", description: "DocType name" } }, required: ["doctype"] } }, { name: "get_required_fields", description: "Get a list of required fields for a DocType", inputSchema: { type: "object", properties: { doctype: { type: "string", description: "DocType name" } }, required: ["doctype"] } }, { name: "get_api_instructions", description: "Get detailed instructions for using the Frappe API", inputSchema: { type: "object", properties: { category: { type: "string", description: "Instruction category (DOCUMENT_OPERATIONS, SCHEMA_OPERATIONS, ADVANCED_OPERATIONS, BEST_PRACTICES)" }, operation: { type: "string", description: "Operation name (e.g., CREATE, GET, UPDATE, DELETE, LIST, GET_DOCTYPE_SCHEMA, etc.)" } }, required: ["category", "operation"] } } ]; //# sourceMappingURL=frappe-instructions.js.map