Your coding agent just generated a build report, a test transcript, a screenshot, or a 200 MB bundle. Where does it go? Pasted into chat (gets lost), dumped toDocumentation Index
Fetch the complete documentation index at: https://docs.artifacta.io/llms.txt
Use this file to discover all available pages before exploring further.
/tmp (gets cleaned), pushed into a random S3 bucket (no
session view, no metadata, no shareable link). Artifacta is the artifact
store built for that — purpose-built for AI agents from the ground up —
and @artifacta-mcp/mcp is how your agent talks to it.
The server runs over MCP stdio, so it works in Claude Code, Codex, Cursor,
Windsurf, Cline, Zed, and Claude Desktop, plus any other MCP-compatible
host. Once configured, your agent can store files, list past artifacts, mint
private download URLs for its own follow-up calls, and — with consent —
publish public share links, all without leaving the editor.
This guide gets you from zero to first artifact in under five minutes.
Heads-up for Claude Desktop and Cursor. Three tools are classified
destructive —
create_download_link (public share URLs), delete_artifact
(soft-delete by id), and seal_session (irreversible, no unseal) — and are
hidden from tools/list unless you add --allow-destructive to the launch
args. See Claude Desktop & Cursor: destructive
tools for the recommended config
and Autonomy boundary for the full compliant /
non-compliant client behavior.Install
The server is distributed via npm. Most clients launch it withnpx, so there
is nothing to install globally on your machine.
You will need:
- Node.js 20 or newer. The package’s
enginesfield rejects earlier versions before any tool executes. - An Artifacta API key. Create one in the dashboard’s API keys
page. The key shape is
ak_live_followed by 32 alphanumeric characters.
@artifacta-mcp/mcp
unpinned so npx resolves to the latest published release on host restart;
patch and minor fixes (including security patches) roll out without a config
edit. Pin to a specific version — e.g. @artifacta-mcp/mcp@1.0.0 — only if
you need a frozen install, such as a managed deployment with gated config
rollouts. The current published line is 1.0.0 — the stable contract;
no further breaking changes to the existing 11 tools / 4 resources without
v2.
Claude Desktop
Open Claude Desktop’s settings → Developer → Edit Config, and add an entry undermcpServers. The full file lives at
~/Library/Application Support/Claude/claude_desktop_config.json on macOS and
%APPDATA%\Claude\claude_desktop_config.json on Windows.
claude_desktop_config.json
create_download_link (public share URLs),
delete_artifact, and seal_session — are hidden unless you add
--allow-destructive. See Autonomy boundary for the
matrix and create_download_link consent
for how to approve share links in chat.
Restart Claude Desktop. The Artifacta tools appear in the tool palette and
the agent can call them directly.
Cursor
Add the same block to~/.cursor/mcp.json (create the file if it does not
exist):
~/.cursor/mcp.json
--allow-destructive so create_download_link, delete_artifact, and
seal_session appear in the tool list. See Autonomy
boundary and create_download_link
consent.
Restart Cursor and the Artifacta tools become available in agent mode.
Claude Code
For a single project, drop a.mcp.json at the repo root (commit it so the
whole team picks up the server):
.mcp.json
${ARTIFACTA_API_KEY} from your shell environment at
launch, so the literal key stays out of the committed file. For a one-line
equivalent without editing JSON, use the CLI:
ARTIFACTA_API_KEY in the shell that launches Claude Code. The
--allow-destructive rule from Claude Desktop / Cursor applies here too —
without it create_download_link, delete_artifact, and seal_session
are hidden from the tool list. See Autonomy
boundary.
Codex
Codex (OpenAI CLI) reads MCP configuration from~/.codex/config.toml —
TOML, not JSON. Add an [mcp_servers.artifacta] table:
~/.codex/config.toml
mcp_servers with an underscore — mcp-servers or
mcpservers is silently ignored. For a project-scoped install, the same
table goes in .codex/config.toml at the project root (Codex must trust
the project first). Restart Codex; Artifacta tools appear in the next
session, with the same --allow-destructive rule.
Other MCP clients
Windsurf, Cline, Zed, and Continue all accept the samemcpServers JSON
shape as Claude Desktop — drop the Claude Desktop block above into the
client’s MCP config file (consult the client’s docs for the path) and
restart. The --allow-path and --allow-destructive flags carry over
unchanged.
Verifying the install
Run the version flag from any shell:1.0.0 the binary resolved correctly through npx.
Claude Desktop & Cursor: destructive tools
- Three tools are classified destructive:
create_download_linkmints a publicdl.artifacta.io/lnk_…URL,delete_artifactsoft-deletes an artifact by id, andseal_sessionmarks a session as irreversible (nounseal). - Hosts that advertise
experimental.confirmationsprompt before each call; Claude Desktop and Cursor do not, so all three tools are hidden fromtools/listby default. - Add
--allow-destructiveto the launchargsto expose them; each call then emits a one-line stderr audit[artifacta-mcp] destructive call: <tool>(<args>)instead of a host confirmation UI. The flag is never read from the environment ormcp.toml— it must be in the launch command. - Approve destructive calls explicitly in chat before the agent runs them.
For share links, see
create_download_linkconsent; for delete and seal, the same principle applies — read the agent’s plan, confirm, then proceed. - If you use
store_artifact.path, combine--allow-destructivewith--allow-pathin the sameargsarray — see Path confinement and--allow-path.
First call: whoami
whoami is the right starting tool: it confirms authentication, surfaces the
plan tier, and reports current usage so the agent can size subsequent
operations against quota. It is free of side effects and quota-cheap.
A typical agent prompt that exercises it:
“Confirm we’re authenticated against my Artifacta account, then list the last 10 artifacts.”The agent will call
whoami, receive a response shaped like the example
below, then chain list_artifacts with limit: 10:
whoami response
artifacta://whoami. The MCP server caches the
api_key_last_4 so that a later authentication failure can include the key
suffix in the remediation message (“Last-known key suffix: ****abcd.”).
Using Artifacta from your coding agent
Oncewhoami confirms auth, here are the four flows that cover most agent
work. Paste any of these prompts into your coding agent — it will pick the
right tool(s) on its own.
1. Save a generated file
“SaveThe agent calls./out/build_report.htmlto sessionbuild_2118and tag itkind=report, status=green.”
store_artifact with path: "./out/build_report.html",
session_id: "build_2118", and metadata: { kind: "report", status: "green" },
then returns the new art_… id. Re-running the same prompt after a crash
returns the same artifact instead of creating a duplicate — the MCP server
auto-injects an Idempotency-Key and surfaces it on success as
_meta.idempotency_key. Local file paths must clear
path confinement.
2. Find prior work
“Show me the test outputs from sessionThe agent callsci_run_42taggedkind=failure, newest first.”
list_artifacts with session_id: "ci_run_42" and
metadata: { kind: "failure" }. Results come back in
created_at DESC, artifact_id DESC order — the API’s only sort contract —
with opaque cursor pagination if the list is long.
3. Hand a file to a human
“Publish a 24-hour share link for artifact art_a1b2c3d4e5f6g7h8.”
The agent calls create_download_link with expires_in: 86400, then prints
the resulting https://dl.artifacta.io/lnk_… URL. On Claude Desktop, Cursor,
Claude Code, and Codex this requires --allow-destructive in the launch
args — without it the tool is hidden from tools/list.
get_artifact_download_url is not a substitute: that returns a private
1-hour presigned URL for the authenticated caller, not a shareable public
link.
4. Resume a session across runs
“Re-open sessionThe agent callsnightly_eval_2026_05_25, list its artifacts, and append today’s run output from./eval/out.jsonl.”
list_artifacts with the session id, then store_artifact
with the same session_id to append. Sessions are user-defined strings
supplied at upload — there is no separate create_session tool, and the
session row appears the first time an artifact is stored against that id.
Subsequent runs just keep writing to the same string.
Write tools
v0.2 added four write tools and one preview resource so an agent can produce, persist, and share artifacts end-to-end. They are unchanged in v1.0.| Tool | What it does | Idempotency / retry |
|---|---|---|
store_artifact | Create an artifact from inline content or a local path. | Auto Idempotency-Key; safe to replay. |
request_upload_url | Mint a presigned R2 upload URL for files larger than store_artifact’s 500 MB ceiling. Pro-only — Free-tier keys receive quota_exceeded with an upgrade URL. | Non-idempotent — no auto-retry on 5xx. |
complete_upload | Finalize a presigned upload into a committed artifact. | Idempotent — auto-retries 5xx. |
create_download_link | Mint a public dl.artifacta.io/lnk_… share link. | Non-idempotent; consent-gated. |
artifacta://artifact/{id}/bytes resource exposes an artifact’s
bytes inline for preview. See Resources for the full resource
surface, including the 100 MB cap behavior.
A note on sessions
session_id is a user-defined string supplied at upload time
(store_artifact.session_id, or carried through request_upload_url →
complete_upload). There is no separate create_session tool — a session row
appears the first time an artifact is stored against that id, and surfaces in
list_sessions and artifacta://session/{session_id} from that point on.
Sessions can be sealed with seal_session (v1.0 — irreversible, no
unseal). Once sealed, further uploads against that session_id are
refused at the API layer with session_sealed. list_sessions and
artifacta://session/{session_id} continue to report is_sealed for
read-only visibility. See Destructive tools for the
full description and the autonomy-boundary gating that protects the call.
store_artifact: content vs path
store_artifact accepts exactly one of two inputs:
content— the bytes inline, base64-encoded, up to 10 MB decoded. Best for small, in-memory results (a generated report, a JSON blob).path— a path to a local file, streamed to the API as multipart, up to 500 MB. Best for files already on disk. The path must pass path confinement. For files larger than 500 MB, switch torequest_upload_url→complete_upload— note that path is Pro-only; Free-tier keys receivequota_exceededwith an upgrade URL, so on Freestore_artifact.pathis the upload ceiling.
path.
Path confinement and --allow-path
store_artifact.path reads files from the local filesystem, so it is guarded by
the path-confinement engine:
- Default allow-list: the directory the MCP server was launched in (its working directory). A path outside it is refused.
- Extend it with one or more
--allow-path=<dir>launch flags:
claude_desktop_config.json
--allow-path and --allow-destructive belong in the same args
array when you need local file uploads and public share links.
- The deny-list always wins, even inside an allow-listed directory:
~/.ssh,~/.aws,~/.gnupg,~/.config/gh,~/.kube,~/.netrc,~/.artifacta,/etc,~/Library/Keychains, and anycredentials.jsonor.env*file are refused. Symlinks are resolved withrealpath()before the check, so a symlink pointing outside the allow-list (or into the deny-list) is refused after resolution. Sockets, FIFOs, and device files are refused.
--allow-path only accepts absolute paths; a relative value exits at
startup with code 2. The CLI flag is not inferred from a config-file field,
but the server also appends roots from the
ARTIFACTA_MCP_ALLOW_PATH environment variable (colon-separated absolute
paths) when present in the launched server’s env block — that env var
widens the allow-list at startup the same way --allow-path does, so audit
it whenever you review who can read local files through store_artifact.path.
Ambiguous completion: when a write may or may not have happened
request_upload_url and create_download_link are non-idempotent — the API
does not honor an Idempotency-Key on them. So when one returns a 5xx or the
network drops, the MCP server makes exactly one attempt and returns
guidance instead of silently retrying:
The request may or may not have completed. Do not retry blindly — verify current state first (e.g. list links / list artifacts) or escalate to a human.This is deliberate: a blind retry could mint a second public download link or a duplicate upload slot. The correct agent behavior is to verify or escalate, not retry. (
store_artifact and complete_upload, which are
idempotent, do retry 5xx automatically — a replay is safe there.)
create_download_link consent
create_download_link produces a public URL, so it is classified
destructive for consent purposes:
- Clients that advertise
experimental.confirmationsreceiverequiresConfirmation: trueand prompt the human before the call runs. - Claude Desktop and Cursor do not advertise confirmations. Without
--allow-destructivein the launchargs,create_download_linkis omitted fromtools/listentirely — see Claude Desktop & Cursor: public share links for the recommended install config. - Other clients that do not advertise confirmations behave the same:
the tool stays hidden unless the server was launched with
--allow-destructive(and each such call then emits a one-line stderr audit). This prevents an agent from silently leaking a shareable URL.
Destructive tools
v1.0 adds two destructive tools. They share the same consent surface ascreate_download_link: filtered from tools/list for non-compliant
clients (unless --allow-destructive is set), and carrying
requiresConfirmation for compliant ones. See Autonomy
boundary for the full matrix.
| Tool | What it does | Replay behavior |
|---|---|---|
delete_artifact | Soft-delete an artifact by id (DELETE /v1/artifacts/{artifact_id}). | A second call on an already-deleted artifact returns { artifact_id, deleted: true, already_deleted: true } rather than an error — safe to retry. |
seal_session | Mark a session irreversible (no unseal) so further uploads against that session_id are refused. | A re-seal returns the existing sealed_at — passthrough at the API. |
destructive and follow the autonomy boundary below.
Neither injects Idempotency-Key (the API gates injection to
POST /v1/artifacts only); both use the idempotentWrite retry policy
(429 once, 5xx up to 3× with jitter) because each operation is naturally
idempotent.
Example agent prompts
“Delete artifactThe agent callsart_a1b2c3d4e5f6g7h8— it has the wrong session id and I am going to re-upload it underbuild_2118.”
delete_artifact with artifact_id: "art_a1b2c3d4e5f6g7h8",
then re-runs store_artifact with the right session_id. On a compliant
client the host prompts before the delete fires; on Claude Desktop / Cursor
the agent prints its plan and waits for chat confirmation, then dispatches
the call (--allow-destructive must be in the launch args).
“Seal session nightly_eval_2026_05_25 — the run is finished and I don’t
want any further uploads against that id.”
The agent calls seal_session with session_id: "nightly_eval_2026_05_25".
After the call, list_sessions reports is_sealed: true and any further
store_artifact against that session id receives session_sealed.
Autonomy boundary
The MCP server filters and prompts for tools based on the client’s declared capabilities ininitialize. Three tools are classified
destructive: create_download_link, delete_artifact, seal_session.
The matrix:
| Client | Default tool list | requiresConfirmation | With --allow-destructive |
|---|---|---|---|
Compliant (advertises experimental.confirmations — e.g. Claude Code) | Destructive tools present. | Set to true on each destructive tool; the host prompts the human before the call. | No change in surface; the flag is unused (the confirmation UI is already intact). |
Non-compliant (no experimental.confirmations — Claude Desktop, Cursor, Codex, most others today) | Destructive tools absent from tools/list. The agent cannot call them. | Not applicable. | Destructive tools appear in tools/list. Each call emits a one-line stderr audit [artifacta-mcp] destructive call: <tool>(<args>) — no host UI confirmation. |
--allow-destructiveis never read from the environment ormcp.toml— it must be in the per-launch CLI args. This prevents a leftover env export from silently unlocking destructive tools.- The
ARTIFACTA_MCP_REQUIRE_WRITE_CONFIRM=1env override promotesrequiresConfirmationon the four write tools (store_artifact,request_upload_url,complete_upload,create_download_link) for compliant clients that want a stricter surface. It does not affect destructive tools — those always require confirmation on compliant clients. - On compliant clients,
create_download_linkis destructive too — the host prompts before each share-link mint. The same one-line stderr audit still emits when--allow-destructiveis the only reason a tool was exposed.
Security model
A consolidated reference for the four security mechanisms the MCP server relies on.1. Path confinement
Applies to:store_artifact.path (the only tool that reads local files).
- Default allow-list = server CWD. Extend with
--allow-path=<absolute-dir>(relative paths exit at startup with code 2; the flag is never read from the environment). - Deny-list always wins:
~/.ssh,~/.aws,~/.gnupg,~/.config/gh,~/.kube,~/.netrc,~/.artifacta,/etc,~/Library/Keychains, anycredentials.json, any.env*. - Symlinks are resolved via
realpath()before allow-list and deny-list checks. Special files (sockets, FIFOs, devices) are refused. - 500 MB ceiling per file, regardless of plan tier. >500 MB → use
request_upload_url→complete_upload.
--allow-path
for configuration examples.
2. Idempotency-Key auto-injection
POST /v1/artifacts(thestore_artifactendpoint) — the only endpoint that auto-injects an Idempotency-Key. The MCP server attachesmcp_<uuid4>unless the caller passes their ownidempotency_key. The effective key is surfaced on success as_meta.idempotency_key.- Every other write endpoint —
request_upload_url,complete_upload,create_download_link,delete_artifact,seal_session— does not inject.complete_upload,delete_artifact, andseal_sessionare naturally idempotent at the API layer (replays return the existing record).request_upload_urlandcreate_download_linkare non-idempotent; see ambiguous-completion below.
3. Retry policy
Per plan §6.1, retries are tied to backend idempotency:| Tool | Retry policy | 5xx auto-retry? | Idempotency-Key injected? |
|---|---|---|---|
whoami, list_artifacts, get_artifact, get_artifact_download_url, list_sessions | safe | Yes (3× w/ jitter) | n/a (GET) |
store_artifact | idempotentWrite | Yes (3× w/ jitter) | Yes |
request_upload_url | nonIdempotentWrite | No (1 call, then §6.1 ambiguous-completion text) | No |
complete_upload | idempotentWrite | Yes (3× w/ jitter) | No (natural idempotency) |
create_download_link | nonIdempotentWrite | No (1 call, then §6.1 ambiguous-completion text) | No |
delete_artifact, seal_session | idempotentWrite | Yes (3× w/ jitter) | No (natural idempotency) |
Retry-After header value if
present, otherwise jittered backoff. The 3-consecutive-failure outage
notifier writes a single Artifacta API unreachable… line to stderr after
the third sequential transport-level failure and resets on the next
success.
4. Destructive-tool gating
See Autonomy boundary. One-paragraph summary: tools classifieddestructive (create_download_link, delete_artifact,
seal_session) are hidden from non-compliant clients unless the
per-launch --allow-destructive flag is set, and carry
requiresConfirmation: true for compliant clients. Each call emits a
one-line stderr audit when the flag is the reason the tool was exposed
without a confirmation surface.
Resources
In addition to tools, the MCP server exposes four resource URIs. Hosts that prefer the resource model — or want to surface Artifacta data in a side panel without firing a tool call — can read these directly.| URI | Returns | Notes |
|---|---|---|
artifacta://whoami | Same payload as the whoami tool. | Cheap; safe to poll. |
artifacta://artifact/{artifact_id} | Same metadata body as get_artifact. | Tenant-internal fields (tenant_id, deleted_at) are stripped at the MCP boundary. |
artifacta://artifact/{artifact_id}/bytes | Inline bytes (text or blob, routed by content type). | Hard-capped at 100 MB — see size cap below. |
artifacta://session/{session_id} | Aggregate view of a session’s artifacts + seal state. | Read-only; sessions cannot be sealed in v0.2 (see A note on sessions). |
…/bytes size cap
The bytes resource is hard-capped at 100 MB. Exactly 100 MB inline is
allowed; 100 MB + 1 byte is refused. Oversize requests fail at the MCP
resources/read layer with an InvalidRequest error — not a tool error
envelope — whose message steers the agent to get_artifact_download_url
(which mints a private 1-hour presigned URL for the authenticated caller; use
create_download_link only if a public, shareable URL is required).
Two refusal variants exist, both returning the same InvalidRequest class:
- Metadata gate — caught from the artifact’s recorded size with a single
get_artifactcall, so an over-cap fetch never touches R2. - R2 oversize gate — backstop in case the metadata size under-reports the actual blob size on disk.
InvalidRequest error class and reissue the read
as a get_artifact_download_url tool call; the resource cannot be widened with
a flag.
Troubleshooting
unauthorized on every call
The MCP server surfaces an unauthorized error when the API rejects the
configured key. Common causes:
ARTIFACTA_API_KEYis not set in the MCP host’s environment. Editing your shell’s.zshrcdoes not propagate to Claude Desktop or Cursor — they read theenvblock from yourmcpServersconfig. Put the key directly inclaude_desktop_config.jsonor~/.cursor/mcp.jsonand restart the host.- The key was rotated. The remediation message includes the
last-known key suffix (
Last-known key suffix: ****abcd). If that suffix does not match the key you currently have in the dashboard, regenerate or paste the new key into the host config. - The key is malformed. Keys must match
ak_live_plus 32 alphanumeric characters. The server exits at startup with code 2 if the shape check fails — check the host’s stderr log for the rejection message. - The tenant is in deletion grace period. The server replaces the
generic remediation with
"Account is scheduled for deletion — see https://app.artifacta.io/dashboard/account."Restore the account from the dashboard before the grace period ends.
request_id in _meta.request_id — and contact support with that
id.
Destructive tools missing from tools/list
If create_download_link, delete_artifact, or seal_session is missing
while every other Artifacta tool appears, you are likely on Claude
Desktop, Cursor, or another non-compliant client without
--allow-destructive in the launch args. Those hosts do not implement
MCP write confirmations, so the server hides destructive-classified tools
by default. See Autonomy boundary for the matrix.
For create_download_link specifically: get_artifact_download_url is
not a substitute — it returns a time-limited presigned URL for the
authenticated caller, not a public share link. Add "--allow-destructive"
to the args array (alongside --allow-path if you use local file
uploads), restart the host, and confirm the tool appears. See Claude
Desktop & Cursor: destructive
tools.
tools/list shows nothing
Make sure the host launched the server. Common causes:
npxcould not resolve@artifacta-mcp/mcp(no network, expired npm cache). Runnpx -y @artifacta-mcp/mcp --versionfrom a shell to reproduce.- The host is running on Node 18 or older. The package’s
engines.nodeis>=20.0.0; the npm install step refuses to run on older Node.
Path arguments are refused even though the file exists
The local path-confinement engine refuses any path outside the server’s allow-list (default: the host’s working directory) and refuses paths inside the built-in deny-list (~/.ssh, ~/.aws, ~/.config/gh, /etc, …) even
when the allow-list is widened. Pass --allow-path=/your/dir at launch to
extend the allow-list, but the deny-list always wins.
This guards the store_artifact path argument (v0.2). See Path confinement
and --allow-path for the full deny-list and
configuration examples.
What’s next
- Anthropic MCP introduction — protocol fundamentals if you are new to MCP.