Skip to main content
Glama

Search Contracts & RFPs

search_procurement
Read-onlyIdempotent

CONTRACTS & PROCUREMENT — Search government contracts, RFPs, RFIs, BAAs, and solicitations from SAM.gov. Better than searching SAM.gov directly — includes semantic search and NAICS industry filtering to exclude commodity noise. Use when user wants: contracts, RFPs, procurement, bids, government work. Examples: "IT consulting services", "construction management", "cybersecurity contracts". BATCH MODE (paid): pass a queries[] array of 2-5 variations instead of query to run them in parallel, dedupe, and return all unique results in one call — this replaces the former batch_search_procurement tool. When sam_filters.place_of_performance_state (alias: pop_state, accepted in both single and batch mode) is set, the response includes a placeOfPerformance field reporting how many results are confirmed performed in that state (matched), how many have no confirmed location and are shown demoted with a caveat (unknownServed, excluded instead when user_context.location_strict is true), and how many were excluded for being tagged to a different, parseable state (otherStateExcluded; geography we could not parse into any state, such as a bare address or ZIP code, counts as unknownServed instead); a batch call sums these across every sub-query. Paid plans see new listings in search, alerts and AI search within a day of when we add them; the free plan sees them there after 10 days. Counts toward your monthly searches. A batch counts as 1 call.

Input Schema

