Skip to main content

Get Report Metadata (Research)

researchmcp-research_get_report

Fetch full metadata for a known report_id.

Use after one of the search tools (research_article_search, research_chunk_search, research_image_search) when you have a report_id and want more context (full excerpt, modified date) without re-running a search. Cheap direct id lookup. For the full article text use research_read_report; for a public link use research_report_links.

Try queries like

research_get_report(report_id=152777) on an id from a prior search hit; "when was report 152777 published", "details on report 160001".

Parameters​

NameTypeRequiredConstraintsDescription
report_idintegeryes—The report_id returned by a previous search tool.

Returns​

  • On hit: {"result": {"report": {report_id, title, date, modified, excerpt,
  • tags}}}. tags is the report's curated taxonomy tags (article_types,
  • topics, gender, season, year, moments), empty list per
  • untagged axis — use it to settle the audience or season of a report
  • you have only seen as an id.
  • On miss: {"result": {"report": None}}. Not an error.
  • On retrieval failure: {"error": {code, message}}
  • code is 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_get_report",
"arguments": {
"report_id": 1
}
}
}'

Input schema​

{
"type": "object",
"properties": {
"report_id": {
"description": "The report_id returned by a previous search tool.",
"type": "integer"
}
},
"required": [
"report_id"
]
}

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": {
"report": {
"anyOf": [
{
"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": "null"
}
]
}
},
"required": [
"report"
],
"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
}