Metadata-Version: 2.4
Name: artifacta-mcp
Version: 1.0.0
Summary: Artifacta MCP server — exposes the Artifacta artifact store to AI agents via the Model Context Protocol
Project-URL: Homepage, https://artifacta.io
Project-URL: Documentation, https://docs.artifacta.io/mcp
Project-URL: Repository, https://github.com/sagapeak/artifacta
Project-URL: Issues, https://github.com/sagapeak/artifacta/issues
Author-email: Artifacta <team@artifacta.io>
License-Expression: MIT
License-File: LICENSE
Keywords: agents,ai,artifacts,mcp,model-context-protocol
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.10
Requires-Dist: artifacta-cli<2.0.0,>=0.3.0
Requires-Dist: jsonschema>=4.20.0
Requires-Dist: mcp>=1.0.0
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Description-Content-Type: text/markdown

# artifacta-mcp

Artifacta MCP server (Python) — the artifact store for AI agents, exposed
via the Model Context Protocol.

This is the Python port of [`@artifacta/mcp`](../typescript). Same tool
surface, same path-confinement engine, same error contract. Reuses the
[`artifacta`](https://pypi.org/project/artifacta-cli/) SDK as the single
HTTP client — no parallel client implementation.

## Installation

Recommended (no global install):

```bash
pipx run artifacta-mcp
```

Or install into a virtualenv:

```bash
python -m venv .venv && source .venv/bin/activate
pip install artifacta-mcp
artifacta-mcp --version
```

Python 3.10+ required.

## Configuration

| Source | How to set |
|--------|-----------|
| `ARTIFACTA_API_KEY` env var | `export ARTIFACTA_API_KEY=ak_live_...` (required) |
| `ARTIFACTA_API_URL` env var | Override API base (default: `https://api.artifacta.io`) |
| `--allow-path=PATH` | Add `PATH` (absolute) to the path-confinement allow-list. May be passed multiple times. |
| `ARTIFACTA_MCP_ALLOW_PATH` | Colon-separated additional allow-list paths. |
| `--allow-destructive` | Expose destructive tools (`delete_artifact`, `seal_session`, `create_download_link`) to clients that do **not** advertise `experimental.confirmations`. Compliant clients always get them with `requiresConfirmation` set. |
| `ARTIFACTA_MCP_REQUIRE_WRITE_CONFIRM=1` | For compliant clients, also require confirmation for `store_artifact`, `request_upload_url`, `complete_upload`, and `create_download_link`. |

Obtain an API key at [https://app.artifacta.io/dashboard/keys](https://app.artifacta.io/dashboard/keys).

## Register with Claude Desktop

Add this block to `~/Library/Application Support/Claude/claude_desktop_config.json`
(macOS) or the equivalent on your platform:

```json
{
  "mcpServers": {
    "artifacta": {
      "command": "pipx",
      "args": ["run", "artifacta-mcp"],
      "env": {
        "ARTIFACTA_API_KEY": "ak_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      }
    }
  }
}
```

Restart Claude Desktop. The `whoami` tool is the fastest way to confirm
authentication.

## Register with Cursor

Add to `~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "artifacta": {
      "command": "pipx",
      "args": ["run", "artifacta-mcp"],
      "env": {
        "ARTIFACTA_API_KEY": "ak_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      }
    }
  }
}
```

## Tool surface

Same eleven tools as the TypeScript package (plan §2):

| Tool | Safety | Notes |
|------|--------|-------|
| `whoami` | safe | Identity + plan + quota |
| `list_artifacts` | safe | Pagination via opaque `cursor`; metadata filter requires Pro for multi-key |
| `get_artifact` | safe | Metadata only — no bytes |
| `get_artifact_download_url` | safe | Presigned R2 URL, 1-hour expiry |
| `list_sessions` | safe | Sessions synthesized from artifacts |
| `store_artifact` | writeIdempotent | Inline `content` ≤10 MB OR local `path` ≤500 MB |
| `request_upload_url` | writeNonIdempotent | Pro only; 5xx is ambiguous — read §6.1 guidance |
| `complete_upload` | writeIdempotent | Finalizes a `request_upload_url` artifact |
| `create_download_link` | destructive | Public URL — gated behind `--allow-destructive` for non-compliant clients |
| `delete_artifact` | destructive | Soft-delete; hard-delete after 30 days |
| `seal_session` | destructive | **Irreversible** — no `unseal` endpoint |

The destructive-tool gating engine (`safety/registry`) hides destructive
tools from clients that do not advertise `experimental.confirmations` in
`initialize`, unless `--allow-destructive` is passed at launch. When that
flag exposes a destructive tool, each call emits a `[artifacta-mcp]
destructive call: <tool>(<args>)` audit line to stderr with secret
redaction and 200-char truncation.

## Path confinement

`store_artifact` with the `path` argument validates the path against:

- An **allow-list** of absolute roots (CWD by default; widen with
  `--allow-path=/abs/dir` or `ARTIFACTA_MCP_ALLOW_PATH=/a:/b`).
- A built-in **deny-list** that always wins: `~/.ssh`, `~/.aws`, `~/.gnupg`,
  `~/.config/gh`, `~/.kube`, `~/.artifacta`, `~/.netrc`, `~/Library/Keychains`,
  `/etc`, `/private/etc`, `/var/lib`, `/proc`, `/sys`, `/dev`.
- Filename pattern denies: `credentials.json`, `.env*`.
- A **500 MB** size ceiling.
- Symlink resolution **before** the allow/deny check (so a symlink under your
  CWD that points into `/etc/passwd` is denied as `/etc/passwd`, not allowed
  by allow-list membership of the link site).

The Python engine is cross-validated against the TypeScript engine via the
shared fixture at `mcp/shared/path-confinement-fixture.json`. Identical
accept/reject is a tested contract.

## Troubleshooting

### "Authentication failed" on the first call

The error message includes structured remediation:
1. Confirm `ARTIFACTA_API_KEY` is set in the MCP server's environment
   (the host process — Claude Desktop, Cursor — must pass it through).
2. Verify the key at <https://app.artifacta.io/dashboard/keys>.
3. The error message includes the last 4 chars of the cached key
   (`****<last4>`) when known, so you can confirm which key was used.

### `delete_artifact` / `seal_session` / `create_download_link` not visible

By design — these are destructive and hidden from clients that do not
advertise `experimental.confirmations`. Either:

- Use a client that advertises the capability (it gets the tool with
  `requiresConfirmation: true`), or
- Pass `--allow-destructive` at launch (you give up the consent surface and
  accept the per-call stderr audit line as your only signal).

### `invalid_request: Path '…' is outside the MCP server's allow-list`

Path confinement refused the upload. Widen with `--allow-path=/abs/dir` or
send bytes inline via the `content` field. If the path resolved to
`/etc`, `~/.ssh`, `.env`, or similar — that's the deny-list firing and is
**not** overridable.

### `request_upload_url` failed with "Artifacta API failed mid-write"

`request_upload_url` is non-idempotent (the API does not honor
`Idempotency-Key` here). On 5xx or network error the reservation may have
been created. Per plan §6.1: call `list_artifacts` with the same
`session_id`/`agent_id` before retrying to avoid duplicate artifacts.

## Versioning

The Python package shares the **major.minor** version with the TypeScript
package (`@artifacta/mcp`). Patch versions are independent. See the
[CHANGELOG](../typescript/CHANGELOG.md) for the canonical release notes.

## Development

```bash
cd mcp/python
python -m venv .venv && source .venv/bin/activate
pip install -e '.[dev]'
pytest
ruff check src tests
python -m build
```

## License

MIT — see [LICENSE](LICENSE).
