GAO Bid Protests

Bid protest decisions, and how agencies actually get challenged.

Compliance · all 19 sources

Endpoint

Point a client at this source alone when you know the dataset you need. A shorter tool list selects more reliably and costs less context than the aggregate endpoint, and both share the same key and quota.

https://port.harborgovcon.com/servers/gao-bid-protests/mcp

Or take the whole gateway in one connection: https://port.harborgovcon.com/mcp.

Tools

8 tools on this server. Every tool is namespaced gao_bid_protests_<tool> on the aggregate endpoint and keeps its bare name here.

protest_decision_pdf_urlprotest_velocity_by_agencyprotests_by_protesterprotests_for_agencyprotests_for_solicitationrecent_sustained_protestssearch_protestssupplements_for

A first call

MCP is session based. Initialize once, keep the session id, then ask this server what it carries. tools/list takes no arguments, so it is the call that works before you know anything about the schema.

# 1. Initialize and keep the session id from the response header.
SID=$(curl -sD - -o /dev/null https://port.harborgovcon.com/servers/gao-bid-protests/mcp \
  -H "Authorization: Bearer $HARBOR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}' \
  | tr -d '\r' | awk -F': ' 'tolower($1)=="mcp-session-id"{print $2}')

# 2. Complete the handshake.
curl -s https://port.harborgovcon.com/servers/gao-bid-protests/mcp \
  -H "Authorization: Bearer $HARBOR_KEY" \
  -H "Mcp-Session-Id: $SID" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

# 3. Ask this server what it carries.
curl -s https://port.harborgovcon.com/servers/gao-bid-protests/mcp \
  -H "Authorization: Bearer $HARBOR_KEY" \
  -H "Mcp-Session-Id: $SID" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

Every tool's arguments are in its own schema, which the tools/list response carries. A refusal names what was wrong rather than returning an empty result, so a failed call is safe to read literally: see Errors.