DEV Community

Cover image for Building a Recall Response Console With ToolJet MCP (and Examining ToolJet’s Approach to AI App Building)
Karan Rathod for ToolJet

Posted on

Building a Recall Response Console With ToolJet MCP (and Examining ToolJet’s Approach to AI App Building)

Building the first version of an internal application is only one part of the job. The more difficult challenge is keeping it useful as the process, data, and people around it continue to change.

Internal tools are constantly evolving. Operations asks for another filter. Finance adds an approval step. Compliance updates a process. A team needs a new field, a different table layout, or another way to query the same data. Individually, these are small requests. Across dozens or hundreds of internal applications, they become a much larger maintenance problem than the initial build.

For this tutorial, we wanted to show what that approach looks like in practice. We gave Codex a detailed brief for a manufacturing recall system and used ToolJet MCP to build it. The resulting application is large enough to take us through the structure of a ToolJet MCP build—from planning and validation to queries, components, and later iterations—and to show how the finished app remains editable inside ToolJet.

The final application had 10 tables, 109 seeded rows, 28 queries, and 109 components across three pages.

ToolJet MCP did not generate a complicated React codebase and hand it over. It used ToolJet’s own APIs to create pages, components, queries, events, layouts, and data inside the platform. Once Codex finished, the result was still a normal ToolJet application. That is a fairly important difference when the person maintaining the app later may not be the person who prompted it into existence.

The App We Asked Codex to Build

The original brief was around 1,400 words. It described a Recall Response Console for a manufacturing company in South Australia, used by quality, operations, compliance, supply-chain, and customer-response teams.

The main instruction was simply:

Build this application in ToolJet. Follow the attached brief, keep the data consistent across every page, and verify each phase before moving on.

The first page was a Recall Command Centre. It needed portfolio-level KPIs for active recalls, units at risk, recovered units, financial exposure, and completion rate. Below that, the highest-priority recall had its own spotlight with severity, recall reason, affected batches, unit counts, and regulatory status. We also wanted the progress of affected inventory to be visible from production all the way through recovery.

The page included a portfolio table covering every recall. Users could filter by status, severity, category, owner, date, and region, and search across products, SKUs, lots, and recall IDs. The lower half added views for recovery, exposure, geographic distribution, and recall activity.

Clicking a recall opened the second page, the Recall Case & Response Workspace. This was designed for the team handling an individual recall rather than monitoring the whole portfolio.

The selected case shows 18,420 affected units, 16,210 located, 13,840 quarantined, and 11,920 recovered. The page follows the response from Issue Detected through Investigation, Recall Initiated, Containment, Recovery, Verification, and Closed. It also includes affected production lots, a distribution trace, stakeholder communication, response actions, root-cause investigation, and an audit trail.

We later gave Codex one much shorter follow-up instruction:

Add another relevant page with urgent actions.

Because the data model and application structure already existed, this did not need another large specification. Codex reused recall_actions and turned the request into a cross-recall Response Desk. For the iteration review, it produced one focused HTML artifact rather than another bundle of disconnected files.

The Response Desk pulls urgent work across recalls into one queue and groups it around overdue, due today, blocked, and critical actions. A user can complete an action from the queue or open the related recall for more context.

The app itself is useful, but it also gives us enough surface area to look at how ToolJet MCP approaches generation.

ToolJet MCP Is Not Just Generating More Frontend Code

A common direction in AI app building is to make the coding agent better at producing larger amounts of application code. In many cases, that means generating React components, data-fetching logic, state management, and the glue needed to connect everything together.

That approach can work very well when the output is supposed to be a codebase. The trade-off is that every generated app also becomes another codebase that somebody has to understand and maintain.

Internal apps tend to make that trade-off more visible. One company may have a large number of small operational tools, each with a different owner and a different lifespan. Many of the people maintaining them will understand the business process far better than they understand React.

ToolJet MCP takes a different route. Instead of asking the model to generate the application framework every time, it exposes smaller APIs for working with the framework that already exists.

Codex(or any other coding agent) can create a page, add components, configure queries, work with the ToolJet Database, connect events, change layouts, and update existing objects. The model still decides what needs to be built, but it does not have to express every part of that decision as frontend code.

That keeps the output inside ToolJet’s application model. A table created through MCP is still a ToolJet table component. A database operation remains a ToolJet query. A page created by the agent still appears in the normal page structure.

This also gives the agent a much narrower surface to work with. It can ask the platform to perform a specific operation rather than repeatedly producing large blocks of code and then reasoning about the result.

