MCP reference
Every MCP tool, from the same list the computer sends a connected assistant.
Your computer is an MCP server at your owner address plus /mcp, for example https://yourname.emptyos.com/mcp. Getting started shows how to add it to an assistant, and Client access explains what each access level allows.
- Every connection receives the full tool list. If a Read-only connection calls a Full access tool, the computer returns
permission-requiredand the Client access address. - A successful call returns its JSON result as
structuredContentand as text. If the computer refuses a valid call, the result setsisErrorand includes{"error", "code"}. More fields can appear, such as the page's current head. A call with a missing or invalid parameter returns a JSON-RPC error. - The endpoint uses Streamable HTTP and keeps no session. Each POST carries one JSON-RPC message. A request returns one JSON response. A notification returns an empty
202. AcceptedMCP-Protocol-Versionvalues are2025-06-18and2025-11-25. The endpoint refuses a batch. It refuses a browser request that sendsOrigin. - Each tool lists the hints sent with it.
read-onlymeans the call does not change the computer.destructivemeans the call can change or remove something.idempotentmeans sending the same arguments again has no further effect.open worldmeans the call can reach something outside the computer.
Read tools
Every connection can call these tools.
get_status
Computer status. Summarize this EmptyOS computer. The result includes the hostname, software version, counts of Things, Projects, and Databases, service states, and anything that needs attention. The data matches empty status --json.
No parameters.
Hints: read-only, idempotent.
list_things
List Things. List every Thing on this computer. A Thing is a published site, file, or service. The result includes its description, icon, type, route, visibility, Project, linked Databases, sharing, service state, and last commit time. The data matches empty things --json.
No parameters.
Hints: read-only, idempotent.
describe_thing
Describe a Thing. Describe one Thing by id. The result includes its type, source directory, manifest fields, route, URL, visibility, viewers, Project, linked Databases and whether each one exists, how it runs, and its Git state. The data matches empty thing describe <id> --json.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The Thing id, as listed by list_things. Matches ^[a-z0-9_-]+$. |
Hints: read-only, idempotent.
get_thing_logs
Service logs. Read the most recent log lines of a service Thing from its system journal. Static Things have no logs. The data matches empty thing logs <id> --lines <count> --json.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The service Thing id. Matches ^[a-z0-9_-]+$. |
lines |
integer | No | How many recent lines to read. From 1 to 1000. The default is 100. |
Hints: read-only, idempotent.
list_projects
List Projects. List the Projects on this computer, with each description and how many Things it contains. The data matches empty projects --json.
No parameters.
Hints: read-only, idempotent.
list_datasets
List Databases. List the Databases (SQLite files) on this computer, with each name and size. This tool does not query them. The data matches empty datasets --json.
No parameters.
Hints: read-only, idempotent.
describe_dataset
Describe a Database. Describe one Database by id. The result includes its name, type, the database file's size and last change, and which Things use it. The result also includes the environment variable a service reads the database from. The data matches empty dataset describe <id> --json. This tool runs no query.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The Database id, as listed by list_datasets. Matches ^[a-z0-9_-]+$. |
Hints: read-only, idempotent.
Full access tools
These tools need Full access.
read_skill
Read an EmptyOS skill. Read the installed instructions without running a shell command. Needs the owner's "Full access" permission. Before work beyond publishing one page or uploading one file or a ready static site, call with name "operate-emptyos-computer"; this also returns EMPTY.md, labeled as the startup guide. Before creating or changing a Thing's source, dependencies, build, runtime configuration, or Database schema, also call with name "build-emptyos-things". Omit document to read SKILL.md. For a linked reference or template, call again with the same name and its document path from available_documents. Reads the computer's current installed files, including owner edits. It only returns text; it does not run the instructions or grant permission to change the computer.
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
operate-emptyos-computer or build-emptyos-things |
Yes | The installed skill name. |
document |
SKILL.md or references/manifest-contracts.md or assets/manifests/thing-file.yaml or assets/manifests/thing-static.yaml or assets/manifests/thing-service.yaml or assets/manifests/project.yaml or assets/manifests/dataset-sqlite.yaml or references/stack-selection.md or references/verification-contract.md or references/activation-and-validation.md or assets/thing.gitignore |
No | A document from this skill's available_documents; paths are relative to its directory. The default is SKILL.md. |
Hints: read-only, idempotent.
publish_page
Publish a page. Publish one HTML document as a new private Thing on this computer. Only the owner can open it until it is shared or made public. Use the optional description to add useful context beyond the name in Home. Put CSS and JavaScript in the document. End the page's top header with <emptyos-badge></emptyos-badge> and load <script src="/_system/app/badge.js" defer></script>; EmptyOS shows the signed-in owner or viewer there, and a globe with the word Public on a public Thing. Do not add other EmptyOS branding or computer-navigation links unless the owner asks. Needs the owner's "Full access" permission for this connection. A repeat of a successful call returns the existing page. The result's access sentence says who can open the Thing; tell the owner.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The new Thing id. Use lowercase letters, digits, and hyphens. It becomes part of the page address. Matches ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$. |
name |
string | Yes | The display name. At most 80 characters. |
description |
string | No | Optional text Home shows under the name. Use a few words that add context beyond the name; omit it when it would only repeat the name. At most 200 characters after whitespace is collapsed to spaces. Empty text means no description. |
html |
string | Yes | The complete HTML document. |
project_id |
string | No | An existing Project to put the page in. Matches ^[a-z0-9_-]+$. |
Hints: idempotent.
read_page
Read a page. Read the committed public files of a generated static page (type: static), created by publish_page or empty put, including the head to pass to update_page. For a service (type: service) or a custom static layout, use start_command with the directory returned by describe_thing. A text file comes back whole. The result lists a binary file, or a very large file, without its content. Needs the owner's "Full access" permission for this connection.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The page's Thing id. Matches ^[a-z0-9_-]+$. |
Hints: read-only, idempotent.
update_page
Update a page. Replace, add, or remove public files in a generated static page (type: static), created by publish_page or empty put. For a service (type: service) or a custom static layout, use start_command with the directory returned by describe_thing. Use the head from read_page. A file you do not name stays as it is. The computer publishes the new version and keeps the old one, so the owner can undo the change from Home. If the page changed after you read it, the computer refuses the call. Read the page again. Needs the owner's "Full access" permission for this connection.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The page's Thing id. Matches ^[a-z0-9_-]+$. |
expected_head |
string | Yes | The head that read_page returned. Matches ^[0-9a-f]{40}([0-9a-f]{24})?$. |
files |
array of {path, content} |
No | Files to create or replace. Paths are relative to the page, for example index.html or css/site.css. At most 50 items. |
remove |
array of strings | No | Paths of files to delete. At most 50 items. |
Hints: destructive, idempotent.
fetch_thing
Fetch a Thing. Request one path of a Thing as its owner and return the HTTP status, the response headers, and the body. Use it to check what a site, file, or service serves, for example after you publish it. Gateway answers as it answers the owner's browser, but the result does not show the headers Recovery adds for browsers (no-store caching, frame protection, and nosniff). A private service sees a placeholder owner (emptyos-fetch, fetch@example.invalid), not the owner's account. A GET runs the service's code, so it can have the same effects as an owner visit. Redirects are not followed. A text body returns its first 64 KiB; every complete body returns its size and SHA-256. Use range to read a later part or to check byte-range support. Needs the owner's "Full access" permission for this connection. The data matches empty thing fetch <id> [<path>] --json.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The Thing id, as listed by list_things. Matches ^[a-z0-9_-]+$. |
path |
string | No | The path at the Thing's address, with an optional query. The default is /. At most 2048 characters. |
method |
GET or HEAD |
No | The default is GET. |
range |
string | No | One byte range to send as the Range header, such as bytes=0-1023. |
Hints: none.
create_project
Create a Project. Create a Project, a named group of Things. Needs the owner's "Full access" permission for this connection. A repeat of a successful call returns the existing Project.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The new Project id. Matches ^[a-z0-9_-]+$. |
name |
string | Yes | The display name. At most 80 characters. |
Hints: idempotent.
assign_project
Move a page to a Project. Move one page into a Project that already exists. Needs the owner's "Full access" permission for this connection.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The page's Thing id. Matches ^[a-z0-9_-]+$. |
project_id |
string | Yes | The Project id. Matches ^[a-z0-9_-]+$. |
Hints: idempotent.
share_thing
Share a Thing. Let one person open a private Thing. Before sharing a browser UI, check for EmptyOS branding or computer-navigation links added without an owner request and remove them; keep the EmptyOS account badge. Sharing does not rewrite the Thing's HTML. EmptyOS emails that person the link when it can. Report the result's delivery sentence: emailQueued says whether this call queued an email (null means unknown), and emailStatus explains why. Queued does not confirm delivery. A repeated share queues no new email; it does not establish whether an earlier email was sent. Give the owner the returned link to send if needed. The person you named opens that link and signs in with Google as that email. The result's access sentence says who can open the Thing; tell the owner. Needs the owner's "Full access" permission for this connection.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The Thing id. Matches ^[a-z0-9_-]+$. |
email |
string | Yes | The Google account email of the person to share with. |
Hints: idempotent, open world.
unshare_thing
Stop sharing a Thing. Stop sharing a Thing with one person, or with everyone it is shared with. The computer refuses their next visit. Needs the owner's "Full access" permission for this connection.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The Thing id. Matches ^[a-z0-9_-]+$. |
email |
string | No | The person to stop sharing with. To stop sharing with everyone, omit this and set all to true. |
all |
boolean | No | Stop sharing with everyone. |
Hints: destructive, idempotent, open world.
set_thing_visibility
Make a Thing public or private. Set a Thing to public or private. Anyone with the public address can open a public Thing. A public service receives no visitor identity, so the app must protect owner actions and private records itself, for example with an owner key and unguessable record links. Before making a browser UI public, check for EmptyOS branding or computer-navigation links added without an owner request and remove them; keep the EmptyOS account badge. This tool does not rewrite the Thing's HTML. The result's access sentence says who can open the Thing; tell the owner. Needs the owner's "Full access" permission for this connection.
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | The Thing id. Matches ^[a-z0-9_-]+$. |
visibility |
public or private |
Yes | Who can open the Thing. |
Hints: destructive, idempotent, open world.
start_command
Run an owner command. Build and edit apps, websites, and services on this computer, including services that keep data in declared Databases, or run another noninteractive shell command as the trusted computer owner. Needs the owner's "Full access" permission. First use read_skill with name "operate-emptyos-computer"; before creating or changing a Thing, also read "build-emptyos-things". Read their linked references and templates with read_skill, not a shell command. Write and verify an app's source here when it runs on this computer or keeps data here. Output that needs tools this computer lacks, such as rendered media, can be made in your own workspace and sent with prepare_thing_upload. Use empty commands for publication, Databases, and sharing. Set wait_seconds to wait up to 10 seconds for the result in this call; the default is 0 (return immediately). Admission time counts toward the wait. If the returned state is starting or running, continue with read_command. The wait does not stop the command. To retry a lost response, send the same operation_id, command, and timeout_seconds; wait_seconds can change. A command can finish after access is removed, including during a wait. At most four commands run at once. Each command can run for 600 seconds and capture 1 MiB of output. A result expires after 24 hours or 128 completed commands. A change this command makes does not automatically support Undo.
| Parameter | Type | Required | Description |
|---|---|---|---|
operation_id |
string | Yes | A unique operation id for this connection. Reuse it only to retry the same command. Matches ^[A-Za-z0-9_-]{1,80}$. |
command |
string | Yes | The shell command. At most 65536 bytes. |
timeout_seconds |
integer | No | How long the command may run. From 1 to 600. The default is 120. |
wait_seconds |
integer | No | How long this call waits for completion, including admission time. A wait deadline leaves the command running. From 0 to 10. The default is 0. |
Hints: destructive, idempotent, open world.
read_command
Read command progress. Read this connection's command state and the captured stdout and stderr. Needs the owner's "Full access" permission. Poll until the state is succeeded, failed, cancelled, timed-out, or interrupted. An interrupted command might have changed files. Inspect the computer before you run another command.
| Parameter | Type | Required | Description |
|---|---|---|---|
operation_id |
string | Yes | A unique operation id for this connection. Reuse it only to retry the same command. Matches ^[A-Za-z0-9_-]{1,80}$. |
Hints: read-only, idempotent.
cancel_command
Cancel an owner command. Stop this connection's command and its service processes. Needs the owner's "Full access" permission. Cancelling does not undo a change the command already made. Poll read_command for the final result.
| Parameter | Type | Required | Description |
|---|---|---|---|
operation_id |
string | Yes | A unique operation id for this connection. Reuse it only to retry the same command. Matches ^[A-Za-z0-9_-]{1,80}$. |
Hints: destructive, idempotent, open world.
prepare_thing_upload
Prepare a Thing upload. Upload a file, a ready static site, or a Thing already built in your cloud workspace, without copying it through tool text. Use it when your workspace has tools the work needs and this computer lacks, such as for rendered media or a built static site. Needs the owner's "Full access" permission. Choose a kind. "file" sends one file as it is; an .html file becomes the page. Give filename and name. "site" sends a tar or tar.gz archive with index.html at its root, made with tar -czf site.tgz -C <site-directory> .; give name. For file and site, the computer writes the manifest and verify script, and the result is a private page; update_page can change its files whose paths use only letters, digits, dots, hyphens, and underscores. "bundle" sends a Git bundle with exactly one parentless commit on main, a thing.yaml manifest, and an executable verify script (optional prepare); give expected_head. Give the size and SHA-256 of the exact bytes you send. POST them to the returned URL as application/octet-stream with Content-Length and Authorization: Bearer
| Parameter | Type | Required | Description |
|---|---|---|---|
operation_id |
string | Yes | Matches ^[A-Za-z0-9_-]{1,80}$. |
id |
string | Yes | A new Thing id. Matches ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$. |
kind |
file or site or bundle |
Yes | What the bytes are: one file, a tar or tar.gz archive of a static site, or a Git bundle of a manifested Thing. |
size_bytes |
integer | Yes | From 1 to 67108864. |
sha256 |
string | Yes | Matches ^[a-f0-9]{64}$. |
filename |
string | No | For kind file: the file name to publish, such as talk.mp4 or index.html. |
name |
string | No | For kind file or site: the display name. At most 80 characters. |
description |
string | No | For kind file or site: optional text Home shows under the name. Use a few words that add context beyond the name. At most 200 characters. |
project_id |
string | No | For kind file or site: an existing Project to put the Thing in. Matches ^[a-z0-9_-]+$. |
expected_head |
string | No | For kind bundle: the full lowercase commit id. Matches ^[a-f0-9]{40}(?:[a-f0-9]{24})?$. |
Hints: idempotent.
import_uploaded_thing
Import an uploaded Thing. Verify and import the complete upload sent to prepare_thing_upload. Needs the owner's "Full access" permission. For a file or site, the computer first builds the page with its manifest and verify script. The existing importer validates the result and runs prepare and verify before installing a new Thing; the command output reports the new Thing and its URL. Existing Things are never replaced, and services stay stopped. Call within three minutes after the upload completes. This uses the owner command runner and waits up to ten seconds; if starting or running, poll read_command with the returned operation_id. Retry a lost response with the same upload_id. A command can finish after access is removed. A Gateway restart invalidates uploads that have not started importing; started imports remain readable through read_command. A failed import needs inspection before a new upload; command results have the same retention as start_command.
| Parameter | Type | Required | Description |
|---|---|---|---|
upload_id |
string | Yes | Matches ^[a-f0-9]{32}$. |
Hints: destructive, idempotent, open world.