boston-harbor-ferries
Provides a standalone MCP server that wraps FreeBSD's leave command for setting reminders and checking active reminders.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@boston-harbor-ferriesTrack the Crispus Attucks ferry"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Boston Harbor Ferries
APRS-based Boston Harbor commuter ferry tracker with MCP server support.
Tightly scoped to track Seaport Ferry vessels operating in Boston Harbor.
Data provided by aprs.fi - https://aprs.fi
Features
Track all 4 Seaport Ferry vessels in real-time
In-memory caching with 120-second TTL (respects aprs.fi API terms)
Rate limiting: 10 requests/minute (configurable)
Rich CLI with beautiful terminal output
MCP server for integration with Claude Code and other AI assistants
Run with
uvx(no installation required)Live position tracking and historical data export
Related MCP server: marta-mcp
Tracked Vessels
Seaport Ferry - North Station Route
PHILLIS WHEATLEY (MMSI: 368227350)
SAMUEL WHITTEMORE (MMSI: 368227370)
COMMONWEALTH (MMSI: 368351390)
Route: LoveJoy Wharf (North Station) β Fan Pier (Seaport) β Pier 10 Travel time: ~30 minutes
Seaport Ferry - East Boston Route
CRISPUS ATTUCKS (MMSI: 368157410) - π Live Position
Route: Lewis Mall Wharf (East Boston) β Fan Pier (Seaport) Travel time: ~10 minutes
π’ Latest Position: 42.351318Β°N, 71.038918Β°W (Course: 339Β°) π View 24-Day Activity Analysis - Speed patterns, hourly heatmaps, route visualization π Live Position Data - Real-time JSON feed
Historical Data: 4,777 positions over 24 days (Sep 15 - Oct 10) β’ Avg speed: 12.4kn β’ Operating hours: 05:00-19:00
π Activity Heatmap (Last 2 Weeks)
Activity by hour - darker blocks indicate more position reports:
00 04 08 12 16 20
β β β β β β
09-29 β βββββββ ββββββββ
09-30 β βββββββ βββββββ
10-01 β ββββββ βββββ
10-02 β βββββββ βββββ
10-03 β βββββββββββββββ
10-06 β ββββββββββββββββ
10-07 β βββββββ ββββββ
10-08 β ββββββ ββββββ
10-09 β ββββββββββββββββ
10-10 β βββββββLegend: β Low β Medium β High β Peak Pattern: Clear AM (06-10) and PM (15-18) commute peaks
π’ Speed Distribution
Speed (knots) β Frequency
βββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββ
2- 4 β ββββββ 188
4- 6 β βββββββ 202
6- 8 β βββββ 148
8-10 β ββββββ 176
10-12 β ββββββββ 229
12-14 β ββββββββββββ 349
14-16 β βββββββββββββββββββββββ 673
16-18 β ββββββββββββββββββββββββββββββββββββββββ 1123
18-20 β βββ 93
20-22 β 21Peak Speed: 16-18 knots (75% of time cruising >10kn)
πΊοΈ Route Map
Boston Harbor
ββββββββββββββββββββββββ
β β
Lewis Mall Wharf Fan Pier
(East Boston) (Seaport)
β β
β ~10 min β
β 8-12 kn β
βββββββββ¬βββββββββ
β
CRISPUS ATTUCKS
(90 passengers)Operating: 05:00-19:00 daily β’ Peak: 06-10, 15-18
Installation
Run with uvx (recommended)
# Set your API key
export APRS_API_KEY="your-key-from-aprs.fi"
# Run commands directly
uvx --from . harbor-ferry list-vessels
uvx --from . harbor-ferry track 368157410
uvx --from . harbor-ferry track-allInstall in development mode
cd boston_harbor_ferries
pip install -e .Configuration
Get your free API key from https://aprs.fi (requires registration).
Set the API key via environment variable:
export APRS_API_KEY="your-api-key-here"Or create a .env file:
APRS_API_KEY=your-api-key-here
APRS_CACHE_TTL_SECONDS=120
APRS_MAX_REQUESTS_PER_MINUTE=10CLI Usage
# List all known ferries
harbor-ferry list-vessels
# Show routes and schedules
harbor-ferry routes
# Track a specific ferry
harbor-ferry track 368157410
# Track all ferries
harbor-ferry track-all
# Force fresh data (bypass cache)
harbor-ferry track 368157410 --no-cache
# Cache management
harbor-ferry cache-info
harbor-ferry clear-cacheMCP Server Usage
The MCP server allows AI assistants like Claude Code to track ferries in real-time.
Quick Start
# Test the MCP server
gmake test-mcp
# Expected output:
# β MCP server responding to JSON-RPC
# Tools: list_ferries, track_ferry, track_all_ferries, get_ferry_routes, clear_cacheAvailable MCP Tools
list_ferries- List all known Boston Harbor ferries with detailsget_ferry_routes- Get route information and schedulestrack_ferry- Track specific ferry by MMSI numbertrack_all_ferries- Get all ferry positions at onceclear_cache- Force fresh data (bypasses 2-minute cache)
Claude Code/Desktop Integration
See docs/CLAUDE_CODE_INTEGRATION.md for complete integration guide.
Adding to Claude Code
From within this repository directory:
# Add the MCP server to Claude Code
claude mcp add-json boston-harbor-ferries \
'{"command":"uv","args":["run","python","-m","boston_harbor_ferries.mcp_server"],"env":{"APRS_API_KEY":"'"${APRS_API_KEY}"'"}}'
# Verify it's connected
claude mcp list
# Should show: boston-harbor-ferries - β Connected
# View available tools
claude mcp get boston-harbor-ferriesClaude Desktop Configuration
For global access in all Claude Desktop conversations:
Linux: ~/.config/Claude/claude_desktop_config.json
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"boston-harbor-ferries": {
"command": "uv",
"args": [
"run",
"--directory",
"/full/path/to/boston-harbor-ferries",
"python",
"-m",
"boston_harbor_ferries.mcp_server"
],
"env": {
"APRS_API_KEY": "your-api-key-here"
}
}
}
}Example Questions for Claude
Once configured, you can ask Claude:
"Where is CRISPUS ATTUCKS right now?"
"Show me all active ferries"
"What are the ferry routes in Boston Harbor?"
"Clear the cache and check ferry positions again"
Understanding Position Data
Operating Hours: Ferries transmit APRS positions during service hours (05:00-19:00 daily)
Peak times: 06:00-10:00 (morning) and 15:00-18:00 (evening)
Off-hours: No position data when ferries are not operating
Data age: Position reports update every 1-2 minutes when active
If you see old position data (>1 hour), the ferry is likely docked between runs or service has ended for the day. Check during peak commute hours for live tracking.
All 6 MCP tools tested and working β
(see gmake test)
Bonus: FreeBSD Leave Reminder MCP Server
This repository also includes a standalone MCP server that wraps FreeBSD's leave(1) command for setting reminders.
See LEAVE_MCP.md for complete documentation.
Quick test:
gmake test-leave-mcpTools available:
set_reminder- Set a reminder for a specific time or durationcheck_reminders- View active reminderscancel_reminders- Cancel all reminders
Example: "Remind me to leave in 30 minutes" β Uses +0030 format
Python API
from boston_harbor_ferries import APRSClient, VESSELS
# Initialize client (loads API key from env)
with APRSClient() as client:
# Track specific ferry
position = client.get_vessel_position("368157410")
if position:
print(f"{position.vessel.name} at {position.latitude}, {position.longitude}")
# Track all ferries
positions = client.get_all_ferries()
for pos in positions:
print(f"{pos.vessel.name}: {pos.age_seconds:.0f}s old")API Terms Compliance
This tool complies with aprs.fi API terms of service:
β Credits aprs.fi as data source in all output
β Provides link back to aprs.fi
β Free to use for all users
β Includes User-Agent header with app name/version
β Each user uses their own API key
β Built-in rate limiting (10 req/min default)
β Intelligent caching (2 min TTL default)
β Only queries when actively needed (no background polling)
Development
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Type checking
mypy boston_harbor_ferriesLicense
MIT
Acknowledgments
Data provided by aprs.fi - Hessu's excellent APRS infrastructure service.
Ferry service operated by Seaport Ferry.
Available Tools
6 toolsclear_cacheA
Clear all cached ferry position data
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the full burden. It clearly identifies what is destroyed ('all cached ferry position data'), but it does not disclose irreversibility, authorization needs, or potential effects on active tracking sessions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no filler. Every word contributes meaning: the action, the target, and the scope.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is minimally viable for a simple parameterless tool, but without annotations or an output schema it leaves gaps around side effects, return behavior, and when exactly the agent should invoke it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema has full coverage, so there is nothing for the description to add. Baseline 4 is appropriate for a parameterless tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Clear') and an explicit resource ('all cached ferry position data'). It is unambiguous and easily distinguished from the sibling tracking/list/route/weather tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use guidance or alternatives are provided, but the cache-invalidation purpose is implied by the description. Since no sibling performs the same operation, an agent can infer when it applies, though prerequisites and avoid scenarios are not stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ferry_routesB
Get information about ferry routes and schedules
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It only says 'Get information', implying a read operation, but does not disclose whether schedules are live or static, what fields are returned, whether results are cached, or any other behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one short sentence with no filler or redundancy. It is concise, though it largely paraphrases the tool name and adds little new information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter read tool, the description gives the basic purpose. However, with no output schema, no annotations, and sibling tools like list_ferries, an agent may not know what data to expect or when this tool is the right choice over its siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and 100% schema description coverage, so no parameter documentation is needed. The description adds no parameter detail, but none is required here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Get') and resource ('ferry routes and schedules'), so an agent can tell what the tool does. It does not explicitly differentiate itself from sibling tools like list_ferries, but the route/schedule focus is reasonably specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance about when to use this tool versus list_ferries, track_ferry, or get_harbor_weather. No alternatives, exclusions, or context cues are provided; an agent must infer usage from the name and one-line description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_harbor_weatherA
Get current weather conditions for Boston Harbor from nearby CWOP station (EW2727)
| Name | Required | Description | Default |
|---|---|---|---|
| station | No | CWOP station callsign (default: EW2727). Options: EW2727 (Boston Harbor), DW3706 (Winthrop/East Boston) | EW2727 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the data source and that conditions are 'current', but does not explain update latency, what weather fields are returned, units, or failure behavior if the station is unreachable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence that conveys location, data source, and currency without any filler. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple with one optional parameter, so the description is mostly adequate for selection and invocation. However, since there is no output schema, the description does not explain what 'weather conditions' includes, which an agent might need to set expectations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the parameter description already documents the default and available station options. The tool description adds no additional parameter meaning, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get'), a precise resource ('current weather conditions for Boston Harbor'), and a source ('nearby CWOP station EW2727'). It is unmistakably distinct from the ferry-related sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: this is for current weather conditions at Boston Harbor. It does not explicitly mention alternatives or exclusions, but the sibling tools are clearly about ferry tracking, so usage intent is well understood.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_ferriesA
List all known Boston Harbor commuter ferries with their details
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavior disclosure burden. It clearly signals a read-only enumeration and scopes the result to 'all known' ferries, but it does not mention output shape, data freshness, or whether this is a live or cached view. That is acceptable but minimal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no filler. It communicates the essential scope and operation efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless list operation, this is mostly complete: it identifies the resource, scope, and that details are returned. The main gap is the absence of explicit differentiation from the tracking siblings and lack of detail on what 'details' specifically includes, but the low complexity keeps this adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema coverage is trivially 100%, so there is no parameter documentation burden. Baseline 4 applies because no parameters need semantic explanation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource: list all Boston Harbor commuter ferries with their details. It is unambiguous about the operation, though it does not explicitly differentiate itself from track_all_ferries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is for retrieving a static catalog of all ferries, but it provides no explicit guidance on when to choose it over track_ferry, track_all_ferries, or get_ferry_routes. Usage context is only inferred from the word 'list'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
track_all_ferriesA
Get current positions of all Boston Harbor commuter ferries
| Name | Required | Description | Default |
|---|---|---|---|
| use_cache | No | Use cached data if available (default: true) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral burden. 'Get' reasonably signals a read-only operation, but the description does not mention cache behavior even though use_cache defaults to true, which may affect how 'current' the positions are. It also does not describe response format or error behavior, but it does not misrepresent the core action.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with no filler. It front-loads the verb and object, immediately communicates the tool's purpose, and every word carries meaningful scope information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with one optional parameter and no output schema, the description tells the agent what to expect: positions of all Boston Harbor ferries. The schema handles the cache flag. A minor gap is the lack of output shape detail, but this is not critical at this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the only parameter, use_cache, is already documented with its type, default, and meaning. The description adds nothing about the parameter, but the schema fully covers it, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get'), a concrete resource ('current positions'), and a clear scope ('all Boston Harbor commuter ferries'). This distinguishes it from singular track_ferry and static list_ferries without needing to open the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'all' and 'current positions' implies when to use it, but the description does not explicitly say when not to use it or name alternatives such as track_ferry for a single ferry or list_ferries for non-position data. Usage context is inferred, not stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
track_ferryB
Get current position and status of a Boston Harbor ferry by MMSI number
| Name | Required | Description | Default |
|---|---|---|---|
| mmsi | Yes | Vessel MMSI number (e.g., '368157410' for Crispus Attucks) | |
| use_cache | No | Use cached data if available (default: true) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the full behavioral burden. It states a read-only 'get' but does not disclose that the default use_cache=true may return stale/cached data, despite claiming 'current' position. Error behavior and data freshness are also unaddressed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, directly front-loaded sentence with no filler. Every word earns its place: verb, scope, resource, and key input are all present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple single-vessel lookup, the description plus schema is minimally viable, but there is no output schema and the description does not explain what 'status' includes, nor how to obtain an MMSI (e.g., via list_ferries). The caching nuance is also left to the schema. Adequate but with clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with clear descriptions for both mmsi (including an example) and use_cache (default and meaning). The description adds no parameter-level detail, but it does not need to because the schema fully documents them, placing it at the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb ('Get') and resource ('current position and status of a Boston Harbor ferry'), and uniquely scopes it by MMSI. This differentiates it from siblings like track_all_ferries (all vessels) and list_ferries (listing, not tracking).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no explicit guidance on when to use this tool instead of track_all_ferries or list_ferries. The 'by MMSI number' phrase subtly implies a known specific vessel, but no direct alternatives or conditions are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.1.0- First observed
clear_cache - First observed
get_ferry_routes - First observed
get_harbor_weather - First observed
list_ferries - First observed
track_all_ferries - First observed
track_ferry
TDQS
Scored across 6 tools
Tool purposes are mostly distinct: track_ferry is singular position lookup, track_all_ferries is plural positions, list_ferries is static fleet details, and routes/weather/cache are separate concerns. There is minor potential confusion between list_ferries and track_all_ferries, but descriptions clarify the difference.
All tool names follow a clear verb_noun pattern: track, list, get, clear. The naming is consistent and predictable, with no style mixing or vague verbs.
Six tools is well-scoped for a ferry information server. Each tool serves a clear purpose without redundancy, covering tracking, fleet information, routes, weather, and cache management.
The tool set covers the core ferry domain well: list fleet, track individual/all ferries, get routes and schedules, and check weather. Minor gaps exist such as no terminal status or service alerts, but these are not obvious dead ends for basic ferry tracking use cases.
Maintenance
Related MCP Connectors
MCP server giving AI agents one-connection access to supply-chain & logistics data: AIS vessel track
MBTA MCP β Boston real-time transit via the MBTA v3 API (api-v3.mbta.com)
MCP server for Travel & Transportation
VesselFinder MCP β wraps the VesselFinder AIS API (vesselfinder.com)
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA fully MCP-compliant, open-source maritime data service that provides real-time vessel tracking, port information, route planning, and weather/tide data for maritime applications.14MIT
- AlicenseAqualityBmaintenanceMCP server for Atlanta MARTA real-time transit data, enabling queries about train arrivals and bus positions via natural language.4MIT
- AlicenseCqualityCmaintenanceMCP server for the UK Bus Open Data Service, enabling timetable queries, stop search, route discovery, journey planning, and real-time bus tracking.1641 PyPIMIT
- AlicenseNot gradedqualityDmaintenanceMCP server that enables AI assistants to access real-time vessel tracking, port information, and maritime data through the Datalastic Marine AIS Data API.1MIT