The Build Happened in Validated Phases

The MCP did not try to write the entire application in one enormous operation.

Plan the next phase
        ↓
Validate it
        ↓
Fix validation errors
        ↓
Apply the phase
        ↓
Verify the result
Enter fullscreen mode Exit fullscreen mode

Before a phase could be applied, the proposed application specification was linted. A successful lint produced a temporary token that was then consumed by the write operation. If linting failed, that phase did not get written.

That validation caught several real problems during the build. One database column was using a reserved SQL keyword. Another binding could reference a component before it had mounted. One action was targeting a component with the wrong property. Those issues were rejected before the corresponding phase was applied.

This does not make AI-generated apps magically error-free. It does give the agent a more structured way to fail. A bad change can be rejected as an invalid application operation rather than first becoming a large piece of broken code that has to be debugged afterwards.

The same idea applies to components. The platform already knows what a table, container, input, or query is. The agent can work with those contracts rather than inventing its own version each time. That is a more useful abstraction when trying to keep token usage under control as apps become larger.

Why Token Usage Fell Across the Build

The runtime exposed an approximate budget counter during this build. It is not a precise usage meter and should not be treated as an API bill, but the pattern was useful.

The first major turn, covering planning, the data model, and Page 1, used roughly 190k tokens. Page 2 and its mutations used around 84k. The later Response Desk iteration used about 51k.

The first pass had much more work to do. Codex had to read platform references, understand component contracts, establish the data model, and create the initial application structure.

Later work could reuse those decisions. When we added the Response Desk, ToolJet MCP did not need to create another data model. It reused recall_actions, added the required rows, and built the page on top of the existing application. The component types were already known and the broader application structure was already in context.

The practical benefit is not only lower token usage. It also means later changes fit into the same application model rather than slowly turning the project into a collection of generated code paths.

You Are Not Forced to Keep Using AI Afterwards

Once your app is ready, the next change does not have to go through Codex.

For a larger feature, it probably makes sense to continue using ToolJet MCP. The agent already understands the structure and can make coordinated changes across the application. For a small UI change, someone can simply open ToolJet.

The generated table remains a normal ToolJet component, editable through the visual builder.

The visual builder still sees the components normally. A user can resize a table, move it, change its styling, modify properties, or add another component without touching the process that generated the original page.

We did not spend a lot of time manually editing this app after the MCP build. That is not the point of showing the visual builder. The value is that the generated app has not lost the normal editing model of the platform.

The same applies to the data layer.

The query created during the build is still understandable in GUI mode: update recall_actions where the row ID matches the selected action.

A query created during the MCP build can still be opened in ToolJet’s query editor. In GUI mode, a user can see the data source, table, operation, and filters without tracing generated code. Someone comfortable with SQL can work in SQL mode. Someone who is not can use the GUI.

That is crucial for internal software because maintenance often ends up with the person who understands the workflow rather than the person who originally built the app.

This Is a Different Bet on AI App Building

There are two ways to look at an AI agent building software.

One is to keep making the agent better at producing code. Better models produce cleaner components, larger applications, and fewer mistakes. For some types of software, that is exactly what you want.

The other option is to give the agent better abstractions to work with.

ToolJet MCP follows the second approach. The model still does a lot of the difficult work. It reads the brief, plans the application, decides how to structure the pages, creates the data model, and connects the interactions. The platform handles the parts that already have a well-defined representation.

A table does not need a new React implementation. A database update does not need another custom data-access layer. A page does not need to become another routing problem.

That is also why this model makes sense for internal applications. The first build can be fast without turning every app into a new engineering project.

If a company eventually has hundreds of internal tools, the ability to generate them is only one part of the equation. They also need to be understandable and changeable after the person who created them has moved on.

What This Build Left Behind

By the end, we had a three-page Recall Response Console with a real data model, working queries, cross-page navigation, response actions, and enough operational detail to make the app useful beyond a demo.

More importantly, the result still behaved like a ToolJet application.

Codex, Claude Code or any other agent could continue making changes through MCP. A developer could work directly with SQL where needed. A business user could work with a query through GUI mode. Someone could open the visual builder and adjust a component without first learning how an AI agent generated it.

That is a different outcome from generating another React codebase, even if both approaches can produce a very similar screenshot.

For enterprise internal tools, that distinction becomes more important as the number of applications grows. Generating software is getting cheaper very quickly. Keeping all of that software maintainable is going to be the harder problem.

ToolJet MCP is built around that assumption.

Top comments (0)