Skip to main content
Glama

bls-labor-mcp-server

Search BLS Series

bls_search_series
Read-only

Search the BLS series catalog by natural language query, survey code, geographic area, or keywords to resolve cryptic SeriesIDs. Returns matching series with decoded components (survey, area, item, seasonal flag, and publication frequency for surveys that publish one series at several frequencies) and plain-language names, ranked by relevance and paged with limit and offset. Use this before bls_get_series when you have a concept but not a SeriesID. Operates offline against an index of the major surveys — no API quota consumed. Survey filter accepts the two-letter code of an indexed survey (CU, AP, CE, LN, LA, PC, WP, JT, EC, PR, MP, CW, CM, CI, SM, LE, EI, SU, IP, BD, LU, EE; OE is indexed only when the server sets BLS_CATALOG_INCLUDE_OES=true, and otherwise composes OEWS SeriesIDs from the OE code tables, marked composed and unconfirmed); series in other surveys are fetched by SeriesID with bls_get_series. Area filter accepts place names, USPS state codes, and FIPS, CBSA, and CPI area codes.

Input Schema

NameRequiredDescriptionDefault
areaNoGeographic area to narrow results to, case-insensitive. A USPS state code (TX) or 2-digit state FIPS code (48) selects the state: its statewide series, the areas in it (metro areas reaching into it included), and series with no decoded area whose title names it. An all-digit area code selects the area it names in every survey that decodes it: 3 digits a combined statistical area (CSA), 4 a CPI area (0000 is the U.S. city average), 5 a county FIPS or metro area (CBSA) code, 7 a city or town (state + place FIPS); a code naming no indexed area returns no series. Any other value, such as a place name ("Seattle") or a SeriesID fragment ("ST48"), matches as a substring of the area name, title, or SeriesID; another all-digit value does too, with a notice. Under survey OE with no indexed OE rows, area selects the OEWS areas to compose: a USPS state code or 2-digit state FIPS names the state, a 5-digit CBSA or 7-digit OEWS area code (0042660, 5300000) its area, and any other value is a substring of an OEWS area name; each metro or state it names also composes its state and national rows. Without this filter, a place query names in full (every distinctive word of it, e.g. "black hawk") ranks first among the series matching every query word; otherwise, among equal matches, current series rank first, then national ones.
limitNoMaximum number of results to return (default 10); requests above 50 are clamped to 50 with notice.
queryYesNatural language or keyword query (e.g. "unemployment rate", "CPI food", "nonfarm payrolls"). Also accepts a SeriesID directly for exact lookup.
offsetNoNumber of ranked results to skip, for paging past the first page (default 0). Pass nextOffset from the previous response to get the next page.
surveyNoTwo-letter LABSTAT survey abbreviation to filter results, case-insensitive (e.g. CU for CPI, CE for CES, SM for state and metro CES, LN for CPS, LA for LAUS, JT for JOLTS). Indexed surveys: CU, AP, CE, LN, LA, PC, WP, JT, EC, PR, MP, CW, CM, CI, SM, LE, EI, SU, IP, BD, LU, EE; OE (OEWS) is indexed only when the server sets BLS_CATALOG_INCLUDE_OES=true, and without its rows OE composes OEWS SeriesIDs from the OE code tables for the occupation, place, and data type the query and area name, each marked composed. Omit to search all indexed surveys.
seasonal_adjustmentNoWhen true, return only seasonally adjusted series. When false, return only not-seasonally-adjusted. Omit to return both.

Output Schema

