= Agent-native apps :nav-title: Agent-native apps :description: An app with two interfaces: screens for people and MCP for AI agents, on one backend with one set of permissions. How Ulabase makes it, and how an assistant helps you build it. :keywords: agent-native app, AI-native app, agent interface, MCP for apps, AI agents and permissions, build an app with AI :group: Start :order: 15 An agent-native app has two interfaces. People use its **UI**, the screens. AI agents such as Claude or ChatGPT use its **agent interface**, the xref:mcp.adoc[MCP server]. Both reach the same data, through the same backend, with the same permissions. Every Ulabase service has both from the start. You write the screens; the agent interface is already there. == Two interfaces, one backend A yoga studio takes bookings. * A **member** opens the app and books Tuesday's class. * Another member asks Claude: _"Book me on Tuesday's class at the studio."_ Claude signs in to the studio's service as that member and makes the booking. * The **owner** asks their own agent: _"How many bookings this week, by class?"_ Three ways in, and one rule decides what each of them may do: the permission you wrote for the `bookings` collection. == One permission for both A permission decides on the user and the user's roles, whichever interface the request comes through. An agent always works as a user: it signs in as that user, or uses an xref:api-keys.adoc[API key] the user issued with the roles you allowed. This permission lets members book and see only their own bookings, from the app and from an agent alike: [source,json] ---- { "_id": "membersBook", "roles": ["member"], "predicate": "path-prefix('/bookings')", "priority": 100, "mongo": { "readFilter": { "owner": "@user._id" }, "writeFilter": { "owner": "@user._id" }, "mergeRequest": { "owner": "@user._id" } } } ---- A member's agent reads the member's bookings and no others. The rule lives in one place, on the xref:managing-permissions.adoc[Permissions] page, and covers agents with no extra line. == The core APIs, for both Each service has the APIs an app needs: accounts and teams, data with its rules, payments, email and live updates, listed in xref:overview.adoc[What Ulabase is]. The screens call them through the xref:kit.adoc[Ulabase Kit]. An agent finds the ones you publish in the MCP catalogue. == Built with an assistant You can build an agent-native app with an AI assistant writing the code. Three things keep it on track: * **The documentation, as an MCP server.** Add `https://d0c5a1.ulabase.app/mcp` to Claude Code, Cursor or ChatGPT. The assistant reads these pages while it works, so the calls it writes match the real API. * **Your service's MCP server.** With a role you give it, the assistant creates collections and indexes and reads the data. * **The xref:cli.adoc[ulabase CLI].** The assistant writes the service's configuration as a setup file in your repository and applies it with `ulabase setup`. The configuration sits in git next to the app, and a second run changes only what is not already so. [source,bash] ---- claude mcp add --transport http ulabase-docs https://d0c5a1.ulabase.app/mcp ---- The starters, a React, Angular, Vue or ecommerce app that already signs users in, give the assistant a working app to start from. See xref:getting-started.adoc[Getting started]. == Where to go next * xref:mcp.adoc[MCP server]: publish collections and aggregations, and connect an agent. * xref:managing-permissions.adoc[Permissions]: the rules both interfaces follow. * xref:api-keys.adoc[API keys]: how a user gives an agent access, with the roles you allow. * xref:kit.adoc[Ulabase Kit] and xref:cli.adoc[ulabase CLI]: the screens and the configuration.