This repository provides the decentralised.art MCP server and its decentralised-art-mcp CLI.
It exposes format-agnostic protocol operations under the core.* namespace.
Agents can read the full decentralised.art documentation in markdown, starting from
https://decentralised.art/llms.txt.
The MCP bundles the complete, unabridged llms-full.txt as well as individual
platform pages: agents can read them through MCP resources or core.documentation,
without visiting the website. Start with getting-started for account onboarding,
then read llms-full for system-wide concepts and good practices before designing operations.
If you are a user of this repo, the important question is simple:
- install it
- run it as an MCP server
- register it in your MCP-capable host
- use it
When the MCP server is running, an MCP host can use tools such as:
core.documentationcore.create_accountcore.connector_existscore.get_connectorcore.get_transformationcore.get_conditioncore.transformation_existscore.condition_existscore.get_feed_pagecore.get_feed_stream_replaycore.list_formatscore.get_formatcore.get_accountcore.get_noncecore.create_connectorcore.create_transformationcore.create_conditioncore.simulate_connectorcore.prepare_publicationcore.publish_entitycore.confirm_publicationcore.execute_connectorcore.ensure_preflightcore.build_parent_connector
It also exposes these MCP resources (URI prefix decentralised-art://resource/):
core.getting-startedcore.primercore.docs.llms-full— completellms-full.txt, preserved verbatimcore.docs.tutorialcore.docs.mcpcore.docs.sdkcore.docs.api-referencecore.docs.aboutcore.docs.roadmap
Hosts that expose only tools can read the identical text through
core.documentation. It defaults to getting-started; pass topic to select
a guide. Long guides return next_start_line for continuation.
To read the full platform documentation through a tool, call
core.documentation with {"topic":"llms-full"} and follow next_start_line
until it is null. Resource-capable hosts can read the complete text at
decentralised-art://resource/core.docs.llms-full in one request. Bundling makes
the text discoverable; the host still has to load it into the agent's context.
A new signing identity does not require the user to supply an existing private
key. On macOS/Linux, an agent can call core.create_account with a stable ID:
{"account_id":"draft_owner"}The server generates and persists the Ethereum key locally, returning only
account_id, address and created. Retrying the same ID reuses that identity.
Pass account_id to draft creation, preflight and publication tools. No gas,
funds or API request is needed to create an account; drafts also spend no gas.
Account creation does not create a website profile. These identities do not
expire automatically, even when used temporarily.
Keys are stored in plaintext in an owner-only directory (0700), with key files
mode 0600. The default is ~/.decentralised-art-mcp/accounts, outside the installed
package; use DECENTRALISED_ART_ACCOUNT_ROOT for a persistent absolute location.
Keep it outside source control and preserve it across upgrades/restarts. Losing
its keys loses control of its owners' operations. The tool enforces POSIX file
permissions; other platforms must configure an existing key through host secret
settings. No tool returns or exports the generated private keys.
For an existing owner, use its original local account ID or configure
PRIVATE_KEY locally. Never ask users to paste private keys into chat. An
explicit account_id takes precedence over the environment's PRIVATE_KEY;
passing both account_id and a private_key tool argument is rejected.
Never replace an existing draft's signer with a fresh account.
The chain client uses contracts generated from the pinned api-spec OpenAPI
source at submodules/api-spec (currently pinned to a6d9127).
Endpoint paths, authentication requirements, query and
create/publication request shapes, and execution/publication responses are
checked against those contracts. MCP tool schemas describe MCP inputs, not HTTP
requests. To update the API contract, update the submodule, run
python scripts/generate_api_contracts.py, and run make test; CI checks that
the committed generated file matches the pinned spec. The generated contract is
packaged with the MCP server, so installed clients do not need the submodule.
core.create_* creates local drafts. core.simulate_connector previews them
without login or gas and returns {particles, execution_mode: "simulation"}.
core.execute_connector requires published entities and returns
{block_number, block_hash, runner, registry, particles, execution_mode: "chain"} without
login or gas; the server makes a read-only call at its configured chain block.
Keep the full chain result when using its particles so the block, runner and registry
provenance is retained. Simulation returns only particles and has no chain provenance.
Transformation and condition detail responses use args_count;
Solidity source is no longer part of runtime details.
Chain login signs the EIP-4361 message returned by /nonce/{address} using
EIP-191, then submits {address, nonce, signature} to /auth. Deployments that
return only a decimal nonce use Login nonce: <nonce> and submit
{address, message, signature}. That compatibility contract is generated from
api-spec commit c628d96, frozen in scripts/compat/legacy_auth_contracts.json
so regeneration needs no historical Git objects.
The MCP's core.get_nonce returns the address and the challenge as issued;
message is present when the deployment supplies it.
Publication is explicit and owner-paid. First inspect core.prepare_publication,
then call core.publish_entity with kind, name, max_fee_per_gas,
max_total_fee (both limits in wei; total means gas limit times max fee), and a
unique record_path inside DECENTRALISED_ART_ARTIFACT_ROOT. chain_id defaults to Sepolia
(11155111). Dependencies must be published before their parents. No chain RPC
URL is required: the account signs locally and the server relays one transaction.
Publish serially for each owner and resolve pending transactions before preparing
the next entity: the registry publication nonce is shared by that owner. Separate
MCP sessions are not a safe way to parallelize one owner's publications.
The publication record is persisted before broadcast. On timeout or lost response,
reuse the same record to confirm the transaction; do not create another record to
retry sending. core.confirm_publication also checks an existing transaction by
name, content hash and transaction hash. mined is not finalized/indexed: a newly
mined connector may remain unavailable to chain execution until the safe block
advances. Retry execution without republishing or substituting simulation output.
Preferred onboarding flow:
cd /path/to/mcp
make install
make smoke
make stdioThat gives users a one-command install path, a one-command verification path, and a one-command MCP server launch path.
If your target is Claude Desktop, build the installable bundle with:
make mcpbThat writes a .mcpb file into dist/.
Published GitHub releases also attach the built .mcpb artifact automatically.
If you want to activate the environment manually after install:
source .venv/bin/activateIf someone cloned the repo and wants the shortest path:
git clone https://github.com/decentralised-art/mcp.git
cd mcp
make install
make smoke
make stdioIf your goal is to make this MCP server available to Codex, do this:
- Install the repo-local environment:
cd /path/to/mcp
make install
make smoke- Add this to
~/.codex/config.toml:
[mcp_servers.decentralised-art]
command = "/path/to/mcp/.venv/bin/python"
args = ["-m", "decentralised_art_mcp.server", "stdio"]
[mcp_servers.decentralised-art.env]
PYTHONPATH = "/path/to/mcp/src"
API_BASE = "https://api.decentralised.art/chain"
PRIVATE_KEY = "<optional>"
DECENTRALISED_ART_TIMEOUT = "15"
DECENTRALISED_ART_ARTIFACT_ROOT = "/path/to/mcp/decentralised-art-mcp-artifacts"Notes:
- replace
/path/to/mcpwith the real absolute path where you cloned this repo - for a fresh signing identity, leave
PRIVATE_KEYempty and usecore.create_account - for an existing owner, configure
PRIVATE_KEYlocally through secret settings - reads, simulation, and onchain execution work without
PRIVATE_KEY
-
Restart Codex or start a fresh Codex session.
-
Verify that Codex sees the server:
codex mcp list- In the new session, ask Codex to use it explicitly. For example:
Use the decentralised.art MCP to list formatsUse the decentralised.art MCP to read core.primer
Important:
- a newly registered MCP server usually will not appear inside an already-running session
- the reliable path is: add config, restart Codex, open a new session
The safest way to register this MCP server in any MCP host is to point the host at the project-local venv Python.
Command:
/path/to/mcp/.venv/bin/pythonArgs:
-m decentralised_art_mcp.server stdioWorking directory:
/path/to/mcpEnvironment:
PYTHONPATH=/path/to/mcp/src
API_BASE=https://api.decentralised.art/chain
PRIVATE_KEY=<optional-existing-owner-key-configured-locally>
DECENTRALISED_ART_TIMEOUT=15
DECENTRALISED_ART_ARTIFACT_ROOT=/path/to/mcp/decentralised-art-mcp-artifactsUse this as a generic starting point for an MCP-capable host that accepts JSON server definitions:
{
"decentralised-art": {
"command": "/path/to/mcp/.venv/bin/python",
"args": ["-m", "decentralised_art_mcp.server", "stdio"],
"cwd": "/path/to/mcp",
"env": {
"PYTHONPATH": "/path/to/mcp/src",
"API_BASE": "https://api.decentralised.art/chain",
"PRIVATE_KEY": "<optional>",
"DECENTRALISED_ART_TIMEOUT": "15",
"DECENTRALISED_ART_ARTIFACT_ROOT": "/path/to/mcp/decentralised-art-mcp-artifacts"
}
}
}If your host supports MCP registration but uses a different config format, keep the same values and translate only the wrapper syntax.
After you register the server in any MCP host, restart that host or start a fresh session before testing tool access.
These are the concrete MCP clients I expect most people to use first:
- Codex
- VS Code
- Cursor
- Claude Code
- MCP Inspector
Replace /path/to/mcp below with the directory where you cloned this repo.
OpenAI documents Codex MCP configuration in ~/.codex/config.toml. For this server, add:
[mcp_servers.decentralised-art]
command = "/path/to/mcp/.venv/bin/python"
args = ["-m", "decentralised_art_mcp.server", "stdio"]
[mcp_servers.decentralised-art.env]
PYTHONPATH = "/path/to/mcp/src"
API_BASE = "https://api.decentralised.art/chain"
PRIVATE_KEY = "<optional>"
DECENTRALISED_ART_TIMEOUT = "15"
DECENTRALISED_ART_ARTIFACT_ROOT = "/path/to/mcp/decentralised-art-mcp-artifacts"Codex CLI and the Codex app share this configuration.
VS Code reads either workspace .vscode/mcp.json or user-profile MCP configuration. A workspace config for this server looks like:
{
"servers": {
"decentralised-art": {
"type": "stdio",
"command": "/path/to/mcp/.venv/bin/python",
"args": ["-m", "decentralised_art_mcp.server", "stdio"],
"env": {
"PYTHONPATH": "/path/to/mcp/src",
"API_BASE": "https://api.decentralised.art/chain",
"PRIVATE_KEY": "<optional>",
"DECENTRALISED_ART_TIMEOUT": "15",
"DECENTRALISED_ART_ARTIFACT_ROOT": "/path/to/mcp/decentralised-art-mcp-artifacts"
}
}
}
}Cursor supports project .cursor/mcp.json and global ~/.cursor/mcp.json. For a stdio server, the official docs require type: "stdio". Use:
{
"mcpServers": {
"decentralised-art": {
"type": "stdio",
"command": "/path/to/mcp/.venv/bin/python",
"args": ["-m", "decentralised_art_mcp.server", "stdio"],
"env": {
"PYTHONPATH": "/path/to/mcp/src",
"API_BASE": "https://api.decentralised.art/chain",
"PRIVATE_KEY": "<optional>",
"DECENTRALISED_ART_TIMEOUT": "15",
"DECENTRALISED_ART_ARTIFACT_ROOT": "/path/to/mcp/decentralised-art-mcp-artifacts"
}
}
}
}Claude Code supports project-scoped .mcp.json files and a claude mcp add workflow. If you want a checked-in project config, create .mcp.json at the repo root:
{
"mcpServers": {
"decentralised-art": {
"command": "/path/to/mcp/.venv/bin/python",
"args": ["-m", "decentralised_art_mcp.server", "stdio"],
"env": {
"PYTHONPATH": "/path/to/mcp/src",
"API_BASE": "https://api.decentralised.art/chain",
"PRIVATE_KEY": "<optional>",
"DECENTRALISED_ART_TIMEOUT": "15",
"DECENTRALISED_ART_ARTIFACT_ROOT": "/path/to/mcp/decentralised-art-mcp-artifacts"
}
}
}
}CLI alternative:
claude mcp add --transport stdio --scope project \
--env PYTHONPATH=/path/to/mcp/src \
--env API_BASE=https://api.decentralised.art/chain \
--env DECENTRALISED_ART_TIMEOUT=15 \
--env DECENTRALISED_ART_ARTIFACT_ROOT=/path/to/mcp/decentralised-art-mcp-artifacts \
decentralised-art -- /path/to/mcp/.venv/bin/python -m decentralised_art_mcp.server stdioClaude Desktop now supports local MCP extensions as MCP Bundles (.mcpb). This repo includes a direct bundle path.
Build the bundle:
cd /path/to/mcp
make install
make mcpbThat produces a file like:
dist/decentralised-art-mcp-<version>.mcpbThe same bundle is also uploaded automatically to the corresponding GitHub release asset when a release is published.
Install it in Claude Desktop using any of these:
- double-click the
.mcpbfile - drag the
.mcpbfile into Claude Desktop - use
Developer -> Extensions -> Install Extension
After installation, Claude Desktop will prompt for the bundle's user config:
api_baseprivate_keytimeoutartifact_rootaccount_root(optional; empty uses~/.decentralised-art-mcp/accounts)
Implementation notes:
- the bundle is built as a
manifest_version: "0.4"MCPB - it uses the
uvruntime path instead of bundling a whole Python virtual environment - this keeps the artifact small and avoids the portability problems of shipping Python site-packages directly
The official MCP Inspector docs show launching a local Python server through a command runner. For this repo, a direct invocation looks like:
npx @modelcontextprotocol/inspector \
/path/to/mcp/.venv/bin/python \
-m decentralised_art_mcp.server stdioIf you want the server to inherit the repo-local environment cleanly, run it with:
PYTHONPATH=/path/to/mcp/src \
API_BASE=https://api.decentralised.art/chain \
DECENTRALISED_ART_TIMEOUT=15 \
DECENTRALISED_ART_ARTIFACT_ROOT=/path/to/mcp/decentralised-art-mcp-artifacts \
npx @modelcontextprotocol/inspector \
/path/to/mcp/.venv/bin/python \
-m decentralised_art_mcp.server stdioThese are the main runtime settings:
API_BASE- default:
https://api.decentralised.art/chain
- default:
PRIVATE_KEY- optional; reads, simulation, and chain execution need no signing identity
- existing-owner signer for draft creation and publication; fresh owners can instead use
core.create_accountandaccount_id - signs the chain API nonce flow (
GET /chain/nonce/{address}thenPOST /chain/auth)
- this chain token is separate from the app/services SIWE session used by
services-backend DECENTRALISED_ART_TIMEOUT- request timeout in seconds
DECENTRALISED_ART_ARTIFACT_ROOT- directory for persistent publication transaction records
- default:
decentralised-art-mcp-artifacts
DECENTRALISED_ART_ACCOUNT_ROOT- owner-only local directory for generated signing keys
- default:
~/.decentralised-art-mcp/accounts - use a persistent absolute path; keep separate from publication records and source control
Version 0.2.0 renamed everything that still used the old dcn naming:
| Before | Now |
|---|---|
package and command dcn-mcp |
decentralised-art-mcp |
module dcn_mcp.server |
decentralised_art_mcp.server |
DCN_TIMEOUT |
DECENTRALISED_ART_TIMEOUT |
DCN_ARTIFACT_ROOT |
DECENTRALISED_ART_ARTIFACT_ROOT |
default folder dcn-mcp-artifacts |
decentralised-art-mcp-artifacts |
resource core.dcn_core_primer |
core.primer |
After pulling, run make install again and update your host configuration to the new module
name. The old DCN_TIMEOUT and DCN_ARTIFACT_ROOT settings are still read when the new ones
are unset, and an existing dcn-mcp-artifacts folder keeps being used when no new folder
exists, so pending publication records are never lost.
There are three levels of verification.
cd /path/to/mcp
source .venv/bin/activate
python -m unittest discover -s tests -vImportant test coverage includes:
- registry and schema validation
- core resource exposure
- fake-client integration for core tools
- real MCP stdio lifecycle smoke test
cd /path/to/mcp
source .venv/bin/activate
python -m decentralised_art_mcp.server list-tools
python -m decentralised_art_mcp.server list-resources
python -m decentralised_art_mcp.server invoke core.build_parent_connector '{"name":"piece","child_names":["a","b"]}'Register the server in your MCP host and confirm that the host can:
- list tools
- list resources
- read
core.primer - call
core.build_parent_connector
The preferred user interface is now make:
Creates or updates .venv and installs decentralised-art-mcp in editable mode.
Runs the repo smoke test.
Runs the full test suite.
Runs the real MCP stdio server from the local environment.
Builds a Claude Desktop .mcpb bundle in dist/.
Lists local tool metadata.
Lists local resource metadata.
Reads the core primer resource.
Runs one sample tool invocation locally.
These still exist underneath the Makefile:
Creates .venv, upgrades pip, and installs decentralised-art-mcp in editable mode.
Runs the real MCP stdio server from the local environment.
Builds a Claude Desktop .mcpb bundle in dist/.
Runs the repo test suite and local MCP checks.
Run as a real MCP stdio server:
python -m decentralised_art_mcp.server stdioList tools:
python -m decentralised_art_mcp.server list-toolsList resources:
python -m decentralised_art_mcp.server list-resourcesRead a resource:
python -m decentralised_art_mcp.server read-resource core.primerInvoke a tool:
python -m decentralised_art_mcp.server invoke core.connector_exists '{"name":"pitch"}'Tool invocation returns a structured envelope:
{"ok": true, "data": {...}}or
{ "ok": false, "error": { "code": "validation_error", "message": "..." } }The HTTP client implements the decentralised.art protocol using contracts
generated from api-spec. The MCP server exposes those operations, local signing
account onboarding and bundled documentation as core.* tools and resources.
Format-specific interpretation and general file-writing
belong in separate plugins.
- The official server exposes only
core.*tools and resources. - Generic structural helpers such as parent connector building remain in
core.
The MCP transport supports paginated:
tools/listresources/list
Pagination is implemented with opaque numeric cursors managed by the server.
- Platform pages have a single published source at
https://decentralised.art/llms-full.txt. Refresh the complete document and individual snapshots before a release withmake sync-docs. The complete file is preserved byte for byte, with its source URL, retrieval date and SHA-256 in a separatellms-full.metadata.json. New platform pages are retained in the full file even before they have individual MCP topics. For a previously downloaded copy, use.venv/bin/python scripts/sync_documentation.py --source-file /path/to/llms-full.txt --retrieved-at YYYY-MM-DD. - Keep account behavior documented in
core.getting-started, initialization instructions, creation-tool descriptions and missing-account errors. Website snapshots may describe an earlier release; the bundled onboarding guide documents the installed MCP. - Use the project-local
.venvfor work on this repository. - Do not rely on the shared interpreter for long-term use.
- The current server uses the official MCP Python SDK low-level server so that exact JSON Schemas stay under our control.