Endpoints
| Endpoint | Method | Description |
|---|---|---|
| /mcp | POST | Streamable HTTP transportRecommended |
| /sse | GET | SSE transportDeprecated |
Server URL
http://staging-asset-management.mcp.cloudinary.com/mcp
Configuration
Add this to your MCP client configuration. OAuth is used by default when no headers are provided.
Minimal (OAuth)
{
"mcpServers": {
"@cloudinary/asset-management-mcp": {
"url": "http://staging-asset-management.mcp.cloudinary.com/mcp"
}
}
}
With API Key
{
"mcpServers": {
"@cloudinary/asset-management-mcp": {
"url": "http://staging-asset-management.mcp.cloudinary.com/mcp",
"headers": {
"cloudinary-url": "cloudinary://api_key:api_secret@cloud_name"
}
}
}
}
Authentication
| Method | Description |
|---|---|
| OAuth 2.0 | Default. The OAuth flow is initiated automatically when the client connects with no auth headers. |
| API Key | Pass cloudinary-url header, or individual cloudinary-cloud-name, cloudinary-api-key, cloudinary-api-secret headers. |
Configuration Headers
Optional headers to customize server behavior. Applied at session creation time.
| Header | Description |
|---|---|
cloudinary-region |
API region: api, api-eu, or api-ap |
cloudinary-tools |
Comma-separated list of tools to enable (e.g. search-assets,list-images) |
Response Headers
API response headers are collected into _meta.headers on each tool result. The debug preset is active by default.
| Header | Description |
|---|---|
cloudinary-collect-headers |
Control which response headers are returned. Accepts:
debug — rate-limit + request ID (default)
ratelimit — rate-limit headers only
all — every response header
Or a comma-separated list of exact names, prefix:<value>, regex:<pattern>, and preset names
|
cloudinary-embed-headers |
Set to true to also include collected headers in the response body as _headers, for clients that don't surface _meta |
Tool result structure
{
"_meta": {
"headers": {
"x-featureratelimit-limit": "5000",
"x-featureratelimit-remaining": "4998",
"x-featureratelimit-reset": "Thu, 13 Feb 2026 00:00:00 GMT",
"x-request-id": "bfeaccc60050594832508590a358a1a4"
}
},
"content": [{ "type": "text", "text": "{...}" }]
}
Available Tools (23)
upload-asset
asset-rename
generate-archive
download-asset-backup
delete-asset
list-images
list-videos
list-files
get-asset-details
asset-update
list-tags
delete-derived-assets
get-usage-details
create-asset-relations
delete-asset-relations
move-folder
create-folder
delete-folder
search-folders
`, and `metadata.` match on tokens split by whitespace and punctuation — `tags:analysis` matches the tag `full-analysis`. `public_id`, `folder`, `asset_folder`, and `format` match the whole value — `public_id:dog` will not match `dog_pldcwy`; use `public_id="dog_pldcwy"` (exact) or `public_id:dog*` (prefix). These exact-match fields still accept a trailing `*` for prefix match (except `folder` / `asset_folder`, where wildcards are ignored).
- **Dates**: ISO-8601 in quotes (`uploaded_at>"2024-01-15"`) or relative shorthand `Nh`, `Nd`, `Nw`, `Nm`, `Ny` (`uploaded_at>1d`, `created_at:[4w TO 1w]`). Send raw `<`/`>`, never HTML-escaped.
- **Quoting**: wrap any value containing a space, colon, or other reserved character (`! ( ) { } [ ] ^ ~ ? \ = & < > |`) in double quotes, or escape each character with `\`. Examples: `tags:"service:mantels"`, `aspect_ratio:"16:9"`, `folder:"My Folder"`.
## Common mistakes
- Use `folder:` or `asset_folder:` (singular); `folders:`, `asset_folder_id:`, and other invented variants are not valid fields. Pass the exact folder name — wildcards do not apply here.
- There is no "has any value" / presence probe. `folder:*`, `metadata.alt:*`, `context.key:*`, `tags:*`, and `-tags:*` are all parse errors. See *"Which assets have any value for `metadata.`?"* under **Common tasks** for workarounds.
- `NOT foo AND bar` is a parse error. Write it as `bar AND NOT foo` or `-foo AND bar`, and keep every `NOT` between two clauses (`a AND NOT b AND NOT c` is fine; `NOT b AND NOT c …` is not).
- `public_id:dog` will not match `dog_pldcwy`. Use `public_id="dog_pldcwy"` (exact) or `public_id:dog*` (prefix).
- `tags=service:mantels` fails because the unquoted colon is parsed as a field separator. Use `tags="service:mantels"` or `tags=service\:mantels`.
- Do not HTML-escape operators. Send `uploaded_at<1h`, not `uploaded_at<1h`.
- Do not leave an operand empty (e.g. `tags: AND -tags:foo`). Omit the empty clause entirely.
## Tips
- Set `max_results: 0` to return only `total_count` and `aggregations` without any resource payload — useful for counts and aggregation-only queries.
- `total_count` is always present in the response; prefer it over running an aggregation just to get a count.
- `aggregate` (both simple and range variants) and the `metadata`, `image_metadata`, `image_analysis` values of `with_field` require a Tier 2 search plan.
- Range aggregations require each range to include a `key` label (1–20 chars, `[a-zA-Z0-9_-]+`) and at least one of `from` / `to`.
## Common tasks
- **Count matching assets** — put the filter in `expression` with `max_results: 0` and read `total_count` from the response. Works on every tier; no `aggregate` needed.
- **Preview one matching asset** — set `max_results: 1`; add `with_field: ["tags", "context"]` (or `metadata`, Tier 2) to inspect values. Prefer this over fetching and scanning a full page.
- **Distribution of values for a field** — Tier 2: `aggregate: [format|resource_type|type]` for enum counts, or range aggregations on `bytes`, `image_pixels`, `video_pixels`, or `duration`. Tier 1 fallback: run N small queries with `max_results: 0`, one per candidate value, and read `total_count` from each.
- **"Which assets have any value for `metadata.`?"** — not expressible directly (`metadata.X:*` is a parse error; there is no presence probe). Workarounds: (a) if the field has a known value set, enumerate — `metadata.region:(apac OR emea OR amer)`; (b) query broadly with `with_field: ["metadata"]` (Tier 2) and filter client-side for entries where the field is set; (c) at ingest time, attach a sentinel tag whenever the field is set, then search by that tag.
- **Newest / largest N** — keep the filter in `expression` and sort explicitly: `sort_by: [{uploaded_at: "desc"}]` with `max_results: 10`.
- **Filter by folder** — both `asset_folder:"parent/child"` and `folder:"parent/child"` match an exact folder path; there is no wildcard or "contains". To query across multiple folders, enumerate: `asset_folder:("campaigns/2024" OR "campaigns/2025")`.
- **Filter by metadata when you only know the label** — first call `list-metadata-fields` to resolve the label to an `external_id`, then query `metadata.:value`.
- **Multiple independent filters in one turn** — prefer one `expression` with `OR` / parentheses over firing many parallel calls: `metadata.region:apac OR metadata.region:emea` in a single request is faster and more reliable than two parallel requests.
## Examples
- `tags:shirt AND uploaded_at>1d`
- `resource_type:image AND bytes>1000000 AND (format:png OR format:jpg)`
- `folder:products AND context.category:electronics`
- `tags:"service:mantels" AND -tags:discontinued`
">search-assets
visual-search-assets
get-tx-reference
transform-asset