From ba39e4d16214da02c4484ec06ca252650dabd752 Mon Sep 17 00:00:00 2001 From: zgaetano Date: Tue, 31 Mar 2026 15:33:31 -0400 Subject: [PATCH] Add erpnext-mcp/src/schemas/common.ts --- erpnext-mcp/src/schemas/common.ts | 177 ++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 erpnext-mcp/src/schemas/common.ts diff --git a/erpnext-mcp/src/schemas/common.ts b/erpnext-mcp/src/schemas/common.ts new file mode 100644 index 0000000..0762edb --- /dev/null +++ b/erpnext-mcp/src/schemas/common.ts @@ -0,0 +1,177 @@ +import { z } from "zod"; + +// ── Shared Schemas ────────────────────────────────────────── + +export const PaginationSchema = z.object({ + limit: z + .number() + .int() + .min(1) + .max(100) + .default(20) + .describe("Max results to return (1-100, default 20)"), + offset: z + .number() + .int() + .min(0) + .default(0) + .describe("Number of results to skip for pagination"), +}); + +export const FilterSchema = z + .array( + z.tuple([ + z.string().describe("Field name"), + z.string().describe("Operator: =, !=, >, <, >=, <=, like, not like, in, not in, between, is"), + z.union([z.string(), z.number(), z.boolean(), z.array(z.union([z.string(), z.number()]))]) + .describe("Value to compare against"), + ]) + ) + .optional() + .describe( + 'Filters as array of [field, operator, value] tuples. Example: [["status","=","Open"],["grand_total",">",1000]]' + ); + +export const FieldsSchema = z + .array(z.string()) + .optional() + .describe( + 'Fields to return. Example: ["name","customer_name","grand_total"]. Default returns only "name".' + ); + +export const OrderBySchema = z + .string() + .optional() + .describe('Sort order. Example: "modified desc" or "creation asc"'); + +export const DoctypeSchema = z + .string() + .min(1) + .describe( + 'ERPNext DocType name (e.g. "Sales Order", "Customer", "Item", "Purchase Invoice")' + ); + +export const DocNameSchema = z + .string() + .min(1) + .describe( + 'Document name/ID (e.g. "SO-00001", "CUST-00001", "ITEM-00001")' + ); + +export const DocDataSchema = z + .record(z.unknown()) + .describe("Document field values as key-value pairs"); + +// ── Composite Schemas ─────────────────────────────────────── + +export const ListDocumentsSchema = z + .object({ + doctype: DoctypeSchema, + fields: FieldsSchema, + filters: FilterSchema, + order_by: OrderBySchema, + group_by: z.string().optional().describe("Group by field name"), + }) + .merge(PaginationSchema) + .strict(); + +export const GetDocumentSchema = z + .object({ + doctype: DoctypeSchema, + name: DocNameSchema, + fields: FieldsSchema, + }) + .strict(); + +export const CreateDocumentSchema = z + .object({ + doctype: DoctypeSchema, + data: DocDataSchema, + }) + .strict(); + +export const UpdateDocumentSchema = z + .object({ + doctype: DoctypeSchema, + name: DocNameSchema, + data: DocDataSchema, + }) + .strict(); + +export const DeleteDocumentSchema = z + .object({ + doctype: DoctypeSchema, + name: DocNameSchema, + }) + .strict(); + +export const SubmitDocumentSchema = z + .object({ + doctype: DoctypeSchema, + name: DocNameSchema, + }) + .strict(); + +export const CancelDocumentSchema = z + .object({ + doctype: DoctypeSchema, + name: DocNameSchema, + }) + .strict(); + +export const SearchLinkSchema = z + .object({ + doctype: DoctypeSchema, + txt: z.string().describe("Search text to match against document names/titles"), + filters: z.record(z.unknown()).optional().describe("Additional filters"), + page_length: z.number().int().min(1).max(50).default(20).describe("Max results"), + }) + .strict(); + +export const GetCountSchema = z + .object({ + doctype: DoctypeSchema, + filters: FilterSchema, + }) + .strict(); + +export const RunReportSchema = z + .object({ + report_name: z.string().min(1).describe("Name of the report to run"), + filters: z.record(z.unknown()).optional().describe("Report filters"), + }) + .strict(); + +export const CallMethodSchema = z + .object({ + method: z + .string() + .min(1) + .describe( + 'Dotted path to the whitelisted method (e.g. "erpnext.stock.utils.get_stock_balance")' + ), + args: z.record(z.unknown()).optional().describe("Method arguments"), + }) + .strict(); + +export const GetDocTypeMetaSchema = z + .object({ + doctype: DoctypeSchema, + }) + .strict(); + +export const BulkUpdateSchema = z + .object({ + doctype: DoctypeSchema, + names: z.array(z.string()).min(1).describe("Array of document names to update"), + data: DocDataSchema, + }) + .strict(); + +export const WorkflowActionSchema = z + .object({ + doctype: DoctypeSchema, + name: DocNameSchema, + action: z.string().min(1).describe("Workflow action to apply"), + }) + .strict();