AI · ENGINEERING · 2026-05-08 · Createrun Engineering · 9 min read

Why we built our own MCP server (and what it does)

We wanted an AI agent that could actually author our platform's artifacts, with every change checked by the same validator the Editor uses. This post explains how we got there.

The starting problem

Createrun is an enterprise application development platform. One development path uses its framework: customers author forms, queries and workflows in a browser-based Editor, with code extensions where needed. Some of those artifacts are simple, like a contact form with three fields. Some are not, like a 12-stage supplier-audit workflow with conditional manager-only approvals, dynamic stage targets, and 20 forms tied together by foreign keys.

We watched customers paste descriptions of those complex artifacts into ChatGPT and try to extract usable JSON. The output was often wrong: hallucinated field types ("number" where the platform expects "text + Integer + currency contentType"), inline buttons in items, which our validator forbids, and missing two-layer polymorphism on our dynamic field properties. The agent did not know our shape rules, and we had no way to teach it.

Why MCP rather than an OpenAPI spec

An API schema can describe callable methods. Our authoring experience also needed to address these practical concerns:

  1. Tool descriptions consume context. Exposing a large method catalog at once can leave less room for the application task.
  2. Platform shapes need examples. Our dynamic fields combine a type discriminator with provider-specific attributes. A schema needs enough supporting context for a client to construct that shape.
  3. Examples need to be retrievable. We wanted canonical attribute envelopes available when needed, without duplicating the entire catalog in each prompt.

Our MCP server gives clients access to operation schemas and retrievable examples. The server's tool design and validation provide the platform-specific behavior; how a client discovers tools and includes examples in model context depends on that client. MCP is the connection protocol, not a guarantee of correct authoring.

What we shipped

A tool surface grouped by capability area: Session, Form, Query, Workflow, Meta, Compile, Design, Data, and Batch. Every tool follows one description template:

// Tool description template
//   Purpose: ...
//   PRECONDITIONS: ...
//   EXAMPLE: ...
//   RETURNS: ...
//   ERRORS: ...

add_field(formRef, name, type, contentType?, options?)
update_field(formRef, fieldRef, ...)
remove_field(formRef, fieldRef)
add_part(formRef, type, ...)
remove_page(formRef, pageRef)
set_form_actions(formRef, actions[])
convert_to_bpm(formRef, stages[])
...

Tool coverage changes with each release; ask for the supported operations and limits for your evaluation version.

The headline tool is convert_to_bpm. Hand-rolling a BPM workflow for an existing form means injecting a WORKFLOW part, defining a flow with stages, adding a "Waiting" indicator, generating child runtime forms, and wiring stage-targeted Approve/Reject actions. convert_to_bpm does all of that as one batch, validated at every step, with the same best-effort atomicity as the batch API described below.

Batched mutations

Real authoring is multi-step: add a field, add another, change a third, set form-level actions, then compile. If any step fails, you do not want a half-modified form sitting in production.

We added batch transactions: begin_batch returns a batch ID, subsequent mutating tools queue against it, and commit_batch applies the queued operations with best-effort recovery. This is not a strict all-or-nothing transaction guarantee. Reads pass through. rollback_batch cleans up. Cross-operation references use the form name (formRef=formName), so the agent does not have to read back the generated GUID after each create.

Test mode

Agent runs need to be reproducible, both for our regression suite and for customer debugging. set_test_mode capture dumps every payload to per-session local test dumps, and a later replay under dryrun validates behavior without touching the live database. We use it for our scenario suite and for customer support sessions.

One validator for every mutation

Every shape mutation flows through a single validator. The agent cannot author "type=number" hallucinations or inline buttons in items, because the validator rejects them fail-fast with a specific error code. The validator is the source of truth: when we fixed the type catalog, the agent's failure mode shifted from "produces invalid forms" to "asks for clarification."

What's next

Sub-mutators for queries and workflows (add_query_column, add_join, add_filter; add_workflow_step, add_transition, set_trigger). Phase 4, data CRUD: runtime form-data CRUD becomes available after publish, because the user-data tables ship with publish, so a compile alone is not enough. Server-side git triggers, so the agent can take a new solution from creation to repository to clone on its own.

Updated 2026-09-05: the Data CRUD phase described under "What's next" has since shipped.

What the client changes

A compatible external AI client uses MCP for supported application operations. Review the resulting Createrun project objects and any authored files; do not assume that every operation emits a source file. Forms and BPM workflows are configured through the visual model, while custom components, task objects, providers and GateMethods are code extension points. Modeled framework functionality is compiled into DLLs that use the Createrun runtime.

Try it

An external AI client connects through MCP; the Createrun Agent runs inside the Editor experience, and manual authoring remains available. Read the development overview or Start for free and connect your client to your instance.

← Back to blog