Search Visuals (Messaging)
messagingmcp-messaging_search
Search messaging channel visuals (homepage and newsletter screenshots) by meaning.
Ranks whole-page captures against an embedding of the page's OCR text plus a
VLM-written caption, so the query can match either what the page says or what
it shows. Each hit's image_description is that caption (may be empty when
captioning failed) and ocr_text is a whole-page OCR snippet — page-level
text, not scoped to one promotion. Use this tool to find promotional visuals
matching a topic or creative brief; pair with enrich_with_vm for full OCR.
Parameters
| Name | Type | Required | Constraints | Description |
|---|---|---|---|---|
query | string | yes | — | Natural-language query describing the promotional content to find. |
start_date | string | no | — | Inclusive start date (YYYY-MM-DD) on the shot date. |
end_date | string | no | — | Inclusive end date (YYYY-MM-DD) on the shot date. |
regions | string[] | no | — | Regions to filter by, e.g. ['UK', 'US']. Omit for all; matches any listed region. Exact match, so use the values list_retailers reports for the retailer. |
retailers | string[] | no | — | Retailer slugs to filter by, e.g. ['zara', 'h-m']. Omit for all; matches any listed retailer. Slugs match exactly and are case-sensitive, so take them from list_retailers: match the request against retailer_name, then pass that row's retailer slug and one of the regions it reports. |
verticals | string[] | no | — | Verticals (industries) to filter by: subset of ['Apparel', 'Homeware', 'Beauty']. Omit for all; matches any listed vertical. Values match exactly (case-sensitive). |
channel_type | string[] | no | — | Filter to channel types: subset of ['homepage', 'newsletter']. Omit for all channels. |
k | integer | no | default: 5 · 1–50 | Number of results to return. |
include_repeats | boolean | no | default: false | When False (default), return chain-heads only — one result per unique shoot, excluding re-captures of unchanged pages. Set True to include all captures. |
Returns
- On success: {"result": {"total": int, "hits": list[MessagingHit]}}.
totalis the number of hits RETURNED (capped by k) — not a corpus-wide- match count; ranked retrieval has no meaningful total, so do not report
- it as "N matching pages".
- Each hit: image_id, retailer, retailer_name, channel_type, region,
- date, image_url, image_description, ocr_text, channel_name,
- channel_target, verticals, score.
- On failure: {"error": {code, message}}
codeisinvalid_input,upstream_unavailable,internal(our own bad data; a retry returns the same error), ornot_entitled(authorization refused).
Try it
Loading interactive widget…
Code examples
- curl
- TypeScript
- Python
curl -s https://mcp.edited.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-06-18" \
-H "x-api-key: $MCP_API_KEY" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "messagingmcp-messaging_search",
"arguments": {
"query": "Nike",
"start_date": "example",
"end_date": "example",
"k": 5,
"include_repeats": false
}
}
}'
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const client = new Client({ name: "demo", version: "1.0.0" }, { capabilities: {} });
await client.connect(
new StreamableHTTPClientTransport(new URL("https://mcp.edited.com/mcp"), {
requestInit: { headers: { "x-api-key": process.env.MCP_API_KEY ?? "" } },
}),
);
const result = await client.callTool({
name: "messagingmcp-messaging_search",
arguments: {
"query": "Nike",
"start_date": "example",
"end_date": "example",
"k": 5,
"include_repeats": false
},
});
import os
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
headers = {"x-api-key": os.environ["MCP_API_KEY"]}
async with streamablehttp_client("https://mcp.edited.com/mcp", headers=headers) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool(
"messagingmcp-messaging_search",
{"query": "Nike", "start_date": "example", "end_date": "example", "k": 5, "include_repeats": False},
)
Input schema
{
"type": "object",
"properties": {
"query": {
"description": "Natural-language query describing the promotional content to find.",
"type": "string"
},
"start_date": {
"description": "Inclusive start date (YYYY-MM-DD) on the shot date.",
"format": "date",
"type": "string"
},
"end_date": {
"description": "Inclusive end date (YYYY-MM-DD) on the shot date.",
"format": "date",
"type": "string"
},
"regions": {
"description": "Regions to filter by, e.g. ['UK', 'US']. Omit for all; matches any listed region. Exact match, so use the values `list_retailers` reports for the retailer.",
"items": {
"type": "string"
},
"type": "array"
},
"retailers": {
"description": "Retailer slugs to filter by, e.g. ['zara', 'h-m']. Omit for all; matches any listed retailer. Slugs match exactly and are case-sensitive, so take them from `list_retailers`: match the request against `retailer_name`, then pass that row's `retailer` slug and one of the regions it reports.",
"items": {
"type": "string"
},
"type": "array"
},
"verticals": {
"description": "Verticals (industries) to filter by: subset of ['Apparel', 'Homeware', 'Beauty']. Omit for all; matches any listed vertical. Values match exactly (case-sensitive).",
"items": {
"enum": [
"Apparel",
"Homeware",
"Beauty"
],
"type": "string"
},
"type": "array"
},
"channel_type": {
"description": "Filter to channel types: subset of ['homepage', 'newsletter']. Omit for all channels.",
"items": {
"enum": [
"homepage",
"newsletter"
],
"type": "string"
},
"type": "array"
},
"k": {
"default": 5,
"description": "Number of results to return.",
"maximum": 50,
"minimum": 1,
"type": "integer"
},
"include_repeats": {
"default": false,
"description": "When False (default), return chain-heads only — one result per unique shoot, excluding re-captures of unchanged pages. Set True to include all captures.",
"type": "boolean"
}
},
"required": [
"query"
]
}
Output schema
Describes both branches of the envelope — result on success, error on a refusal. Validate against this rather than pattern-matching the prose above; see Concepts → Response shape.
{
"type": "object",
"properties": {
"result": {
"properties": {
"total": {
"type": "integer"
},
"hits": {
"items": {
"description": "One matching visual, with its provenance and relevance score.",
"properties": {
"image_id": {
"type": "string"
},
"retailer": {
"description": "The retailer slug — the value retailer filters accept.",
"type": "string"
},
"retailer_name": {
"description": "Display name, not filterable.",
"type": "string"
},
"channel_type": {
"type": "string"
},
"region": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"date": {
"type": "string"
},
"image_url": {
"type": "string"
},
"image_description": {
"description": "Full VLM caption, untruncated.",
"type": "string"
},
"ocr_text": {
"description": "OCR page text, truncated to a snippet.",
"type": "string"
},
"channel_name": {
"type": "string"
},
"channel_target": {
"type": "string"
},
"verticals": {
"description": "Human-readable vertical names; [] if none.",
"items": {
"type": "string"
},
"type": "array"
},
"score": {
"type": "number"
}
},
"required": [
"image_id",
"retailer",
"retailer_name",
"channel_type",
"region",
"date",
"image_url",
"image_description",
"ocr_text",
"channel_name",
"channel_target",
"verticals",
"score"
],
"type": "object"
},
"type": "array"
}
},
"required": [
"total",
"hits"
],
"type": "object"
},
"error": {
"type": "object",
"description": "Present instead of `result` when the call was rejected. Branch on `code`; never string-match `message`.",
"properties": {
"code": {
"type": "string",
"enum": [
"invalid_input",
"not_entitled",
"upstream_unavailable",
"internal"
]
},
"message": {
"type": "string"
},
"field": {
"type": "string",
"description": "Offending parameter, when the failure is attributable to one."
},
"details": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"code",
"message"
]
}
},
"oneOf": [
{
"required": [
"result"
]
},
{
"required": [
"error"
]
}
],
"x-fastmcp-wrap-result": true
}