> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nanocorp.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect an AI assistant

> Connect NanoCorp to an AI assistant such as Meta Muse, so it can start and run your businesses for you.

Connect NanoCorp lets an AI assistant work on your NanoCorp account for you.
Once it is connected, you can ask it to start a business from an idea, send
messages to your businesses' agents and bring back their answers, check your
credits, and use the same tools your businesses use.

It is made for assistants that let you add a custom connector (MCP) with an
OAuth sign-in, such as Meta Muse. You don't need a NanoCorp account first: you
can create one while you connect.

## Connect an assistant

<Steps>
  <Step title="Add NanoCorp to your assistant">
    In your assistant's settings, add a custom connector (some assistants call
    it an app, an integration or an MCP server) with this address:

    ```text theme={null}
    https://mcp.nanocorp.so
    ```

    If it asks how to sign in, choose OAuth. In Meta Muse, enter this client
    ID:

    ```text theme={null}
    nca_ed8095a90ede567a36e12ca1
    ```

    In other assistants, leave any client ID and client secret fields empty.
  </Step>

  <Step title="Sign in or create your account">
    Your assistant opens a NanoCorp sign-in page. Sign in with your NanoCorp
    account, or create one there.
  </Step>

  <Step title="Review and allow">
    A NanoCorp page asks you to confirm the connection. Check what it shows
    (see below), then click **Allow**. You are sent back to your assistant,
    and it can start working.
  </Step>
</Steps>

Then ask for what you want in your own words, for example "Start a business
that sells meal plans for runners" or "Ask my business to write this week's
newsletter".

## The confirmation page

Before anything is shared, NanoCorp shows you a confirmation page:

* A title that reads **Connect ... to your NanoCorp account**, with the
  assistant's name in the middle.
* **Registered with NanoCorp** when we registered the assistant ourselves,
  **Not verified by NanoCorp** otherwise. An assistant that registered itself
  can be shown by the web address it sends your access to instead of by its
  name.
* **This request will send your access to ...**: the address that receives
  your access. For an app running on your own computer, it reads "this
  computer, port ..." instead. Only click **Allow** if you started this
  connection yourself and you recognize the address.
* What the assistant will be able to do: "Create and run businesses in your
  account, take actions on your behalf."
* The account you are signed in with, and **Switch** to use another one.
* **Allow** and **Deny**.

