> Documentation index: [/llms.txt](/llms.txt). Every page as one file: [/llms-full.txt](/llms-full.txt).

# Let an agent use an app

Let an agent use an app [#let-an-agent-use-an-app]

An agent reads and writes an app through tools the app serves over MCP. Today the app must be `public` and the connection carries the app's token in its URL; see [why](overview#why-some-paths-need-a-public-app).

Steps [#steps]

1. In the app's chat, ask App Builder for an MCP endpoint. Include the last three lines; each one avoids a known failure behind the app gateway:

   ```text
   Add an MCP server at /mcp with the official `mcp` Python SDK: FastMCP with
   stateless_http=True and json_response=True, mounted into the FastAPI app with its
   session manager lifespan running. Tools: report_finding(title, severity, summary, url)
   and list_findings(status=None).
   Accept the token from the `token` query parameter and compare it, in constant time,
   with the app secret RADAR_MCP_TOKEN.
   Construct FastMCP with TransportSecuritySettings(enable_dns_rebinding_protection=False).
   Read app secrets at request time from os.environ, falling back to
   /home/user/.alo/app_env.json.
   ```

   | Line                           | Why                                                                                  |
   | ------------------------------ | ------------------------------------------------------------------------------------ |
   | Token from the query parameter | The gateway does not pass `Authorization` to the app                                 |
   | DNS-rebinding protection off   | The MCP SDK otherwise answers `421 Invalid Host header` to calls through the gateway |
   | Secrets read at request time   | A newly set secret works without restarting the app                                  |

2. Set the token as an app secret: in the app's settings, or `PUT /api/v1/agents-v2/apps/{app_id}/secrets/{key}/` (key or bearer).

3. Set the app's visibility to **Public**: in the app's settings, or `PATCH /api/v1/agents-v2/apps/{app_id}/` with `{"visibility": "public"}` (key or bearer, owner only).

4. Add an MCP connection whose URL is the app's own address, its MCP path and the token, for example `https://<app_id>.<apps domain>/mcp/mcp?token=…`. **Open in new tab** on the app's card shows the app's own address. See [Connect MCP servers](../../connectors/mcp) for the fields.

5. Give the connection to the agent: in the agent's editor under **Connectors**, or `enabled_mcp_connection_ids` on the agent (key or bearer).

6. Ask the agent to use the app, for example `Report this as a high finding in Risk Radar.`

Approvals for write tools [#approvals-for-write-tools]

The agent asks the person before a tool that writes, if the tool says so: `readOnlyHint` `false` or `destructiveHint` `true` in its MCP annotations. A tool with no annotations runs without asking. Ask App Builder to annotate every tool that changes data.

Inside the app's own chats [#inside-the-apps-own-chats]

An agent in a chat started from the app, such as its App Builder chat, works in the app's sandbox. It can call the app directly there, even when the app is private.

Limits and security [#limits-and-security]

| Limit                                                                                                  | What to do                                                                                    |
| ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |
| The app must be `public`, so anyone with its link can open it                                          | Keep data that only some people may see out of the app, or check the token on read routes too |
| The token is in the URL, and URLs can end up in logs                                                   | Treat the connection URL as a secret                                                          |
| `GET /api/v1/mcp-connections/` returns the URL, token included, to everyone who can see the connection | Keep the connection `private`, the default                                                    |
| One shared token: anyone who can use the connection can read and write the app                         | Rotate it by changing the app secret and the connection URL                                   |
