Skip to main content
Glama

Hn Search Content

hn_search_content
Read-only

Search Hacker News stories, comments, polls, and jobs via Algolia — by keyword, by filters alone, or both. Filterable by content type, author, parent story, date range, and minimum points.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pageNoPage number for pagination (0-indexed).
sortNoSort order. "relevance" for best match, "date" for most recent first.relevance
tagsNoFilter results by content type: "story", "comment", "poll", or "job", or the story subsets "ask_hn", "show_hn", and "front_page". Omit to search all types.
viewNoHow much of each hit to return. "full" includes every field. "compact" omits the two body-text fields — `text` and `highlights.text` — which together can repeat a long comment twice per hit; everything else (id, title, url, domain, author, points, comment count, timestamp, parent story, title highlight, matchedWords) is unchanged. Use "compact" to scan many results, then pass a hit id to hn_get_thread to read the body you skipped.full
countNoNumber of results to return.
queryNoSearch terms. Supports simple keywords — Algolia handles stemming and relevance. Trimmed before searching; blank or whitespace-only input is rejected. Omit for a filter-only search, which needs at least one of tags, author, storyId, minPoints, or a dateRange bound.
authorNoFilter results to a specific author. Useful for finding a user's posts on a topic (hn_get_user only shows recent submissions). Trimmed before filtering; omit the field to search all authors rather than passing a blank string.
storyIdNoRestrict results to one discussion: the id of a story or poll root, combined with the other filters. Pair with tags "comment" to search within a thread. Take it from hits[].storyId or the root item of hn_get_thread — a comment id matches nothing.
dateRangeNoFilter to a creation-time window with a start, an end, or both. An empty object is rejected — omit dateRange instead.
minPointsNoMinimum score. Applies to stories and polls, including the ask_hn, show_hn, and front_page subsets. Comments and jobs carry no points in the search index, so any minPoints excludes them — combining it with tags "comment" or "job" is rejected.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
capNoThe count cap that was applied.
hitsNoSearch results ranked by sort order.
pageNoCurrent page number (0-indexed).
errorNoPresent when the call failed. Absent on success.
queryNoThe query that was searched. Absent for a filter-only search.
shownNoNumber of hits returned.
noticeNoAgent guidance: the next page to request while more pages remain, the last valid page when the requested page is past the end, or the filters to relax when a first page comes back empty. Absent on the last page of a non-empty result.
totalHitsNoTotal matching results across all pages.
truncatedNoTrue when more pages remain after this one (page + 1 < totalPages). Absent on the last page Algolia serves.
totalPagesNoNumber of pages Algolia will actually serve for this query. Not derived from totalHits — broad queries report a totalHits far larger than the reachable page range, so paginate against this value.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedOutput schema / properties / hits / items / properties / highlights / properties / text / description
      Previous value: -"Body snippet (comment_text or story_text) with matched terms wrapped in `<em>…</em>`. Absent when the body did not match, and always absent under view \"compact\" — matchedWords still lists what matched."New value: +"Body snippet (comment_text or story_text), HTML stripped, with matched terms wrapped in `<em>…</em>`. A literal `<em>` typed into the body is indistinguishable from a marker. Absent when the body did not match, and always absent under view \"compact\" — matchedWords still lists what matched."
    • changedOutput schema / properties / hits / items / properties / highlights / properties / title / description
      Previous value: -"Title snippet with matched terms wrapped in `<em>…</em>`. Absent when the title did not match."New value: +"Title snippet with matched terms wrapped in `<em>…</em>`. Titles are not HTML, though some arrive entity-encoded; entities are decoded and no tags are stripped, so a literal `<em>` in the title is indistinguishable from a marker. Absent when the title did not match."
  2. Changed19 schema fields changed
    • changedInput schema / properties / dateRange / description
      Previous value: -"Filter to a date window. Useful for finding discussions about recent events."New value: +"Filter to a creation-time window with a start, an end, or both. An empty object is rejected — omit dateRange instead."
    • changedInput schema / properties / dateRange / properties / end / description
      Previous value: -"End date (ISO 8601). Results created before this date."New value: +"Exclusive upper bound — only items created strictly before this instant match. Same formats and UTC reading as start, and must be later than start. A date-only end excludes that whole UTC day: to include it, pass the next day or a full timestamp."
    • addedInput schema / properties / dateRange / properties / end / pattern
      Added value: +"^(\\d{4})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.\\d{1,3})?)?(?:Z|[+-](\\d{2}):(\\d{2}))?)?)?)?$"
    • changedInput schema / properties / dateRange / properties / start / description
      Previous value: -"Start date (ISO 8601). Results created after this date."New value: +"Exclusive lower bound — only items created strictly after this instant match. ISO 8601: YYYY, YYYY-MM, YYYY-MM-DD, or YYYY-MM-DDThh:mm[:ss[.sss]] with an optional Z or ±hh:mm offset. Reduced and date-only forms mean UTC midnight at the start of that period; a date-time without an offset is read as UTC."
    • addedInput schema / properties / dateRange / properties / start / pattern
      Added value: +"^(\\d{4})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.\\d{1,3})?)?(?:Z|[+-](\\d{2}):(\\d{2}))?)?)?)?$"
    • changedInput schema / properties / minPoints / description
      Previous value: -"Minimum score/points. Filters out low-engagement content."New value: +"Minimum score. Applies to stories and polls, including the ask_hn, show_hn, and front_page subsets. Comments and jobs carry no points in the search index, so any minPoints excludes them — combining it with tags \"comment\" or \"job\" is rejected."
    • changedInput schema / properties / query / description
      Previous value: -"Search terms. Supports simple keywords — Algolia handles stemming and relevance. Trimmed before searching; blank or whitespace-only input is rejected."New value: +"Search terms. Supports simple keywords — Algolia handles stemming and relevance. Trimmed before searching; blank or whitespace-only input is rejected. Omit for a filter-only search, which needs at least one of tags, author, storyId, minPoints, or a dateRange bound."
    • addedInput schema / properties / storyId
      Added value: +{
      +  "description": "Restrict results to one discussion: the id of a story or poll root, combined with the other filters. Pair with tags \"comment\" to search within a thread. Take it from hits[].storyId or the root item of hn_get_thread — a comment id matches nothing.",
      +  "exclusiveMinimum": 0,
      +  "maximum": 9007199254740991,
      +  "type": "integer"
      +}
    • changedInput schema / properties / tags / description
      Previous value: -"Filter results by content type. Omit to search all types."New value: +"Filter results by content type: \"story\", \"comment\", \"poll\", or \"job\", or the story subsets \"ask_hn\", \"show_hn\", and \"front_page\". Omit to search all types."
    • changedInput schema / properties / tags / enum
      Previous value: -[
      -  "story",
      -  "comment",
      -  "ask_hn",
      -  "show_hn",
      -  "front_page"
      -]New value: +[
      +  "story",
      +  "comment",
      +  "poll",
      +  "job",
      +  "ask_hn",
      +  "show_hn",
      +  "front_page"
      +]
    • removedInput schema / required
      Removed value: -[
      -  "query"
      -]
    • changedOutput schema / anyOf
      Previous value: -[
      -  {
      -    "not": {
      -      "required": [
      -        "error"
      -      ]
      -    },
      -    "required": [
      -      "hits",
      -      "query",
      -      "totalHits",
      -      "page",
      -      "totalPages"
      -    ]
      -  },
      -  {
      -    "required": [
      -      "error"
      -    ]
      -  }
      -]New value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "hits",
      +      "totalHits",
      +      "page",
      +      "totalPages"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `upstream_rejected`: Algolia answered with a 4xx status other than 429 — it rejected the request as built. `upstream_rate_limited`: Algolia answered with HTTP 429. `upstream_unavailable`: Algolia answered with a 5xx status. `upstream_html`: Algolia served an HTML error page with a 200 status, which it does under rate limiting or maintenance. `upstream_malformed`: Algolia answered with a 200 status and a body that is not JSON. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `missing_query_or_filter`: Neither a query nor any filter was supplied, so there is nothing to search by. `invalid_date_range`: dateRange was supplied with neither bound, or with start not before end. `min_points_unscored_type`: minPoints was combined with tags \"comment\" or \"job\", record types Algolia stores without points. `upstream_rejected`: Algolia answered with a 4xx status other than 429 — it rejected the request as built. `upstream_rate_limited`: Algolia answered with HTTP 429. `upstream_unavailable`: Algolia answered with a 5xx status. `upstream_html`: Algolia served an HTML error page with a 200 status, which it does under rate limiting or maintenance. `upstream_malformed`: Algolia answered with a 200 status and a body that is not JSON. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "upstream_rejected",
      -  "upstream_rate_limited",
      -  "upstream_unavailable",
      -  "upstream_html",
      -  "upstream_malformed"
      -]New value: +[
      +  "missing_query_or_filter",
      +  "invalid_date_range",
      +  "min_points_unscored_type",
      +  "upstream_rejected",
      +  "upstream_rate_limited",
      +  "upstream_unavailable",
      +  "upstream_html",
      +  "upstream_malformed"
      +]
    • changedOutput schema / properties / hits / items / description
      Previous value: -"A single Algolia search hit (story or comment)."New value: +"A single Algolia search hit (story, comment, poll, or job)."
    • changedOutput schema / properties / hits / items / properties / title / description
      Previous value: -"Story title (present for stories)."New value: +"Item title (present for stories, polls, and jobs)."
    • changedOutput schema / properties / notice / description
      Previous value: -"Recovery hint when results are empty — names the filters applied, for relaxing the search. Absent on non-empty result pages."New value: +"Agent guidance: the next page to request while more pages remain, the last valid page when the requested page is past the end, or the filters to relax when a first page comes back empty. Absent on the last page of a non-empty result."
    • changedOutput schema / properties / query / description
      Previous value: -"The query that was searched."New value: +"The query that was searched. Absent for a filter-only search."
    • changedOutput schema / properties / truncated / description
      Previous value: -"True when the hit list was capped by the count parameter."New value: +"True when more pages remain after this one (page + 1 < totalPages). Absent on the last page Algolia serves."
  3. Changed6 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / additionalProperties
      Added value: +false
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedOutput schema / anyOf
      Added value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "hits",
      +      "query",
      +      "totalHits",
      +      "page",
      +      "totalPages"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / error
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when the call failed. Absent on success.",
      +  "properties": {
      +    "code": {
      +      "description": "JSON-RPC error code for this failure.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "properties": {
      +        "reason": {
      +          "description": "Machine-readable failure mode. Declared by this tool: `upstream_rejected`: Algolia answered with a 4xx status other than 429 — it rejected the request as built. `upstream_rate_limited`: Algolia answered with HTTP 429. `upstream_unavailable`: Algolia answered with a 5xx status. `upstream_html`: Algolia served an HTML error page with a 200 status, which it does under rate limiting or maintenance. `upstream_malformed`: Algolia answered with a 200 status and a body that is not JSON. Other values are possible when a failure originates below the handler.",
      +          "examples": [
      +            "upstream_rejected",
      +            "upstream_rate_limited",
      +            "upstream_unavailable",
      +            "upstream_html",
      +            "upstream_malformed"
      +          ],
      +          "type": "string"
      +        },
      +        "recovery": {
      +          "additionalProperties": {},
      +          "description": "Actionable next step for the caller.",
      +          "properties": {
      +            "hint": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "hint"
      +          ],
      +          "type": "object"
      +        },
      +        "retryable": {
      +          "description": "Whether retrying may succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "message": {
      +      "description": "Human-readable description of what went wrong.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "message"
      +  ],
      +  "type": "object"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "hits",
      -  "query",
      -  "totalHits",
      -  "page",
      -  "totalPages"
      -]
  4. Changed3 schema fields changed
    • addedInput schema / properties / view
      Added value: +{
      +  "default": "full",
      +  "description": "How much of each hit to return. \"full\" includes every field. \"compact\" omits the two body-text fields — `text` and `highlights.text` — which together can repeat a long comment twice per hit; everything else (id, title, url, domain, author, points, comment count, timestamp, parent story, title highlight, matchedWords) is unchanged. Use \"compact\" to scan many results, then pass a hit id to hn_get_thread to read the body you skipped.",
      +  "enum": [
      +    "full",
      +    "compact"
      +  ],
      +  "type": "string"
      +}
    • changedOutput schema / properties / hits / items / properties / highlights / properties / text / description
      Previous value: -"Body snippet (comment_text or story_text) with matched terms wrapped in `<em>…</em>`. Absent when the body did not match."New value: +"Body snippet (comment_text or story_text) with matched terms wrapped in `<em>…</em>`. Absent when the body did not match, and always absent under view \"compact\" — matchedWords still lists what matched."
    • changedOutput schema / properties / hits / items / properties / text / description
      Previous value: -"Comment or story body text (HTML stripped)."New value: +"Comment or story body text (HTML stripped). Absent when the hit has no body, and always absent under view \"compact\" — call hn_get_thread with this id to read it."
  5. Changed10 schema fields changed
    • changedInput schema / properties / author / description
      Previous value: -"Filter results to a specific author. Useful for finding a user's posts on a topic (hn_get_user only shows recent submissions)."New value: +"Filter results to a specific author. Useful for finding a user's posts on a topic (hn_get_user only shows recent submissions). Trimmed before filtering; omit the field to search all authors rather than passing a blank string."
    • addedInput schema / properties / author / minLength
      Added value: +1
    • changedInput schema / properties / count / type
      Previous value: -"number"New value: +"integer"
    • addedInput schema / properties / minPoints / maximum
      Added value: +9007199254740991
    • changedInput schema / properties / minPoints / type
      Previous value: -"number"New value: +"integer"
    • addedInput schema / properties / page / maximum
      Added value: +9007199254740991
    • changedInput schema / properties / page / type
      Previous value: -"number"New value: +"integer"
    • changedInput schema / properties / query / description
      Previous value: -"Search terms. Supports simple keywords — Algolia handles stemming and relevance."New value: +"Search terms. Supports simple keywords — Algolia handles stemming and relevance. Trimmed before searching; blank or whitespace-only input is rejected."
    • addedInput schema / properties / query / minLength
      Added value: +1
    • changedOutput schema / properties / totalPages / description
      Previous value: -"Total pages available."New value: +"Number of pages Algolia will actually serve for this query. Not derived from totalHits — broad queries report a totalHits far larger than the reachable page range, so paginate against this value."
  6. Changed3 schema fields changed
    • addedOutput schema / properties / cap
      Added value: +{
      +  "description": "The count cap that was applied.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / shown
      Added value: +{
      +  "description": "Number of hits returned.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / truncated
      Added value: +{
      +  "description": "True when the hit list was capped by the count parameter.",
      +  "type": "boolean"
      +}
  7. Changed4 schema fields changed
    • removedOutput schema / properties / message
      Removed value: -{
      -  "description": "Recovery hint when results are empty — names the filters that were applied, for relaxing the search. Absent on non-empty result pages.",
      -  "type": "string"
      -}
    • addedOutput schema / properties / notice
      Added value: +{
      +  "description": "Recovery hint when results are empty — names the filters applied, for relaxing the search. Absent on non-empty result pages.",
      +  "type": "string"
      +}
    • changedOutput schema / properties / page / description
      Previous value: -"Current page number."New value: +"Current page number (0-indexed)."
    • changedOutput schema / required
      Previous value: -[
      -  "hits",
      -  "totalHits",
      -  "page",
      -  "totalPages",
      -  "query"
      -]New value: +[
      +  "hits",
      +  "query",
      +  "totalHits",
      +  "page",
      +  "totalPages"
      +]
  8. Changed2 schema fields changed
    • addedOutput schema / properties / hits / items / properties / domain
      Added value: +{
      +  "description": "Bare hostname derived from url (e.g. \"github.com\", with leading \"www.\" stripped). Absent when url is missing or unparseable.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / hits / items / properties / highlights
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Algolia per-field highlight metadata showing which terms matched and where. Absent when no fields produced a match.",
      +  "properties": {
      +    "matchedWords": {
      +      "description": "Deduplicated union of matched terms across all searchable fields (title, url, author, comment_text, story_text, story_title).",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "text": {
      +      "description": "Body snippet (comment_text or story_text) with matched terms wrapped in `<em>…</em>`. Absent when the body did not match.",
      +      "type": "string"
      +    },
      +    "title": {
      +      "description": "Title snippet with matched terms wrapped in `<em>…</em>`. Absent when the title did not match.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "matchedWords"
      +  ],
      +  "type": "object"
      +}
  9. Changed2 schema fields changed
    • changedOutput schema / properties / hits / items / properties / storyId / description
      Previous value: -"Parent story ID (present for comment results)."New value: +"Parent story ID for comment hits; equals `id` for story hits."
    • changedOutput schema / properties / message / description
      Previous value: -"Recovery hint when results are empty — names the filters that were applied so the agent knows what to relax. Absent on non-empty result pages."New value: +"Recovery hint when results are empty — names the filters that were applied, for relaxing the search. Absent on non-empty result pages."
  10. Changed1 schema field changed
    • addedOutput schema / properties / message
      Added value: +{
      +  "description": "Recovery hint when results are empty — names the filters that were applied so the agent knows what to relax. Absent on non-empty result pages.",
      +  "type": "string"
      +}
  11. Changed1 schema field changed
    • addedOutput schema / properties / hits / items / description
      Added value: +"A single Algolia search hit (story or comment)."
  12. First observed

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true, so the description carries a lower burden. It adds no destructive/auth/rate-limit caveats and does not disclose behavioral quirks beyond the searchable scope; deeper constraints like exclusive date bounds and minPoints excluding comments/jobs are documented in the schema, not the description. Adequate, but not additive beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the verb and object, and every phrase earns its place. It summarizes the search modes and filter categories without repeating schema details or adding filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex tool with 10 parameters, nested objects, and an output schema, the overall definition is complete: parameter descriptions cover edge cases such as empty dateRange rejection and minPoints incompatibility, and the output schema removes the need to describe return values. The main description is a solid high-level summary, though explicit sibling-tool selection is left to schema cross-references.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and each parameter already has a rich description including trimming, exclusivity, enums, defaults, and edge-case behavior. The main description only restates the filterable dimensions at a high level and adds no syntax or constraint details beyond what the schema provides, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names the action ('Search'), the resource ('Hacker News stories, comments, polls, and jobs'), the mechanism ('via Algolia'), and both usage modes (keyword, filters, or both). This clearly distinguishes it from the sibling get tools, which retrieve specific items rather than search across content.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description conveys when to use the tool—when searching HN by keyword and/or filters—but it does not explicitly state when not to use it or when to prefer a sibling tool. The only cross-tool routing appears inside the view parameter ('pass a hit id to hn_get_thread'), not in the main description, so usage guidance is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.