Your app's MCP
Every Amba app has its own MCP endpoint whose tools are the app's collections and deployed functions — typed list/get/find/insert/update/delete/aggregate per collection, typed invocation per function, behind an explicit exposure allowlist you control.
The MCP server at mcp.amba.dev exposes Amba's own platform tools — the ones an agent uses to provision a backend. Your app gets a second MCP surface whose tools are your app's own collections and deployed functions, projected into typed tools.
Expose a recipes collection and your app's MCP endpoint gains recipes_list, recipes_get, recipes_find, recipes_insert, recipes_update, recipes_delete, and recipes_aggregate — no tool code to write. The find tool carries a typed, per-column where schema, so an agent queries your data without hand-writing any query strings. Expose a deployed function and it becomes a callable tool too — typed, when the function declares its input schema.
Expose, then connect
Nothing is exposed by default. The agent surface is an explicit allowlist: a collection or function only becomes a tool after you opt it in. That keeps an internal audit_log collection from ever appearing to an in-app agent just because it exists.
The lists are full-set replacements per kind: send the complete set you want exposed; an empty array hides everything of that kind.
Then point your MCP client at your app's endpoint:
Your project id is shown in the console and returned by amba_developer_signup. The same Bearer token the platform MCP uses works here.
Live generation. Tools are generated from your exposed collections at connect time. Alter a collection, change the allowlist, or redeploy a function and the next
tools/listreflects it — no redeploy of anything else, no manual registration.
What you get per collection
For every exposed collection, your app's MCP exposes:
| Tool | What it does |
|---|---|
<collection>_list | Page through rows, newest first. Returns a next_cursor. |
<collection>_get | Fetch one row by id. |
<collection>_find | Query with a typed, per-column where filter. |
<collection>_insert | Insert a row — only your writable columns are accepted. |
<collection>_update | Merge-patch a row by id. |
<collection>_delete | Soft-delete (or hard: true to remove — developer scope only). |
<collection>_aggregate | count / sum / avg / min / max, optionally grouped. |
<collection>_find_nearest | Vector similarity search — appears automatically when the collection has a vector column (end-user scope). |
Two meta tools come along for discovery: <app>_list_collections (the index of exposed collections/functions and their tools) and <app>_whoami (which app + scope you're connected to).
Typed inputs, generated descriptions
Inputs are derived from your live schema. Server-managed columns (id, created_at, updated_at, and friends) are stamped automatically and never appear as input. A text column becomes a string field; an integer column a whole number; an array column an array — and each find filter exposes the operators that make sense for the type (eq, gt, in, like, contains, …):
Every tool ships an SDK-grade description generated from your columns, so an agent never needs to leave the chat to figure out the shape.
Functions as tools
An exposed deployed function appears as <app>_fn_<name> on the end-user scope and invokes through the same execution path (and URL) every other caller uses — same credentials, same rate limits, same identity headers.
Declare the function's input shape at deploy time and the tool is fully typed:
The supported schema subset is type: "object" with string / number / integer / boolean / array / object properties, enum, and required — anything outside it is rejected at deploy time rather than silently ignored. A function without a declared schema still works as a tool: it gets a generic { body?, query? } input and a description that says so honestly. Promoting an old version restores the annotation that shipped with it.
A round-trip an agent can do
- Provision a
recipescollection through the platform MCP (amba_collections_create). - Expose it:
amba_app_mcp_set_exposurewithcollections: ["recipes"]. - Connect to
https://mcp.amba.dev/app/<project-id>/mcp. recipes_inserta row, thenrecipes_findit back — typed, end to end.
That's the wedge: the moment you model your data, one exposure call makes it a typed agent tool surface.
Pagination that just works
list and find default to created_at desc ordering and return a next_cursor from the very first page — pass it back as cursor for the next one. An agent paginates a large collection without ever reading docs.
Two scopes
The same endpoint serves two credential modes:
- Developer scope —
Authorization: Bearer <developer token>. Operates across all rows (no per-user scoping). This is the building agent's mode: seed data, inspect state, migrate content. (Function tools live on the end-user scope only — function execution authenticates with client keys.) - End-user scope —
X-Api-Key: <client key>plusAuthorization: Bearer <end-user session token>. Tools execute through the same enforcement path as the client SDK: reads and writes honor each collection's access policy (ownerreads return only the signed-in user's rows;publicreads return everything), and ownership is stamped from the session. This is the in-app assistant's mode — an agent acting for one signed-in user can only ever see and touch what that user could.
There is no policy bypass: the MCP layer never compiles a query — every call proxies to the same routes the SDK uses, so a policy you set once holds everywhere.
Configuration
GET/PATCH /v1/admin/projects/<project-id>/app-mcp/config (or amba_app_mcp_get_config / amba_app_mcp_update_config) controls the surface:
enabled— kill switch for the whole agent surface (default on; the allowlist already defaults everything to hidden).auth_mode— which credentials may connect:all(default),client_only(only your app's client keys + end-user sessions — the developer mode is rejected), ordeveloper_only.slug— reserve a friendly hostname label for your agent surface (lowercase DNS label, globally unique).
Hostname
Setting a slug reserves https://<slug>.mcp.amba.host/mcp for your app. Hostname availability is rolling out — until it activates for your account, use the path-addressed endpoint above (connection.url in the config response); both addresses serve the same surface, with the same auth and the same allowlist, so nothing about your setup changes when the hostname goes live.
Metering
Tool calls against your app's MCP are metered as agent tool calls — a usage axis you can watch alongside MAU, events, and storage in amba_billing_status, amba billing status, and the console's billing page. Successful calls count; failed calls don't.