Connect an AI agent
You will issue a service token, connect an agent to the factory over MCP, and ask it three real questions about the demo estate. Then you will read the same record with plain HTTP, and revoke the token.
Before you start
Shell access to the machine the factory runs on — issuing a token is a command-line action, deliberately, like adding the first person. And an MCP-capable client; these steps use Claude Code, but any client that speaks MCP's Streamable HTTP transport or stdio connects the same way.
1. Issue a service token
python -m dpf token create claude-desktop --note "tutorial walkthrough"
What you should see: the token, printed once, starting dpf_…. Only its hash is
kept, so this is the only time you will see it in full — store it now.
export DPF_TOKEN=dpf_…
2. Connect over HTTP
claude mcp add --transport http data-product-factory \
https://<your host>/dataproductfactory/api/v1/mcp \
--header "Authorization: Bearer $DPF_TOKEN"
Use wherever this deployment actually runs in place of <your host>. Any other
client that speaks MCP's Streamable HTTP transport connects the same way: JSON-RPC
posted to that one URL, with the same header.
Or, without a token, on the same machine. An agent running beside the factory can read over stdio instead — no token, no network. Open Ontology in the sidebar, then select Connect with MCP, for a client config with this machine's own paths already filled in:
{"mcpServers": {"data-product-factory": {
"command": "/path/to/.venv/bin/python",
"args": ["-m", "dpf", "mcp"],
"cwd": "/path/to/dataproductfactory"
}}}
or run it directly: python -m dpf mcp.
3. Ask it three real questions
The server has five read-only tools: products, search, describe, facet and
gaps. Three questions reach four of them.
"Which data products are live, and how far along are the rest?" calls
products — shortened to two rows here:
[
{"slug": "PRODUCT_A", "name": "Product A",
"live": true, "version": "2.0.0"},
{"slug": "PRODUCT_B", "name": "Product B",
"live": false, "version": "0.2.0"}
]
"Where does this measure column come from, and what else is attached to it?"
calls search to find the column's id, then describe on it (shortened here):
{
"node": {"id": "attribute:PRODUCT.table_name.column_name",
"description": "What the column means, and what it excludes.",
"type": "DECIMAL(18,2)", "semantic": "measure", "unit": "EUR"},
"related": [
{"predicate": "derives_from", "id": "source:SOURCE.TABLE", "system": "SYSTEM"},
{"predicate": "has_attribute_of", "id": "table:PRODUCT.table_name"}
]
}
"What is undocumented?" calls gaps:
[
{"id": "attribute:PRODUCT_A.table_name.column_name",
"gap": "not linked to a glossary term"},
{"id": "attribute:PRODUCT_B.table_name.column_name",
"gap": "not linked to a glossary term"}
]
— one row like that for every attribute nobody has linked to a glossary term yet.
4. Read the same record with curl
The MCP tools and the plain API read the same record; they only answer in different shapes.
export DPF=https://<your host>/dataproductfactory/api/v1
curl -H "Authorization: Bearer $DPF_TOKEN" $DPF/products
curl -H "Authorization: Bearer $DPF_TOKEN" "$DPF/events?product=PRODUCT&limit=5"
What you should see: the same facts as above — the product you asked about,
live, with its gates — from the first call, and a page of its audit log, oldest
first, ending in a next cursor to poll from, from the second. Every endpoint,
field and error code is in Read API and MCP.
Note
The tools and the endpoints both read. Neither decides anything — nothing here drafts, sends, answers, signs or promotes. Every decision in the record still carries the name of the person who made it.
5. Revoke the token
python -m dpf token revoke claude-desktop
What you should see: a line confirming it is revoked. The next call made with
it gets 401, on the next request, not after a delay.
What you did
- Every endpoint and tool, its parameters and its error codes, are in Read API and MCP.
- Why the factory's API reads and never writes is Decision 0006.
- How the agents built into the factory itself are kept to proposing, never deciding, is in Agents.