Skip to main content

List Reports (Research)

researchmcp-research_list_reports

Browse what has been published lately, newest-first by publish date.

This is a browsing tool, not a discovery tool — reach for it only when the question is about recency itself: "what has EDITED published lately", "what reports do we have from last month". It orders by publish date with no topic, audience or coverage filter, so it will not surface the reports that define a topic even when they exist.

For anything topic-shaped — a trend, a category, a season's direction — do not start here: call research_analyze_query and then research_article_search (drilling in with research_chunk_search), which rank on topic, audience and season rather than date order.

The date window is the report's publish date, not the season it is about: a report covering SS27 typically publishes months earlier, so a calendar-SS27 window would miss it.

Both dates are optional; research_analyze_query converts a natural-language window into them. Omit cursor on the first call.

Try queries like

"what reports do we have from last month", "list reports since January", "anything published this week".

Parameters​

NameTypeRequiredConstraintsDescription
start_datestringno—Inclusive lower bound (YYYY-MM-DD).
end_datestringno—Inclusive upper bound (YYYY-MM-DD).
limitintegernodefault: 20 · 1–100Page size.
cursorstringno—Opaque pagination token from a previous response's next_cursor.

Returns​

  • On success: {"result": {"total": int, "reports": list[ReportSummary],
  • "next_cursor": str | None}}. Each report carries report_id,
  • title, date, modified, excerpt, and tags — the report's
  • curated taxonomy tags (article_types, topics, gender, season,
  • year, moments), which tell you a "SS27 Buyers' Guide" is menswear
  • before you open it. An untagged axis is an empty list. For a public
  • link to a report_id call research_report_links; for the full article
  • text call research_read_report.
  • total is the number of reports on this page (it feeds the
  • mcp.tool.result_count metric); use next_cursor (None on the
  • last page) to gauge whether more exist.
  • On retrieval failure or invalid cursor/limit: {"error": {code, message}}
  • code is invalid_input, upstream_unavailable,
  • internal (our own bad data; a retry returns the same error), or
  • not_entitled (authorization refused).

Try it​

Loading interactive widget…

Code examples​

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": "researchmcp-research_list_reports",
"arguments": {
"start_date": "example",
"end_date": "example",
"limit": 20,
"cursor": "example"
}
}
}'

Input schema​

{
"type": "object",
"properties": {
"start_date": {
"description": "Inclusive lower bound (YYYY-MM-DD).",
"format": "date",
"type": "string"
},
"end_date": {
"description": "Inclusive upper bound (YYYY-MM-DD).",
"format": "date",
"type": "string"
},
"limit": {
"default": 20,
"description": "Page size.",
"maximum": 100,
"minimum": 1,
"type": "integer"
},
"cursor": {
"description": "Opaque pagination token from a previous response's `next_cursor`.",
"type": "string"
}
}
}

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"
},
"reports": {
"items": {
"properties": {
"report_id": {
"type": "integer"
},
"title": {
"type": "string"
},
"date": {
"format": "date",
"type": "string"
},
"modified": {
"format": "date-time",
"type": "string"
},
"excerpt": {
"type": "string"
},
"tags": {
"description": "The parent report's curated taxonomy tags, keyed by the public intent axes.\n\nPopulated on every search hit, browse row and report lookup so a consumer can\nsee a report's audience, season and subject matter *at discovery time* — a\ntitle alone does not say whether a \"SS27 Buyers' Guide\" is menswear or\nwomenswear, and grounding a womenswear claim in a menswear report is the\nfailure this prevents.\n\nThe values are drawn from the vocabulary the search tools' intent params\naccept, so a tag read off a hit can usually be threaded straight back in to\nnarrow a follow-up search. Two limits on that, both worth knowing before\ntreating a threaded tag as a guaranteed narrowing:\n\n- **The vocabularies are not identical.** These are curated report-side\n labels, so a value can exist here that the params do not recognise (prod\n carries ``moments: [\"pride\"]``, which is outside ``MomentsParam``'s enum).\n Threading such a value is ignored by ``normalise_intent`` or rejected by the\n param schema — never a silent narrowing.\n- **``year`` and ``moments`` are not pure ranking axes.** Unlike the other\n four, they also derive the publish-date window when no explicit dates are\n given (see ``retrieval/date_window.py``), so threading one back moves the\n filter as well as the boost.\n\nEvery axis is always present on the model; an untagged axis is an empty list.\nCoverage is uneven and heavily skewed by report class — buyers' guides are\nclose to fully tagged for ``gender``, while a large minority of the corpus\ncarries no taxonomy at all — so an empty axis is common and means \"not\ncurated\", never \"out of scope\". (One near-exception: a topic tag that exists\nonly as an all-encompassing label is dropped rather than surfaced, matching\nwhat the scorer sees — see ``canonicalise_topics``.)\n\nTwo exceptions, both id re-fetches: the chunk and image indices carry no\ntaxonomy tags and ``get_chunk`` / ``get_image`` do not spend a second query\nresolving them, so the field stays at its empty default there — and the\nresearch_get_chunk / research_get_image tools serve ``ChunkRow`` / ``ImageRow``,\nwhich have no ``tags`` field at all, rather than let an empty axis read as\n\"this report is untagged\". So `tags` is absent from those two tools' published\nschemas; wherever it *is* published, an empty axis does mean untagged.",
"properties": {
"article_types": {
"items": {
"type": "string"
},
"type": "array"
},
"topics": {
"items": {
"type": "string"
},
"type": "array"
},
"gender": {
"items": {
"type": "string"
},
"type": "array"
},
"season": {
"items": {
"type": "string"
},
"type": "array"
},
"year": {
"items": {
"type": "string"
},
"type": "array"
},
"moments": {
"items": {
"type": "string"
},
"type": "array"
}
},
"type": "object"
}
},
"required": [
"report_id",
"title",
"date",
"modified",
"excerpt"
],
"type": "object"
},
"type": "array"
},
"next_cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"required": [
"total",
"reports",
"next_cursor"
],
"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
}