Tools
What your agent can do once it's connected to Nova.
These are the tools the Nova MCP server exposes. You don't call them directly — your agent does, in response to natural-language instructions. Knowing what's available helps you write better prompts and understand what your agent is doing.
Easy starting point
get_agent_prompt returns the same instructions Nova's own web builder follows when it builds apps. Tell your agent to call it on its first turn (with mode: "build" for a new app or mode: "edit" for an existing one) and follow the text it returns. You don't have to do this — your agent can drive the tools however it wants — but starting from the instructions Nova already tunes for these tools is the fastest path to good results.
Browsing apps
| Tool | What it does |
|---|---|
list_apps | List your apps with optional status filter, sort, and pagination. |
search_apps | Fuzzy search by name. Case-insensitive, tolerates typos. |
get_app | Summarize one app: modules, forms, fields, case types. |
Creating and deleting apps
| Tool | What it does |
|---|---|
create_app | Create a new empty app and return its ID. Build it up with the other tools — every change is checked as it lands, so there's no separate finishing step. |
delete_app | Soft-delete an app. Recoverable within the returned window. |
Building a new app from a description
A new app is planned first, then built module by module. The two planning tools record the design in the conversation — they don't change the app; the app grows through update_app and create_module, each call checked as it lands.
| Tool | What it does |
|---|---|
generate_schema | Plan the data model: case types and their properties. First step; changes nothing. |
plan_app_design | Plan the app design: modules, forms, purposes, per-form design notes (and, on Connect apps, Connect settings for each form that takes part — forms can stay out of Connect). Run after generate_schema; changes nothing. |
update_app | Set the app's name and/or its CommCare Connect type. On a Connect build, set the type before creating modules. |
Working on modules
| Tool | What it does |
|---|---|
create_module | Add a new module together with its forms (each with fields), its case-list columns, and — when its case type is new to the app — the case type's record, in one call. A module lands complete or not at all. Refine the case list afterward via the case-list tools below. |
update_module | Rename a module and/or set its case type (with starter case-list columns when the module has none) — set the case type before adding registration, follow-up, or close forms to a module created without one. |
remove_module | Delete a module. |
get_module | Show details for one module, including the structured case-list config. |
Working on the case list
A module's case list is the screen that lists existing cases and the search bar that filters them. Each case-list configuration has three slots: the columns shown in the list, an optional filter predicate, and the search inputs the user types into.
| Tool | What it does |
|---|---|
add_case_list_columns | Add one or more columns to the case list (plain / date / phone / id-mapping / image-map / interval / calculated). Pass the whole set in one call. |
update_case_list_column | Replace a column's body, addressed by the column's uuid. |
remove_case_list_column | Remove one column by uuid. |
reorder_case_list_columns | Reorder columns by passing the desired uuid sequence. |
set_case_list_filter | Set or clear the optional filter predicate that narrows the list. |
add_search_inputs | Add one or more search inputs (simple property bind or advanced predicate) in one call. |
update_search_input | Replace a search input's body, addressed by the input's uuid. |
remove_search_input | Remove one search input by uuid. |
reorder_search_inputs | Reorder search inputs by passing the desired uuid sequence. |
Working on case search
Case search is the search experience that surrounds the case list — the screen title, helper text, and button labels the user sees, plus a few niche search-side filters most authors never reach for. These tools set those slots; the search inputs themselves live on the case list above. Each setting is independent — pass null on any slot to clear it.
| Tool | What it does |
|---|---|
set_case_search_display | Set the search-screen labels: title, subtitle, empty-list text, search and search-again button labels, and the predicate that decides when to show the search button. |
set_case_search_advanced | Set the advanced cluster: an expression naming owner ids whose cases are excluded from search results. |
Working on forms
CommCare has four form types: registration creates a new case, followup updates a case, close loads and closes a case, survey is standalone (no case).
| Tool | What it does |
|---|---|
create_form | Add a new form to a module together with its fields, in one call. |
update_form | Rename, change CommCare Connect config, set close condition or post-submit destination. |
remove_form | Delete a form. |
get_form | Show details for one form. |
Working on fields (questions)
A field is a single question on a form: text input, dropdown, date, number, repeat group, label, and so on. Most fields also save to a case property; some (on survey forms, or label-only fields) don't.
| Tool | What it does |
|---|---|
add_fields | Insert one or more fields in one call. Use beforeFieldId / afterFieldId to control position; omit both to append. |
edit_field | Change a field's properties: label, validation, visibility, choices, case wiring. |
remove_field | Delete a field. |
get_field | Show one field's properties. |
search_blueprint | Search across the whole app for a field id, case property, label, case type, XPath fragment, or module/form name. |
Working with media
You can attach images, audio, and video to parts of an app — a field's label or hint, a dropdown choice, a module or form menu tile, or the app logo. First upload the files, then attach them by their asset id. Every attach checks the asset before anything saves: it must be in your library, fully uploaded, and the right type for the slot (an audio file can't become a menu icon), and the app's total attached media must stay within the export limit. A bad id fails the call with a message saying what to fix, and nothing is saved.
| Tool | What it does |
|---|---|
upload_media_asset | Upload an image, audio, or video file (sent as base64) and get back its asset id. Audio must be .mp3 or .wav and video .mp4 — CommCare HQ can't accept .m4a or .ogg. |
list_media_assets | List your uploaded files and their asset ids — how your agent finds the ids the attach tools need. |
remove_media_asset | Delete a file from your library. Refuses if any live app still uses it. |
attach_field_media | Set or clear the image/audio/video on a field's label, hint, help, or validation message. |
attach_option_media | Set or clear the media on one choice of a dropdown (single- or multi-select). |
set_module_media | Set or clear a module's home-screen icon and audio label. |
set_form_media | Set or clear a form's menu icon and audio label. |
set_app_logo | Set or clear the app logo shown on the login and home screens. |
Exporting and uploading
| Tool | What it does |
|---|---|
compile_app | Compile to CommCare HQ format — the JSON shape HQ accepts (a zip bundling that JSON with the media files when your app has media), or a .ccz archive. |
get_hq_connection | Check whether you've added an HQ API key in Nova settings, and if so, which project spaces (domains) it can reach. |
upload_app_to_hq | Push the app to CommCare HQ as a new app. Pass domain to choose the target space when your key reaches several; returns the HQ app URL. |
HQ has no atomic update API, so every upload creates a new app on HQ. Your Nova copy doesn't change. To retire the previous HQ version, archive it on HQ.
Edits are checked as they happen, and exports are checked again at the door. A tool call that would break the app — a bad expression, a duplicate name, a reference to something that doesn't exist, or a piece left unfinished (an empty form, a case list with no columns) — fails with a message naming each problem, and nothing is saved. Structure always lands whole: create_form requires the form's fields, and create_module requires its forms, case-list columns, and (for a new case type) the case type's record, so a rejection is always fixable by adjusting the same call. compile_app and upload_app_to_hq refuse (invalid_input) while the app still has unresolved findings, listing each one.