MCP for agents
Sitebin speaks the Model Context Protocol, so Claude, ChatGPT and any other MCP client can publish a website and manage it afterwards — without you pasting files anywhere. It is the same API, the same permissions and the same quotas, reached over the protocol those clients already speak.
app.sitebin.io that means an account
— reached by signing in from the client or with an API token — and a
site created anonymously (a Drop) stays outside it, just as it stays
outside the API. Self-hosted community instances have no accounts, so
the endpoint is open there.Connect
The endpoint is https://app.sitebin.io/mcp, streamable
HTTP. There are two ways to tell it which account the agent is
publishing for, and every client supports at least one of them — plus
a site's own edit password, which works without any account at all.
Sign in from the client (OAuth)
A client that implements MCP authorization — Claude, ChatGPT's connectors, and most others that can add a remote server — needs only the URL. The first time the agent does something that needs your account, the client registers itself with our authorization server and opens a browser window where you sign in to your Sitebin account, accept the terms if you have not yet, and approve what the agent may do. It then holds an access token bound to this server. No token to create, nothing to paste — and no account needed beforehand: the first sign-in creates it.
claude mcp add --transport http sitebin https://app.sitebin.io/mcp
With an API token
Scripts, CI, and clients that only know how to send a header use an
account API token instead. Create one in the dashboard at
/account, then pass it as a bearer token:
claude mcp add --transport http sitebin \ https://app.sitebin.io/mcp \ --header "Authorization: Bearer $TOKEN"
Clients that only speak stdio, or that cannot set a header, can
bridge through mcp-remote, which also handles the OAuth
sign-in if you leave the header off:
npx mcp-remote https://app.sitebin.io/mcp \ --header "Authorization: Bearer $TOKEN"
What the agent can do
| Tool | What it does |
|---|---|
create_site | Publish files as a new site. Returns the public URL, the edit id, and — once — the edit password. |
list_sites | The sites your account owns, with their names and custom domains. Needs your account — a sign-in or an API token. |
get_site | Name, settings, usage and the file list. |
update_site | Name, mode, entry file, view password, expiry, WebDAV/FTP, SPA fallback, browser caching (cache: auto, revalidate, hour, day, week, year, off). The name is a private label for your site list; an empty string removes it. |
list_files | The site's files with their sizes. |
read_file | One file's contents. |
write_files | Add or overwrite files. With replace, the site ends up holding exactly what was passed. |
delete_file | Remove one file. |
delete_site | Remove the site and everything in it. |
add_domain | Attach a custom domain. The domain is attached once its DNS proves it belongs to the site; until then the result lists it under pending_domains with the TXT record (or CNAME) to create, and its warnings say what the check found. The agent creates the record and calls add_domain again, or waits — the instance re-checks pending domains itself. On a container site, target names the HTTP port the domain serves (app:3000). Enterprise. |
remove_domain | Detach a custom domain, or withdraw a pending claim. |
set_domain_redirect | Make a custom domain redirect to another of the site's custom domains — example.de to example.at — with 301 (default), 302, 307 or 308, keeping the path. An empty to serves the site again. Enterprise. |
set_view_address | Switch the site's generated address off, or redirect it to one of its custom domains — or back to serve. Needs a custom domain that serves the site. A container site has one generated address per HTTP port; endpoint picks which. Enterprise. |
set_domain_target | Point a container site's custom domain at another of its HTTP ports — without touching the compose file, so the app does not restart. Enterprise. |
download_site | The whole site as a zip. |
open_upload | A short-lived token and URLs for files too large to pass as arguments. The agent uploads with its own HTTP client — a zip for a whole site, or single files, or over WebDAV — using the curl commands in the result. The token opens nothing else and expires five minutes after its last use, and an hour after it was opened at the latest. |
list_forms | The site's email forms, each with its status and the HTML snippet to paste. Every submission arrives as a plain-text email with the visitor's files and submission.json attached. |
add_form | Add a form. Its recipient confirms by email first; until then the form is pending and refuses submissions. Submissions arrive as plain-text emails, not designed ones; the agent is told to have the user add the sender to their safe senders. Needs form mail on the instance; Pro and Studio on the hosted service. |
update_form | Change a form's name, recipient, captcha, attachments or thank-you page. A new recipient confirms again. |
remove_form | Delete a form. |
resend_form_confirmation | Email the recipient the confirmation link again. |
How it behaves
Signed in or with a token, every site the agent
creates belongs to your account and gets your plan's quotas and
lifetime. list_sites shows them, and the credential
replaces the edit password on all of them — so the agent never has to
hold a per-site secret, and never has to ask you for one.
Without either, an agent passes a site's
edit_password with every call, and that keeps working
whether or not the client can sign in. On app.sitebin.io
it cannot create sites that way: anonymous publishing belongs on the
drop page, in front of a person. A call that needs an account —
create_site, list_sites, or a site tool
without its password — is answered with a sign-in request, which a
client that supports OAuth turns into the browser window above.
Files travel as JSON — {"path": "index.html", "text": "…"},
or base64 for images. One call carries up to 8 MiB, but a model writes every byte of an
argument out itself, so for anything beyond a few hundred KB the
agent calls open_upload and uploads with curl
instead — if it can make HTTP requests of its own. Every site an
agent creates or changes is recorded as coming through MCP, with the
account and the client's address, which is how abuse gets traced if it
ever happens.
Locked sites. A site the operator has
locked — held as evidence of abuse
— is not served and cannot be changed. get_site and
list_sites still answer for it, with a
locked object (at, and reason
when the operator gave one) and no files; every other tool refuses it
with "This site is locked by the operator". The field appears
only on a locked site, so every other result is exactly what
it was. An account the operator has suspended is refused on every
call. A write whose files match a known phishing or scam kit on an
anonymous or Free site locks that site on the spot, and the tool answers
with the same sentence: "held for review".
Authentication
/mcp accepts three kinds of credential side by side, so
none of them ever breaks a script or agent using another:
- a site's edit password, passed as
edit_passwordto each call on that site; - an account API token in an
Authorizationheader — the same token the API takes. It carries no scopes and grants everything its account can do; - an OAuth 2.1 access token issued by our
authorization server after you signed in and consented. It is valid
for
/mcponly — the JSON API takes API tokens, not OAuth tokens.
A client may connect without any of them and list the tools. Only a
call that needs an account is answered 401 with a
challenge naming the metadata and the scopes, which is what starts a
sign-in; a call that needs a permission the token was not granted is
answered 403 with insufficient_scope, which
a client turns into a request for that permission.
How the OAuth connection works
On app.sitebin.io the MCP server is an
OAuth 2.1 protected resource and the
IT-Trail SaaS Stack that also runs Sitebin's
sign-in is its authorization server. The pieces a
client relies on:
- Discovery. A call that needs an account is answered
with a
WWW-Authenticatechallenge pointing at/.well-known/oauth-protected-resource/mcp, which names the authorization server, the resource identifier (https://app.sitebin.io/mcp) and the scopes. - Dynamic client registration. The client registers
itself with the authorization server (RFC 7591) — no
pre-shared client id, which is what lets a connector you have never
told us about connect. Registered clients are capped and
rate-limited, may only ask for Sitebin's scopes and the standard
sign-in ones, may only send you back to your own machine or to a
known connector host (Claude, ChatGPT, VS Code), must use PKCE
S256, and always ask for your consent. - Sign-in, terms and consent. You sign in to the same
account you use at
app.sitebin.io. If you have not accepted the current platform terms, Sitebin's terms and the data processing agreement, you are shown them first — the same page a sign-in in the browser shows, and a token is never issued past it. Then a consent screen names the client and the scopes it asks for. - Scoped, audience-bound tokens.
sitebin:sites:readcoverslist_sites,get_site,list_files,read_file,download_siteandlist_forms;sitebin:sites:writecovers the rest, includingadd_form,update_form,remove_formandresend_form_confirmation. A token is accepted only when it is an access token whose signature, issuer and expiry check out, whose audience contains this server's resource identifier — so a token minted for another app on the same authorization server is refused — and whose holder has accepted the current terms. Sitebin asks the authorization server about the terms itself, so a client that skipped the sign-in page gets nothing. A first valid token creates your Sitebin account, exactly as a first sign-in in the browser does. - Revocation. The Applications page of your account console lists every client you have authorised and lets you revoke it; the client's own settings do the same from its side.
- Unused registrations expire. A client that was
registered and never signed in is removed after three days; one
that nobody has used for 90 days is removed too. If a connector you
have not used in months stops connecting — an
invalid_clienterror, or a sign-in that never comes back — remove it in your client and add it again; it registers afresh on the spot.
Sitebin itself is a resource server and never an authorization
server: it issues no tokens, registers no clients and shows no consent
screen. A self-hosted instance gets the same behaviour by pointing
SITEBIN_MCP_OAUTH_ISSUER (and optionally
SITEBIN_MCP_OAUTH_RESOURCE) at its own sign-in issuer —
the two must be the same — when that authorization server offers
dynamic client registration, PKCE and audience-bound tokens. The SaaS
Stack does so from an mcp block at app onboarding; other
compliant issuers work the same way. With the issuer unset, none of
this is mounted, and API tokens and edit passwords are the
credentials.
Connector directories
The OAuth flow above — a protected resource with discovery, dynamic
client registration, PKCE and consent — is the one the connector
catalogues at Anthropic and OpenAI require of a remote MCP server, and
app.sitebin.io supports it. Whether Sitebin appears in
those catalogues is up to their operators and their review; until it
does, add it as a custom connector by URL, which is the same flow with
one more field to fill in.
Rate limits
The same ones the API has: site creation is limited per IP, and
password attempts per IP and per site. An agent gets no more room than
curl does.