Affected capability
DataHub
Feature description
Add an MCP tool to Data Hub Simple REST that answers the canonical (public website) URL of an asset — the link a human is meant to open, or a page is meant to embed.
Today every asset URL an MCP agent can reach is access-controlled by the bundle: the pimcore://datahub/{config}/asset/{id} resource returns bytes into the session, and the binaryData.*.path REST download path is bearer-gated. Neither is a link that can be handed to a person. The canonical URL is the only one missing, and it already reaches the agent in no other response.
Shape agreed with the maintainers in the design discussion (pimcore/data-hub-simple-rest#353):
pimcore_datahub_get_canonical_urls(config: string, ids: int[])
- Opt-in per configuration via a new
schema.assets.allowCanonicalUrl flag ("Deliver Canonical URLs" in Studio), default off. While it is off the whole call is refused with an expected-tier error. A canonical URL is the one asset URL this bundle does not access-control, so publishing it is an explicit administrative decision rather than a consequence of enabling assets.
- Bounded batch of at most 100 ids, one result entry per requested id, keyed by the id:
{"results": {"123": {"status": "ok", "original": "<url>", "thumbnails": {"<name>": "<url>"}}, "456": {"status": "not_found"}}}. A longer list is rejected rather than truncated. Batching was requested so an agent that just listed a page of assets does not need one MCP round-trip per link.
- Same per-id check chain as
resources/read, on every call: API-key scope for the configuration, general.active, schema.assets.enabled, index membership, and a live workspace permission check. Any failure — nonexistent, not published, outside the workspace, a folder — yields the identical opaque not_found entry, and never aborts the rest of the batch.
- Resolution through Pimcore core with the asset loaded:
Asset::getFrontendFullPath() for the original and Asset\Image\Thumbnail::getPath(['frontend' => true, 'deferredAllowed' => true]) for each thumbnail the configuration publishes. Nothing is reconstructed from the indexed document and no host is guessed, so frontend_prefixes and the ASSET_PATH / ASSET_IMAGE_THUMBNAIL listeners see a real subject and a result is absolute only where those make it so. The deferred flag means asking for a link never triggers thumbnail generation.
- Read-only and idempotent (
readOnlyHint / idempotentHint / openWorldHint: false), with a declared outputSchema. Costs one asset load per requested id, only on this explicit call; nothing changes in search or tree results.
Design discussion: pimcore/data-hub-simple-rest#353
Affected capability
DataHub
Feature description
Add an MCP tool to Data Hub Simple REST that answers the canonical (public website) URL of an asset — the link a human is meant to open, or a page is meant to embed.
Today every asset URL an MCP agent can reach is access-controlled by the bundle: the
pimcore://datahub/{config}/asset/{id}resource returns bytes into the session, and thebinaryData.*.pathREST download path is bearer-gated. Neither is a link that can be handed to a person. The canonical URL is the only one missing, and it already reaches the agent in no other response.Shape agreed with the maintainers in the design discussion (pimcore/data-hub-simple-rest#353):
pimcore_datahub_get_canonical_urls(config: string, ids: int[])schema.assets.allowCanonicalUrlflag ("Deliver Canonical URLs" in Studio), default off. While it is off the whole call is refused with an expected-tier error. A canonical URL is the one asset URL this bundle does not access-control, so publishing it is an explicit administrative decision rather than a consequence of enabling assets.{"results": {"123": {"status": "ok", "original": "<url>", "thumbnails": {"<name>": "<url>"}}, "456": {"status": "not_found"}}}. A longer list is rejected rather than truncated. Batching was requested so an agent that just listed a page of assets does not need one MCP round-trip per link.resources/read, on every call: API-key scope for the configuration,general.active,schema.assets.enabled, index membership, and a live workspace permission check. Any failure — nonexistent, not published, outside the workspace, a folder — yields the identical opaquenot_foundentry, and never aborts the rest of the batch.Asset::getFrontendFullPath()for the original andAsset\Image\Thumbnail::getPath(['frontend' => true, 'deferredAllowed' => true])for each thumbnail the configuration publishes. Nothing is reconstructed from the indexed document and no host is guessed, sofrontend_prefixesand theASSET_PATH/ASSET_IMAGE_THUMBNAILlisteners see a real subject and a result is absolute only where those make it so. The deferred flag means asking for a link never triggers thumbnail generation.readOnlyHint/idempotentHint/openWorldHint: false), with a declaredoutputSchema. Costs one asset load per requested id, only on this explicit call; nothing changes in search or tree results.Design discussion: pimcore/data-hub-simple-rest#353