Search Promo Text (Messaging)
messagingmcp-search_promo_text
Relevance-scored text search across promo description / conditions / categories / codes.
The searched text is plain English (extraction translates all source
languages), and the corpus targets quantified-discount promotions — free
shipping, loyalty perks, and single-product sales are excluded by policy, so
searching for them is unreliable (compound offers like "20% off plus free
shipping" do match; a few stray pure records exist); see
explain_promo_data. Returns one entry per distinct
promotion (highest-scoring row per promo), each with the list_promos field
set plus active_window, any_inferred, and a raw BM25 score (ordering
only — not a probability). total_matched and coverage mirror list_promos.
Double-quote a span to match it as an exact phrase ("40% off"); quotes can be
mixed with loose terms and repeated, but everything is OR-combined — a hit
needs only one of the phrases/terms, so a mixed query does NOT require the
phrase. To require a phrase, send it alone. Phrasing matches adjacent words,
not literal punctuation. categories is a keyword field — it only matches a
whole value exactly, not individual words.
Parameters
| Name | Type | Required | Constraints | Description |
|---|---|---|---|---|
query | string | yes | — | Keyword or short phrase to match across promo text. Lean, specific terms work best — the corpus is already filtered to promos so generic words match everything. Wrap a span in double quotes to match it as an exact phrase, e.g. "40% off" — quotes can be mixed with loose terms and repeated, e.g. "buy one get one" student. Phrasing matches adjacent words, not literal punctuation (a % is not indexed). |
fields | string[] | null | no | default: null | Which text fields to search. Subset of ['description', 'conditions', 'categories', 'codes']. None = all four (description and codes boosted). |
retailers | string[] | null | no | default: null | Retailer slugs to filter by, e.g. ['zara', 'h-m']. None = all; matches any listed retailer. Call list_retailers and match the requested retailer against its retailer_name, then pass the row's retailer slug and a region it covers exactly as reported there. Slugs match exactly, so a display name or wrong case matches nothing. |
regions | string[] | null | no | default: null | Regions to filter by, e.g. ['UK', 'US']. None = all; matches any listed region. list_retailers reports the exact region values for each retailer; use those, since regions match exactly. |
start_date | string | null | no | default: null | Start of the active-date window (inclusive, YYYY-MM-DD). |
end_date | string | null | no | default: null | End of the active-date window (inclusive, YYYY-MM-DD). |
include_inferred | boolean | no | default: true | Include inferred promotions (default True). False = observed only. |
limit | integer | no | default: 10 · 1–20 | Max distinct promotions. Default 10. |
Returns
- On success: {"total_matched", "coverage", "returned", "promos": [...],
- "filter_echo"}.
- On failure: {"error": str}.
Try it
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-search_promo_text",
"arguments": {
"query": "Nike",
"fields": null,
"retailers": null,
"regions": null,
"start_date": null,
"end_date": null,
"include_inferred": true,
"limit": 10
}
}
}'
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-search_promo_text",
arguments: {
"query": "Nike",
"fields": null,
"retailers": null,
"regions": null,
"start_date": null,
"end_date": null,
"include_inferred": true,
"limit": 10
},
});
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-search_promo_text",
{"query": "Nike", "fields": None, "retailers": None, "regions": None, "start_date": None, "end_date": None, "include_inferred": True, "limit": 10},
)
Input schema
{
"type": "object",
"properties": {
"query": {
"description": "Keyword or short phrase to match across promo text. Lean, specific terms work best — the corpus is already filtered to promos so generic words match everything. Wrap a span in double quotes to match it as an exact phrase, e.g. \"40% off\" — quotes can be mixed with loose terms and repeated, e.g. \"buy one get one\" student. Phrasing matches adjacent words, not literal punctuation (a `%` is not indexed).",
"type": "string"
},
"fields": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"description": "Which text fields to search. Subset of ['description', 'conditions', 'categories', 'codes']. None = all four (description and codes boosted)."
},
"retailers": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"description": "Retailer slugs to filter by, e.g. ['zara', 'h-m']. None = all; matches any listed retailer. Call `list_retailers` and match the requested retailer against its `retailer_name`, then pass the row's `retailer` slug and a region it covers exactly as reported there. Slugs match exactly, so a display name or wrong case matches nothing."
},
"regions": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"description": "Regions to filter by, e.g. ['UK', 'US']. None = all; matches any listed region. `list_retailers` reports the exact region values for each retailer; use those, since regions match exactly."
},
"start_date": {
"anyOf": [
{
"format": "date",
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Start of the active-date window (inclusive, YYYY-MM-DD)."
},
"end_date": {
"anyOf": [
{
"format": "date",
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "End of the active-date window (inclusive, YYYY-MM-DD)."
},
"include_inferred": {
"default": true,
"description": "Include inferred promotions (default True). False = observed only.",
"type": "boolean"
},
"limit": {
"default": 10,
"description": "Max distinct promotions. Default 10.",
"maximum": 20,
"minimum": 1,
"type": "integer"
}
},
"required": [
"query"
]
}