NameRequiredDescriptionDefault
limitNoMax results (default: 25)
queryNoNatural language search query. Provide either query (single search) or queries (batch mode) — exactly one.
sinceNoStateless alternative to posted_within_days/new_within_days: ISO 8601 instant. Only opportunities ingested at/after this instant. Store the previous response newSince.newest and pass it here to manage your own watermark.
cursorNoPagination cursor from previous response
offsetNoBatch mode only: number of merged results to skip for pagination (default 0). Ignored in single-query mode.
sourceNoFilter to a specific source/domain, e.g. "sam.gov" or an agency source domain.
statusNoFilter by status
compactNoReturn compact results (default: true). Set to false for full details.
queriesNoBATCH MODE (paid, replaces batch_search_procurement): array of 2-5 search queries to run in parallel, dedupe, and merge. Example for IT services: ["IT services contract", "software development federal", "technology consulting government", "computer services procurement"]. When set, query is ignored and the batch response params (detail_level, max_results, offset, max_response_tokens) apply.
max_resultsNoBatch mode only: maximum merged results to return (default 10). Ignored in single-query mode (use limit).
min_qualityNoMinimum record-completeness tier (default: medium). any removes this quality-tier filter; relevance, access and other filters still apply.
sam_filtersNoSAM.gov specific filters
detail_levelNoBatch mode only: controls response verbosity (minimal/compact [default]/full). Ignored in single-query mode.
organizationNoFilter by contracting agency
user_contextNoUser context for better filtering
new_within_daysNoBackwards-compatible alias for posted_within_days. Only opportunities WE ADDED (ingested) in the last N days for recurring/delta checks ("what is new since my last check"). Additive to all other filters. In queryless browse mode without a single source, the recency window is sampled across sources round-robin by ingest recency so one bulk harvester cannot own the digest; each source remains newest first. The response includes newSince and windowCoverage: sourcesSampled counts distinct sources returned by the grouped provider query before MCP quality, judge, recency-withhold, and page filters; it is absent when no grouped sample was available, including when sampling was not attempted, and 0 means the grouped query succeeded but returned no sourced rows; sourcesServed counts distinct sources delivered on this page. windowCoverage.order is "recency" for the queryless browse digest or "relevance" when a query is present. windowIncomplete/incompleteReason is separate from ceilingTruncated, which is true only when the 2,000-row ceiling excluded records; ceilingTruncated and hardCeiling are present only when order is "recency" and are omitted entirely under "relevance" (query mode never walks past a single bounded fetch, so no ceiling logic runs). Not the opportunity posted date or deadline.
procurement_typeNoFilter by industry. professional_services = consulting/engineering/R&D (NAICS 54xxxx). it_services = software/IT (NAICS 5415xx). construction = building (NAICS 23xxxx). manufacturing = production (NAICS 31-33xxxx).
posted_within_daysNoPreferred alias for new_within_days: only opportunities WE ADDED (ingested) in the last N days. In queryless browse mode without a single source, the recency window is sampled across sources round-robin by ingest recency so one bulk harvester cannot own the digest; each source remains newest first. In windowCoverage, sourcesSampled counts distinct sources returned by the grouped provider query before MCP quality, judge, recency-withhold, and page filters; it is absent when no grouped sample was available, including when sampling was not attempted, and 0 means the grouped query succeeded but returned no sourced rows; sourcesServed counts distinct sources delivered on this page. windowCoverage.order is "recency" for the queryless browse digest or "relevance" when a query is present. windowIncomplete/incompleteReason is separate from ceilingTruncated, which is true only when the 2,000-row ceiling excluded records; ceilingTruncated and hardCeiling are present only when order is "recency" and are omitted entirely under "relevance" (query mode never walks past a single bounded fetch, so no ceiling logic runs). Uses the same ingest freshness field as newSince/recurring checks; not the opportunity posted date or deadline. If both posted_within_days and new_within_days are supplied, posted_within_days wins.
max_response_tokensNoBatch mode only: token budget for the response (default 4000). Server auto-caps results to fit. Ignored in single-query mode.
deadline_within_daysNoOnly opportunities closing within N days

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedInput schema / properties / min_quality / description
      Previous value: -"Minimum quality threshold (default: medium)"New value: +"Minimum record-completeness tier (default: medium). any removes this quality-tier filter; relevance, access and other filters still apply."
    • changedInput schema / properties / user_context / properties / location_strict / description
      Previous value: -"When sam_filters.place_of_performance_state is also set: false (default) demotes results with no confirmed location below confirmed matches and caveats them; true excludes them instead of demoting."New value: +"With a recognized location, requests geographic filtering; nationwide or unspecified records and explicitly broader fallbacks may remain. Check geographyFilterOutcome and warnings. With sam_filters.place_of_performance_state (or pop_state in batch), true additionally excludes records without a confirmed performance location; false demotes and caveats them."
  2. Changed5 schema fields changed
    • addedInput schema / properties / sam_filters / properties / department
      Added value: +{
      +  "description": "Top-level federal department or independent agency, e.g. \"Department of Energy\", \"DOE\", \"Defense\", \"GSA\". Matched against the live SAM.gov department facet (agency name, acronym, or \"Department of X\" phrasing all resolve); an unrecognized value is applied as-is and reported in the response as departmentFilter.",
      +  "type": "string"
      +}
    • changedInput schema / properties / sam_filters / properties / place_of_performance_state / description
      Previous value: -"State code (e.g., \"CA\", \"TX\")"New value: +"State code (e.g., \"CA\", \"TX\"). Alias: pop_state (used by search_grantsplus/batch_search_procurement) is also accepted here."
    • addedInput schema / properties / sam_filters / properties / pop_state
      Added value: +{
      +  "description": "Alias for place_of_performance_state — state code (e.g., \"CA\", \"TX\"). When both are sent, place_of_performance_state wins.",
      +  "type": "string"
      +}
    • changedInput schema / properties / sam_filters / properties / psc_code / description
      Previous value: -"Product Service Code"New value: +"Product Service Code. NOT YET APPLIED to results — accepted for schema compatibility with other tools but currently reported in the response as an ignored filter; do not rely on it to narrow results."
    • addedInput schema / properties / user_context / properties / location_strict
      Added value: +{
      +  "description": "When sam_filters.place_of_performance_state is also set: false (default) demotes results with no confirmed location below confirmed matches and caveats them; true excludes them instead of demoting.",
      +  "type": "boolean"
      +}
  3. Changed2 schema fields changed
    • changedInput schema / properties / new_within_days / description
      Previous value: -"Backwards-compatible alias for posted_within_days. Only opportunities WE ADDED (ingested) in the last N days for recurring/delta checks (\"what is new since my last check\"). Additive to all other filters. In queryless browse mode without a single source, the recency window is sampled across sources round-robin by ingest recency so one bulk harvester cannot own the digest; each source remains newest first. The response includes newSince and windowCoverage: sourcesSampled counts distinct sources returned by the grouped provider query before MCP quality, judge, recency-withhold, and page filters; it is absent when no grouped sample was available, including when sampling was not attempted, and 0 means the grouped query succeeded but returned no sourced rows; sourcesServed counts distinct sources delivered on this page. windowIncomplete/incompleteReason is separate from ceilingTruncated, which is true only when the 2,000-row ceiling excluded records. Not the opportunity posted date or deadline."New value: +"Backwards-compatible alias for posted_within_days. Only opportunities WE ADDED (ingested) in the last N days for recurring/delta checks (\"what is new since my last check\"). Additive to all other filters. In queryless browse mode without a single source, the recency window is sampled across sources round-robin by ingest recency so one bulk harvester cannot own the digest; each source remains newest first. The response includes newSince and windowCoverage: sourcesSampled counts distinct sources returned by the grouped provider query before MCP quality, judge, recency-withhold, and page filters; it is absent when no grouped sample was available, including when sampling was not attempted, and 0 means the grouped query succeeded but returned no sourced rows; sourcesServed counts distinct sources delivered on this page. windowCoverage.order is \"recency\" for the queryless browse digest or \"relevance\" when a query is present. windowIncomplete/incompleteReason is separate from ceilingTruncated, which is true only when the 2,000-row ceiling excluded records; ceilingTruncated and hardCeiling are present only when order is \"recency\" and are omitted entirely under \"relevance\" (query mode never walks past a single bounded fetch, so no ceiling logic runs). Not the opportunity posted date or deadline."
    • changedInput schema / properties / posted_within_days / description
      Previous value: -"Preferred alias for new_within_days: only opportunities WE ADDED (ingested) in the last N days. In queryless browse mode without a single source, the recency window is sampled across sources round-robin by ingest recency so one bulk harvester cannot own the digest; each source remains newest first. In windowCoverage, sourcesSampled counts distinct sources returned by the grouped provider query before MCP quality, judge, recency-withhold, and page filters; it is absent when no grouped sample was available, including when sampling was not attempted, and 0 means the grouped query succeeded but returned no sourced rows; sourcesServed counts distinct sources delivered on this page. windowIncomplete/incompleteReason is separate from ceilingTruncated, which is true only when the 2,000-row ceiling excluded records. Uses the same ingest freshness field as newSince/recurring checks; not the opportunity posted date or deadline. If both posted_within_days and new_within_days are supplied, posted_within_days wins."New value: +"Preferred alias for new_within_days: only opportunities WE ADDED (ingested) in the last N days. In queryless browse mode without a single source, the recency window is sampled across sources round-robin by ingest recency so one bulk harvester cannot own the digest; each source remains newest first. In windowCoverage, sourcesSampled counts distinct sources returned by the grouped provider query before MCP quality, judge, recency-withhold, and page filters; it is absent when no grouped sample was available, including when sampling was not attempted, and 0 means the grouped query succeeded but returned no sourced rows; sourcesServed counts distinct sources delivered on this page. windowCoverage.order is \"recency\" for the queryless browse digest or \"relevance\" when a query is present. windowIncomplete/incompleteReason is separate from ceilingTruncated, which is true only when the 2,000-row ceiling excluded records; ceilingTruncated and hardCeiling are present only when order is \"recency\" and are omitted entirely under \"relevance\" (query mode never walks past a single bounded fetch, so no ceiling logic runs). Uses the same ingest freshness field as newSince/recurring checks; not the opportunity posted date or deadline. If both posted_within_days and new_within_days are supplied, posted_within_days wins."
  4. Changed2 schema fields changed
    • changedInput schema / properties / new_within_days / description
      Previous value: -"Backwards-compatible alias for posted_within_days. Only opportunities WE ADDED (ingested) in the last N days — for recurring/delta checks (\"what is new since my last check\"). Additive to all other filters. Sorts newest-ingested-first; response includes newSince.newCount and the newest/oldest ingest timestamp in the window. Not the opportunity posted date or deadline."New value: +"Backwards-compatible alias for posted_within_days. Only opportunities WE ADDED (ingested) in the last N days for recurring/delta checks (\"what is new since my last check\"). Additive to all other filters. In queryless browse mode without a single source, the recency window is sampled across sources round-robin by ingest recency so one bulk harvester cannot own the digest; each source remains newest first. The response includes newSince and windowCoverage: sourcesSampled counts distinct sources returned by the grouped provider query before MCP quality, judge, recency-withhold, and page filters; it is absent when no grouped sample was available, including when sampling was not attempted, and 0 means the grouped query succeeded but returned no sourced rows; sourcesServed counts distinct sources delivered on this page. windowIncomplete/incompleteReason is separate from ceilingTruncated, which is true only when the 2,000-row ceiling excluded records. Not the opportunity posted date or deadline."
    • changedInput schema / properties / posted_within_days / description
      Previous value: -"Preferred alias for new_within_days: only opportunities WE ADDED (ingested) in the last N days. Uses the same ingest freshness field as newSince/recurring checks; not the opportunity posted date or deadline. If both posted_within_days and new_within_days are supplied, posted_within_days wins."New value: +"Preferred alias for new_within_days: only opportunities WE ADDED (ingested) in the last N days. In queryless browse mode without a single source, the recency window is sampled across sources round-robin by ingest recency so one bulk harvester cannot own the digest; each source remains newest first. In windowCoverage, sourcesSampled counts distinct sources returned by the grouped provider query before MCP quality, judge, recency-withhold, and page filters; it is absent when no grouped sample was available, including when sampling was not attempted, and 0 means the grouped query succeeded but returned no sourced rows; sourcesServed counts distinct sources delivered on this page. windowIncomplete/incompleteReason is separate from ceilingTruncated, which is true only when the 2,000-row ceiling excluded records. Uses the same ingest freshness field as newSince/recurring checks; not the opportunity posted date or deadline. If both posted_within_days and new_within_days are supplied, posted_within_days wins."
  5. Changed1 schema field changed
    • changedInput schema / anyOf
      Previous value: -[
      -  {
      -    "required": [
      -      "query"
      -    ]
      -  },
      -  {
      -    "required": [
      -      "queries"
      -    ]
      -  }
      -]New value: +[
      +  {
      +    "required": [
      +      "query"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "queries"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "source"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "organization"
      +    ]
      +  }
      +]
  6. Changed8 schema fields changed
    • addedInput schema / anyOf
      Added value: +[
      +  {
      +    "required": [
      +      "query"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "queries"
      +    ]
      +  }
      +]
    • addedInput schema / properties / detail_level
      Added value: +{
      +  "description": "Batch mode only: controls response verbosity (minimal/compact [default]/full). Ignored in single-query mode.",
      +  "enum": [
      +    "minimal",
      +    "compact",
      +    "full"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / max_response_tokens
      Added value: +{
      +  "description": "Batch mode only: token budget for the response (default 4000). Server auto-caps results to fit. Ignored in single-query mode.",
      +  "minimum": 500,
      +  "type": "number"
      +}
    • addedInput schema / properties / max_results
      Added value: +{
      +  "description": "Batch mode only: maximum merged results to return (default 10). Ignored in single-query mode (use limit).",
      +  "minimum": 1,
      +  "type": "number"
      +}
    • addedInput schema / properties / offset
      Added value: +{
      +  "description": "Batch mode only: number of merged results to skip for pagination (default 0). Ignored in single-query mode.",
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / queries
      Added value: +{
      +  "description": "BATCH MODE (paid, replaces batch_search_procurement): array of 2-5 search queries to run in parallel, dedupe, and merge. Example for IT services: [\"IT services contract\", \"software development federal\", \"technology consulting government\", \"computer services procurement\"]. When set, query is ignored and the batch response params (detail_level, max_results, offset, max_response_tokens) apply.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "maxItems": 5,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • changedInput schema / properties / query / description
      Previous value: -"Natural language search query"New value: +"Natural language search query. Provide either query (single search) or queries (batch mode) — exactly one."
    • removedInput schema / required
      Removed value: -[
      -  "query"
      -]
  7. Changed1 schema field changed
    • addedInput schema / properties / source
      Added value: +{
      +  "description": "Filter to a specific source/domain, e.g. \"sam.gov\" or an agency source domain.",
      +  "type": "string"
      +}
  8. Changed3 schema fields changed
    • changedInput schema / properties / new_within_days / description
      Previous value: -"Only opportunities WE ADDED (ingested) in the last N days — for recurring/delta checks (\"what is new since my last check\"). Additive to all other filters. Sorts newest-ingested-first; response includes newSince.newCount and the newest/oldest ingest timestamp in the window. Not the opportunity posted date or deadline."New value: +"Backwards-compatible alias for posted_within_days. Only opportunities WE ADDED (ingested) in the last N days — for recurring/delta checks (\"what is new since my last check\"). Additive to all other filters. Sorts newest-ingested-first; response includes newSince.newCount and the newest/oldest ingest timestamp in the window. Not the opportunity posted date or deadline."
    • addedInput schema / properties / posted_within_days
      Added value: +{
      +  "description": "Preferred alias for new_within_days: only opportunities WE ADDED (ingested) in the last N days. Uses the same ingest freshness field as newSince/recurring checks; not the opportunity posted date or deadline. If both posted_within_days and new_within_days are supplied, posted_within_days wins.",
      +  "type": "number"
      +}
    • changedInput schema / properties / since / description
      Previous value: -"Stateless alternative to new_within_days: ISO 8601 instant. Only opportunities ingested at/after this instant. Store the previous response newSince.newest and pass it here to manage your own watermark."New value: +"Stateless alternative to posted_within_days/new_within_days: ISO 8601 instant. Only opportunities ingested at/after this instant. Store the previous response newSince.newest and pass it here to manage your own watermark."
  9. Changed2 schema fields changed
    • addedInput schema / properties / new_within_days
      Added value: +{
      +  "description": "Only opportunities WE ADDED (ingested) in the last N days — for recurring/delta checks (\"what is new since my last check\"). Additive to all other filters. Sorts newest-ingested-first; response includes newSince.newCount and the newest/oldest ingest timestamp in the window. Not the opportunity posted date or deadline.",
      +  "type": "number"
      +}
    • addedInput schema / properties / since
      Added value: +{
      +  "description": "Stateless alternative to new_within_days: ISO 8601 instant. Only opportunities ingested at/after this instant. Store the previous response newSince.newest and pass it here to manage your own watermark.",
      +  "type": "string"
      +}
  10. Changed2 schema fields changed
    • changedInput schema / properties / sam_filters / properties / set_aside / description
      Previous value: -"Set-aside type: 8A, HUBZone, WOSB, SDVOSB, etc."New value: +"Set-aside type. Supported: SDVOSB, VOSB, WOSB, EDWOSB, 8a/8(a), HUBZone, SBA/\"Small Business\" (each expands to all matching SAM codes and CSV labels). Actually filters results."
    • addedInput schema / properties / user_context / properties / organization_type / description
      Added value: +"Common natural-language phrasing (e.g. \"501(c)(3) nonprofit\") is also parsed; unparseable values are ignored with an explicit note in the response."
  11. First observed

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already cover safety (readOnly, idempotent, non-destructive), but the description adds substantial behavioral context beyond them: batch mode is a paid feature that counts as one monthly search call, free-plan listings lag paid plans by 10 days, and the exact response semantics of place_of_performance_state (matched/unknownServed/otherStateExcluded) including how location_strict changes demotion to exclusion.

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-loads purpose, triggers, and examples before the dense operational detail, and every sentence carries information. The place-of-performance clause is a single sprawling parenthetical with an embedded tangent about unparseable geography, which hurts readability but not density.

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 20-parameter, nested-object tool with no output schema, the description covers cost/rate-limit behavior, batch-mode substitution, alias precedence, and the shape of the geography response fields. What is missing is any statement of return-value structure for the ordinary (non-geo) case, which the absent output schema leaves undocumented.

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

Parameters4/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 20 params and the baseline is 3. The description goes further by explaining cross-parameter interactions the schema only hints at: alias precedence (place_of_performance_state vs pop_state, posted_within_days vs new_within_days), that batch mode ignores query and swaps in the batch params, and what the placeOfPerformance response fields mean.

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 government contracts, RFPs, RFIs, BAAs, and solicitations from SAM.gov') and explicitly positions itself against both a data source (searching SAM.gov directly) and a sibling ('this replaces the former batch_search_procurement tool'). An agent can identify the tool without opening the schema.

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

Usage Guidelines4/5

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

Gives explicit trigger phrases ('Use when user wants: contracts, RFPs, procurement, bids, government work') plus concrete query examples, and explains when to switch to batch mode (queries[] with 2-5 variations). It does not, however, state when to prefer the close sibling search_grants_and_procurement or search_grantsplus over this tool.

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.

Resources