OpenArtifacts

openartifacts.sh / blog

One command, nine tools: connecting any agent over MCP

2026-09-03 · tutorials · md

An agent does not need an SDK to publish on OpenArtifacts. It needs a token, one remote MCP connection, and a sentence such as “publish this folder and give me the URL.” The server turns that sentence into the same versioned publish the REST API would have made.

The original plan for this post said eight tools. The live server has nine. Invites arrived before the article did, and a catalog should describe the software rather than preserve a round number.

Connect it

First mint an account and keep both values in the response. The token is shown once. The claim URL is how the human keeps the account and its pages past the 30-minute provisional window.

curl -sX POST https://api.openartifacts.sh/v1/signup

Put the returned token in your shell, then add the remote server to Claude Code:

export OA_TOKEN='oa_sk_...'

claude mcp add --transport http \
  --header "Authorization: Bearer $OA_TOKEN" \
  openartifacts https://mcp.openartifacts.sh/mcp

Check it with claude mcp get openartifacts or the /mcp panel inside Claude Code. Claude Code's current remote MCP documentation calls this transport http; the MCP specification calls it Streamable HTTP.

OpenArtifacts uses the small end of that specification. A client sends JSON-RPC over HTTP and gets a JSON response; there is no separate process for the user to install. The MCP specification also allows remote servers to offer streaming and resumable sessions, but a publishing tool does not need that machinery to be useful.

Now give the agent a concrete job:

Publish the site in this directory as release-notes. Keep the paths relative, then give me the live URL and the account claim URL.

The model discovers the tools through tools/list, asks before using them according to the client's permission policy, and calls publish_artifact. MCP tools are model-controlled functions with JSON Schema inputs; that is the contract defined by the MCP tools specification, not an OpenArtifacts convention.

What the nine tools actually do

publish_artifact accepts a slug and text files shaped as {path, content}. It creates an artifact on first use and a new version on later uses of the same slug. Its response includes the stable public URL. Binary assets are the one deliberate gap: use the multipart REST endpoint for those.

list_artifacts returns the account's artifacts with URL, visibility, moderation state, and active version.

get_artifact returns one artifact and its complete version list. Call it before a rollback instead of guessing version numbers.

rollback_artifact moves the live pointer to an existing version. The URL does not change and the old version is not copied.

delete_artifact stops the URL from serving. Publishing the slug later can restore the artifact at the same host.

get_account reports expiry, allowance, balance, member count, and whether invite codes may be redeemed by agents. While the account is provisional it also returns the claim URL that should be shown to the human immediately.

create_claim_link rotates that URL. Rotation invalidates the earlier code; it does not extend an already expired account.

create_invite makes a bounded code for a claimed, shared account. A human opens the invite URL. Another agent redeems the code through the REST join endpoint and receives an artifact-only token on the shared account. We cover the ownership and offboarding consequences in Team up: invites, member tokens, and agents that share an allowance.

add_credits exists only on local development's fake dev rail today. The production-shaped x402 and MPP entries are typed stubs, not payment promises. An agent must tell the human an amount and get agreement before moving money.

The tool result is meant to be read

An HTTP API often treats a non-2xx status as the end of the useful response. Tool callers need the opposite. A missing artifact, exhausted allowance, or bad slug comes back as an MCP tool result with isError: true and a JSON body:

{
  "code": "payment_required",
  "message": "...",
  "hint": "tell the human the amount, then take this next action"
}

That is a business failure, not a broken JSON-RPC connection. The agent can read the hint, explain the state, and recover. Invalid JSON-RPC still uses a protocol error. Keeping those two classes separate turned out to matter more than using an MCP SDK.

The tools also share the public REST API's boundaries. Tokens carry scopes. A token pinned to one artifact cannot list or change its neighbours. Fresh content is limited to 50 files and 10 MB. The result is not an MCP-flavoured shadow product; it is another door into the same artifacts, versions, account, and URLs.

Why MCP is the shortest integration

REST is still the sharpest interface for scripts, and the multi-file publishing guide shows every byte on the wire. MCP wins when a person wants to delegate an outcome rather than orchestrate calls. The tool descriptions tell the model that reused slugs create versions, claim links expire, team allowances are shared, and public URLs belong in the final answer.

That last detail is easy to underrate. A deployment tool that successfully publishes but forgets to surface the URL has failed its user. OpenArtifacts puts that instruction in the server initialization text and in the publish tool description because agents read contracts literally.

Starting is free: the unauthenticated signup call creates a working provisional account with five publishes and no form. Claiming it unlocks 100 free publishes per UTC month. MCP changes how the agent discovers the operations; it does not add a second signup ceremony.

Addendum, 2026-09-30: services over MCP

The server has grown from nine tools to thirteen since this post, and publish_artifact now runs services as well as sites. The title and the tour above describe the server as it shipped on 2026-09-03; this section covers what changed.

A service is the same publish with "type": "service" and a start command that listens on $PORT. install, port, size and sleep_after_s are optional, and all of them can live in an oa.json among the files instead, so a repository that already carries its deploy config publishes unchanged. Arguments override oa.json. Over MCP a service bundle holds up to 500 files and 10 MB, because the whole JSON-RPC body is parsed in memory; leave dependencies out and let install fetch them.

Four tools operate what was published:

The part worth designing for is the crash loop. A process that dies at boot is restarted with backoff, so for about half a minute it sits in starting with nothing in error. An agent that polls for healthy there wastes turns. So as soon as restarts rises above zero, the status hint says how many times the process exited, with the last exit code, and to call get_logs now. After five exits the state becomes crashed and error carries the last 50 log lines. The loop that closes it is short: publish, get_service_status with wait_s, read the logs, fix the files, and publish_artifact again with the same slug. The URL does not change.

Publish this FastAPI app as a service called notes-api, wait until it is healthy, and give me the URL. If it crashes, read the logs and fix it.

Two things stay off MCP on purpose. Environment variables and one-off commands (exec) are REST and CLI only, because secrets and arbitrary commands do not belong in a chat transcript; the human sets them with oa env set or PUT /v1/artifacts/<slug>/env. Status and logs can still contain whatever the service printed, so both tool descriptions ask the model to summarise rather than repeat values.

The add_credits paragraph above is also out of date. The standard payment rails went live on 2026-09-24, and on a connection made with an API token add_credits now returns a signed payment link, valid for up to 24 hours. A human opens it to pay by card, and an MPP or x402 client can pay the same URL in USDC. Nothing is added until the payment lands, so the agent states the amount first. The ChatGPT app connects over OAuth and keeps simulated credit on development deployments only. Two tools also gained role checks that match the REST API: create_invite needs an admin, and create_claim_link needs the owner.

Your agent can have a URL before you finish this sentence — free, no signup form.

curl -X POST https://api.openartifacts.sh/v1/signup
curl -X POST https://api.openartifacts.sh/v1/publish \
  -H "Authorization: Bearer oa_sk_..." -F slug=my-page -F files=@index.html

Or hand it the whole flow at once: the skill. Claiming your account unlocks 100 free publishes a month.


← all posts · openartifacts.sh · skill.md