# From start to finish

The order of what you can do with this server, with the tools used at each step.

## 1. Find out where you are

`whoami` tells you whose token this is and whether it can only read or can also write.
`list_projects` gives the projects, each one's address, and the identifier (ref) to pass to every other tool.

If there is no project, create one with `create_project`. A database, auth and file storage come with it.

**The region is chosen once, at creation, and cannot be changed later.** Check where you can create with `list_regions` first.
Leave it empty and the project is created in the default region. **Pricing is the same in every region**, so the customer can simply pick the closest.

A region where `can_create` in `list_regions` is false has its prices set but no machines, or nowhere for a database, yet.
Trying to create a project there is refused. Leave a request with `request_region` instead.
**Someone will contact you directly.** Say what you plan to put where, and that is what gets read first.
No date is promised. If you need something in the meantime, create the project in an open region; later
it has to be created anew, not moved.
`list_server_sizes` gives each server size's monthly price per region (with no currency, the organisation's billing currency). It only reads.

## 2. Find out what is there now

`list_tables` gives the tables, each table's columns, a rough row count, and **whether access rules are on and how many rules there are**.
A table with zero rules shows nothing to the publishable key. Look for tables where this number is zero first.

`list_users` returns the **sign-ups of the service** that uses the project.
They are completely separate from platform accounts (you), and the two never mix.
They don't all come at once. `total` is the full count; if `has_more` is true, raise `offset` and call again.
**Using the length of `users` as the head count is wrong.** A person sees the scroll bar stop; you don't.

`list_buckets` is file storage, `usage` is this month's usage.

Right after a project is created, its database may not exist yet. It usually takes a few seconds.
Meanwhile other tools refuse with "still being created". Wait and call again.
If you get "could not be created", try again with `retry_provisioning`.
**Either way, don't create a new project.** Keep preparing the same project; a new one only doubles the bill.

Pause a project you aren't using with `pause_project` and turn it back on with `resume_project`. While paused, the site, API and functions answer 503
(`project_paused`) and scheduled jobs don't run, but the data stays as it is.
A project the Free plan paused after 3 unused days is turned back on the same way, with `resume_project` (or a new deployment).
When a database has been unusable for 90 days (a failed payment, the Free plan, a pause), it is taken off the server and moved to archive storage.
`archive_at` in `list_projects` is when it moves, and `get_project_archive` gives the reason and the dates. Mail goes out 30, 7 and 1 day before.
For a year after the move, `restore_project_archive` restores it as it was (the payment or plan issue has to be resolved first), and `create_archive_download_url` downloads the archive.
Meanwhile the other tools refuse with "in archive storage", and the API answers 503 (`project_archived`). After a year the archive and the files are deleted.
To use an ORM or a migration tool (Prisma, Drizzle, psql), get the address with `get_database_connection` and
create a password with `reset_database_password` (shown only once). 5432 is the session pooler and 6543 the transaction pooler, and both accept TLS only.
If the deployed app reads `DATABASE_URL`, make it with `keep_for_deploys: true`. The password is then kept sealed, and production servers, middleware and functions get `DATABASE_URL` (6543), `POSTGRES_URL` (6543) and `DIRECT_URL` (5432) at runtime. Builds never get them. Your deployed code can then read every row without row level security, so turn it on only when the user wants it. A new password made without the option stops the handover, and running production servers get the new value when they restart or are redeployed.
Backups are made automatically every night between 03:00 and 05:00 in the project region's local time (`list_backups`). Before a migration or a bulk delete, make one yourself with `create_backup`.
`restore_backup` returns tables, sign-ups and files to that point, and backs up the current state first, so a wrong restore can be restored again.
`delete_project` deletes the data **permanently**. Call it only when the user has clearly asked, with the project name in `confirm`.

## 3. Build

Tables with `run_sql`, rules with `run_sql` too, and check with `read_rows` or `query_sql`.
`query_sql` runs a single query in a read-only transaction, so a read token can call it and it cannot change any data. It does not open Vault secrets.
A read token gets deploy hook addresses hidden (`list_deploy_hooks`; `secret_hidden`). The signing keys of database webhooks, log drains and notification channels are shown once, at creation, whatever the token; lists show only the last four characters (`signing_secret_last4`).
Buckets with `create_bucket`, test sign-ups with `add_user`.
The address and keys to put in the app come from `get_project_keys`. Frontend code gets only the address and publishable key from `only: "publishable"`.

## Options on the connection address

Options added after this connection's address narrow the tools it shows and what it can do. The server enforces them, so a tool missing from the list is refused even when called by name. `whoami` says which are in effect, in `bound`, `read_only` and `features`.

- `?project_ref=<ref>`: holds the connection to one project. A tool called without `ref` uses it, and any other ref is refused. `list_projects` shows this project only, and tools that reach other projects or the whole organisation (`create_project`, the team, notification channels, the audit log, billing) are left out.
- `?read_only=true`: only tools that change nothing. The whole connection acts as a read token.
- `?features=database,deploy`: only the groups of tools named (`whoami` and `list_projects` are always there). Groups: account, database, auth, storage, functions, deploy, domains, branching, logs, billing, ai, realtime, queues, gpu.
- `?lang=ko|en|ja`: the language of the tool descriptions and errors. English when nothing is asked.

For example `https://<address>/mcp?project_ref=<ref>&read_only=true` is a connection that can only read that project. If the user wants more than it allows, ask them to connect again with different options.

## What happens when the order is wrong

Create a table without creating rules and you get an empty array back with no error.
This one thing is most of the problems people run into on this platform. Read blackwall://access-rules.

---

https://end.blackall.ai/docs/start?lang=en