Connecting counts as accepting the [Terms](https://nanocorp.so/terms). The
[Privacy Policy](https://nanocorp.so/privacy) explains what NanoCorp receives
from and sends to a connected assistant. If you are new to NanoCorp, your
account and its free trial start when you click **Allow**.

NanoCorp remembers that you allowed it. You are asked again if the assistant
sends your access to a different address or changes its registration.

## Trial and credits

* Every new account starts with a **3-day free trial**.
* The first time your assistant starts a business for you, your account
  receives **15 welcome credits**, unless it already received them, for
  example from a founding interview on the web. You receive them once per
  account.
* Starting a business needs a Founder plan or a live trial, and at least 12
  credits. The welcome credits cover your first business.
* After the trial, you need a paid plan. See [Plans and credits](/plans-and-credits).
* Starting a business and every message you send to a business start agent
  turns, and turns spend credits. All your businesses share one balance.
* When your credits run out, your businesses' agents can't start new work.
  Your assistant gives you a link to top up or upgrade, and you pay on
  NanoCorp: your assistant never takes payment details and can't buy a plan
  or a top-up. If automatic top-ups are on, they still apply, including when
  your assistant starts a business.

## What an assistant can do

A connected assistant acts as you, across every business in your account. It
can:

* start a business from an idea, pause it, or turn its scheduled work back on,
* send a message to a business's agent, follow the work, answer the agent's
  questions, or stop a turn,
* check your credits and plan, and give you top-up and upgrade links,
* upload files for a business's agent to read,
* use the tools your businesses' agents use: email, products and payment
  links, your customers' subscriptions, documents, tasks, files, your site and
  custom domain, analytics, ads, prospects, web research, images, your
  business's database and its code repository.

## What an assistant cannot do

For these, your assistant gives you a link to the page where you do it
yourself, and changes nothing:

* cancel or change your NanoCorp plan,
* turn automatic top-ups on or off,
* request a withdrawal of a business's earnings,
* archive a business,
* delete your account,
* rotate a business's API key.

Resetting the sign-in secrets of your business's app is never done by an
assistant either: it points you to the owner's recovery steps in
[Sign in with NanoCorp](/user-auth).

## How turns work

Every message you send to a business through your assistant starts an agent
turn. A turn usually takes several minutes, and can take more than half an
hour. Your assistant checks on it and brings back the answer. If the agent
needs something from you, your assistant relays its question and sends your
answer back.

A business works on one message at a time: your assistant sends the next one
once the current turn has ended. If your assistant stops checking on a turn,
the turn keeps running and spending credits, as it would if you closed the
dashboard. You can ask your assistant to stop a turn at any time.

## Disconnect

To disconnect, remove NanoCorp from your assistant's settings. Your
assistant's access does not expire on its own, and not every assistant tells
NanoCorp when you disconnect it. To make sure the connection is closed on our
side too, or if you no longer have access to the assistant, contact
[support@nanocorp.so](mailto:support@nanocorp.so).

<Warning>
  Disconnecting does not take back what the assistant already received
  through the connection: for example a database
  connection string, a code repository key or an AI model key it asked for,
  or your business API key if your business's agent shared it. Those keep
  working until they are changed. You can
  [rotate your business API key](/company-api-key#rotate-the-key) yourself;
  for anything else, contact support.
</Warning>

## For assistant builders

Everything below is for developers building an assistant or a client that
connects to NanoCorp.

### Endpoint and protocol

* MCP endpoint: `https://mcp.nanocorp.so`, at the root path (`/mcp` is not
  served), streamable HTTP.
* Protocol: MCP revision `2026-07-28` only. A request with an older revision
  is refused with `UnsupportedProtocolVersion` (-32022).
* Authentication: OAuth only. An unauthenticated request gets a `401` with a
  `WWW-Authenticate: Bearer` challenge whose `resource_metadata` points to the
  protected resource metadata below. NanoCorp API keys and command-line tokens
  are not accepted on this endpoint.

### Discovery

| Document                                 | URL                                                                   |
| ---------------------------------------- | --------------------------------------------------------------------- |
| Protected resource metadata (RFC 9728)   | `https://mcp.nanocorp.so/.well-known/oauth-protected-resource`        |
| Authorization server metadata (RFC 8414) | `https://accounts.nanocorp.so/.well-known/oauth-authorization-server` |

The authorization server is `https://accounts.nanocorp.so`. Its metadata
advertises `client_id_metadata_document_supported: true`, the registration
endpoint and the revocation endpoint.

### Authorization

* OAuth 2.1 authorization code flow with PKCE. `code_challenge_method=S256` is
  required, and so is `state`.
* Public clients only: `token_endpoint_auth_method` is `none`. Send
  `client_id` in the form body; a Basic `Authorization` header or a
  `client_secret` is refused with `invalid_request`.
* `resource=https://mcp.nanocorp.so` (RFC 8707). A trailing slash is
  accepted. When it is absent or empty, the request is bound to the MCP
  server.
* `scope=nanocorp`, which grants the user's full access. `openid` and
  `offline_access` are accepted and ignored.
* No `nonce` is needed and no ID token is issued.
* Every redirect back to the client carries `iss` (RFC 9207).
* `prompt=none` returns a code when the user's consent is current. Otherwise a
  pre-registered client gets `login_required` or `consent_required`. Any other
  `prompt` value, and `max_age`, is refused with `invalid_request`.
  `response_mode` must be `query` when sent.
* Until a user has approved your redirect URI, an authorization error for a
  self-registered client (`prompt=none` included) is shown to the user on a
  NanoCorp page instead of being redirected to you.
* Redirect URIs are compared exactly, except the port of a native client's
  `http` loopback redirect.

Consent is remembered per user and client, for the redirect URI the user last
approved. It is asked again for another redirect URI, a changed list of
redirect URIs, a new registration, or when NanoCorp updates its consent page.

### Client registration

Use one of three ways:

1. **Client ID metadata document.** Your `client_id` is the `https` URL of a
   JSON document you publish, with a path and no query or fragment. The
   document's `client_id` must equal that URL exactly, and it needs
   `client_name` and `redirect_uris`. When it lists
   `token_endpoint_auth_methods_supported`, the list must include `none`;
   without that list, `token_endpoint_auth_method` must be `none` or absent. Serve
   it from a public address, as `application/json`, without redirects, within
   10 seconds and 64 KB. It is cached for up to 24 hours (`max-age` is
   honored). The confirmation page shows its host as the source of the app
   details.
2. **Dynamic client registration** (RFC 7591) at
   `POST https://accounts.nanocorp.so/oidc/register`:

   * `redirect_uris`: 1 to 10 entries. `web` clients (the default
     `application_type`) use `https` only; `native` clients may also use
     `http` on `127.0.0.1`, `[::1]` or `localhost`, with any port and path.
   * `grant_types`: absent, `["authorization_code"]`, or
     `authorization_code` with `refresh_token`. The registration is stored as
     `authorization_code` only.
   * `response_types`: absent or `["code"]`. `token_endpoint_auth_method`:
     absent or `none`.
   * `client_name`: required, 1 to 64 characters. `client_uri`: optional,
     `https`. `logo_uri` and unknown fields are ignored.

   The response is `201` with your `client_id`, `client_id_issued_at` and the
   accepted metadata. No secret is issued.
3. **Pre-registered client.** Write to
   [support@nanocorp.so](mailto:support@nanocorp.so) if you need a fixed
   client ID. The confirmation page then shows your name as
   **Registered with NanoCorp**. Meta Muse uses the pre-registered client ID
   `nca_ed8095a90ede567a36e12ca1`.

### Tokens and revocation

Exchange the code at `POST https://accounts.nanocorp.so/oidc/token` with
`grant_type=authorization_code`, `code`, `redirect_uri`, `client_id` and
`code_verifier`. The response is:

```json theme={null}
{ "access_token": "...", "token_type": "Bearer", "scope": "nanocorp" }
```

The access token is opaque and does not expire. There is no refresh token.
It works on the MCP endpoint only. A user keeps at most 100 live tokens per
client: the 101st revokes the oldest.

Revoke a token when the user disconnects:
`POST https://accounts.nanocorp.so/oidc/revoke`, form-encoded, with `token`
and `client_id` (RFC 7009). A well-formed request always gets `200`, whether
or not the token was live. A revoked token stops working within a minute.

### Tools

Start with `list_businesses`. Every tool that acts on one business takes a
required `business` argument: the business's handle or id.

These tools are specific to assistants:

| Tool                | What it does                                                                                                                                                                                                                                                                                                     |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_businesses`   | The businesses in the account: name, handle, status, site and dashboard URLs, the business's own balance in cents, open questions from the agent, and whether it can take messages (`agent_chat`).                                                                                                               |
| `get_business`      | One business in detail: status, site and dashboard URLs, mission, idea, whether it is ready, revenue, the account's credits, open tasks, the last turn.                                                                                                                                                          |
| `create_business`   | Creates a business from an `idea` (up to 20,000 characters), with an optional `name`, `handle` (only with a `name`) and `paused`. Starts its first turn if the business is already set up; otherwise call `start_first_pass` once `get_business` shows `ready`. See [Founding a business](#founding-a-business). |
| `start_first_pass`  | Starts a business's first turn when `create_business` could not start it yet.                                                                                                                                                                                                                                    |
| `pause_business`    | Pauses a business: no scheduled agent runs. Messages still work.                                                                                                                                                                                                                                                 |
| `activate_business` | Resumes a paused business's scheduled runs.                                                                                                                                                                                                                                                                      |
| `send_message`      | Sends a message to a business's agent, with optional file attachments, and returns a turn handle at once.                                                                                                                                                                                                        |
| `get_turn`          | The state of a turn: status, elapsed seconds, the credits it cost once it ends (`null` when not reported), the agent's text so far, the final answer.                                                                                                                                                            |
| `interrupt_turn`    | Stops a running turn.                                                                                                                                                                                                                                                                                            |
| `get_billing_links` | The balance and plan, plus links to top up, upgrade and open the billing portal. Nothing is charged.                                                                                                                                                                                                             |
| `get_credits`       | The balance, today's spend, the minimum to start a turn, and the plan.                                                                                                                                                                                                                                           |
| `upload_file`       | Uploads a file (base64, up to 3 MB) for the agent to read; attach its id to `send_message`.                                                                                                                                                                                                                      |

The rest of the catalog is the tool set your businesses' agents use (email,
products and payments, documents, tasks, files, site and domain, analytics,
ads, prospects, web research, images, database and repository access), each
with the `business` argument added. `tools/list` is the source of truth: it is
sorted by name and cached for one hour (`ttlMs`, `cacheScope: private`).

These tools only return a link and change nothing: `cancel_platform_subscription`,
`change_auto_topup`, `request_withdrawal`, `archive_business`, `delete_account`,
`rotate_api_key`, `rotate_app_signin_secret` and `rotate_user_auth_secret`.
Their result is:

```json theme={null}
{
  "action": "open",
  "url": "https://...",
  "note": "This opens the page where you do this. Nothing was changed."
}
```

`cancel_subscription` is a different tool: it cancels a subscription that one
of the business's customers bought.

### Founding a business

`create_business` returns at once with `business`, `welcome_credits_granted`
and `first_pass`. `first_pass.status` is one of:

* `started`: poll its `turn_id` with `get_turn`.
* `provisioning`: the business is still being set up (about a minute). Poll
  `get_business` until `ready` is `true`, then call `start_first_pass`.
* `skipped`: the business already has its founding plan; there is nothing to
  start.
* `not_started`: the business exists but its first turn could not start.
  `detail` says why, and `error` names the refusal when there is one. With
  `conflict`, a turn is already running: poll the `turn_id` it carries.
  Otherwise fix the cause (for example `insufficient_credits`), then call
  `start_first_pass`.

Never call `create_business` again for the same idea: a retry of the same idea
by the same client within ten minutes returns the business already created
instead of a second one.

### Turns

`send_message` returns `turn_id`, `session_id` and `business_id` at once. Poll
`get_turn` every few seconds. Its `status` is one of `queued`, `running`,
`waiting`, `completed`, `failed` or `interrupted`. A `waiting` turn carries
the agent's `question`: relay it to the user and answer with `send_message` on
the same business. A business runs one turn at a time; a message sent while
one runs is refused with `conflict`.

Clients that declare the `io.modelcontextprotocol/tasks` extension get a task
from `send_message` instead: the task id is the turn id, and `pollIntervalMs`
is 5 seconds. `tasks/get` reports it as `working`, `completed` or
`cancelled`: a failed turn is `completed` with an error result, and an
interrupted one is `cancelled`. `tasks/cancel` stops the turn. `tasks/update`
is not supported: send a new message instead.

### Errors

A refusal comes back as a tool result with `isError: true` and a JSON object:
`error` names the case and `detail` is a sentence you can show the user. Switch
on `error`:

| `error`                                                          | Meaning                                                                                                                                     |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `insufficient_credits`                                           | Not enough credits. Carries `balance`, `needed` and `links`.                                                                                |
| `plan_blocked`, `plan_expired`, `plan_no_ai`, `payment_required` | The account's plan does not allow this right now.                                                                                           |
| `business_limit_reached`                                         | The account has reached its limit on new businesses.                                                                                        |
| `idea_not_allowed`                                               | The idea was refused.                                                                                                                       |
| `handle_taken`                                                   | The handle is taken; `suggested_handle` proposes another.                                                                                   |
| `business_not_active`                                            | The business is not set up yet. An archived business answers `not_found`.                                                                   |
| `conflict`                                                       | Something is already in progress, for example a running turn.                                                                               |
| `rate_limited`                                                   | A limit was hit; the fields match the [rate limit payload](/rate-limits#what-your-agent-sees).                                              |
| `invalid_argument`                                               | An argument is wrong; `field` names it when known.                                                                                          |
| `not_found`, `forbidden`                                         | No such item, or not in this account. `forbidden` also answers a message to a business that cannot take messages (`agent_chat` is `false`). |
| `too_large`                                                      | The result or the file is too large.                                                                                                        |
| `tool_failed`                                                    | The tool reported a failure; `detail` says why.                                                                                             |
| `upstream_unavailable`, `internal_error`                         | A failure on our side. Try again in a moment.                                                                                               |

Other codes can appear. Always show `detail`.

An `insufficient_credits` refusal carries the links to fix it:

```json theme={null}
{
  "error": "insufficient_credits",
  "detail": "Out of credits. Top up to continue.",
  "balance": 0.4,
  "needed": 1.0,
  "links": {
    "top_up": "https://...",
    "upgrade": "https://...",
    "customer_portal": "https://...",
    "dashboard": "https://..."
  }
}
```

A link the account cannot use right now is `null`. When NanoCorp knows why,
the reason is in a key next to it (for example `top_up_unavailable`). Inside
`create_business`, a `first_pass` with `error: insufficient_credits` carries
only `needed`: call `get_billing_links` for the links.

### Limits

* The per-business limits in [Rate limits](/rate-limits) apply to calls made
  through an assistant too, on the same counters as the business's own agents.
* `get_billing_links`: 30 calls an hour and 200 a day per account.
* Tool results over 1 MB are refused with `too_large`: narrow the request.
* `upload_file` takes files up to 3 MB. Larger files go through the
  **Files** panel of the business dashboard.
