MCP overview
The server is named 0bull Phone Farm and is served at:
Code
It drives the 0bull phone farm on behalf of the authenticated user: managing posting accounts on TikTok, Instagram and YouTube, publishing videos as submissions, running account lifecycle actions, controlling the physical farm phones, and ordering or managing billing for new ones. See Connecting to add it to your client, and the tool reference for all 24 tools.
Platforms
Accounts and submissions carry a platform of tiktok, instagram or youtube, and
it defaults to tiktok everywhere: a client written before the parameter existed keeps
working unchanged.
An account id is a UUID that identifies its own platform, so the tools that take one
(get-account-tool, delete-account-tool, login-account-tool, stop-login-tool,
logout-account-tool) never ask which platform it is on. Only create-account-tool,
list-accounts-tool and create-submission-tool take a platform, because they have no
id to read it from.
Where the platforms genuinely differ:
| TikTok | YouTube | ||
|---|---|---|---|
| Required to create | username, password, slot | handle | handle |
| Credentials | Required | Optional | Optional |
| Caption | Up to 2200 chars, optional | Up to 2200 chars, optional | The Short's title, up to 100 chars, required |
Instagram and YouTube accounts created without credentials are record-only: a handle
somebody signed in on the handset by hand, which the farm holds no way to sign in itself.
They are active and post fine, but login-account-tool refuses them: there is nothing
to type into a login form. Supply a username and password (at creation, or later) and the
login is queued on the phone like TikTok's.
logout-account-tool works on TikTok, Instagram and YouTube. A platform's flow can decline
after it checks the phone, and when it does the account status is left unchanged rather
than reported as signed out.
Everything phone-touching is asynchronous
This is the single thing that surprises callers, and it follows from what 0bull is: there is a real phone at the other end, and tapping through an app takes time.
So a tool call that reaches a phone queues the work and returns straight away. The response tells you the work was accepted. It does not tell you the work succeeded. Concretely:
create-account-toolcreates the account row and queues a login on a physical phone. It returns the account immediately, inpending_login. (An Instagram or YouTube account created without credentials queues nothing and comes backactive.)create-submission-toolcreates the submission and queues a publish. It returns the submission immediately, inpending.login-account-tool,logout-account-tool,run-macro-tool, andrun-phone-agent-toolonly acknowledge the start.
To learn what actually happened, poll get-account-tool or get-submission-tool until
the status reaches a resting state. A real phone is tapping through a real app; this takes
as long as it takes.
The read tools (list-*, get-*, list-phones-tool, phone-snapshot-tool,
phone-ocr-tool) and the pure database operations (delete-*, cancel-submission-tool)
are synchronous and answer immediately. phone-control-tool is synchronous too: it is a
direct farmd socket op rather than queued work.
Account status
Poll get-account-tool and read status. The vocabulary is the same on all three
platforms:
| Status | Meaning |
|---|---|
pending_login | Login queued, not yet started. |
logging_in | A login is mid-flight on the phone. Do not start another. |
needs_verification | The platform challenged the login; it needs human attention. |
active | Logged in and present on its phone. The only status that can post. |
failed | The login failed. login_error carries the reason. |
logged_out | Signed out on the phone, on any platform. |
create-submission-tool rejects any account that is not active.
Submission status
Poll get-submission-tool and read status:
| Status | Meaning |
|---|---|
scheduled | Queued for a future run. |
pending | Queued, not yet picked up. |
ingesting | The video is being fetched or prepared. |
driving | The phone is being driven through the platform's app. |
published | Posted. Terminal. |
drafted | Saved as a draft on the phone. Terminal. |
failed | The run failed. Terminal. |
cancelled | Cancelled before finishing. Terminal. |
pending, ingesting, and driving are in-flight: cancel-submission-tool works on
these, delete-submission-tool does not. Once a status is terminal the reverse is true.
Billing and ordering phones
Four tools cover renting phones and checking on billing: get-billing-tool,
start-rental-tool, request-phones-tool, and get-billing-request-tool.
get-billing-tool reads the account's rentals: how many phones it has, what each one costs
and when it renews, plus any orders still waiting on an admin to assign a phone. Call it
first, before proposing any change.
start-rental-tool opens a Stripe Checkout link for a first order. The link only saves a
card, it charges nothing. The order is placed once checkout completes, and each phone is
charged a full month the moment an admin assigns it. Orders are final: there is nothing to
cancel while one waits.
request-phones-tool changes an existing rental's phone count, given either a new total or
a signed adjustment. It normally files the change and returns an approval link, so poll
get-billing-request-tool for the answer. If the caller has set a standing allowance in
their MCP settings, an increase within it is applied immediately, and the response says
applied: true. Read that field rather than assuming: it means the order was placed, not
that a card was charged. The card is still only charged when an admin assigns the phone.
Both start-rental-tool and request-phones-tool require accept_terms: true. Before
calling either, show the user 0bull.net/terms and
0bull.net/privacy, and get their agreement to those and to
monthly renewal charges. Without it, both tools refuse.
Scoping
Every call is scoped to the caller's own accounts and phone grants. You see your own accounts and submissions; you reach a phone only if you hold a grant on its slot.
Accounts and submissions you may not access return Account not found. /
Submission not found., the same error as a genuinely missing record, so the tools never
leak the existence of records you cannot see. A "not found" may mean it does not exist, or
it is not yours.
Rate limit
60 requests per minute, the same ceiling as the REST API. Polling a status is a normal thing to do, just leave a second or two between calls rather than spinning as fast as the limit allows. A phone takes far longer than a minute to finish a login or a publish.
Authentication
The server uses OAuth, with the authorization endpoints published alongside it. Your client discovers them and walks you through authorization in a browser: you never copy a token. See Connecting.

