MCP-KittoX: the MCP server
Kittox Enterprise feature
MCP-KittoX is part of the Kittoˣ Enterprise edition and ships together with KIDEx. It uses the same OnGuard license file (%CSIDL_COMMON_DOCUMENTS%\Ethea\KIDEX\Registration.ini) — a single registration unlocks both. See the Feature Matrix for the full comparison with the Open-Source edition.
MCP-KittoX is a standalone executable (MCPKittoX.exe) that exposes the functionality of KIDEx to AI agents — Claude Desktop, Claude Code, Codex, LM Studio and any other client compatible with the Model Context Protocol.
While KIDEx remains the human-facing visual IDE, MCP-KittoX is the AI-facing design tool: agents can scaffold new applications, reverse- engineer Models from a database, generate Views and Layouts, validate metadata, and refresh translation files — all conversationally, without leaving the agent.
Why use it
- Fast onboarding: an agent can create a complete Kittox app scaffold ("scaffold an app named MyApp under D:\Dev with FireDAC, JWT auth and all 4 deployment modes") without you opening RAD Studio or KIDEx.
- Assisted maintenance: ask the agent to validate the project, refresh the
.potranslation files, or propagate database schema changes back into the Model YAML files. - Enterprise differentiator: pair the visual IDE with an AI tool — the same way a developer pairs an IDE with an LLM-powered code assistant.
Quick start
After installing KIDEx Enterprise (which deploys MCPKittoX.exe to the same Bin\ folder as KIDEX.exe) and registering the OnGuard license, wire your MCP client:
Claude Desktop / Codex (STDIO transport)
%APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"kittox": {
"command": "C:\\Program Files\\Ethea\\KIDEX\\Bin\\MCPKittoX.exe",
"args": ["--stdio", "--workspace=D:\\Dev\\KittoXProjects"]
}
}
}Restart Claude Desktop. The agent will discover all the tools registered by the server (currently 29 — see the Feature Matrix below) and use them autonomously when you ask for Kittox development tasks.
Test the connection
MCPKittoX.exe --versionprints MCP-KittoX 4.0.7 and exits with code 0. From a JSON-RPC client (or MCPJam Inspector), invoke meta_version to verify the license check passes:
{
"name": "MCP-KittoX",
"version": "4.0.7",
"build_date": "2026-05-07",
"mcp_spec": "2025-06-18",
"kittox_version": "4.0.7",
"license_status": "(Trial version. Expiration days: 30)"
}Conversational example: scaffold + reverse-engineer Models
A typical end-to-end interaction once the MCP server is wired:
You — "Scaffold a new Kittox app named
Northwind2underD:\Dev\Examples, then point me at the SQL ServerNorthwinddatabase and generate Models for every table."Agent —
- Calls
project_create_app(project_nameNorthwind2, templateBasic). The wizard's defaults kick in:Auth: TextFilewith the demoFileAuthenticator.txt(admin/admin), JWT envelope,AccessControl: Null.- Asks you to edit
Home\Metadata\Config.yamlsoDatabases.Mainpoints at your SQL Server (or you tell the agent how it's reachable and it edits the file via your IDE).- Calls
project_openon the freshly-generated.kproj.- Calls
models_create_from_dbwithdry_run: trueand shows you the proposed action tree — typically Nadd_modelactions and a few hundredadd_field/add_reference_fieldsub-actions.- After your OK, calls
models_create_from_dbagain withdry_run: false— this time the tool executes the actions and writes the YAML files toHome\Metadata\Models\. Returnsapplied: trueand a summary.- Calls
menu_generate_main_menu—MainMenu.yamlis updated with oneView: Build AutoList / Model: <Name>entry per Model under a top-levelFolder: Menu. TheFolder: Usershipped with the template (Logout / ChangePassword) is preserved.- Suggests the next step (open the project in KIDEx or RAD Studio, customize the auto-generated Views or the menu, or ask the agent to drill into specific files using
models_read/views_read).
The whole exchange runs without you opening RAD Studio or KIDEx — the agent uses MCP-KittoX's tools the same way it would use a filesystem or a shell tool, and the resulting Models/ is identical to what the Model Wizard would have written if you'd driven it visually.
Architecture
| Aspect | Implementation |
|---|---|
| Library | MCPConnect (delphi-blocks, MIT) — attribute-driven, multi-transport |
| Serialization | Neon (MIT) — RTTI-based JSON, snake_case field naming |
| Logging | Logify (MIT) — meta-logging facade |
| Transport (current) | STDIO (Claude Desktop, Codex) |
| Transport (planned) | Indy HTTP (LM Studio, web-based clients) |
| MCP spec | 2025-06-18 |
| Naming convention | snake_case for tool args/results, plural scope for collections (models_list), singular-typed scope for typed creators (view_grid_create) |
| License gate | OnGuard, shared with KIDEx; every tool method calls EnsureLicensed first; unlicensed → EKXLicenseError (EJRPCException) → JSON-RPC error visible to client |
The server is a standalone executable, not embedded in your Kittox runtime nor inside KIDEx. Agents talk to it; KIDEx continues to be the human visual IDE. Both share a common headless layer so that — for instance — the models_create_from_db tool produces a Models/ folder byte-identical to what the Model Wizard writes when driven manually.
Feature Matrix
The following table tracks the implementation status of each MCP tool. Tools are organised by scope: collections use plural names (e.g. models, views) for browse/CRUD operations; typed creators use singular per-controller scopes (e.g. view_grid, view_chart) so the tool surface can grow additively without breaking changes.
Implemented (Phases 1 → 4)
| Scope | Tool | Description | Status |
|---|---|---|---|
meta | meta_version | Server identity, build date, MCP spec, license status | ✅ Done |
meta | meta_capabilities | Registered tool scopes + runtime feature flags (readonly, allow-update, allow-delete, workspace root) | ✅ Done |
meta | meta_list_metadata_templates | List the YAML templates KIDEx uses as design-time defaults | ✅ Done |
project | project_open | Open a Kittox project (.kproj file or Home/ folder) | ✅ Done |
project | project_info | Snapshot of the currently-open project | ✅ Done |
project | project_list_apps | List the application configs (Config.yaml variants) | ✅ Done |
project | project_close | Close the currently-open project | ✅ Done |
project | project_create_app | Generate a new app from a template (Empty / Basic), with full parametrization: DB drivers, auth + JWT envelope, access control, server settings, deployment modes (Standalone / Desktop / ISAPI / Apache), language, charset, theme. Default Auth: TextFile ships with a ready-to-use FileAuthenticator.txt so the generated app authenticates without a users table | ✅ Done |
models | models_list | List all Models in the active project. Each call refreshes the catalog from disk so external edits to YAML files since project_open are picked up. Returns name, physical_name, display_label, plural_display_label, field_count, is_large per entry | ✅ Done |
models | models_read | Read a Model YAML by name (case-insensitive lookup). Returns name (canonical casing), file_name (absolute path), content (raw YAML byte-identical to disk — comments and formatting preserved) | ✅ Done |
models | models_create_from_db | Reverse-engineer Models from a database connection (the headless equivalent of the Model Wizard inside KIDEx). Reads the live schema, diffs it against the open project's Models/, and returns the proposed action tree. Defaults to dry_run: true (preview only); pass dry_run: false to commit. Output is byte-identical to what the visual Model Wizard would write. Auto-populates each Model field's DisplayLabel from the database's native column comment when present (MSSQL extended property MS_Description, PostgreSQL pg_description, Firebird RDB$DESCRIPTION, MySQL COLUMN_COMMENT, Oracle USER_COL_COMMENTS). Accepts an optional field_descriptions array — a list of {model_name, field_name, display_label, hint} overrides — for the case where the agent has descriptions in a non-DB source (CSV export, glossary, prior YAML); override wins on every non-empty property, DB-fetched descriptions are preserved for the rest | ✅ Done |
models | models_delete | Delete a Model YAML by name. Two-step safety: confirm=false (default) returns a no-op preview confirming the file exists; confirm=true executes the delete and requires the server to be started with --allow-delete. Lookup is case-insensitive. Inbound references (other Models with Reference(name), Views with Model: name) are left dangling — the agent is responsible for inspecting and cleaning them up with the read tools beforehand if needed | ✅ Done |
models | models_update | Apply a list of granular operations to a Model's YAML tree and persist. Operations are {path, op, value} records applied in order, where op is 'set' (sets a node at the slash-separated path, creating missing intermediates) or 'delete' (removes a node). Two-step safety: confirm=false (default) returns a no-op preview; confirm=true executes the patch and requires the server to be started with --allow-update. Comments and original formatting of the YAML file are not preserved across the save (the tree is re-serialized) | ✅ Done |
views | views_list | List all Views in the active project. Same disk-refresh semantics as models_list. Returns name, display_label, controller_type, image_name per entry | ✅ Done |
views | views_read | Read a View YAML by name (case-insensitive). Same response shape as models_read | ✅ Done |
views | views_delete | Delete a View YAML by name. Same two-step confirm=false/true + --allow-delete pattern as models_delete. Inbound references from other Views (typically MainMenu entries) are left dangling | ✅ Done |
views | views_update | Apply a list of granular operations to a View's YAML tree and persist. Same {path, op, value} shape and confirm / --allow-update semantics as models_update | ✅ Done |
views | views_controllers | Discovery — list every controller type currently registered in the running MCPKittoX.exe binary, i.e. every value an agent can write after Controller: in a view YAML. Returns name (the registry key, e.g. 'List', 'Form', 'BorderPanel') and class_name (the underlying Delphi class) for each entry, sorted alphabetically. The list reflects the units linked in the running binary: any Enterprise add-on (Chart, Calendar, GoogleMap, Dashboard) registered via its own initialization section appears here automatically | ✅ Done |
view_grid | view_grid_create | Scaffold a data grid View (Type: Data with Controller: [List](List)) from a Model of the open project — the headless equivalent of KIDEx's Create DataView… context action. Output is byte-identical to the visual DataView wizard: a MainTable referencing the Model with every field as a column, a recursively-built detail-table block per detail reference, and a default FreeSearch filter over the text fields (both delegate to the framework's TKAutoListViewBuilder). model_name (required) selects the Model; view_name (optional) is the persistent file name, defaulting to the Model's plural name. Non-destructive: refuses to overwrite an existing View and reports the existing path instead — enabled by default, no --allow flag needed | ✅ Done |
layouts | layouts_list | List all Layouts in the active project (the YAML files under Home/Metadata/Views/Layouts/). Same disk-refresh semantics as models_list. Returns name, is_form_layout, is_grid_layout per entry | ✅ Done |
layouts | layouts_read | Read a Layout YAML by name (case-insensitive). Same response shape as models_read (name, file_name, content) | ✅ Done |
layouts | layouts_delete | Delete a Layout YAML by name. Same two-step confirm=false/true + --allow-delete pattern as models_delete | ✅ Done |
layouts | layouts_update | Apply a list of granular operations to a Layout's YAML tree and persist. Same {path, op, value} shape and confirm / --allow-update semantics as models_update | ✅ Done |
resources | resources_list | List static resources under the open project's Home/Resources/ (app) and/or the framework's shipped Home/Resources/ (system). Two-tier lookup mirrors the runtime /res/* precedence: each entry carries a source: 'app' | 'system' discriminator. Optional filters: subpath (e.g. 'icons/outlined'), pattern glob ('*.svg'), include_app / include_system, recursive. Returns path (forward-slashed, relative), source, size_bytes, mime_type per entry. Filesystem is enumerated live on every call | ✅ Done |
resources | resources_read | Read a single static resource by forward-slashed relative path. App takes precedence over system, mirroring the runtime resolver. Text resources (text/*, JSON, XML, JS, SVG, YAML) are returned as UTF-8 in content; binaries as base64 in content_base64. Files above 1 MB return metadata only with content_too_large: true (clients can still fetch via the runtime's /res/<path> HTTP route). Path-traversal (.., drive letters, absolute) is rejected | ✅ Done |
menu | menu_generate_main_menu | Create or refresh the project's MainMenu.yaml (the TreeView referenced by the standard HomeView). Adds one inline View: Build AutoList / Model: <Name> entry under a top-level Folder: Menu for every Model in the project. Idempotent: when the file already exists, only the Models not yet referenced are appended (any hand-edited folders or entries are preserved, including the standard Folder: User with Logout / ChangePassword). When the file does not exist, the tool creates it from scratch with the standard scaffold. Single parameter file_name (default 'MainMenu') | ✅ Done |
db | db_list_connections | List every database connection defined under Databases/ in the open project's Config.yaml. Returns name (the YAML key), driver ('FD' / 'DBX' / 'ADO') and display_label per entry. Credentials and connection-string sub-nodes (Password, User_Name, Server, ...) are not included | ✅ Done |
db | db_test | Test a single database connection by opening it and immediately closing it. On success returns success: true with the driver name; on failure returns success: false with error_class + error_message captured structurally, so an agent can branch on the exception type (driver not deployed, server down, wrong credentials, OLEDB provider missing). The test goes through a standalone connection that does not pollute the runtime per-request connection pool. Lookup is case-insensitive | ✅ Done |
db | db_list_tables | Enumerate the tables exposed by a database connection via the framework's TEFDBInfo.Schema introspection — the same primitive the Model Wizard uses internally before diff-ing against existing Models. Opens a standalone connection, iterates Schema.Tables, returns a flat array of table names plus count. Optional include_views: Boolean (default false) merges DB views into the result (mirrors the use_views parameter of models_create_from_db). On connection failure the exception is propagated verbatim (class name + message). Use db_test first if you want a non-throwing probe | ✅ Done |
db | db_describe_table | Describe a single database table via the framework's schema introspection (TEFDBInfo.Schema.FindTable) — columns with data_type (KittoX-normalized: String, Integer, Decimal, Date, DateTime, Boolean, Memo, Blob, ...), size, scale, nullable, is_pk, is_fk, native column description (when the DB exposes one); the ordered primary key column list; and the foreign keys (each with name, local columns, ref_table and ref_columns). Same primitive the Model Wizard reads to build the action tree for one table. Opens a standalone connection. On connection failure the exception is propagated verbatim. Both connection_name and table_name lookups are case-insensitive | ✅ Done |
db | db_introspect | Full schema snapshot of a database connection — one db_describe_table-shaped entry per table the framework exposes, in declaration order. Composition of db_list_tables + db_describe_table over a single CreateDBInfo so the framework reads the metadata cursors only once (more efficient than calling db_describe_table N times). Optional include_views: Boolean (default false) extends the snapshot to DB views. Payload size grows linearly with the schema; on very large databases prefer iterating db_list_tables + db_describe_table to stream the output | ✅ Done |
config | config_read | Read a single Config YAML by app name ('default' for Config.yaml, '<X>' for Config<X>.yaml / Config_<X>.yaml). Returns app_name, file_name, content (raw YAML, UTF-8, byte-identical to disk — no sanitization). Use project_list_apps first to discover the available app names | ✅ Done |
config | config_update | Apply a list of granular operations ({path, op, value} with op = 'set' | 'delete') to a Config YAML and persist via the same TEFYAMLReader + TEFYAMLWriter pair KIDEx's Config Editor uses on Ctrl+S. confirm=false (default) is a no-op preview; confirm=true executes the patch and requires the server to be started with --allow-update. When the patched file is the active Config.yaml the runtime's in-memory config is invalidated so subsequent reads pick up the new state. Touches the most sensitive file in the project (DB credentials, auth/JWT keys) — the dual --allow-update + confirm=true gating exists for this reason. Comments and original formatting of the YAML are not preserved across save | ✅ Done |
locale | locale_list_languages | List every language declared under the open project's Home/Locale/ directory. Returns name (language code, e.g. 'it', 'en'), path (absolute directory), and po_count (number of .po files under <lang>/LC_MESSAGES/) per entry. Returns an empty list when Locale/ does not exist or contains no .po files. Sorted alphabetically by name | ✅ Done |
locale | locale_read_po | Read a single .po file at <AppHome>/Locale/<language_name>/LC_MESSAGES/<domain>.po. Returns language_name, domain, file_name, content (raw .po text, UTF-8, byte-identical to disk). domain defaults to 'default' (KittoX uses a single domain) | ✅ Done |
validate | validate_config | Run KIDEx's TConfigValidator headlessly against the open project's Config YAML for the requested app name. Same validator class the Config Editor invokes on the Validate Metadata button. Captures every info / warning / error log line emitted during the run (via a TEFLogEndpoint sink on TEFLogger.Instance, classifying messages by their / / source prefix) and returns per-tag counts plus the full message list. Use 'default' for Config.yaml, suffix for variants | ✅ Done |
validate | validate_models | Run TModelValidator headlessly. Pass a model name (case-insensitive) to validate a single Model, empty string to validate every Model in the project. Same uniform result shape as validate_config: scope, name, file_name, per-tag counts, lines | ✅ Done |
validate | validate_views | Run TViewValidator headlessly. Single view by name or empty for all. Same result shape as the other validate_* tools | ✅ Done |
validate | validate_layouts | Run TLayoutValidator headlessly. Single layout by name or empty for all. Same result shape | ✅ Done |
validate | validate_all | Orchestrate the four validators (Config → Models → Views → Layouts) in sequence sharing a single log sink so the returned result aggregates info/warning/error counts and messages across all four. scope='all', name='', file_name='' | ✅ Done |
Planned (Phase 5 and beyond)
| Scope | Tool | Description | Status |
|---|---|---|---|
models | models_generate_ddl | Forward-engineer CREATE/ALTER TABLE from a Model | ⏳ Todo |
models | models_apply_to_db | Execute generated DDL against the database (with two-step confirmation) | ⏳ Todo |
models | models_patch_node | Granular edit of a single Model YAML node | ⏳ Todo |
view_list | view_list_create | Scaffold a List view from a Model | ⏳ Todo (future) |
view_grouping_list | view_grouping_list_create | Scaffold a GroupingList view | ⏳ Todo (future) |
view_chart | view_chart_create | Scaffold a ChartPanel view (bar/line/pie/doughnut) | ⏳ Todo (future) |
view_calendar | view_calendar_create | Scaffold a CalendarPanel view | ⏳ Todo (future) |
view_googlemap | view_googlemap_create | Scaffold a GoogleMap view | ⏳ Todo (future) |
view_template_data | view_template_data_create | Scaffold a TemplateDataPanel view | ⏳ Todo (future) |
locale | locale_update_files | Run Update Locale Files headlessly: extract translatable strings from YAML metadata + Delphi sources, merge with existing .po files preserving translations | ⏳ Todo (Phase 3) |
Safety: write operations are opt-in
By default MCPKittoX.exe exposes read tools only. Update operations require --allow-update on the command line; delete operations require --allow-delete. Delete tools further follow a two-step preview→confirm pattern: a first call with confirm: false returns the impact (would_delete, references_count, would_break: [...]); a second call with confirm: true actually executes, only if the preview is still in cache for the session.
Workspace sandboxing (--workspace=PATH) prevents path traversal outside an allowed root.
CLI flags
MCPKittoX.exe [options]
Transport:
--stdio STDIO transport (default — for Claude Desktop, Codex)
--http Indy HTTP transport (planned)
--port=PORT HTTP port (default 4000, ignored in --stdio)
--bind=ADDRESS HTTP bind address (default 127.0.0.1)
Project:
--project=PATH Project to open at startup (optional)
--workspace=PATH Sandbox root — projects must live underneath
Security:
--api-key=KEY API key required for HTTP transport
--readonly Disable all write tools (creates / updates / deletes)
--allow-update Enable *_update tools (off by default)
--allow-delete Enable *_delete tools (off by default)
Diagnostics:
--log-file=PATH Logify file destination
--log-level=LEVEL debug | info | warn | error (default info)
--version Print version and capabilities, exitLicense status
When the server starts, the OnGuard license check runs. The result is:
- printed to stderr as a one-line banner (visible when running interactively):
[LICENSE] (Trial version. Expiration days: 30) [LICENSE] Software registered to "Carlo Barazzetta". [LICENSE] Unregistered version! You must acquire license from "support@ethea.it" - exposed in the JSON-RPC
meta_versionresponse underlicense_status(so an agent can read it and warn the user when expiration is approaching).
If the license is invalid, every tool method throws an EKXLicenseError that propagates through the JSON-RPC envelope as a structured error:
{"error":{"code":-32603,"message":"Unregistered version! You must acquire license from \"support@ethea.it\""},"id":2,"jsonrpc":"2.0"}The server still answers initialize and tools/list so the client can show the tool catalog — but no tool can be invoked successfully until KIDEx is registered.
See also
- KIDEx: the KittoX IDE — the visual IDE whose functionality MCP-KittoX exposes to AI agents; also includes the RAD Studio IDE plugin section that documents the gallery entries under File > New > Other > KittoX Projects
- New Project Wizard — the visual counterpart of
project_create_app; same template engine, identical output - Kitto Enterprise — what's included in the commercial edition
- Feature Matrix — Open Source vs Enterprise comparison
- Model Context Protocol (external) — the protocol specification
- MCPConnect (external) — the underlying Delphi MCP library
