wsdot-mcp-server
WA highway conditions, ferry schedules, vessel locations, toll rates, and border waits via MCP.
我该使用它吗
质量与安全性
基于对工具定义和协议合规性的自动分析。
上下文开销
这是每次将服务器的工具加载到模型上下文窗口时所消耗的大致 token 数。数值越高,可用于其他任务的注意力就越少。
安装
一键安装
将以下内容添加到你的 `claude_desktop_config.json` 文件中:
{
"mcpServers": {
"wsdot-mcp-server": {
"command": "node",
"args": [
"@cyanheads/wsdot-mcp-server"
]
}
}
}可运行的软件包
0.4.0streamable-http远程端点
https://wsdot.caseyjhand.com/mcpstreamable-http它能做什么
工具清单
工具(12)
🟢wsdot_get_mountain_passes
Returns current road conditions for all Washington State mountain passes: status, weather, road condition, traction laws, temperature, and elevation. Includes all 16 passes (Snoqualmie, Stevens, White, Blewett, Cayuse, etc.). Use for "is the pass open?", traction law status, or winter driving planning.
输入模式
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"passes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"mountainPassId": {
"description": "Numeric identifier for the pass. Absent when upstream omits it.",
"type": "number"
},
"mountainPassName": {
"description": "Human-readable pass name (e.g. \"Snoqualmie Pass\"). Absent when upstream omits it.",
"type": "string"
},
"elevation": {
"description": "Pass summit elevation in feet.",
"type": "number"
},
"temperatureInFahrenheit": {
"description": "Current temperature at the pass in Fahrenheit.",
"type": "number"
},
"weatherCondition": {
"description": "Current weather description (e.g. \"Snowing\", \"Cloudy\").",
"type": "string"
},
"roadCondition": {
"description": "Road surface condition (e.g. \"Wet\", \"Snow and Ice Covered\").",
"type": "string"
},
"travelAdvisoryActive": {
"description": "True when a travel advisory is in effect.",
"type": "boolean"
},
"restrictionOne": {
"description": "Primary travel/traction restriction (typically one direction of travel).",
"type": "object",
"properties": {
"text": {
"description": "Restriction / traction-law text (e.g. \"Traction Tires Required, Chains Required (Except All Wheel Drive)\"). Reads \"No current information available\" or \"No restrictions\" when nothing is in effect.",
"type": "string"
},
"travelDirection": {
"description": "Direction this restriction applies to (e.g. \"Northbound\", \"Eastbound\", \"Both directions\").",
"type": "string"
}
},
"additionalProperties": false
},
"restrictionTwo": {
"description": "Secondary travel/traction restriction (typically the opposite direction).",
"type": "object",
"properties": {
"text": {
"description": "Restriction / traction-law text for the second direction.",
"type": "string"
},
"travelDirection": {
"description": "Direction this restriction applies to (e.g. \"Southbound\", \"Westbound\").",
"type": "string"
}
},
"additionalProperties": false
},
"dateUpdated": {
"description": "Timestamp of the last condition update (ISO 8601).",
"type": "string"
},
"latitude": {
"description": "Pass latitude.",
"type": "number"
},
"longitude": {
"description": "Pass longitude.",
"type": "number"
}
},
"additionalProperties": false,
"description": "Conditions for one mountain pass."
},
"description": "All WA mountain pass conditions."
},
"totalCount": {
"type": "number",
"description": "Total number of passes returned."
},
"notice": {
"description": "Optional notice when no pass data is available — e.g. API temporarily unavailable. Absent on normal results.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSDOT Traffic API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSDOT rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"passes",
"totalCount"
]
},
{
"required": [
"error"
]
}
]
}🟢wsdot_search_alerts(stateRoute, region, startMilepost, endMilepost, offset, ...)
Returns active WA highway alerts: incidents, construction, closures, and restrictions. Filter by state route ("I-90", "90", "SR 520", or "520" all work), WSDOT region (Northwest, Olympic, Southwest, South Central, North Central, Eastern), or milepost range, matched against the alert's full extent. Omit all filters to return all current statewide alerts. Results are ordered by alertId and paged — pass offset/limit to page through the full set. A page ends at limit or at a 24,000-byte response budget, whichever comes first; the notice reports the next offset.
输入模式
{
"type": "object",
"properties": {
"stateRoute": {
"description": "State route to filter by. Accepts natural forms — \"I-90\", \"90\", \"090\", \"SR 520\", \"520\" — matched case- and space-insensitively to the route number. A route-type prefix is compared only when both sides carry one, so \"SR 26\" never matches US 26 while a bare \"26\" matches either. Omit to include all routes.",
"type": "string",
"maxLength": 200
},
"region": {
"description": "WSDOT region name as it appears in alert data: \"Northwest\", \"Olympic\", \"Southwest\", \"South Central\", \"North Central\", or \"Eastern\". Matching is case-insensitive; any other value is rejected. These are names, not the two-letter codes wsdot_search_cameras takes.",
"type": "string",
"maxLength": 200
},
"startMilepost": {
"description": "Start of the milepost range. An alert matches when its extent overlaps the range, so a closure running from MP 10 to MP 30 is returned for a range starting at MP 20. Either bound may be given alone; when both are given, startMilepost must not exceed endMilepost. Alerts reporting no milepost are always included.",
"type": "number"
},
"endMilepost": {
"description": "End of the milepost range. Matched by extent overlap like startMilepost, so an alert beginning inside the range and continuing past it is returned.",
"type": "number"
},
"offset": {
"description": "Zero-based index of the first alert to return, for paging. Defaults to 0.",
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"limit": {
"description": "Maximum alerts to return in this page (1–500). Defaults to 20. A page of long alerts can end sooner, at the 24,000-byte response budget.",
"type": "integer",
"minimum": 1,
"maximum": 500
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"alerts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"alertId": {
"description": "Unique alert identifier.",
"type": "number"
},
"headlineDescription": {
"description": "Short summary of the alert, as plain text. Upstream authors these in a rich-text editor, so any markup is normalized away and a link is rendered inline as \"link text (url)\".",
"type": "string"
},
"extendedDescription": {
"description": "Full description of the alert, normalized to plain text on the same terms as headlineDescription. Often absent — most alerts carry only a headline.",
"type": "string"
},
"eventCategory": {
"description": "Category (e.g. \"Incident\", \"Construction\", \"Closure\").",
"type": "string"
},
"eventStatus": {
"description": "Current status of the event.",
"type": "string"
},
"priority": {
"description": "Priority level.",
"type": "string"
},
"region": {
"description": "WSDOT region where the alert is located.",
"type": "string"
},
"county": {
"description": "County where the alert is located.",
"type": "string"
},
"startRoadwayLocation": {
"description": "Start location of the alert.",
"type": "object",
"properties": {
"roadName": {
"description": "Road name.",
"type": "string"
},
"direction": {
"description": "Travel direction code: N/S/E/W, B (both directions), A (alternating); may appear as NB/SB/EB/WB.",
"type": "string"
},
"milePost": {
"description": "Starting milepost.",
"type": "number"
},
"latitude": {
"description": "Latitude.",
"type": "number"
},
"longitude": {
"description": "Longitude.",
"type": "number"
}
},
"additionalProperties": false
},
"endRoadwayLocation": {
"description": "End location of the alert, if the event spans a range.",
"type": "object",
"properties": {
"roadName": {
"description": "Road name.",
"type": "string"
},
"direction": {
"description": "Travel direction code: N/S/E/W, B (both directions), A (alternating); may appear as NB/SB/EB/WB.",
"type": "string"
},
"milePost": {
"description": "Ending milepost.",
"type": "number"
},
"latitude": {
"description": "Latitude.",
"type": "number"
},
"longitude": {
"description": "Longitude.",
"type": "number"
}
},
"additionalProperties": false
},
"startTime": {
"description": "When the event started or is scheduled to start (ISO 8601).",
"type": "string"
},
"endTime": {
"description": "When the event is expected to end (ISO 8601).",
"type": "string"
},
"lastUpdatedTime": {
"description": "When this alert was last updated (ISO 8601).",
"type": "string"
}
},
"additionalProperties": false,
"description": "A highway alert or incident."
},
"description": "Matching highway alerts."
},
"totalCount": {
"type": "number",
"description": "Total alerts matching the filters across all pages (not just this page)."
},
"nextOffset": {
"description": "Offset to pass to retrieve the next page, or null when this is the last page.",
"type": [
"number",
"null"
]
},
"hasMore": {
"type": "boolean",
"description": "True when more alerts remain beyond the current page."
},
"appliedFilters": {
"type": "object",
"properties": {
"stateRoute": {
"description": "State route filter applied.",
"type": "string"
},
"region": {
"description": "Region filter applied.",
"type": "string"
},
"startMilepost": {
"description": "Start milepost filter applied.",
"type": "number"
},
"endMilepost": {
"description": "End milepost filter applied.",
"type": "number"
}
},
"additionalProperties": false,
"description": "Active filters applied to the alert search."
},
"notice": {
"description": "Informational note about the page window, or guidance when no alerts matched the filters or the offset ran past the end.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSDOT Traffic API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSDOT rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. `invalid_region`: The region is not one of the WSDOT region names the alerts feed carries. `invalid_milepost_range`: startMilepost is greater than endMilepost. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code",
"invalid_region",
"invalid_milepost_range"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"alerts",
"totalCount",
"nextOffset",
"hasMore",
"appliedFilters"
]
},
{
"required": [
"error"
]
}
]
}🟢wsdot_get_travel_times(route, offset, limit)
Returns current vs. average travel times for named WA highway corridors (I-5, I-90, SR 520, SR 99, I-405, SR 167, etc.). Use for "how congested is I-5?" or commute time estimates. The route filter matches two ways: a route designation ("I-5", "5", "SR 520") returns every corridor measured on that route, and any text also matches corridor names ("Everett"). When current time exceeds average, the corridor is congested. Results are paged — pass offset/limit to page through the full set. A page ends at limit or at a 24,000-byte response budget, whichever comes first; the notice reports the next offset.
输入模式
{
"type": "object",
"properties": {
"route": {
"description": "Optional filter. A route designation — \"I-5\", \"5\", \"005\", \"SR 520\", \"520\" — matches every corridor whose start or end point is on that route, whichever form the feed reports. Any text also matches the corridor name as a case-insensitive substring, so \"Everett\" finds the Seattle-Everett corridors. Omit to return all corridors.",
"type": "string",
"maxLength": 200
},
"offset": {
"description": "Zero-based index of the first corridor to return, for paging. Defaults to 0.",
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"limit": {
"description": "Maximum corridors to return in this page (1–500). Defaults to 50. A large page ends sooner, at the 24,000-byte response budget.",
"type": "integer",
"minimum": 1,
"maximum": 500
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"corridors": {
"type": "array",
"items": {
"type": "object",
"properties": {
"travelTimeId": {
"description": "Unique corridor identifier.",
"type": "number"
},
"name": {
"description": "Corridor name (e.g. \"I-5: Northgate to Downtown\").",
"type": "string"
},
"description": {
"description": "Additional corridor description.",
"type": "string"
},
"currentTimeInMinutes": {
"description": "Current travel time in minutes. Absent when WSDOT reports no measurement for the corridor — a reversible express lane closed in this direction reports none.",
"type": "number"
},
"averageTimeInMinutes": {
"description": "Historical average travel time in minutes. Absent when WSDOT reports no measurement for the corridor.",
"type": "number"
},
"delayInMinutes": {
"description": "Delay above average in minutes. Positive means congestion. Absent when either travel time is unavailable.",
"type": "number"
},
"timeUpdated": {
"description": "When the travel time data was last updated (ISO 8601).",
"type": "string"
},
"distanceInMiles": {
"description": "Corridor distance in miles.",
"type": "number"
},
"startPoint": {
"description": "Start of the measured corridor.",
"type": "object",
"properties": {
"roadName": {
"description": "Road name at the start.",
"type": "string"
},
"direction": {
"description": "Travel direction code: N (north), S (south), E (east), W (west).",
"type": "string"
},
"milePost": {
"description": "Starting milepost.",
"type": "number"
}
},
"additionalProperties": false
},
"endPoint": {
"description": "End of the measured corridor.",
"type": "object",
"properties": {
"roadName": {
"description": "Road name at the end.",
"type": "string"
},
"direction": {
"description": "Travel direction code: N (north), S (south), E (east), W (west).",
"type": "string"
},
"milePost": {
"description": "Ending milepost.",
"type": "number"
}
},
"additionalProperties": false
}
},
"additionalProperties": false,
"description": "Travel time data for one highway corridor."
},
"description": "Travel time corridors matching the filter."
},
"totalCount": {
"type": "number",
"description": "Total corridors matching the filter across all pages (not just this page)."
},
"nextOffset": {
"description": "Offset to pass to retrieve the next page, or null when this is the last page.",
"type": [
"number",
"null"
]
},
"hasMore": {
"type": "boolean",
"description": "True when more corridors remain beyond the current page."
},
"routeFilter": {
"description": "The route name filter applied (lowercased), or absent if no filter was used.",
"type": "string"
},
"notice": {
"description": "Informational note about the page window, or guidance when no corridors matched the route filter or the offset ran past the end.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSDOT Traffic API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSDOT rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"corridors",
"totalCount",
"nextOffset",
"hasMore"
]
},
{
"required": [
"error"
]
}
]
}🟢wsdot_get_toll_rates(stateRoute, offset, limit)
Returns current dynamic toll rates for WA express lanes and tolled facilities: SR 99 (WSDOT Tunnel), SR 167 HOT Lanes, I-405 Express Lanes, SR 509 tolled segment, and the SR 520 Bridge. Rates are time-banded and change dynamically based on traffic conditions. Filter to one facility with stateRoute ("SR 520", "520", "I-405", or "405" all work). Each row reports stateRoute as the bare, zero-padded number the feed carries ("099", "405") — the posted designation is in the rendered text. Results are paged — pass offset/limit to page through the matching set. A page ends at limit or at a 24,000-byte response budget, whichever comes first; the notice reports the next offset.
输入模式
{
"type": "object",
"properties": {
"stateRoute": {
"description": "Tolled route to filter by. Accepts natural forms — \"SR 520\", \"520\", \"0520\", \"I-405\", \"405\" — matched case- and space-insensitively against each row's posted designation, so a route-type prefix must agree: \"SR 405\" matches nothing because the I-405 Express Lanes are an Interstate. A route with no tolled facility returns an empty page whose notice names the tolled routes. Omit to include every facility.",
"type": "string",
"maxLength": 200
},
"offset": {
"description": "Zero-based index of the first toll rate to return, for paging. Defaults to 0.",
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"limit": {
"description": "Maximum toll rates to return in this page (1–500). Defaults to 50. A large page ends sooner, at the 24,000-byte response budget.",
"type": "integer",
"minimum": 1,
"maximum": 500
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"rates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"tripName": {
"description": "Name of the tolled trip or lane segment.",
"type": "string"
},
"stateRoute": {
"description": "Route number as the feed reports it: bare and zero-padded, with no route type (\"099\", \"405\"). The rendered text shows the posted designation (SR 99, I-405).",
"type": "string"
},
"travelDirection": {
"description": "Direction code the feed assigns the toll trip: N, S, E, or W. On SR 99, SR 509, and SR 520 it is one fixed code per facility (S, S, and E) although trips run both ways, so read the direction of travel from the segment ends — startLocationName/endLocationName and startMilepost → endMilepost — not from this code.",
"type": "string"
},
"startMilepost": {
"description": "Starting milepost of the toll segment.",
"type": "number"
},
"endMilepost": {
"description": "Ending milepost of the toll segment.",
"type": "number"
},
"tollRateInDollars": {
"description": "Current toll rate in US dollars.",
"type": "number"
},
"message": {
"description": "Dynamic message associated with this toll.",
"type": "string"
},
"startLocationName": {
"description": "Human-readable start location name.",
"type": "string"
},
"endLocationName": {
"description": "Human-readable end location name.",
"type": "string"
},
"startLatitude": {
"description": "Latitude of the segment start point.",
"type": "number"
},
"startLongitude": {
"description": "Longitude of the segment start point.",
"type": "number"
},
"endLatitude": {
"description": "Latitude of the segment end point.",
"type": "number"
},
"endLongitude": {
"description": "Longitude of the segment end point.",
"type": "number"
},
"timeUpdated": {
"description": "When this toll rate was last updated (ISO 8601).",
"type": "string"
}
},
"additionalProperties": false,
"description": "Current toll rate for one segment or trip."
},
"description": "Current toll rates for the matching tolled facilities."
},
"totalCount": {
"type": "number",
"description": "Total toll rate entries matching the filter across all pages (not just this page)."
},
"nextOffset": {
"description": "Offset to pass to retrieve the next page, or null when this is the last page.",
"type": [
"number",
"null"
]
},
"hasMore": {
"type": "boolean",
"description": "True when more toll rates remain beyond the current page."
},
"appliedFilters": {
"description": "Active filters applied to the toll rates. Absent when no filter was applied.",
"type": "object",
"properties": {
"stateRoute": {
"description": "State route filter applied.",
"type": "string"
}
},
"additionalProperties": false
},
"notice": {
"description": "Informational note about the page window, or guidance when no toll rate data is available, the route has no tolled facility, or the offset ran past the end.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSDOT Traffic API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSDOT rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"rates",
"totalCount",
"nextOffset",
"hasMore"
]
},
{
"required": [
"error"
]
}
]
}🟢wsdot_get_border_waits
Returns current vehicle wait times at WA→Canada land border crossings: I-5 (Peace Arch, Blaine), SR 543 (Pacific Highway, Blaine), SR 539 (Lynden), and SR 9 (Sumas). Each crossing reports a general-purpose lane and a Nexus lane; SR 539 adds a truck lane and SR 543 adds truck and FAST truck lanes — eleven entries in crossings[], one per lane. crossingName is a route code (e.g. "I5", "I5Nexus", "SR543Trucks"); the readable name is in location.description. Wait times are in minutes. A crossing reporting no current data is still returned — only waitTimeInMinutes is omitted. Use for "how long is the border wait?" questions.
输入模式
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"crossings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"crossingName": {
"description": "Route-code crossing identifier (e.g. \"I5\", \"I5Nexus\", \"SR539\", \"SR9\"). See location.description for the readable name.",
"type": "string"
},
"waitTimeInMinutes": {
"description": "Current vehicle wait time in minutes. Omitted when the crossing reports no data (WSDOT emits a -1 sentinel for closed/unmonitored crossings).",
"type": "number"
},
"updateTime": {
"description": "When this wait time was last updated (ISO 8601).",
"type": "string"
},
"location": {
"description": "Geographic location and readable name of the crossing.",
"type": "object",
"properties": {
"description": {
"description": "Readable crossing/lane name (e.g. \"I-5 General Purpose\", \"I-5 Nexus Lane\").",
"type": "string"
},
"roadName": {
"description": "Road serving the crossing.",
"type": "string"
},
"direction": {
"description": "Travel direction code (N/S/E/W/B); frequently null for border crossings.",
"type": "string"
},
"milePost": {
"description": "Milepost of the crossing.",
"type": "number"
},
"latitude": {
"description": "Latitude of the crossing.",
"type": "number"
},
"longitude": {
"description": "Longitude of the crossing.",
"type": "number"
}
},
"additionalProperties": false
}
},
"additionalProperties": false,
"description": "Wait time data for one border crossing."
},
"description": "All WA/Canada border crossing wait times."
},
"totalCount": {
"type": "number",
"description": "Total number of crossings returned."
},
"notice": {
"description": "Optional notice when no crossing data is available. Absent on normal results.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSDOT Traffic API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSDOT rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"crossings",
"totalCount"
]
},
{
"required": [
"error"
]
}
]
}🟢wsdot_search_cameras(stateRoute, region, startMilepost, endMilepost, titleContains, ...)
Returns WSDOT highway camera locations, descriptions, and image URLs. Camera images are copyright WSDOT — only metadata and image URLs are returned, not image bytes. Filter by state route ("I-90", "90", "SR 520", or "520" all work), WSDOT region, milepost range, or words in the camera title ("Snoqualmie"). Results are ordered by cameraId and paged — pass offset/limit to page through the full set. A page ends at limit or at a 24,000-byte response budget, whichever comes first; the notice reports the next offset.
输入模式
{
"type": "object",
"properties": {
"stateRoute": {
"description": "State route to filter by. Accepts natural forms — \"I-90\", \"90\", \"090\", \"SR 520\", \"520\" — matched case- and space-insensitively to the route number. Camera road names carry a route-type prefix, which is compared when the filter carries one too: \"SR 26\" excludes US 26, while a bare \"26\" returns both. A lettered suffix is part of the route, so \"US 97\" excludes US 97A. Omit to include all routes.",
"type": "string",
"maxLength": 200
},
"region": {
"description": "WSDOT region code: NW (Northwest), SW (Southwest), OL (Olympic), ER (Eastern), SC (South Central), NC (North Central), OS (Oregon — the TripCheck cameras around Portland), or WA (airport cameras plus a few ferry-terminal cameras — most ferry-terminal cameras sit in NW and OL). Matching is case-insensitive; any other value is rejected. These are codes, not the region names wsdot_search_alerts takes.",
"type": "string",
"maxLength": 200
},
"startMilepost": {
"description": "Start of the milepost range to filter cameras. Either bound may be given alone; when both are given, startMilepost must not exceed endMilepost. Cameras reporting no milepost are always included.",
"type": "number"
},
"endMilepost": {
"description": "End of the milepost range to filter cameras.",
"type": "number"
},
"titleContains": {
"description": "Words to find in the camera title, as WSDOT wrote it. Case-insensitive; every whitespace-separated word must appear, in any order — \"Snoqualmie\" returns \"Snoqualmie Summit\" and \"East Snoqualmie Summit\" but not a nearby camera titled \"Hyak\". Most titles lead with route and milepost (\"I-90 at MP 52: …\"), so filter a route with stateRoute rather than here. Combines with the other filters. Omit to include every title.",
"type": "string",
"maxLength": 200
},
"offset": {
"description": "Zero-based index of the first camera to return, for paging. Defaults to 0.",
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"limit": {
"description": "Maximum cameras to return in this page (1–500). Defaults to 50. A large page ends sooner, at the 24,000-byte response budget.",
"type": "integer",
"minimum": 1,
"maximum": 500
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"cameras": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cameraId": {
"description": "Unique camera identifier.",
"type": "number"
},
"title": {
"description": "Camera title or location description.",
"type": "string"
},
"description": {
"description": "Additional description.",
"type": "string"
},
"imageUrl": {
"description": "URL of the WSDOT-hosted camera image (JPEG). WSDOT copyright applies.",
"type": "string"
},
"imageWidth": {
"description": "Image width in pixels.",
"type": "number"
},
"imageHeight": {
"description": "Image height in pixels.",
"type": "number"
},
"roadName": {
"description": "Road the camera monitors.",
"type": "string"
},
"direction": {
"description": "Traffic-direction code monitored: N/S/E/W, B (both), NB/SB/EB/WB. Some sites use other location-specific markers.",
"type": "string"
},
"milePost": {
"description": "Milepost location of the camera.",
"type": "number"
},
"region": {
"description": "WSDOT region.",
"type": "string"
},
"latitude": {
"description": "Camera latitude.",
"type": "number"
},
"longitude": {
"description": "Camera longitude.",
"type": "number"
}
},
"additionalProperties": false,
"description": "Camera metadata and image URL for one WSDOT highway camera."
},
"description": "Camera metadata and image URLs. Images are copyright WSDOT."
},
"totalCount": {
"type": "number",
"description": "Total cameras matching the filters across all pages (not just this page)."
},
"nextOffset": {
"description": "Offset to pass to retrieve the next page, or null when this is the last page.",
"type": [
"number",
"null"
]
},
"hasMore": {
"type": "boolean",
"description": "True when more cameras remain beyond the current page."
},
"appliedFilters": {
"type": "object",
"properties": {
"stateRoute": {
"description": "State route filter applied.",
"type": "string"
},
"region": {
"description": "Region filter applied.",
"type": "string"
},
"startMilepost": {
"description": "Start milepost filter applied.",
"type": "number"
},
"endMilepost": {
"description": "End milepost filter applied.",
"type": "number"
},
"titleContains": {
"description": "Title words filter applied.",
"type": "string"
}
},
"additionalProperties": false,
"description": "Active filters applied to the camera search."
},
"notice": {
"description": "Informational note about the page window, copyright, or empty results. Absent when not applicable.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSDOT Traffic API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSDOT rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. `invalid_region`: The region is not one of the region codes the camera feed carries. `invalid_milepost_range`: startMilepost is greater than endMilepost. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code",
"invalid_region",
"invalid_milepost_range"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"cameras",
"totalCount",
"nextOffset",
"hasMore",
"appliedFilters"
]
},
{
"required": [
"error"
]
}
]
}🟢wsdot_get_ferry_terminals
Returns all WSF ferry terminals with their numeric IDs, names, abbreviations, and coordinates. Call this first to resolve human-readable terminal names (e.g. "Bainbridge Island", "Seattle", "Kingston") to the numeric terminal IDs required by the schedule and space tools. The terminal list is small (20 terminals) and rarely changes.
输入模式
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"terminals": {
"type": "array",
"items": {
"type": "object",
"properties": {
"terminalId": {
"description": "Numeric terminal ID used in schedule and space API calls. Absent when upstream omits it.",
"type": "number"
},
"terminalName": {
"description": "Full terminal name (e.g. \"Bainbridge Island\"). Absent when upstream omits it.",
"type": "string"
},
"terminalAbbrev": {
"description": "Short abbreviation (e.g. \"BI\").",
"type": "string"
},
"latitude": {
"description": "Terminal latitude.",
"type": "number"
},
"longitude": {
"description": "Terminal longitude.",
"type": "number"
}
},
"additionalProperties": false,
"description": "A WSF ferry terminal with its ID and location."
},
"description": "All WSF ferry terminals."
},
"totalCount": {
"type": "number",
"description": "Total number of terminals returned."
},
"notice": {
"description": "Optional notice when no terminal data is available. Absent on normal results.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSF Ferry API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSF rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"terminals",
"totalCount"
]
},
{
"required": [
"error"
]
}
]
}🟢wsdot_get_ferry_routes(tripDate)
Returns the main WSF ferry routes operating on a given date, each with the directed terminal pairs it serves that day (terminalPairs) — departing and arriving terminal IDs and names, which are exactly the pairs wsdot_get_ferry_schedule accepts for that date. Route IDs correspond to impactedRouteIds in ferry alerts from wsdot_get_ferry_alerts, though some alert route IDs (seasonal, San Juan interisland, or Sidney B.C.) may not appear in this list. For the full terminal list with coordinates, use wsdot_get_ferry_terminals.
输入模式
{
"type": "object",
"properties": {
"tripDate": {
"description": "Date for which to list routes, in ISO 8601 format (YYYY-MM-DD). Defaults to today if omitted.",
"type": "string"
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"routes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"routeId": {
"description": "Numeric route identifier. Corresponds to impactedRouteIds in ferry alerts.",
"type": "number"
},
"routeAbbrev": {
"description": "Short route abbreviation (e.g. \"SEA-BBI\").",
"type": "string"
},
"description": {
"description": "Full route description (e.g. \"Seattle/Bainbridge Island\").",
"type": "string"
},
"terminalPairs": {
"description": "Directed terminal pairs this route serves on the requested date; empty when it serves none. Absent only when upstream omits the route ID the lookup needs.",
"type": "array",
"items": {
"type": "object",
"properties": {
"departingTerminalId": {
"type": "number",
"description": "Departing terminal ID — the departingTerminalId to pass to wsdot_get_ferry_schedule."
},
"departingTerminalName": {
"description": "Departing terminal name. Absent when upstream omits it.",
"type": "string"
},
"arrivingTerminalId": {
"type": "number",
"description": "Arriving terminal ID — the arrivingTerminalId to pass to wsdot_get_ferry_schedule."
},
"arrivingTerminalName": {
"description": "Arriving terminal name. Absent when upstream omits it.",
"type": "string"
}
},
"required": [
"departingTerminalId",
"arrivingTerminalId"
],
"additionalProperties": false,
"description": "One direction of service between two terminals on the requested date."
}
}
},
"additionalProperties": false,
"description": "A WSF ferry route operating on the requested date."
},
"description": "Ferry routes operating on the requested date."
},
"tripDate": {
"type": "string",
"description": "Date for which routes were retrieved (ISO 8601)."
},
"totalCount": {
"type": "number",
"description": "Total number of routes returned."
},
"notice": {
"description": "Optional notice when no routes are available for the date. Absent on normal results.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSF Ferry API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSF rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. `invalid_date`: The tripDate is not a valid YYYY-MM-DD date, or WSF rejects it as outside the dates it has published a schedule for. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code",
"invalid_date"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"routes",
"tripDate",
"totalCount"
]
},
{
"required": [
"error"
]
}
]
}🟢wsdot_get_ferry_schedule(departingTerminalId, arrivingTerminalId, tripDate, remainingOnly)
Returns departure times for a specific WSF ferry route on a given date. Requires numeric terminal IDs — use wsdot_get_ferry_terminals to resolve terminal names to IDs; terminalPairs on wsdot_get_ferry_routes lists the pairs with service on a date. Set remainingOnly to true to show only future departures for today (useful for "next ferry" queries). For future dates, all sailings for that day are returned. Each sailing carries its vessel ID, WSF's loading-rule code, and the pair's annotations that apply to it — notes such as "No interisland vehicles" that decide whether a sailing takes a car. Sailing times are ISO 8601 UTC while tripDate is the Pacific service day, so evening sailings carry the next UTC date — convert to America/Los_Angeles before quoting a clock time. Cancellations are not carried here — WSF drops a cancelled sailing from the schedule instead of flagging it, so a listed sailing is not confirmation that it will run. Check wsdot_get_ferry_alerts for disruptions; those are scoped to a route, not an individual sailing.
输入模式
{
"type": "object",
"properties": {
"departingTerminalId": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "Numeric ID of the departing terminal. Use wsdot_get_ferry_terminals to look up terminal IDs."
},
"arrivingTerminalId": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "Numeric ID of the arriving terminal."
},
"tripDate": {
"description": "Date in ISO 8601 format (YYYY-MM-DD). Defaults to today if omitted.",
"type": "string"
},
"remainingOnly": {
"description": "When true, returns only future sailings for today. Ignored for future dates. Default: false.",
"type": "boolean"
}
},
"required": [
"departingTerminalId",
"arrivingTerminalId"
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"departingTerminalName": {
"description": "Departing terminal name.",
"type": "string"
},
"arrivingTerminalName": {
"description": "Arriving terminal name.",
"type": "string"
},
"annotations": {
"description": "Notes WSF attaches to this pair's sailings (vehicle restrictions, routing, delays), converted from HTML to plain text with link destinations kept as \"text (url)\". Sailings point at the ones that apply to them through annotationIndexes. Empty when the pair has none.",
"type": "array",
"items": {
"type": "string",
"description": "One note, as plain text."
}
},
"sailingNotes": {
"description": "A note covering every sailing on this pair (e.g. a boarding-pass requirement), converted from HTML to plain text. Absent when WSF publishes none, which is the case for most pairs.",
"type": "string"
},
"sailings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"departureTime": {
"description": "Scheduled departure time (ISO 8601, UTC). WSF publishes schedules in Pacific time, so a sailing late in the service day carries the following UTC calendar date and will not match tripDate. Convert to America/Los_Angeles before showing a clock time.",
"type": "string"
},
"arrivalTime": {
"description": "Scheduled arrival time (ISO 8601, UTC), on the same terms as departureTime. Absent on the routes WSF publishes no arrival time for.",
"type": "string"
},
"vesselName": {
"description": "Vessel assigned to this sailing.",
"type": "string"
},
"vesselId": {
"description": "ID of the assigned vessel — the same vesselId wsdot_get_vessel_locations reports.",
"type": "number"
},
"loadingRule": {
"description": "WSF's loading-rule code for this sailing. WSF does not document the codes: 3 appears on nearly every sailing, and 1 has appeared only on sailings whose annotation restricts vehicles. Read the sailing’s annotations for the restriction itself.",
"type": "number"
},
"vesselHandicapAccessible": {
"description": "Whether WSF marks the assigned vessel as handicap accessible.",
"type": "boolean"
},
"annotationIndexes": {
"description": "Positions in annotations of the notes that apply to this sailing; each resolves to an entry. Empty when none apply.",
"type": "array",
"items": {
"type": "number",
"description": "A position in annotations."
}
}
},
"additionalProperties": false,
"description": "One scheduled sailing with departure time, vessel assignment, and the notes that apply to it."
},
"description": "Scheduled sailings for this route and date."
},
"tripDate": {
"type": "string",
"description": "Date of the schedule (ISO 8601)."
},
"remainingOnly": {
"type": "boolean",
"description": "Whether the result holds only today's remaining sailings. False for any date other than today, whatever was requested."
},
"totalSailings": {
"type": "number",
"description": "Total number of sailings returned."
},
"notice": {
"description": "Optional notice when no sailings are found — e.g. invalid terminal pair or no service for this date. Absent when sailings are present.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSF Ferry API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSF rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. `invalid_terminal_pair`: The terminal ID pair is invalid or does not form a valid ferry route. `invalid_date`: The tripDate is not a valid YYYY-MM-DD date, WSF rejects it as outside the dates it has published a schedule for, or WSF lists no routes on it. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code",
"invalid_terminal_pair",
"invalid_date"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"sailings",
"tripDate",
"remainingOnly",
"totalSailings"
]
},
{
"required": [
"error"
]
}
]
}🟢wsdot_get_vessel_locations
Returns real-time AIS positions, speed, heading, ETA, and dock status for all active WSF vessels. Use for "where is the ferry now?", vessel tracking, or checking if a vessel is in service. Position data may lag by 30–60 seconds. Many fields are null for vessels not currently operating.
输入模式
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"vessels": {
"type": "array",
"items": {
"type": "object",
"properties": {
"vesselId": {
"description": "Unique vessel identifier.",
"type": "number"
},
"vesselName": {
"description": "Vessel name (e.g. \"Yakima\", \"Walla Walla\").",
"type": "string"
},
"inService": {
"description": "Whether the vessel is currently in service.",
"type": "boolean"
},
"atDock": {
"description": "True when the vessel is docked at a terminal.",
"type": "boolean"
},
"departingTerminalId": {
"description": "Terminal the vessel is departing from.",
"type": "number"
},
"departingTerminalName": {
"description": "Departing terminal name.",
"type": "string"
},
"arrivingTerminalId": {
"description": "Terminal the vessel is heading toward.",
"type": "number"
},
"arrivingTerminalName": {
"description": "Arriving terminal name.",
"type": "string"
},
"latitude": {
"description": "Current latitude (AIS position).",
"type": "number"
},
"longitude": {
"description": "Current longitude (AIS position).",
"type": "number"
},
"speed": {
"description": "Speed in knots.",
"type": "number"
},
"heading": {
"description": "Heading in degrees (0–359).",
"type": "number"
},
"leftDock": {
"description": "Time the vessel last left the dock.",
"type": "string"
},
"eta": {
"description": "Estimated arrival time at the destination terminal.",
"type": "string"
},
"scheduledDeparture": {
"description": "Scheduled departure time.",
"type": "string"
},
"opRouteAbbrev": {
"type": "array",
"items": {
"type": "string"
},
"description": "Abbreviations of routes this vessel operates on."
},
"timestamp": {
"description": "AIS data timestamp — indicates position data age.",
"type": "string"
}
},
"required": [
"opRouteAbbrev"
],
"additionalProperties": false,
"description": "Real-time position and status for one WSF vessel."
},
"description": "All WSF vessels with real-time position data."
},
"totalCount": {
"type": "number",
"description": "Total number of vessels returned."
},
"notice": {
"description": "Optional notice when no vessel data is available. Absent on normal results.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSF Ferry API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSF rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"vessels",
"totalCount"
]
},
{
"required": [
"error"
]
}
]
}🟢wsdot_get_terminal_space(departingTerminalId, offset, limit)
Returns real-time drive-up and reservable vehicle space available at WSF terminals for upcoming sailings. Use for "will I make the ferry?" or "how full is the next sailing?" questions. Optionally filter to a specific terminal by ID (use wsdot_get_ferry_terminals for the ID). driveUpSpaceCount is the key field — zero means the drive-up lane is full. Destinations are arrivingTerminalIds, not the itineraryLabel string: a sailing can serve several terminals, and those IDs are what wsdot_get_ferry_schedule accepts. Results are paged by terminal (default 5, max 20): offset/limit select whole terminals and totalCount counts matching terminals, not sailings — every sailing of a returned terminal is included, so page size varies with how many departures each terminal carries.
输入模式
{
"type": "object",
"properties": {
"departingTerminalId": {
"description": "Filter to a specific terminal by numeric ID. Omit to return all terminals.",
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991
},
"offset": {
"description": "Zero-based index of the first terminal to return, for paging. Defaults to 0.",
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"limit": {
"description": "Maximum terminals to return in this page (1–20). Defaults to 5. Counts terminals, not sailings.",
"type": "integer",
"minimum": 1,
"maximum": 20
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"terminals": {
"type": "array",
"items": {
"type": "object",
"properties": {
"terminalId": {
"description": "Terminal numeric ID.",
"type": "number"
},
"terminalName": {
"description": "Terminal name.",
"type": "string"
},
"departingSpaces": {
"type": "array",
"items": {
"type": "object",
"properties": {
"departure": {
"description": "Scheduled departure time for this sailing.",
"type": "string"
},
"isCancelled": {
"description": "Whether this sailing is cancelled.",
"type": "boolean"
},
"vesselName": {
"description": "Vessel assigned to this sailing.",
"type": "string"
},
"arrivingTerminalIds": {
"description": "Numeric IDs of the terminals this sailing serves — the destinations. Pass one to wsdot_get_ferry_schedule as arrivingTerminalId, or resolve names with wsdot_get_ferry_terminals.",
"type": "array",
"items": {
"type": "number"
}
},
"itineraryLabel": {
"description": "Upstream itinerary string for the sailing, e.g. \"Anacortes -> Friday Harbor\". A display label only — it may name the departing terminal or several stops, so do not read it as the destination.",
"type": "string"
},
"displayDriveUpSpace": {
"description": "Whether WSF publishes a drive-up count for this sailing. False means driveUpSpaceCount is not reported, not that the lane is empty.",
"type": "boolean"
},
"displayReservableSpace": {
"description": "Whether this sailing takes vehicle reservations. False means reservableSpaceCount does not apply.",
"type": "boolean"
},
"driveUpSpaceCount": {
"description": "Available drive-up vehicle spaces. Zero means full — oversubscribed sailings report a negative count upstream and are floored to zero here, so this value is never negative.",
"type": "number"
},
"reservableSpaceCount": {
"description": "Available reservable vehicle spaces, floored at zero like driveUpSpaceCount. Zero means no reservable space remains.",
"type": "number"
},
"maxSpaceCount": {
"description": "Maximum vehicle capacity for this sailing.",
"type": "number"
},
"driveUpSpaceHexColor": {
"description": "Color code for drive-up space indicator (for UI rendering).",
"type": "string"
}
},
"additionalProperties": false,
"description": "Space availability for one upcoming sailing."
},
"description": "Upcoming sailings and available vehicle spaces."
}
},
"required": [
"departingSpaces"
],
"additionalProperties": false,
"description": "Space availability at one WSF terminal."
},
"description": "Terminal space availability by terminal."
},
"totalCount": {
"type": "number",
"description": "Total terminals matching the filter across all pages (not just this page). Counts terminals, not sailings."
},
"nextOffset": {
"description": "Offset to pass to retrieve the next page, or null when this is the last page.",
"type": [
"number",
"null"
]
},
"hasMore": {
"type": "boolean",
"description": "True when more terminals remain beyond the current page."
},
"terminalFilter": {
"description": "The terminal ID filter applied, or absent if no filter was used.",
"type": "number"
},
"notice": {
"description": "Informational note about the page window, or guidance when no terminal space data is available, the filter matched nothing, or the offset ran past the end.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSF Ferry API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSF rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"terminals",
"totalCount",
"nextOffset",
"hasMore"
]
},
{
"required": [
"error"
]
}
]
}🟢wsdot_get_ferry_alerts
Returns active WSF ferry service disruptions, delays, and bulletins. Each alert carries a one-line summary plus the bulletin title, kind, and full body — the body is where detail such as a replacement sailing appears. Each alert includes impacted route IDs — cross-reference with wsdot_get_ferry_routes to resolve route IDs to human-readable route names. Some IDs (seasonal, San Juan interisland, or international Sidney B.C. routes) may not appear in wsdot_get_ferry_routes for a given date.
输入模式
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false
}输出模式
{
"type": "object",
"properties": {
"alerts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"alertId": {
"description": "Unique alert identifier.",
"type": "number"
},
"alertTitle": {
"description": "The bulletin's own title.",
"type": "string"
},
"alertDescription": {
"description": "One-line summary of the alert or disruption, as shown on the route pages. Falls back to the title when upstream publishes no summary.",
"type": "string"
},
"bulletinText": {
"description": "Full bulletin body as plain text, normalized from the upstream HTML — links are rendered inline as \"link text (url)\". Detail that appears nowhere else, such as a replacement sailing, lives here.",
"type": "string"
},
"alertType": {
"description": "Alert kind as WSF categorizes it, e.g. \"All Alerts\".",
"type": "string"
},
"affectsAllRoutes": {
"description": "True when the alert applies fleet-wide. A fleet-wide alert need not enumerate routes, so while this is true an empty impactedRouteIds means every route rather than none.",
"type": "boolean"
},
"impactedRouteIds": {
"type": "array",
"items": {
"type": "number"
},
"description": "Route IDs affected by this alert. Cross-reference with wsdot_get_ferry_routes to get route names; some seasonal or interisland route IDs may not be listed there for a given date. Empty means no specific routes unless affectsAllRoutes is true, which makes it fleet-wide."
},
"publishDate": {
"description": "When the alert was published (ISO 8601).",
"type": "string"
}
},
"required": [
"impactedRouteIds"
],
"additionalProperties": false,
"description": "A WSF ferry service alert or disruption."
},
"description": "Active ferry service alerts and disruptions."
},
"totalCount": {
"type": "number",
"description": "Total number of active alerts."
},
"notice": {
"description": "Optional notice when no alerts are active. Absent when alerts are present.",
"type": "string"
},
"error": {
"description": "Present when the call failed. Absent on success.",
"type": "object",
"properties": {
"code": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode. Declared by this tool: `api_unavailable`: WSF Ferry API is unreachable or returns a non-2xx response after retries. `invalid_access_code`: WSF rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered. Other values are possible when a failure originates below the handler.",
"examples": [
"api_unavailable",
"invalid_access_code"
]
},
"recovery": {
"description": "Actionable next step for the caller.",
"type": "object",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"additionalProperties": {}
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"additionalProperties": {}
}
},
"required": [
"code",
"message"
],
"additionalProperties": {}
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"alerts",
"totalCount"
]
},
{
"required": [
"error"
]
}
]
}社区
证据