Skip to content
AINOX App
Esc
↑↓navigate↵open⌘Jpreview
On this page

Build an app over MCP

The loop an MCP client follows to start a thread, wait for the agent, answer its questions, read the code, and publish the app.

Tools that start work return right away. The agent inside AINOX App keeps working in the background, and your client checks on it with get_thread. Every thread is in one of three states:

status Meaning What to do next
running The agent is still replying. Wait, then call get_thread again, or cancel with stop_run.
waiting The agent paused on a tool call that needs your answer. Read pendingToolCalls and answer with resolve_tool_call.
idle The reply is finished. Read it with list_messages, then send_message or publish.

The loop

Start a thread

Call create_thread with what to build, in plain language:

{ "prompt": "A one-page tip calculator with a dark theme" }

It returns the new threadId, and a url that opens the thread in the web app. You can watch the agent work there too.

Poll until the agent stops

Call get_thread every few seconds until status is no longer running. Building a first version often takes a minute or more.

Keep the interval at two seconds or longer. Each key allows 120 requests a minute, shared by everything using it.

Answer any questions

When status is waiting, pendingToolCalls lists what the agent is waiting on. Answer each call with resolve_tool_call, which resumes the run, then go back to polling. See Answering tool calls.

Read the reply and the code

Once status is idle, list_messages returns the conversation, with each message’s text and the names of the tools the agent called. Use list_files and read_file to read the project itself.

Ask for changes

Call send_message with a follow-up prompt and poll again. It refuses while the thread is running or waiting, so finish or stop the current turn first.

Publish

Call publish. The first publish needs a name, which becomes the thread’s title and, lowercased and hyphenated, the app’s subdomain:

{ "threadId": "…", "name": "tip-calc" }

It returns the deploymentId and the public url, but the build runs afterwards. Poll get_thread until deployment.status is completed. Publish again after later changes to update the same deployment; name is ignored from then on.

Answering tool calls

Each entry in pendingToolCalls has a runId and toolCallId to send back, a toolName, a kind, and an input.

Questions (kind: "answers")

The agent asks questions with its ask_user tool, often before it starts a new app or a major feature, so a new thread often stops at waiting before the agent writes any code. input.questions lists them, each with an id, a type, and the options to choose from. Answer with action: "answer" and an answers object keyed by question ID:

Question type Answer value
single_select One option’s label, as a string
multi_select An array of option labels
text The text of the answer
A question with required: false null to skip it
{
  "threadId": "…",
  "runId": "…",
  "toolCallId": "…",
  "action": "answer",
  "answers": { "palette": "Dark", "features": ["Split the bill", "Round up"] }
}

Labels must match an offered option exactly.

Approvals (kind: "approval")

None of the agent’s tools ask for approval today, since they run inside the thread’s own sandbox, but the server still supports the flow. For a tool that needs approval, input holds the command or arguments the agent wants to run. Send action: "approve", or action: "decline" with an optional reason the agent reads before it tries something else.

Deployment status

get_thread includes deployment once a thread has been published. Its status moves through these values:

status Meaning
cloning Unpacking the project’s files.
uploading Storing the source for the build.
waiting Queued for a build worker.
active Building.
completed Live at deployment.url.
failed The build failed. Ask the agent to fix it with send_message, then publish again.
unreachable The upload server did not answer. Try again shortly.

Don’t call publish again while a build is in progress.

Stopping a reply

stop_run cancels the reply in progress and returns stopped: false when nothing was running. A tool call the agent is waiting on stays pending, so a waiting thread still needs resolve_tool_call before it accepts new messages.

Was this page helpful?