A low-code platform with AI-powered schema management, UI builder, business rule automation, and data operations. Provides MCP tools for database schema creation/modification, data querying/writing, UI management, rule automation, and undo operations.
Zenku provides 10 well-defined tools with explicit schemas, detailed descriptions, and clear risk classifications. Strengths: all tools have input schemas with typed parameters, descriptions ranging 94-580+ chars (well above the 10-char floor), enum constraints on categorical parameters, and helpful operation guides. Weaknesses: some descriptions are overly long and verbose (manage_schema, manage_ui exceed 500 chars, diluting key details with implementation minutiae); missing documented output schemas for most tools (only risk levels and file locations are visible, not response field specifications); limited error handling guidance (no recovery paths, retryability classification, or user-fixable vs fatal distinctions); parameters like 'value' in manage_rules lack format/type specificity; no examples of actual invocations or common error cases. Tool composition is strong (each does one clear thing: query, write, schema, ui, rules, undo, i18n, guide). Naming is verb-first and action-oriented. Schema coverage is 7/10 tools with complete input schemas visible; output schemas are inferred but not documented.
Assess impact of destructive schema changes. Must call this tool before executing drop_column, rename_column, change_type, or drop_table. Reports affected interfaces, rules, record count, and foreign key dependencies.
Returns the Zenku External Integration Guide — a reference for any external system (n8n, Zapier, Make, AI agents, etc.) that needs to communicate bidirectionally with Zenku. Read this guide when you need to know: - Which API endpoints to use (/api/ext/ vs /api/data/, and why they differ) - How to authenticate with an API key (Bearer token format and scopes) - The exact webhook payload Zenku sends on after_insert/after_update rules - How to write data back to Zenku (PATCH endpoint or webhook callback) - Common errors and fixes (Docker hostname, n8n expression mode, auth conflicts) - Step-by-step integration walkthrough using n8n as the example
Retrieve database structure information. Use this when you need to know which tables exist or need the detailed column definitions of a specific table before performing queries or modifications. Actions: - list_tables: Returns a list of all user-defined table names. - get_schema: Returns detailed column info (name, type, nullability, etc.) for a specific table.
Create or modify business rules (automation flows, validation). Rules execute automatically at specified trigger points: - on_change: form field value changes (frontend live event, record NOT yet saved). Use for FK lookup auto-fill (e.g., select PO → fill vendor_id immediately). - before_insert / before_update / before_delete: Can intercept, modify data, validate (before DB write) - after_insert / after_update / after_delete: Can trigger side effects (webhooks, create records) - manual: triggered by a custom ViewAction button (trigger_rule behavior) Use trigger_types (array) to apply the same rule to multiple trigger points: - Example: ["on_change", "before_insert"] → live UX fill + DB safety net Action types: - set_field: Set field value (value can be FK dot path like "po_id.vendor_id" or formula like "total * 0.9") - validate: Validation rule (reject operation if condition met, return message) - create_record: Insert new record in another table (NOT allowed in on_change) - update_record: Update existing record in another table (NOT allowed in on_change) - update_related_records: Batch update target table via intermediate detail table (NOT allowed in on_change) - webhook: Call external URL (NOT allowed in on_change) - notify: Record notification Condition operators: eq, neq, gt, lt, gte, lte, contains, changed, was_eq, was_neq - changed: fires whenever the field value changes (use with on_change) - was_eq: Old value equals value before trigger (good for "status changed from X" in after_update rules) - was_neq: Old value not equals value Condition field supports FK paths (cross-table conditions): - To check customer tier in order_items rule, use condition.field "order_id.customer_id.tier" Choosing trigger: - Need live UX (user sees value appear while filling form)? → on_change - Need data integrity even if frontend bypassed? → before_insert / before_update - Need both? → trigger_types: ["on_change", "before_insert"] on_change example — auto-fill vendor when PO is selected: { "trigger_types": ["on_change", "before_insert"], "condition": { "field": "po_id", "operator": "changed" }, "actions": [{ "type": "set_field", "field": "vendor_id", "value": "po_id.vendor_id" }] }
Output schemas not documented. Tool responses are not visible in source, only input schemas shown. LLMs cannot plan downstream calls without knowing what fields to expect (e.g., query_data returns what columns? what pagination?). This forces LLMs to guess or inspect responses at runtime.
Descriptions for manage_schema and manage_ui are excessively verbose (580+ chars), burying key guidance in implementation minutiae. Baseline for A+ tools is 50-200 chars. Long descriptions waste tokens and reduce clarity for LLM selection. The 'Field type mapping' and 'Table Traits' sections in manage_schema, and the 'Type selection guide' in manage_ui, should be moved to a separate reference doc or tightened to 1 - 2 sentences with a pointer to docs.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 56 | 2026-07-28+ | v2 |
Create or modify database table schema. After creating a new table, you must call manage_ui to create the corresponding interface. Field type mapping: - Plain text → TEXT - Number (integer) → INTEGER - Number (decimal/currency) → REAL - Yes/No → BOOLEAN - Date → DATE - DateTime → DATETIME - Reference to another table → INTEGER + references: { table: 'target_table' } Table Traits (advanced features): - When creating a table, you can pass traits: ["state_machine"] to automatically inject status management fields (status, created_by) and enable lifecycle protection (state transitions, edit locking, delete control). - Do NOT manually create status or created_by fields when using state_machine trait — they are auto-injected. - After creating a state_machine table, use manage_ui to create the view, then configure the states and transitions via the trait config.
Create or update user interface. Type determines layout: Type selection guide: - table: General list management (default) - master-detail: Master + details (e.g., orders + order items), requires detail_views - dashboard: Statistics panel, requires widgets (no columns/form needed) - kanban: Kanban board with drag-drop, requires kanban (group_field, title_field) - calendar: Calendar view, requires calendar (date_field, title_field) - gallery: Gallery grid with image cards, requires gallery (image_field, title_field) - form-only: Single-record form (e.g., settings page); auto-creates record if table is empty - timeline: Vertical timeline sorted by date; requires timeline (date_field, title_field) - tree: Hierarchical tree view for self-referential data (org charts, categories, folders); requires tree (parent_field, label_field) - gantt: Gantt chart with date bars; requires gantt (start_field, end_field, title_field) - embed: Embed an external URL or custom HTML; requires embed ({ url } or { html }) Field type determines frontend rendering (for table/master-detail): - text/number/date/boolean/textarea: Basic input - select + options: Static dropdown - relation + relation: Related field (searchable dropdown, stores id) - currency: Currency amount (with thousand separators) - computed: Only set in form.fields, use number type in columns - markdown: Rich formatted content (Tiptap WYSIWYG); stores Markdown text; use for descriptions, notes, specs. Prefer over richtext (deprecated). - sheet: Embedded spreadsheet (Univer); stores full workbook JSON; use only when a field genuinely needs spreadsheet capability (formulas, multi-sheet, formatting). Heavy — avoid unless necessary. - json: JSON editor (CodeMirror); stores any valid JSON string; use for flexible metadata or config fields. form.columns controls form column count (integer 1/2/3): - Always set explicitly when fields >= 5, otherwise form becomes a single long column - Use 2 for most multi-field forms; use 3 when fields exceed 8 group controls sidebar grouping: - Omit for ungrouped views (shown at top) - Set to a short label (e.g., "採購", "庫存") to cluster related views under a collapsible section When users say "statistics/kanban/calendar/gallery", directly create a view of that type without needing a table first.
Query data and answer statistics questions. Can only execute SELECT queries.
Register or update translation entries for user-defined content ($key → display text per locale). Call this after creating schema or views when the user's language is not English, to register translations for field labels, view names, and select option labels. Each entry must have: - key: translation key starting with $ (e.g. "$field.tasks.title", "$view.task_list", "$opt.tasks.status.todo") - locale: language code (e.g. "en", "zh-TW", "vi") - content: the display text in that locale
Undo previous operations. Call when user says "undo", "cancel last action", or "revert to previous version". - target=last: Undo most recent reversible operation - target=by_id: Undo operation by journal id - target=by_time: Undo all operations after specified time (batch rollback)
Perform insert, update, or delete operations on user data tables. Cannot operate on system tables (_zenku_ prefix). Operation guide: - insert: Add a new record, populate data with field values - update: Update records matching where condition, populate data with update values, where is required filter (mandatory to prevent full table updates) - delete: Delete records matching where condition, where is required condition (mandatory to prevent full table deletion) Note: where is a required safety guard for update/delete, cannot be omitted.
Error handling lacks recovery guidance. No tool description states what errors can occur, how they're classified (retryable, user-fixable, fatal), or what the LLM should do next. Example: manage_schema might fail if a table already exists or if a column type is invalid, neither error is documented. This forces LLMs to interpret raw error messages at runtime.
Parameter descriptions lack format specificity. Example: 'value' in manage_rules.actions[].value is described as a string but could be a FK path ('po_id.vendor_id'), a formula ('total * 0.9'), or a literal. The description hints at this but does not formally define allowed formats or constraints. LLMs may pass invalid values without guidance on correction.
manage_ui 'type' parameter has 11 allowed enum values (table, master-detail, dashboard, kanban, calendar, gallery, form-only, timeline, tree, gantt, embed) but descriptions are embedded in the tool description as walls of text rather than in parameter/enum annotations. LLMs cannot easily discover which type suits which use case without parsing long prose.
No confirmation/dry-run pattern for destructive operations. write_data (delete), manage_schema (drop_table), and undo_action are irreversible. Standard production tools offer a 'dry_run' or 'confirm_before_execute' pattern to prevent accidental data loss. This is critical for agent safety.
get_integration_guide has empty input schema (no required parameters). While this is valid, the tool purpose is ambiguous from the name alone, it could return integration docs for any system. Description clarifies it returns 'Zenku External Integration Guide', but the name should reflect that specificity (e.g., 'get_zenku_integration_guide').