NameRequiredDescriptionDefault
capNoThe result limit that capped the returned list.
errorNoPresent when the call failed. Absent on success.
shownNoNumber of series returned in this response.
cappedNoTrue when the FTS candidate pool, after the survey/area/seasonal filters, reached the internal cap (~1000), or when composing OEWS SeriesIDs stopped at its 50-row cap with combinations left. totalCount is then a lower bound and offset paging stops at the pool. Narrow the query, add filters, or use a direct SeriesID to get an exact count.
noticeNoRequested and applied limits when clamped, and how an all-digit area that is not an area code matched, plus guidance on unindexed surveys, offsets past the end, empty results, the next page, the capped candidate pool, or composed OEWS SeriesIDs, which stay unconfirmed until bls_get_series returns them. Absent when neither applies and this page ends an uncapped list of indexed series.
seriesNoMatching series, ordered by relevance.
truncatedNoTrue when ranked results remain past this page; nextOffset fetches them.
areaFilterNoArea filter applied, trimmed. Absent when no area filter was passed or it was blank.
nextOffsetNoOffset of the next page. Present only when truncated is true.
totalCountNoTotal ranked results after every filter (area included), before limit and offset. A lower bound when capped is true — the catalog index may contain more matching series.
catalogSizeNoTotal series in the loaded catalog index. Distinguishes an empty-result search from a failed catalog load.
limitAppliedNoResult limit in effect (defaults to 10 when omitted).
surveyFilterNoSurvey filter applied, trimmed and uppercased. Absent when no survey filter was passed or it was blank.
offsetAppliedNoOffset in effect (defaults to 0 when omitted).
effectiveQueryNoQuery string as the server received and searched on. Confirms interpretation for self-correction.
seasonalFilterNoSeasonal-adjustment filter applied, if any. Absent when not passed.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed8 schema fields changed
    • changedInput schema / properties / area / description
      Previous value: -"State name, MSA name, or FIPS area code to narrow results to a geographic area — a case-insensitive substring of the area name, title, or SeriesID. Without this filter, specific whole place names in query are relevance preferences; otherwise national series rank first among equal matches."New value: +"Geographic area to narrow results to, case-insensitive. A USPS state code (TX) or 2-digit state FIPS code (48) selects the state: its statewide series, the areas in it (metro areas reaching into it included), and series with no decoded area whose title names it. An all-digit area code selects the area it names in every survey that decodes it: 3 digits a combined statistical area (CSA), 4 a CPI area (0000 is the U.S. city average), 5 a county FIPS or metro area (CBSA) code, 7 a city or town (state + place FIPS); a code naming no indexed area returns no series. Any other value, such as a place name (\"Seattle\") or a SeriesID fragment (\"ST48\"), matches as a substring of the area name, title, or SeriesID; another all-digit value does too, with a notice. Under survey OE with no indexed OE rows, area selects the OEWS areas to compose: a USPS state code or 2-digit state FIPS names the state, a 5-digit CBSA or 7-digit OEWS area code (0042660, 5300000) its area, and any other value is a substring of an OEWS area name; each metro or state it names also composes its state and national rows. Without this filter, a place query names in full (every distinctive word of it, e.g. \"black hawk\") ranks first among the series matching every query word; otherwise, among equal matches, current series rank first, then national ones."
    • changedInput schema / properties / survey / description
      Previous value: -"Two-letter LABSTAT survey abbreviation to filter results, case-insensitive (e.g. CU for CPI, CE for CES, LN for CPS, LA for LAUS, JT for JOLTS). Indexed surveys: CU, AP, CE, LN, LA, PC, WP, JT, EC, PR, MP, CW, CM, CI; OE (OEWS) only when the server sets BLS_CATALOG_INCLUDE_OES=true. Omit to search all indexed surveys."New value: +"Two-letter LABSTAT survey abbreviation to filter results, case-insensitive (e.g. CU for CPI, CE for CES, SM for state and metro CES, LN for CPS, LA for LAUS, JT for JOLTS). Indexed surveys: CU, AP, CE, LN, LA, PC, WP, JT, EC, PR, MP, CW, CM, CI, SM, LE, EI, SU, IP, BD, LU, EE; OE (OEWS) is indexed only when the server sets BLS_CATALOG_INCLUDE_OES=true, and without its rows OE composes OEWS SeriesIDs from the OE code tables for the occupation, place, and data type the query and area name, each marked composed. Omit to search all indexed surveys."
    • changedOutput schema / properties / capped / description
      Previous value: -"True when the FTS candidate pool, after the survey/area/seasonal filters, reached the internal cap (~1000). totalCount is then a lower bound and offset paging stops at the pool. Narrow the query, add filters, or use a direct SeriesID to get an exact count."New value: +"True when the FTS candidate pool, after the survey/area/seasonal filters, reached the internal cap (~1000), or when composing OEWS SeriesIDs stopped at its 50-row cap with combinations left. totalCount is then a lower bound and offset paging stops at the pool. Narrow the query, add filters, or use a direct SeriesID to get an exact count."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `catalog_unavailable`: The catalog index failed to load at startup. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `catalog_loading`: The catalog index holds no series yet and a LABSTAT harvest is building it — at first startup, or while an hourly check retries an empty index. `catalog_unavailable`: The catalog index holds no series and no harvest is running — every LABSTAT download failed, or the load stopped with an error. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "catalog_unavailable"
      -]New value: +[
      +  "catalog_loading",
      +  "catalog_unavailable"
      +]
    • changedOutput schema / properties / notice / description
      Previous value: -"Requested and applied limits when clamped, plus guidance on unindexed surveys, offsets past the end, empty results, the next page, or the capped candidate pool. Absent when the limit was unchanged and this page ends an uncapped list with results."New value: +"Requested and applied limits when clamped, and how an all-digit area that is not an area code matched, plus guidance on unindexed surveys, offsets past the end, empty results, the next page, the capped candidate pool, or composed OEWS SeriesIDs, which stay unconfirmed until bls_get_series returns them. Absent when neither applies and this page ends an uncapped list of indexed series."
    • addedOutput schema / properties / series / items / properties / composed
      Added value: +{
      +  "description": "True when the SeriesID was composed from the OEWS code tables rather than read from the index: unconfirmed until bls_get_series returns data for it, since BLS leaves many occupation–area cells unpublished. Composed rows carry no coverage years. Absent for indexed series.",
      +  "type": "boolean"
      +}
    • changedOutput schema / properties / series / items / properties / frequency / description
      Previous value: -"Publication frequency — \"Monthly\", \"Semi-Annual\", \"Quarterly\", or \"Annual\" — for CU, CW, and LN, which publish one series at several frequencies under the same title. Absent for other surveys."New value: +"Publication frequency — \"Monthly\", \"Semi-Annual\", \"Quarterly\", or \"Annual\" — for CU, CW, LN, and BD, which publish one series at several frequencies under the same title. Absent for other surveys."
  2. Changed3 schema fields changed
    • changedInput schema / properties / limit / description
      Previous value: -"Maximum number of results to return (1–50, default 10)."New value: +"Maximum number of results to return (default 10); requests above 50 are clamped to 50 with notice."
    • changedInput schema / properties / limit / maximum
      Previous value: -50New value: +9007199254740991
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance on the result: the survey is not in the offline index, the offset is past the last result, nothing matched, which offset fetches the next page, or, on the last page of a capped list, that other series may also match. Absent when this page ends an uncapped list with results."New value: +"Requested and applied limits when clamped, plus guidance on unindexed surveys, offsets past the end, empty results, the next page, or the capped candidate pool. Absent when the limit was unchanged and this page ends an uncapped list with results."
  3. Changed4 schema fields changed
    • changedInput schema / properties / area / description
      Previous value: -"State name, MSA name, or FIPS area code to narrow results to a geographic area — a case-insensitive substring of the area name, title, or SeriesID. Omit for national series, which then rank first among equal matches."New value: +"State name, MSA name, or FIPS area code to narrow results to a geographic area — a case-insensitive substring of the area name, title, or SeriesID. Without this filter, specific whole place names in query are relevance preferences; otherwise national series rank first among equal matches."
    • addedOutput schema / properties / series / items / properties / endPeriod
      Added value: +{
      +  "description": "Last observation period code in the catalog snapshot, when available (e.g. M08 or Q04).",
      +  "type": "string"
      +}
    • addedOutput schema / properties / series / items / properties / endYear
      Added value: +{
      +  "description": "Last observation year in the catalog snapshot, when available.",
      +  "maximum": 9007199254740991,
      +  "minimum": -9007199254740991,
      +  "type": "integer"
      +}
    • addedOutput schema / properties / series / items / properties / startYear
      Added value: +{
      +  "description": "First observation year in the catalog snapshot, when available; does not imply continuous coverage.",
      +  "maximum": 9007199254740991,
      +  "minimum": -9007199254740991,
      +  "type": "integer"
      +}
  4. Changed2 schema fields changed
    • changedInput schema / properties / survey / description
      Previous value: -"Two-letter LABSTAT survey abbreviation to filter results, case-insensitive (e.g. CU for CPI, CE for CES, LN for CPS, LA for LAUS, JT for JOLTS). Indexed surveys: CU, AP, CE, LN, LA, PC, WP, JT, EC, PR, MP, CW; OE (OEWS) only when the server sets BLS_CATALOG_INCLUDE_OES=true. Omit to search all indexed surveys."New value: +"Two-letter LABSTAT survey abbreviation to filter results, case-insensitive (e.g. CU for CPI, CE for CES, LN for CPS, LA for LAUS, JT for JOLTS). Indexed surveys: CU, AP, CE, LN, LA, PC, WP, JT, EC, PR, MP, CW, CM, CI; OE (OEWS) only when the server sets BLS_CATALOG_INCLUDE_OES=true. Omit to search all indexed surveys."
    • addedOutput schema / properties / series / items / properties / frequency
      Added value: +{
      +  "description": "Publication frequency — \"Monthly\", \"Semi-Annual\", \"Quarterly\", or \"Annual\" — for CU, CW, and LN, which publish one series at several frequencies under the same title. Absent for other surveys.",
      +  "type": "string"
      +}
  5. Changed12 schema fields changed
    • changedInput schema / properties / area / description
      Previous value: -"State name, MSA name, or FIPS area code to narrow results to a geographic area. Omit for national series."New value: +"State name, MSA name, or FIPS area code to narrow results to a geographic area — a case-insensitive substring of the area name, title, or SeriesID. Omit for national series, which then rank first among equal matches."
    • addedInput schema / properties / offset
      Added value: +{
      +  "default": 0,
      +  "description": "Number of ranked results to skip, for paging past the first page (default 0). Pass nextOffset from the previous response to get the next page.",
      +  "maximum": 9007199254740991,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • changedInput schema / properties / survey / description
      Previous value: -"Two-letter LABSTAT survey abbreviation to filter results (e.g. CU for CPI, CE for CES, LN for CPS, LA for LAUS, JT for JOLTS, OE for OEWS). Omit to search all loaded surveys."New value: +"Two-letter LABSTAT survey abbreviation to filter results, case-insensitive (e.g. CU for CPI, CE for CES, LN for CPS, LA for LAUS, JT for JOLTS). Indexed surveys: CU, AP, CE, LN, LA, PC, WP, JT, EC, PR, MP, CW; OE (OEWS) only when the server sets BLS_CATALOG_INCLUDE_OES=true. Omit to search all indexed surveys."
    • changedOutput schema / anyOf
      Previous value: -[
      -  {
      -    "not": {
      -      "required": [
      -        "error"
      -      ]
      -    },
      -    "required": [
      -      "series",
      -      "totalCount",
      -      "capped",
      -      "catalogSize",
      -      "effectiveQuery",
      -      "limitApplied"
      -    ]
      -  },
      -  {
      -    "required": [
      -      "error"
      -    ]
      -  }
      -]New value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "series",
      +      "totalCount",
      +      "capped",
      +      "catalogSize",
      +      "effectiveQuery",
      +      "limitApplied",
      +      "offsetApplied"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • changedOutput schema / properties / areaFilter / description
      Previous value: -"Area filter applied, if any. Absent when no area filter was passed."New value: +"Area filter applied, trimmed. Absent when no area filter was passed or it was blank."
    • changedOutput schema / properties / capped / description
      Previous value: -"True when the FTS candidate pool reached the internal cap (~1000). totalCount is then a lower bound, not an exact match count. Narrow the query, add survey/area filters, or use a direct SeriesID to get an exact count."New value: +"True when the FTS candidate pool, after the survey/area/seasonal filters, reached the internal cap (~1000). totalCount is then a lower bound and offset paging stops at the pool. Narrow the query, add filters, or use a direct SeriesID to get an exact count."
    • addedOutput schema / properties / nextOffset
      Added value: +{
      +  "description": "Offset of the next page. Present only when truncated is true.",
      +  "type": "number"
      +}
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance when no results matched — e.g. how to broaden the query or remove filters. Absent when results are returned."New value: +"Guidance on the result: the survey is not in the offline index, the offset is past the last result, nothing matched, which offset fetches the next page, or, on the last page of a capped list, that other series may also match. Absent when this page ends an uncapped list with results."
    • addedOutput schema / properties / offsetApplied
      Added value: +{
      +  "description": "Offset in effect (defaults to 0 when omitted).",
      +  "type": "number"
      +}
    • changedOutput schema / properties / surveyFilter / description
      Previous value: -"Survey filter applied, if any. Absent when no survey filter was passed."New value: +"Survey filter applied, trimmed and uppercased. Absent when no survey filter was passed or it was blank."
    • changedOutput schema / properties / totalCount / description
      Previous value: -"Total candidates scored before the limit was applied. A lower bound when capped is true — the catalog index may contain more matching series."New value: +"Total ranked results after every filter (area included), before limit and offset. A lower bound when capped is true — the catalog index may contain more matching series."
    • changedOutput schema / properties / truncated / description
      Previous value: -"True when more candidates matched than the limit returned."New value: +"True when ranked results remain past this page; nextOffset fetches them."
  6. 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": [
      +      "series",
      +      "totalCount",
      +      "capped",
      +      "catalogSize",
      +      "effectiveQuery",
      +      "limitApplied"
      +    ]
      +  },
      +  {
      +    "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: `catalog_unavailable`: The catalog index failed to load at startup. Other values are possible when a failure originates below the handler.",
      +          "examples": [
      +            "catalog_unavailable"
      +          ],
      +          "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: -[
      -  "series",
      -  "totalCount",
      -  "capped",
      -  "catalogSize",
      -  "effectiveQuery",
      -  "limitApplied"
      -]
  7. Changed7 schema fields changed
    • addedOutput schema / properties / cap
      Added value: +{
      +  "description": "The result limit that capped the returned list.",
      +  "type": "number"
      +}
    • changedOutput schema / properties / capped / description
      Previous value: -"True when the FTS candidate pool reached the internal cap (~1000). totalFound is then a lower bound, not an exact match count. Narrow the query, add survey/area filters, or use a direct SeriesID to get an exact count."New value: +"True when the FTS candidate pool reached the internal cap (~1000). totalCount is then a lower bound, not an exact match count. Narrow the query, add survey/area filters, or use a direct SeriesID to get an exact count."
    • addedOutput schema / properties / shown
      Added value: +{
      +  "description": "Number of series returned in this response.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / totalCount
      Added value: +{
      +  "description": "Total candidates scored before the limit was applied. A lower bound when capped is true — the catalog index may contain more matching series.",
      +  "type": "number"
      +}
    • removedOutput schema / properties / totalFound
      Removed value: -{
      -  "description": "Total candidates scored before the limit was applied. A lower bound when capped is true — the catalog index may contain more matching series.",
      -  "type": "number"
      -}
    • addedOutput schema / properties / truncated
      Added value: +{
      +  "description": "True when more candidates matched than the limit returned.",
      +  "type": "boolean"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "series",
      -  "totalFound",
      -  "capped",
      -  "catalogSize",
      -  "effectiveQuery",
      -  "limitApplied"
      -]New value: +[
      +  "series",
      +  "totalCount",
      +  "capped",
      +  "catalogSize",
      +  "effectiveQuery",
      +  "limitApplied"
      +]
  8. Changed9 schema fields changed
    • addedOutput schema / properties / capped
      Added value: +{
      +  "description": "True when the FTS candidate pool reached the internal cap (~1000). totalFound is then a lower bound, not an exact match count. Narrow the query, add survey/area filters, or use a direct SeriesID to get an exact count.",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / series / items / properties / area
      Added value: +{
      +  "description": "Geographic area name, when decoded.",
      +  "type": "string"
      +}
    • removedOutput schema / properties / series / items / properties / areaName
      Removed value: -{
      -  "description": "Geographic area name, when decoded.",
      -  "type": "string"
      -}
    • addedOutput schema / properties / series / items / properties / item
      Added value: +{
      +  "description": "Item or subject name, when decoded.",
      +  "type": "string"
      +}
    • removedOutput schema / properties / series / items / properties / itemName
      Removed value: -{
      -  "description": "Item or subject name, when decoded.",
      -  "type": "string"
      -}
    • changedOutput schema / properties / series / items / properties / seasonal / description
      Previous value: -"True when seasonally adjusted."New value: +"Seasonality descriptor matching the data-tool form: \"Seasonally Adjusted\" or \"Not Seasonally Adjusted\"."
    • changedOutput schema / properties / series / items / properties / seasonal / type
      Previous value: -"boolean"New value: +"string"
    • changedOutput schema / properties / totalFound / description
      Previous value: -"Total matches in the catalog before the limit was applied."New value: +"Total candidates scored before the limit was applied. A lower bound when capped is true — the catalog index may contain more matching series."
    • changedOutput schema / required
      Previous value: -[
      -  "series",
      -  "totalFound",
      -  "catalogSize",
      -  "effectiveQuery",
      -  "limitApplied"
      -]New value: +[
      +  "series",
      +  "totalFound",
      +  "capped",
      +  "catalogSize",
      +  "effectiveQuery",
      +  "limitApplied"
      +]
  9. Changed6 schema fields changed
    • addedOutput schema / properties / areaFilter
      Added value: +{
      +  "description": "Area filter applied, if any. Absent when no area filter was passed.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / effectiveQuery
      Added value: +{
      +  "description": "Query string as the server received and searched on. Confirms interpretation for self-correction.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / limitApplied
      Added value: +{
      +  "description": "Result limit in effect (defaults to 10 when omitted).",
      +  "type": "number"
      +}
    • addedOutput schema / properties / seasonalFilter
      Added value: +{
      +  "description": "Seasonal-adjustment filter applied, if any. Absent when not passed.",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / surveyFilter
      Added value: +{
      +  "description": "Survey filter applied, if any. Absent when no survey filter was passed.",
      +  "type": "string"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "series",
      -  "totalFound",
      -  "catalogSize"
      -]New value: +[
      +  "series",
      +  "totalFound",
      +  "catalogSize",
      +  "effectiveQuery",
      +  "limitApplied"
      +]
  10. Changed5 schema fields changed
    • changedOutput schema / properties / catalogSize / description
      Previous value: -"Total series in the loaded catalog index. Used to distinguish an empty-result search from a failed catalog load."New value: +"Total series in the loaded catalog index. Distinguishes an empty-result search from a failed catalog load."
    • addedOutput schema / properties / notice
      Added value: +{
      +  "description": "Guidance when no results matched — e.g. how to broaden the query or remove filters. Absent when results are returned.",
      +  "type": "string"
      +}
    • removedOutput schema / properties / total
      Removed value: -{
      -  "description": "Total matches in the catalog before the limit was applied.",
      -  "type": "number"
      -}
    • addedOutput schema / properties / totalFound
      Added value: +{
      +  "description": "Total matches in the catalog before the limit was applied.",
      +  "type": "number"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "series",
      -  "total",
      -  "catalogSize"
      -]New value: +[
      +  "series",
      +  "totalFound",
      +  "catalogSize"
      +]
  11. First observed

TDQS

A4.6/5.0
Behavior5/5

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

Well beyond the annotations: it discloses that the tool runs offline against a bundled index with no API quota consumed (consistent with openWorldHint=false), that limits above 50 are clamped with a notice, how results are ranked, and the OE caveat that composed SeriesIDs are 'marked composed and unconfirmed.' These are exactly the operational traits an agent needs and that annotations cannot express.

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

Conciseness4/5

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

Front-loaded correctly: purpose first, then the use-before-bls_get_series rule, then operational caveats. It is dense but mostly earns its length; the main waste is re-listing the 23 survey codes and area-code digits that the schema already carries, which could have been left to the schema.

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

Completeness5/5

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

For a six-parameter discovery tool with an output schema, the description covers everything material: what it returns in outline, ranking and paging behavior, offline/quota status, and the OE indexing dependency. Nothing an agent needs in order to call it correctly is missing.

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 coverage is 100%, so the schema already documents all six parameters, including the survey and area code semantics. The description largely restates that content (the survey code list is duplicated verbatim in the schema), adding little parameter-level meaning beyond the schema; at most it reinforces default paging via limit/offset. Baseline 3 is appropriate.

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?

States a specific verb and resource ('Search the BLS series catalog') and enumerates the accepted query forms (natural language, survey code, area, keywords) plus the goal ('resolve cryptic SeriesIDs'). It explicitly distinguishes itself from bls_get_series, so an agent can route correctly without opening either schema.

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

Usage Guidelines5/5

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

Gives an explicit ordering rule: 'Use this before bls_get_series when you have a concept but not a SeriesID,' and closes the loop with 'series in other surveys are fetched by SeriesID with bls_get_series.' The offline/no-quota note further signals when this is the cheap first move.

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.