# Home Source: /docs OrbitOrca runs your web app from a GitHub repository or a zip upload and gives it a public URL, environment variables, logs and analytics from one dashboard. Billing, customer accounts and the other business features plug into the same app without you operating the services behind them. A coding agent can drive all of it through the OrbitOrca MCP server, using a token you control. **[Deploy your first app](/docs/getting-started/deploy-from-github)** From a GitHub repository to a running URL in a few minutes. **[Connect your coding agent](/docs/mcp/overview)** Give Claude Code, Cursor or another agent a token and let it deploy for you. **[Features](/docs/features)** Subdomains, environment variables, logs, analytics, payments. **[Tool reference](/docs/mcp/tools)** Every MCP tool, what it does and what it takes. # Support Source: /docs/support Most problems on the deploy path have a fix on the [troubleshooting](/docs/troubleshooting) page. When that does not cover it, here is how to reach us. ## Where to reach us [#where-to-reach-us] * **Discord** — the fastest channel. * **Email** — `hello@orbitorca.com`. * **The in-app assistant** — ask it about your apps, deploys, or anything else from the dashboard. [Join the Discord](https://discord.gg/PxNHPHDQb) ## What to include [#what-to-include] Give us enough to reproduce the problem without a back-and-forth: * **The app ID** — open the app and use **Copy app ID**. * **What you did and what happened** — the step you were on and the exact message you saw. Quote it. * **When** — roughly when it happened, so we can find it in the logs. * **For a failed deploy** — which step it failed at (build, scan, deploy) and the build log if you have it. * **For a custom domain** — the domain and the DNS record you added. # Troubleshooting Source: /docs/troubleshooting If you hit a message that is not here, or a fix does not work, see [support](/docs/support). ## Importing [#importing] * **"Connect GitHub before importing a private repository."** — Click **Connect GitHub** on the GitHub tab first. * **"GitHub installation not found. Reconnect your account."** — Access to the GitHub App was removed. Reconnect from the GitHub tab. * **"GitHub is temporarily unavailable. Try again shortly."** — A GitHub outage. Retry in a few minutes. * **"No repositories found."** — The GitHub App has access to no repositories. Click **Add repositories** and grant it access on GitHub. * **"File exceeds the 100 MB limit."** — Trim the ZIP; exclude `node_modules`, `.git` and build output. * **"The uploaded file is not a valid ZIP archive."** — Re-create it as a real ZIP and upload again. * **"Import expired or not found. Upload the ZIP again."** — Upload links are short-lived. Re-upload. ## Naming and address [#naming-and-address] * **"App name is required." / "App name must be at most 100 characters."** — Fix the name. * **"Enter a valid repository URL"** — Use a full repository URL, like `https://github.com/org/repo`. * **"This subdomain is already taken." / "This subdomain is reserved."** — Pick another subdomain. ## Readiness scan [#readiness-scan] * **"The readiness scan found a problem that blocks this deploy. Open the scan to see what it found, fix it, then deploy again."** — Work the [fix loop](/docs/concepts/readiness-and-fixes): apply the fix prompt, push or re-upload, re-scan. * **"Our check could not run" / "Scan failed. Please try again."** — A problem on the platform side. Re-scan in a few minutes; if it persists, contact support. * **"Checked earlier code"** — Your source changed since the scan. Re-scan so the result matches what would go live. ## Deploying [#deploying] * **"Run a readiness scan before deploying"** — Deploy is disabled until a scan has run. Run it. * **"Fix scan findings before deploying"** — The last scan blocked. Clear it, then deploy. * **"Blocked by the security scan: `{reason}`. Run the readiness scan to see what it found, fix it, and deploy again."** — The build-time security gate refused the source. Open the scan, fix what it names, deploy again. * **"A deploy is already running. Wait for it to finish, then try again."** — One pipeline runs at a time. * **"An operation is in progress — wait for it to finish"** — Another change is mid-flight. Wait, then retry. * **"This app isn't ZIP-based — update its repository instead."** — This app came from GitHub. Push to its branch instead of uploading a ZIP. * **Deploy failed, with "This may be caused by dedicated database provisioning failing. Contact support if it persists."** — Retry once; if it keeps failing, contact support. ## Branches (GitHub apps) [#branches-github-apps] * **"That branch is not in the repository any more. Pick one from the list."** — The branch was deleted or renamed. Choose a current one. * **"This app was uploaded as a file, so there is no repository to pick a branch from."** — Branch settings do not apply to ZIP apps. ## Environment variables [#environment-variables] * **"Key must start with A–Z or \_ and contain only uppercase letters, numbers, and underscores."** — Rename the key. * **"This key is reserved by the platform (e.g. PORT, DATABASE*URL, META*\*)."** — Pick another name; that key is injected for you. * **"Value is required."** — Enter a value. ## Custom domains [#custom-domains] * **"That doesn't look like a valid domain."** — Enter a full domain, like `shop.example.com`. * **"This domain is already connected to an app."** — It is used elsewhere on the platform. * **"This domain doesn't point at our gateway yet. Update its A-record and try again."** — Add or fix the DNS record, wait for it to propagate, then **Check now**. * **"That's one of our subdomains, so use the subdomain field instead."** — Use the subdomain field. ## Running app [#running-app] * **"App isn't running — deploy it to see its logs."** — Deploy the app first. * **"Couldn't load logs. Try refreshing."** — A transient read error. Refresh. * **"This app was stopped by an admin and can't be restarted. Contact support."** — An administrator suspended it. Reach support. * **"This action isn't available right now — the app may be mid-deploy."** — Wait for the running operation, then retry. ## Database [#database] * **"This app has no database yet. Add one in Settings, then deploy."** — Turn on the database in **Settings** and deploy. * **"This app already has a database, so it can't be taken away. Delete the app if you want its data gone."** — A database, once attached, stays with the app. * **"A database change is still finishing. Try again in a moment."** — Wait for the change to complete. # Apps, builds and deploys Source: /docs/concepts/apps-builds-deploys Three words show up all over the dashboard. Knowing them makes the rest of the docs clear. ## The three things [#the-three-things] * **App** — the record you create when you import a repository or a ZIP. It has a name, a subdomain, settings, and optionally a database. Creating an app builds and runs nothing on its own. * **Build** — turning your source into a runnable image. Each build scans the source, builds the image, and pushes it. Builds have their own history. * **Deploy** — taking a built image and making it live at your app's URL, replacing whatever ran before. Pressing **DEPLOY** runs a build and then a deploy as one pipeline. ## The deploy pipeline [#the-deploy-pipeline] A run moves through these stages, shown live: `QUEUED` → `BUILDING` → `SCANNING` → `PUSHING` → `BUILT` → `PROVISIONING DB` → `DEPLOYING` → `LIVE` `PROVISIONING DB` only appears on the first deploy of an app that has a database. If a run stops early it shows `FAILED`, or **Blocked by scan** when the security scan refused it. While going live you also see rollout stages: **Placing your app**, **Downloading image**, **Starting your app**, **Connecting your domain**. Delivery status on the app summarises where you stand: **Not deployed**, **Up to date**, **Changes pending**, or **Deploy failed**. ## App states [#app-states] The lifecycle label on an app is one of: * **pending** — created, not yet deployed. * **live** — running and serving its URL. * **stopped** — you stopped it; the URL stops serving. Its data and settings are kept, and you can restart it. * **grace** — a short holding state during platform housekeeping. * **suspended** — stopped by an administrator. You cannot restart it yourself; contact support. * **deleted** — removed. This frees the subdomain and cannot be undone. ## Stopped versus deleted [#stopped-versus-deleted] **Stopped** takes the app off the web but keeps everything — restart it any time from **Actions**. **Delete** is permanent: it removes the app, its data, and frees the subdomain. Deleting asks you to type the app name to confirm. ## Restart versus redeploy [#restart-versus-redeploy] * **Restart** runs the same image again — use it to clear a stuck process. It does not rebuild. * **Deploy** (redeploy) builds your current source into a new image and ships it — use it after you change code or [environment variables that need a rebuild](/docs/concepts/environment-variables). See [logs and status](/docs/concepts/logs-and-status) for reading what a running app is doing. # Deploying an app that's already live Source: /docs/concepts/database-migrations Before an app's first readiness check and deploy, the platform asks one question: **is this app already running somewhere, with real users or data?** This page explains why, and what each answer means. ## The question [#the-question] > Is this app already running somewhere, with real users or data? > > * **No, it's new** > * **Yes, it's already live** You answer it per app. Each app gets its own question — an answer never carries over from another app, even one created from the same repository or a different branch of it. ## If it's new [#if-its-new] Answer **No, it's new**. Nothing special happens; continue to the readiness scan and deploy. ## If it's already live [#if-its-already-live] Read this before continuing. Preparing an app for this platform **restructures its code**, and: * The platform **does not move your existing data**, and cannot support migrating an app that is already in production. * The deploy-prep changes can break deployments on other providers you already run. * You continue **at your own risk**. Back up your code and your data first, and ask your coding agent to work on a **new branch** so you can roll back. Only then confirm with **I understand, continue**. ## Through a coding agent [#through-a-coding-agent] An agent connected over [MCP](/docs/mcp/overview) records your answer with `acknowledge_migration_risk`, and both `check_deploy_readiness` and `deploy_app` refuse to run until it is recorded. The agent must ask **you** about the specific app — it will not answer on your behalf, and for a live app it relays the warning above and waits for your explicit consent before recording it. ## Why the gate exists [#why-the-gate-exists] The prompt that prepares your app changes its structure. For a throwaway or brand-new app that is fine. For an app with real users and data it is a decision only you can make, with backups in hand. The gate makes sure that decision is taken on purpose, once, per app. # Environment variables Source: /docs/concepts/environment-variables Environment variables are the key-value config your app reads at runtime — API keys, feature flags, external URLs. Set them in the app's **Environment** section. ## Adding a variable [#adding-a-variable] ### Open Environment [#open-environment] From the app, open **Environment**. ### Add a key and value [#add-a-key-and-value] Enter a **Key** and **Value** and **Add variable**. Keys must start with an uppercase letter or underscore and contain only uppercase letters, numbers and underscores — for example `OPENAI_API_KEY`. ## Values are write-only [#values-are-write-only] After you save, the platform **never shows a value again** — the table shows keys only. To change one, use **Overwrite variable**; the new value replaces the old one permanently, and the old value cannot be shown or recovered. **Remove variable** deletes it for good. ## When changes apply [#when-changes-apply] Saving a variable applies **automatically**: the app restarts within about **10 seconds**, with no downtime and no rebuild. Anything else you save before the restart goes in with the same restart. An app you have not deployed yet picks up its variables on its first deploy. ## Reserved and injected keys [#reserved-and-injected-keys] Some keys belong to the platform and are injected for you. You cannot set them by hand: * **`PORT`** — always `8080`; the port your app must listen on. * **`DATABASE_URL`** — the connection string for your [managed database](/docs/concepts/subdomains-and-domains), injected from your first deploy. * **`META_*`** — reserved platform keys. ## A prompt for your coding agent [#a-prompt-for-your-coding-agent] The **Environment** section offers a prompt listing the exact variable names to read — never the values — so your code picks them up on deploy. Copy it into the agent that builds your app. ## What can go wrong [#what-can-go-wrong] * **"Key must start with A–Z or \_ and contain only uppercase letters, numbers, and underscores."** — Rename the key to match the format. * **"This key is reserved by the platform (e.g. PORT, DATABASE*URL, META*\*)."** — Pick a different name; that key is injected for you. * **"Value is required."** — Enter a value before saving. # Logs and status Source: /docs/concepts/logs-and-status The app page shows whether your app is running, what it is printing, and the history of its deploys. ## Runtime logs [#runtime-logs] Expand **Runtime logs** to see what the running container is printing right now. **Refresh** re-reads them; **Copy** copies the visible output. If the app is not running you see **App isn't running — deploy it to see its logs.** Deploy it first. ## Build logs [#build-logs] During a deploy, the **Build log** streams the build output. When it ends it reads **Build succeeded** or **Build failed**. Past runs are under **History** and **Pipeline runs**. ## Status [#status] The app's delivery status is one of **Not deployed**, **Up to date**, **Changes pending**, or **Deploy failed**. The lifecycle label (**pending**, **live**, **stopped**, and so on) is explained in [apps, builds and deploys](/docs/concepts/apps-builds-deploys). ## History [#history] **History** has two tabs: **Deployments** and **Builds**, each filterable by status. **Pipeline runs** lists every deploy that ran, when, what triggered it (manual or push), and whether it succeeded. ## Restart versus redeploy [#restart-versus-redeploy] * **Restart** (under **Actions**) runs the same image again. Use it to clear a stuck process. It does not rebuild. * **Deploy** builds your current source into a new image and ships it. Use it after changing code. ## What can go wrong [#what-can-go-wrong] * **"Couldn't load logs. Try refreshing."** — A transient read error. Refresh. * **"App is not currently running"** (on Stop) / **"App is not currently stopped"** (on Restart) — The action does not apply in the app's current state. * **"This app was stopped by an admin and can't be restarted. Contact support."** — An administrator suspended it. Reach [support](/docs/support). * **"This action isn't available right now — the app may be mid-deploy."** — Wait for the running operation to finish, then retry. # Plans and quotas Source: /docs/concepts/plans-and-quotas Your plan decides which features you can turn on and how much you can run. The **Plan & usage** page in the dashboard always shows your current plan, what you have used this period, and what changes if you move up. ## Tiers [#tiers] There are four tiers: **Free**, **Starter**, **Pro**, and **Enterprise**. Higher tiers unlock features and raise limits. The **Plan & usage** page lists the exact numbers for your account — they are shown live there rather than repeated here, so this page cannot go stale. ## What a plan gates [#what-a-plan-gates] Two different things: * **Features** — on or off for your tier. These are: **Custom domains**, **Dedicated database**, **Traffic analytics**, **User accounts**, **Payments**, and **MCP access**. On the **Free** tier, user accounts, payments and MCP access are available; custom domains, a dedicated database, and traffic analytics need a paid plan. Traffic analytics needs a dedicated database, so the two move together. * **Limits** — how much you can use: number of **Apps**, an **Assistant budget**, and the **CPU**, **Memory** and **Disk** each app can use. ## Ceilings versus usage [#ceilings-versus-usage] The dashboard separates two kinds of number: * **Usage** counts against your plan for the current period and **resets** on a date shown on the page (for example, the assistant budget). * **Limits per app** are ceilings — the most any single app can claim, such as CPU or memory. They are not a running total. ## What you see at a limit [#what-you-see-at-a-limit] When a plan blocks something, the message names the tier and, where relevant, how to move up: * **"Not included in your `{tier}` plan."** — the feature is off for your tier. Upgrade to a tier that includes it. * **"You have used all `{allowed}` `{limit}` included in your `{tier}` plan."** — you hit a usage limit. It resets on the date shown, or you can upgrade. * **"Upgrade to `{tier}`"** — the button that takes you to the plan that lifts the block. To upgrade, open **Plan & usage** and choose a plan. Billing is handled through Stripe. # Readiness and fixes Source: /docs/concepts/readiness-and-fixes Before you can deploy, the platform scans your source to confirm it can build and run. The same scan runs again as a hard gate at build time, so a green check and a real deploy agree. ## What the scan checks [#what-the-scan-checks] The readiness scan runs these checks: * **Preparing your source** — fetching the code to scan. * **Dockerfile builds** — a valid `Dockerfile` in the root. * **No hardcoded secrets** — no keys or passwords committed in the code. * **Dependencies resolve** — your dependencies can be installed. * **No secrets exposed to the browser** — no server secrets shipped to client-side code. * **AI review** — a broader read of the source for problems the fixed checks miss. **Dockerfile builds**, **No hardcoded secrets** and **No secrets exposed to the browser** can *block* a deploy. **Dependencies resolve** is a warning. ## Outcomes [#outcomes] * **Ready to deploy** — you can deploy. * **Action required** — one or more blocking issues. Fix them, then re-scan. * **Checked earlier code** — your source changed since the last scan, so it no longer describes what would go live. Re-scan. Each finding carries a title, a detail, and a fix. ## The fix loop [#the-fix-loop] When the scan finds something, it also produces a **fix prompt**: instructions written for your coding agent to apply to the code you have open. ### Get the fix prompt [#get-the-fix-prompt] Copy the fix prompt from the scan, or copy the readiness prompt the wizard offers before scanning. ### Apply it [#apply-it] Paste it into your coding agent (Cursor, Lovable, and similar). It edits your code. ### Get the fix to the platform [#get-the-fix-to-the-platform] The scan reads the source the **platform holds**, not your local files. For a GitHub app, commit and push to the connected branch. For a ZIP app, **Re-upload ZIP**. ### Re-scan [#re-scan] Run the scan again. Repeat until it says **Ready to deploy**. You can also fix issues by hand — edit your repo or re-upload your ZIP — and re-scan. Nothing forces you to use an agent. ## Through a coding agent [#through-a-coding-agent] An agent connected over [MCP](/docs/mcp/overview) runs the same scan with `check_deploy_readiness`. It returns `ready`, the per-check summary, the findings, and the same `fixPrompt`. The agent must push (or re-upload) before re-checking, for the same reason: the scan reads what the platform holds, not the agent's working tree. ## What can go wrong [#what-can-go-wrong] * **"The readiness scan found a problem that blocks this deploy. Open the scan to see what it found, fix it, then deploy again."** — A blocking finding stands. Work the fix loop above. * **"Our check could not run"** / **"Scan failed. Please try again."** — A problem on the platform side, not your app. Re-scan in a few minutes; if it persists, contact [support](/docs/support). # Subdomains and domains Source: /docs/concepts/subdomains-and-domains Every app gets a platform subdomain the moment it goes live. You can also serve it on a domain you own; the subdomain keeps working as the technical address either way. ## The platform subdomain [#the-platform-subdomain] When you create an app you pick a **subdomain**, or leave it blank for a generated one. As you type, the dashboard checks it: * **subdomain available** — yours to take. * **subdomain taken** — in use; pick another. * **subdomain reserved** — held by the platform; pick another. * **invalid subdomain format** — use lowercase letters, numbers and hyphens. ## Changing the subdomain [#changing-the-subdomain] You can change it later from the app. The change is safe: the current address keeps working until the new one is verified live, so there is **no downtime**, and it is reversible. The dashboard shows **changing address…** while it finishes. ## Using your own domain [#using-your-own-domain] A custom domain is available on paid plans. Serve the app on a domain like `shop.example.com` while the subdomain stays as the technical address. ### Turn on your own domain [#turn-on-your-own-domain] In the app, enable **Use my own domain** and enter the domain, for example `shop.example.com`. ### Add the DNS record [#add-the-dns-record] Click **Show DNS record**. Add the record it shows at the company you bought the domain from (OVH, GoDaddy, and similar), in its DNS section. It can take a few minutes to an hour to show up. ### Wait for verification [#wait-for-verification] The platform checks for the record and switches the app over when it appears. The domain status moves through **verifying** → **live**. Your app stays reachable on its subdomain the whole time. A domain you add before the first deploy is connected when you deploy. The certificate is handled for you. ## Removing a custom domain [#removing-a-custom-domain] **Remove** sends visitors, password-reset links and payment redirects back to the subdomain and takes the certificate off the gateway. If the domain is live you confirm by typing it. ## What can go wrong [#what-can-go-wrong] * **"That doesn't look like a valid domain."** — Enter a full domain, like `shop.example.com`. * **"This domain is already connected to an app."** — It is in use elsewhere on the platform. * **"This domain doesn't point at our gateway yet. Update its A-record and try again."** — The DNS record is missing or not propagated. Add or fix it, wait, then **Check now**. * **"That's one of our subdomains, so use the subdomain field instead."** — Use the subdomain field, not the custom-domain field. * **not verified** — The platform stopped checking on its own. Confirm the record at your provider, then press **Check now**. # Traffic analytics Source: /docs/features/analytics See who visits your app — visitors, pageviews, and where they come from. There is nothing to add to your code; the platform collects traffic for you. ## Enable [#enable] Open the app's **Analytics** tab and enable it. * **Needs a dedicated database**, which comes with a paid plan. Traffic data grows over time, so it lives with your app rather than on shared storage. See [plans and quotas](/docs/concepts/plans-and-quotas). * It starts counting on your **next deploy**. * **Turning it off deletes the traffic collected so far and cannot be undone.** Turning it back on starts counting from zero. ## What you see [#what-you-see] There is nothing to configure and nothing to add to your app — tracking is injected for you. The **Analytics** tab is the view itself. Pick a **range** (24 hours, 7, 30, or 90 days) and a **granularity**, and you get: * **Pageviews**, **visitors**, **visits**, **bounce rate**, and **average visit time**. * **Active now** — visitors in the last few minutes. * Breakdowns: **top pages**, **referrers**, **countries**, and **devices**. Data appears shortly after your app gets its first visits. ## Plan [#plan] Traffic analytics is available on paid plans, because it needs your app to have its own database. On the **Free** plan the **Analytics** tab explains this and links you to upgrade. See [plans and quotas](/docs/concepts/plans-and-quotas). # User accounts Source: /docs/features/auth Add sign-up and login for your app's end users. The auth service runs alongside your app and keeps its users in the app's own database. User accounts are available on every plan, including Free. ## Enable [#enable] Open the app's tab and turn on **End-user authentication**. * **Your app needs a database first.** If it doesn't have one, enabling auth turns one on for it. * **User accounts are permanent.** Once on, authentication cannot be turned off — it holds your end users' identities for the life of the app. * It activates on your **next deploy**. Until then the app shows **Pending deploy**. ## Configure [#configure] There is little to set up beyond enabling. You manage your end users from the **Users** table: search by email, filter by active / banned / unconfirmed, and ban, unban, reset a password, confirm an email, or delete a user. ## Wire [#wire] Your app talks to the auth service to sign users up, log them in, and read the current user. You don't write this by hand. The dashboard's **agent setup** gives you a **wiring prompt** to paste into your coding agent. A [connected agent](/docs/mcp/overview) can pull the same prompt itself with the `generate_feature_prompt` tool — auth must be enabled in the dashboard first. After wiring, **deploy** to pick it up. ## Your database [#your-database] With user accounts on, an **`auth` schema** appears in your app's database. The platform owns that schema; your app can read from it and keeps its own tables separately. See [what runs here](/docs/getting-started/what-runs-here) for how your app's database is laid out. # Overview Source: /docs/features/overview Beyond hosting, the platform adds business features to your app without you running the services behind them. This page is the map; each feature has its own guide. ## The groups [#the-groups] * **User accounts** — sign-up and login for your app's end users. When enabled, an `auth` schema appears in your database and the platform owns it; your app reads it. See [what runs here](/docs/getting-started/what-runs-here). * **Payments** — Stripe Connect, a product and price catalog, checkout, and a paid state your app can check. * **Add-ons** — extras such as **traffic analytics** for your app. Which features you can turn on depends on your [plan](/docs/concepts/plans-and-quotas). ## Enable, configure, wire [#enable-configure-wire] Most features follow the same three steps: 1. **Enable** — turn the feature on for the app. Some choices are permanent: user accounts, once enabled, cannot be turned off. 2. **Configure** — set it up in the dashboard (for example, finish Stripe onboarding, or create products and prices). 3. **Wire** — connect your app's code to the feature. The dashboard gives you a **wiring prompt** to paste into your coding agent, which edits your code to read the feature. After enabling or wiring a feature, your app usually needs a **deploy** to pick it up. The dashboard shows a pending state until you do. ## Doing it through a coding agent [#doing-it-through-a-coding-agent] An agent connected over [MCP](/docs/mcp/overview) can enable features, configure catalogs, and pull the wiring prompt for you. It cannot create or verify your Stripe account — do that yourself first, then the agent can enable payments, create products and prices, and wire the paywall. ## The guides [#the-guides] * [Payments](/docs/features/payments) * [User accounts](/docs/features/auth) * [Traffic analytics](/docs/features/analytics) # Payments Source: /docs/features/payments Accept payments from your app's end users with Stripe. OrbitOrca runs Stripe for you: your app never holds Stripe keys and never handles webhooks — it just asks the platform whether a customer has paid. Payments are available on every plan, including Free. ## Enable [#enable] Open the app's **Payments** tab and enable payments. This binds the app to a **Stripe Connect account** — either reuse an account you have already connected, or create a new one. For a new account you choose a business country, and **that country cannot be changed later**. * One app connects to **one** Stripe account. Apps that share an account share the same catalog. * Payments can only be turned **off before your first deploy** — after that, they stay on. * Enabling does not let you charge yet: a new account must finish Stripe verification first (see below). ## Configure [#configure] **Finish Stripe onboarding.** Complete Stripe's identity verification. The dashboard's account health moves from **Onboarding** to **Active** and flags anything Stripe still needs. You cannot charge customers until the account is **Active**. **Build your catalog.** Create **Products** and **Prices**: * A product has a **kind** — one-time or subscription — and a **key**. Both are fixed once the product is created. * A price is an amount and currency (plus a billing interval for subscriptions). * **Editing a price changes only the amount.** New buyers pay the new amount right away; existing subscribers move to it on their next billing cycle. Nothing is deleted — the old price is archived, and your app keeps working with no redeploy. Refunds, transactions, payouts, and tax documents are managed in **Stripe**, not the OrbitOrca dashboard. ## Wire [#wire] Your app asks the platform whether a customer has paid and sends them to checkout — it never talks to Stripe directly, and the paid state lives on the platform, not in your app. You don't write this by hand. The **Payments** tab gives you a **wiring prompt** to paste into your coding agent, which edits your code to add checkout and the paywall. A [connected agent](/docs/mcp/overview) can pull the same prompt itself with the `generate_feature_prompt` tool — it includes a live snapshot of your catalog. After wiring, **deploy** to pick it up. ## Through a connected agent [#through-a-connected-agent] An agent connected over [MCP](/docs/mcp/overview) can enable payments, create products and prices, and pull the wiring prompt for you. It **cannot** create or verify your Stripe account — do that yourself first, then let the agent handle the rest. See the [tool reference](/docs/mcp/tools) for what a write token can do. # Deploy from GitHub Source: /docs/getting-started/deploy-from-github Connect your GitHub account, pick a repository and branch, run the readiness check, and deploy. Your app comes up on its own web address. ## Before you start [#before-you-start] Your repository needs a `Dockerfile` in its root and a server that listens on the port the platform provides. The [what runs here](/docs/getting-started/what-runs-here) page is the full list. If it is missing something, the readiness scan tells you exactly what, and hands you a prompt to fix it. ## Steps [#steps] ### Start a new app [#start-a-new-app] In the dashboard, open **New app**. Under **import source**, choose the **GitHub** tab. ### Connect GitHub [#connect-github] Click **Connect GitHub** and approve the OrbitOrca GitHub App. When it returns you see **Connected as** your account. If a repository you expect is missing, click **Add repositories** and grant the GitHub App access to it on GitHub, then come back. ### Pick the repository and branch [#pick-the-repository-and-branch] Search for the repository, select it, then choose the **Branch** to build from. Private repositories work. ### Name it and pick a subdomain [#name-it-and-pick-a-subdomain] Give the app a name. Optionally set a **Subdomain** — leave it blank and one is generated for you. This becomes the app's live address. See [subdomains and domains](/docs/concepts/subdomains-and-domains). ### Answer the "is this already live?" question [#answer-the-is-this-already-live-question] Before the first deploy the platform asks whether this app is **already running somewhere, with real users or data**. For a brand-new app, answer **No, it's new**. If it is already live in production, read [database migrations](/docs/concepts/database-migrations) first — the platform does not move existing data. ### Run the readiness scan [#run-the-readiness-scan] Open the readiness check and **Run scan**. It verifies your source can build and run. If it comes back **Ready to deploy**, continue. If it says **Action required**, see [readiness and fixes](/docs/concepts/readiness-and-fixes) — you get a fix prompt for your coding agent, or you edit the repo yourself and re-scan. ### Deploy [#deploy] Press **DEPLOY**. The pipeline runs through building, scanning, pushing and deploying. When it finishes you see **Your app is live** with the **URL**. Open it. ## What can go wrong [#what-can-go-wrong] * **"Connect GitHub before importing a private repository."** — You picked the GitHub tab without connecting. Click **Connect GitHub** first. * **"GitHub installation not found. Reconnect your account."** — The GitHub App access was removed or expired. Reconnect from the GitHub tab. * **"GitHub is temporarily unavailable. Try again shortly."** — A GitHub outage, not your repo. Retry in a few minutes. * **"That branch is not in the repository any more. Pick one from the list."** — The branch was deleted or renamed. Choose a current branch. * **"This subdomain is already taken." / "This subdomain is reserved."** — Pick another subdomain. * **"Run a readiness scan before deploying"** — Deploy is disabled until a scan has run. Run it first. * **"Fix scan findings before deploying"** — The last scan blocked. Open it, fix what it found, re-scan, deploy. Every deploy-path error, with its fix, is on the [troubleshooting](/docs/troubleshooting) page. # Deploy from a ZIP Source: /docs/getting-started/deploy-from-zip For code that is not in a GitHub repository, upload it as a ZIP. The rest is the same: check it is ready, then deploy. ## Before you start [#before-you-start] Your project needs a `Dockerfile` in its root and a server that listens on the port the platform provides — see [what runs here](/docs/getting-started/what-runs-here). Zip the project **without** `node_modules`, `.git` or build output. The archive limit is **100 MB**. ## Steps [#steps] ### Start a new app [#start-a-new-app] In the dashboard, open **New app**. Under **import source**, choose the **ZIP upload** tab. ### Upload the archive [#upload-the-archive] Drag a ZIP onto **Drag & drop a ZIP file or click to browse**, or click to pick one. When it finishes you see **Ready** with the file name. ### Name it and pick a subdomain [#name-it-and-pick-a-subdomain] Give the app a name and, optionally, a **Subdomain**. Leave it blank for a generated one. This is the app's live address. ### Answer the "is this already live?" question [#answer-the-is-this-already-live-question] Before the first deploy the platform asks whether this app is **already running somewhere, with real users or data**. For a new app, answer **No, it's new**. If it is already live, read [database migrations](/docs/concepts/database-migrations) first. ### Run the readiness scan [#run-the-readiness-scan] **Run scan** to verify the archive can build and run. On **Action required**, fix the issues — edit your project and **Re-upload ZIP**, or apply the fix prompt with your coding agent — then re-scan. See [readiness and fixes](/docs/concepts/readiness-and-fixes). ### Deploy [#deploy] Press **DEPLOY**. When the pipeline finishes you see **Your app is live** with the **URL**. ## Updating a ZIP app later [#updating-a-zip-app-later] A ZIP app has no branch, so a plain deploy re-ships the archive the platform already holds. To ship new code, use **Re-upload & Deploy**: it replaces the source and deploys in one step. ## What can go wrong [#what-can-go-wrong] * **"File exceeds the 100 MB limit."** — Trim the archive. Exclude `node_modules`, `.git` and build output; the platform rebuilds dependencies for you. * **"The uploaded file is not a valid ZIP archive."** — Re-create the archive as a real ZIP and upload again. * **"Import expired or not found. Upload the ZIP again."** — An upload link is short-lived. Re-upload. * **"This app isn't ZIP-based — update its repository instead."** — This app was created from GitHub. Push to its branch instead of uploading a ZIP. * **"Run a readiness scan before deploying" / "Fix scan findings before deploying"** — Run or clear the readiness scan first. Every deploy-path error, with its fix, is on the [troubleshooting](/docs/troubleshooting) page. # What runs here Source: /docs/getting-started/what-runs-here The platform builds your app from a `Dockerfile` and runs it in a container behind a gateway. Follow these rules and it deploys. The [readiness scan](/docs/concepts/readiness-and-fixes) checks most of them before you ship. ## The rules [#the-rules] ### A Dockerfile in the root [#a-dockerfile-in-the-root] There must be a `Dockerfile` in the **root** of your repository or ZIP, not in a subfolder. It starts with a `FROM` line and has a `CMD` or `ENTRYPOINT` that starts your server. Without it there is nothing to build. ### Listen on the port the platform gives you [#listen-on-the-port-the-platform-gives-you] The platform starts your container with the environment variable `PORT` set to `8080` and routes traffic to it. Your app **must** listen on `0.0.0.0` on that port — read `process.env.PORT` (or your language's equivalent) rather than hardcoding. Listening on `127.0.0.1` or `localhost` makes the app unreachable and the deploy fails. `EXPOSE` in the Dockerfile does not affect routing; the real listening port is what counts. ### Be a long-lived server [#be-a-long-lived-server] The process must keep running. A script that starts, does its work and exits is treated as a failed deploy. This is a web server, not a one-shot job. ### Configuration from environment variables, no secrets in the repo [#configuration-from-environment-variables-no-secrets-in-the-repo] Read keys, passwords and URLs from environment variables. Set your own integration keys (like `OPENAI_API_KEY`) in the app's [environment variables](/docs/concepts/environment-variables); the platform stores them and injects them at deploy. Never commit secrets. Some keys are reserved and injected for you — `PORT`, `DATABASE_URL`, and the `META_*` keys. You cannot set those by hand. ### Use the database the platform provides [#use-the-database-the-platform-provides] If your app needs a database, read the connection string from `DATABASE_URL`. The platform provisions a managed Postgres and injects it. Do not run your own database inside the image, do not point at `localhost`, and do not commit credentials. `DATABASE_URL` appears at your **first deploy**, not the moment you create the app. Keep your own tables and migrations in the `public` schema; you have full rights there. An app that needs no database (a static site) can turn the database off in settings. ### The `/__meta/*` path is reserved [#the-__meta-path-is-reserved] The path `/__meta/*` on your app's domain belongs to the platform and is handled before the request reaches your app. Do not define routes under it. ### The `auth` schema belongs to the platform [#the-auth-schema-belongs-to-the-platform] If you turn on user accounts, an `auth` schema appears in your database with the end-user tables. Your app has read-only access there — you can join your records by `user_id`, but not write. Keep your own tables in `public`. ### The container disk is temporary [#the-container-disk-is-temporary] Your app is stateless. The container filesystem is a scratch space: every deploy and restart starts from a clean image, and anything written to disk is lost. Store everything that must survive in your database. Writing to `/tmp` during a request is fine — it just will not persist. ### Optional: a health endpoint [#optional-a-health-endpoint] A `/healthz` endpoint helps diagnostics. By default the platform does a TCP check on port `8080`. ## A prompt for your coding agent [#a-prompt-for-your-coding-agent] Paste this into the agent that builds your app (Cursor, Lovable, and similar): ```text Prepare this app for deployment on the platform: 1. Add a Dockerfile in the root: FROM, install dependencies, CMD that starts the server. 2. The server must listen on 0.0.0.0 and the port from process.env.PORT (the platform sets PORT=8080). Do not hardcode another port. 3. It must be a long-lived HTTP server, not a one-shot script. 4. Read all keys and secrets from environment variables. Do not commit them. 5. If the app uses a database, connect via process.env.DATABASE_URL (a managed Postgres). Do not run your own database in the container, do not point at localhost, keep your tables in the public schema. 6. Do not define any routes under /__meta/*; that prefix belongs to the platform. 7. Do not write persistent data to disk (uploads, SQLite, files); the container filesystem is ephemeral and resets on every deploy. Keep everything that must survive in the database. Then commit and push. ``` ## Checklist before every deploy [#checklist-before-every-deploy] * `Dockerfile` in the root, with `FROM` and `CMD`/`ENTRYPOINT` * App listens on `0.0.0.0:8080` (reads `$PORT`) * Long-lived server (the process does not exit) * No secrets in the repo; config from environment variables * Database, if used, via `DATABASE_URL` — not your own, not `localhost` * No routes under `/__meta/*` * Persistent data in the database, not on disk # Overview Source: /docs/mcp/overview MCP (Model Context Protocol) is an open standard that lets AI coding tools talk to outside services. The OrbitOrca MCP server gives the agent in your editor access to your apps on the platform — so it can check a deploy, read logs, or ship a change without you copy-pasting between the dashboard and your editor. ## What your agent can do [#what-your-agent-can-do] * **Read** (on by default) — list your apps, check status and logs, read environment variables, list products and customers, check deploy readiness, and pull ready-made wiring prompts. * **Write** (a deliberate opt-in) — create, deploy, stop, and restart apps, change settings and environment variables, and manage products and prices. Real changes to your apps and billing. A token you create decides which of these the agent gets. Read-only is the safe default; you add write only when you want the agent to make changes. See [Scopes & safety](/docs/mcp/scopes-and-safety). ## Connect your host [#connect-your-host] Pick your editor: * [Claude Code](/docs/mcp/connect/claude-code) * [Cursor](/docs/mcp/connect/cursor) * [Windsurf](/docs/mcp/connect/windsurf) * [Claude.ai / Claude Desktop](/docs/mcp/connect/claude-ai) * [Any other host](/docs/mcp/connect/other-hosts) (generic Streamable HTTP) Every host points at the same server: ``` https://api.orbitorca.com/mcp ``` You authenticate with a personal access token. The dashboard's **Connect an agent** page creates one and fills it into a ready-to-paste snippet for your editor — open [app.orbitorca.com/mcp](https://app.orbitorca.com/mcp). How tokens work, expiry, and revocation are on [Tokens](/docs/mcp/tokens-and-oauth). # Scopes & safety Source: /docs/mcp/scopes-and-safety A token carries one or both **scopes**: `read` and `write`. The scope decides what the agent in your editor is allowed to do — and several limits sit behind it so a connected agent can't run away with your account. ## What a read token can do [#what-a-read-token-can-do] `read` is always granted and is the default for a new token. With read, the agent can look but not change: * List your apps and check their status, logs, and deploy readiness. * Read environment variable names, subdomains, and settings. * List your products, prices, customers, and connected accounts. * Pull ready-made wiring prompts for platform features. A read token can't deploy, stop, restart, or change anything. It's the safe default — connect with read only unless you specifically want the agent to make changes. ## What a write token can do [#what-a-write-token-can-do] `write` is a deliberate opt-in you add when you create the token. It's additive: a write token also has read. With write, the agent can make real changes: * Create, deploy, stop, and restart apps. * Change app settings, environment variables, subdomains, and branches. * Create and update products and prices, and set up integrations. These are the same actions you can take in the dashboard. Give write only to an editor you trust, and prefer a short expiry. ## What stops a runaway agent [#what-stops-a-runaway-agent] Read and write both sit behind the same guards. **The host approval dialog.** Before your editor calls a tool, it shows you the tool — its name and description — and asks you to approve, and many hosts can remember the choice per tool. Those descriptions are long and explicit on purpose: they're written for the model so it picks the right tool and the right arguments, and so what you approve is unambiguous. Read the description in that dialog before you approve — it says exactly what the tool will do. Hosts that connect over OAuth show the same list up front: the consent screen has a **Show tools** control that expands every tool the connection can use. **Rate limits, per token.** Each token gets a fixed budget per minute: * **30** read calls per minute * **10** write calls per minute Go over and the call is refused with a message the agent can read and back off on — not a hard error that kills the turn: ``` Rate limited — this access token has used its read budget of 30 calls per minute. Wait 42s and try again, and do not retry in a loop. ``` A well-behaved agent waits and continues. (Reading the docs through a connected agent counts against the same read budget.) **Retry safety on writes.** Transport hiccups and model retries mean a write tool can be called twice in quick succession. OrbitOrca collapses a duplicate write within a **30-second** window: calling `deploy_app` twice within 30 seconds deploys once — the second call returns the first result instead of running again. A *deliberate* re-call later (say, setting a subdomain back to a previous value) is outside the window and runs normally. **Revocation.** Revoke a token from the dashboard and it stops working immediately, without touching your other tokens. Do it the moment a token might be exposed. See [Tokens](/docs/mcp/tokens-and-oauth). # Tokens Source: /docs/mcp/tokens-and-oauth A token is how your editor proves it's you to the OrbitOrca MCP server. You create tokens on the dashboard's [Connect an agent](https://app.orbitorca.com/mcp) page, under **Access tokens**. > A token acts as you. Anything it can read, the agent in your editor can read too — and a write token can change your apps and billing. Treat a token like a password: don't paste it into shared files or chats. ## Creating a token [#creating-a-token] When you create a token you choose two things: * **Access** — **Read** (the default) or **Read & write**. Read lets the agent look; write lets it make changes. See [Scopes & safety](/docs/mcp/scopes-and-safety). * **Expiry** — a fixed number of days, or **Never**. A shorter life is safer; pick the shortest that fits how you work. The full token is shown **once**, at creation. Copy it straight into your editor's config — if you lose it, you can't see it again, so you create a new one and revoke the old. ## Managing tokens [#managing-tokens] The **Access tokens** table lists every token by name, scopes, when it was created, when it was last used, and when it expires. From there you can: * **Revoke** a token — it stops working immediately. Do this the moment a token might be exposed, or when you stop using an editor. * **Delete** a revoked token to clear it from the list. A token must be revoked before it can be deleted. * **Revoke all** or **Delete revoked** in bulk, when you want to reset every connection at once. Revoking one token never affects the others — each editor you connect can have its own. ## OAuth connectors [#oauth-connectors] Some hosts — Claude.ai and Claude Desktop — connect over **OAuth** instead of a pasted token: you approve OrbitOrca on a consent screen and the host holds the connection as an app. These show up in your token list as an **app**, and you revoke them the same way. See [Claude.ai / Claude Desktop](/docs/mcp/connect/claude-ai). # Tool reference Source: /docs/mcp/tools This is the full set of tools a connected agent can call, split by scope. Your agent already receives each tool's detailed description and arguments live over MCP — this page is the human overview: what exists, and which scope it needs. ## Read tools [#read-tools] A **read** token can call the tools below. Every one of them only reads — none change anything on your account, so read is the safe default. Reading through a connected agent counts against the read rate limit. See [Scopes & safety](/docs/mcp/scopes-and-safety) for the limits. - `check_deploy_readiness` — Run an app through its readiness checks and return a fix prompt for anything blocking a deploy. - `check_subdomain` — Check whether a subdomain is available. - `generate_feature_prompt` — Generate a wiring prompt for a feature such as payments, auth or analytics. - `get_app_info` — Get an app details and configuration. - `get_app_logs` — Get the recent logs for an app. - `get_app_status` — Get the deploy and runtime status of an app. - `get_github_connection` — Check your GitHub connection status. - `list_app_customers` — List the customers of an app. - `list_connect_accounts` — List your Stripe Connect accounts. - `list_docs` — List the pages of this documentation, grouped by section, each with a slug and description. - `list_env_vars` — List the environment variable names on an app. Values are never returned. - `list_github_branches` — List the branches of a GitHub repository. - `list_github_repos` — List your connected GitHub repositories. - `list_products` — List the products and prices of an app. - `list_user_apps` — List your apps. - `read_doc` — Read one documentation page as Markdown, with the canonical link to cite. ## Write tools [#write-tools] A **write** token is additive: it can call every read tool plus the tools below, each of which makes a real change to your account. The same guards apply to all of them: * **Your host asks first.** Before a tool runs, your editor shows its name and description and waits for your approval. * **Rate limit.** Write calls have a lower per-minute budget than reads. * **Retry-safe.** A duplicate write inside a short window is collapsed, so a retried call does not act twice. See [Scopes & safety](/docs/mcp/scopes-and-safety#what-stops-a-runaway-agent) for the exact numbers. - `acknowledge_migration_risk` — Record your acknowledgement of a database migration risk before it runs. - `create_app_from_github` — Create an app from a connected GitHub repository, public or private. - `create_app_from_repo` — Create an app from a public repository URL. - `create_app_from_zip` — Create an app from an uploaded zip file. - `create_price` — Create a price for a product. - `create_product` — Create a product. - `create_zip_upload` — Get an upload ticket for sending a zip file. - `delete_env_var` — Delete an environment variable from an app. - `deploy_app` — Deploy an app. - `enable_stripe_feature` — Enable a Stripe feature for an app. - `replace_app_source` — Replace the source code of an app. - `restart_app` — Restart an app. - `set_app_analytics` — Turn traffic analytics on or off for an app. - `set_app_branch` — Set the branch a git-backed app deploys from. - `set_env_var` — Create or update an environment variable on an app. - `set_subdomain` — Set the subdomain for an app. - `stop_app` — Stop a running app. - `update_app_settings` — Update the settings of an app. - `update_product` — Update a product. ## Reading these docs without an account [#reading-these-docs-without-an-account] Any tool can read this documentation over plain HTTP, no token needed: [`/llms.txt`](/llms.txt) links every page, [`/llms-full.txt`](/llms-full.txt) is the whole set in one file, and adding `.mdx` to any page URL returns that page as Markdown. # Claude.ai / Claude Desktop Source: /docs/mcp/connect/claude-ai Claude.ai and Claude Desktop add remote MCP servers as **custom connectors**, which authenticate over OAuth — you click **Connect**, approve OrbitOrca on a consent screen, and Claude holds the connection. There's no config file and no token to paste. ### Add the connector [#add-the-connector] In Claude's connector settings, add a custom connector pointing at: ``` https://api.orbitorca.com/mcp ``` ### Approve the connection [#approve-the-connection] Claude sends you to an OrbitOrca consent screen that names the connecting app and asks you to grant access: * **Read** is always granted — the agent can view your resources. It's required to connect. * **Write** is optional — grant it to let the agent create, deploy, and modify your apps and set up integrations. Leave it off for read-only. Approve only if you started this from Claude — the connection acts as you. The request expires about 10 minutes after it starts. ### Try it [#try-it] Ask Claude to *"list my OrbitOrca apps"*. If it comes back with your apps, you're connected. The connection shows up in your dashboard token list as an **app**, alongside any personal access tokens. Revoke it there the same way — see [Tokens](/docs/mcp/tokens-and-oauth). Next: [what the approval grants](/docs/mcp/scopes-and-safety). # Claude Code Source: /docs/mcp/connect/claude-code Add OrbitOrca to Claude Code for your user account — it becomes available across all your local projects. ### Get a token [#get-a-token] Open the dashboard's [Connect an agent](https://app.orbitorca.com/mcp) page and create a token. Read-only is the default; add write only if you want the agent to deploy and change apps. The full token is shown **once**, at creation — copy it now. ### Add the server [#add-the-server] Run this in your terminal, with your token in place of `{{token}}`: ```bash claude mcp add --transport http orbitorca https://api.orbitorca.com/mcp --scope user --header "Authorization: Bearer {{token}}" ``` ### Try it [#try-it] In Claude Code, ask it to *"list my OrbitOrca apps"*. If it comes back with your apps, you're connected. The dashboard's [Connect an agent](https://app.orbitorca.com/mcp) page generates this exact command with your token already filled in — copy it from there if you'd rather not edit by hand. Next: [what a token can and can't do](/docs/mcp/scopes-and-safety). # Cursor Source: /docs/mcp/connect/cursor Cursor reads MCP servers from a JSON config file. Add OrbitOrca there and reload. ### Get a token [#get-a-token] Open the dashboard's [Connect an agent](https://app.orbitorca.com/mcp) page and create a token. Read-only is the default; add write only if you want the agent to deploy and change apps. The full token is shown **once**, at creation — copy it now. ### Add the server [#add-the-server] Add this block to `~/.cursor/mcp.json` (create the file if it doesn't exist), with your token in place of `{{token}}`: ```json { "mcpServers": { "orbitorca": { "url": "https://api.orbitorca.com/mcp", "headers": { "Authorization": "Bearer {{token}}" } } } } ``` Then reload Cursor. ### Try it [#try-it] Ask Cursor to *"list my OrbitOrca apps"*. If it comes back with your apps, you're connected. The dashboard's [Connect an agent](https://app.orbitorca.com/mcp) page generates this block with your token already filled in — copy it from there if you'd rather not edit by hand. Next: [what a token can and can't do](/docs/mcp/scopes-and-safety). # Other hosts Source: /docs/mcp/connect/other-hosts Any MCP host that supports the **Streamable HTTP** transport can connect to OrbitOrca. You need two things: the server URL and an `Authorization` header carrying your token. ### Get a token [#get-a-token] Open the dashboard's [Connect an agent](https://app.orbitorca.com/mcp) page and create a token. Read-only is the default; add write only if you want the agent to make changes. The full token is shown **once**, at creation — copy it now. ### Point your host at the server [#point-your-host-at-the-server] ``` URL: https://api.orbitorca.com/mcp Header: Authorization: Bearer {{token}} Transport: Streamable HTTP ``` Put your token in place of `{{token}}`. Most hosts take these in a small JSON config; the exact shape is up to the host. Every OrbitOrca host — Claude Code, Cursor, Windsurf, and the rest — uses this same URL and header. The [Connect an agent](https://app.orbitorca.com/mcp) page in the dashboard always shows the current values with your token filled in. Next: [what a token can and can't do](/docs/mcp/scopes-and-safety). # Windsurf Source: /docs/mcp/connect/windsurf Windsurf reads remote MCP servers from its own config file. Add OrbitOrca there and refresh. ### Get a token [#get-a-token] Open the dashboard's [Connect an agent](https://app.orbitorca.com/mcp) page and create a token. Read-only is the default; add write only if you want the agent to deploy and change apps. The full token is shown **once**, at creation — copy it now. ### Add the server [#add-the-server] Add this block to `~/.codeium/windsurf/mcp_config.json` (create the file if it doesn't exist), with your token in place of `{{token}}`: ```json { "mcpServers": { "orbitorca": { "serverUrl": "https://api.orbitorca.com/mcp", "headers": { "Authorization": "Bearer {{token}}" } } } } ``` Then open Windsurf's MCP settings and refresh the server list. ### Try it [#try-it] Ask Cascade to *"list my OrbitOrca apps"*. If it comes back with your apps, you're connected. The dashboard's [Connect an agent](https://app.orbitorca.com/mcp) page has ready-to-paste snippets for other editors and always shows the current server URL and your token. Windsurf uses the same URL and `Authorization` header as every other host. Next: [what a token can and can't do](/docs/mcp/scopes-and-safety).