Searoute logo

Searoute

Real shortest sea routes between ports: distance, canals/straits, GeoJSON. UN/LOCODE aware.

Install Searoute

Pick your client, then add it in one click or paste the config.

STDIONode.js
~/Library/Application Support/Claude/claude_desktop_config.json
claude_desktop_config.json
{
  "mcpServers": {
    "searoute": {
      "command": "npx",
      "args": [
        "-y",
        "@searoute-ts/mcp"
      ]
    }
  }
}

Settings β†’ Developer β†’ Edit Config, merge this into mcpServers, then fully quit and reopen Claude Desktop.

Automated check passedβ€” started and listed 2 tools correctly (7d ago).

Overview

Tools2

What Searoute lets your agent do. Expand a tool for its parameters.

Verified live~1.0k tokens of context

Security & health

What it can reach and how reliably it runs β€” from our own checks, not the maintainer’s claims.

ActiveLast checked 2d ago

Recent health check succeeded.

5/5 checks healthy over the last 45d

What it can do

From the 2 tools this server returned when we ran it.

Read-only tools Β· 2
Network at startup3 connections
Files written at startupNone
Install scriptsNone
npm provenanceSigned build
Package age61 days
Maintainers1

Observed 2026-10-21 in an isolated sandbox. A description of reach, not a security audit.

Supply-chain signal

No high-severity advisories surfaced by our automated scan.

Critical 0High 0Medium 0Low 0

Scanned 18h ago via OSV.dev Β· @searoute-ts/mcp (npm)

Adoption & maintenance

Factual signals from GitHub, npm, and our automated checks β€” not a rating.

GitHub stars10Stargazers on the source repository.
npm downloads174Package downloads in the last 30 days.
Last commit13d agoMost recent push to the default branch.
Availability100%Our rolling endpoint + install checks that succeeded.
Install checkPassedOur sandbox started it and listed its tools.
Tools exposed2Callable tools this server registers over MCP.
Directory activity2 viewsConfig copies, upvotes, and views on AllMCPs.

From the project README

searoute-ts

Shortest sea route between any two points on Earth. A TypeScript / JavaScript library for maritime route planning, port-to-port distance, ETA estimation, and shipping-lane visualisation β€” powered by the 2025 Eurostat maritime network.

npm version npm downloads CI license types

Terminal
npm install searoute-ts
server.ts
import { seaRoute } from 'searoute-ts';

const route = seaRoute([121.5, 31.0], [4.4, 51.9]);
// Shanghai β†’ Rotterdam β†’ GeoJSON LineString, ~10,664 nm via Suez Canal

πŸ—ΊοΈ Try the interactive demo β€” click two points on a map and see the route, with all options live. (source)

πŸ“ Port-to-port sea distances β€” distance, sailing time and canal passages for common routes between major ports.

Works from plain JavaScript too β€” the package ships compiled .js plus .d.ts declarations. The -ts in the name is for searchability, not a language requirement.


Why searoute-ts

  • 🚒 Realistic shipping routes, not great-circle lines through Eurasia.
  • πŸ—ΊοΈ Returns GeoJSON β€” drop straight into Leaflet, Mapbox, deck.gl, MapLibre.
  • 🌊 2025 Eurostat marnet with explicit Suez, Panama, Bab-el-Mandeb, Malacca, Gibraltar, Dover, Kiel, Corinth, Bering, Magellan, NW/NE Passage labels.
  • 🚫 Canal & strait restrictions β€” force Cape of Good Hope during a Red Sea disruption with one option.
  • πŸ“¦ Vessel-draft gating β€” auto-block Panama (15.2 m), Suez (20.1 m), Kiel (7 m), Corinth (7.3 m) when the vessel exceeds the canal limit.
  • πŸ›€οΈ K-shortest alternatives β€” seaRouteAlternatives returns the baseline plus up to N realistic alternatives.
  • 🧭 Multi-leg waypoints β€” seaRouteMulti for port rotations and itineraries.
  • ⏱️ ETA from speed β€” speedKnots β†’ durationHours.
  • πŸ› οΈ Modern toolchain β€” TypeScript 5, ESM + CJS dual build, types included, Node 18+, zero peer deps.

Quick examples

Basic β€” shortest route

server.ts
import { seaRoute } from 'searoute-ts';

const route = seaRoute([-74.04, 40.69], [-0.13, 51.5]); // NYC β†’ London
// route.properties.length  // β‰ˆ 3 362 nm
// route.properties.units   // 'nauticalmiles'

With ETA and units

ts
seaRoute(shanghai, rotterdam, {
  units: 'kilometers',
  speedKnots: 22,
});
// β†’ 19 753 km, properties.durationHours β‰ˆ 485 h (β‰ˆ 20 days)

Red Sea / Suez disruption β€” force Cape of Good Hope

ts
seaRoute(shanghai, rotterdam, {
  restrictions: ['suez', 'babelmandeb'],
});
// β†’ routes via Cape of Good Hope, ~25 800 km

Vessel-aware β€” Ultra Large Container Ship

ts
seaRoute(shanghai, newYork, {
  vesselDraftMeters: 16,  // exceeds Panama's 15.2 m TFW
});
// β†’ Panama auto-blocked, route goes via Suez

Port codes (UN/LOCODE)

server.ts
import 'searoute-ts/ports'; // enables UN/LOCODE strings on the core API
import { seaRoute } from 'searoute-ts';

seaRoute('CNSHA', 'NLRTM'); // Shanghai β†’ Rotterdam
seaRoute('CNSHA', [4.4, 51.9]); // mixing a code and coordinates is fine too

The ~1 600-port dataset lives behind the searoute-ts/ports subpath so the core stays lean β€” importing it registers the resolver. You can also resolve codes yourself:

server.ts
import { lookupPort, resolvePort } from 'searoute-ts/ports';

lookupPort('SGSIN'); // β†’ { code, name: 'Singapore', country, coordinates: [lon, lat] }
resolvePort('SGSIN'); // β†’ [103.85, 1.28]

Unknown codes throw UnknownPortError. See Port codes below for provenance.

Load the port dataset from a CDN instead of bundling it

Don't want to bundle the ~135 KB dataset? Fetch it at runtime with loadPorts β€” the analog of loadNetwork. The dataset also ships as a raw dist/ports.json, so jsDelivr/unpkg serve it versioned for free:

server.ts
import { seaRoute, loadPorts } from 'searoute-ts';

// Pin a version for reproducibility, or use @latest to always get the newest.
await loadPorts('https://cdn.jsdelivr.net/npm/searoute-ts@latest/dist/ports.json');

seaRoute('CNSHA', 'NLRTM'); // works β€” the fetched dataset is now registered
Code
https://cdn.jsdelivr.net/npm/searoute-ts@latest/dist/ports.json      # newest
https://cdn.jsdelivr.net/npm/searoute-ts@<version>/dist/ports.json   # frozen/immutable

(dist/ports.json ships from the release that adds port codes onward β€” pin any version at or after it for reproducibility.)

loadPorts registers the fetched dataset (so code strings resolve) and returns it. It uses the global fetch (Node β‰₯18 / browsers); pass { fetch } to override.

Multi-leg / port rotation

server.ts
import { seaRouteMulti } from 'searoute-ts';

seaRouteMulti(
  [shanghai, singapore, mumbai, rotterdam],
  { units: 'kilometers', returnPassages: true },
);
// β†’ one concatenated LineString, total length, union of passages

Alternative routes (Yen-style canal permutation)

server.ts
import { seaRouteAlternatives } from 'searoute-ts';

const alts = seaRouteAlternatives(shanghai, rotterdam, { k: 4 });
//  baseline           19 753 km via Suez
//  no-malacca         20 759 km
//  no-suez            25 315 km (via Panama)
//  no-suez-no-panama  25 845 km (via Cape of Good Hope)

Fetch the network from a URL instead of bundling it (optional)

The network is bundled by default, so seaRoute works offline with zero setup. If you'd rather not ship the ~1 MB network (e.g. to trim a browser bundle, or to use an updated network without upgrading the package), fetch it at runtime and pass it via the existing network option:

server.ts
import { seaRoute, loadNetwork } from 'searoute-ts';

// CORS-enabled, served from GitHub Pages (or point at your own host / a CDN).
const network = await loadNetwork('https://mayurrawte.github.io/searoute-ts/marnet.json');

const route = seaRoute(shanghai, rotterdam, { network });

Only the fetch is async β€” seaRoute itself stays synchronous. loadNetwork uses the global fetch (Node β‰₯18 and all browsers); pass { fetch } to supply your own. This is purely opt-in; nothing changes if you don't use it.

Which option should I use?

ApproachHowData versionWorks offlineBest for
Bundled (default)seaRoute(a, b) β€” no networkpinned to your installed packageβœ…Most users; zero config, deterministic
Latest via URLloadNetwork('…/marnet.json')always the newest hosted❌ needs networkAlways-current data without upgrading
Pinned via CDNloadNetwork('https://cdn.jsdelivr.net/npm/searoute-ts@2.0.1/…')frozen (immutable)❌ needs networkReproducible builds

Versioning the hosted network

You choose the version by choosing the URL:

  • @latest / rolling β€” the GitHub Pages URL above always serves the current network. Convenient, but it can change under you.

  • Pinned & immutable β€” because the package is on npm, jsDelivr and unpkg serve every published version automatically, with immutable per-version URLs:

    Code
    https://cdn.jsdelivr.net/npm/searoute-ts@latest/dist/marnet.json   # newest
    https://cdn.jsdelivr.net/npm/searoute-ts@2/dist/marnet.json        # newest 2.x
    https://cdn.jsdelivr.net/npm/searoute-ts@2.0.1/dist/marnet.json    # frozen
    

    A pinned URL never changes, so your routes stay reproducible. (These standalone-JSON CDN paths land with the package once the network ships as a separate asset β€” see issue #10; until then, use the GitHub Pages URL.)

For production, prefer a pinned URL (or just the bundled default) so your distances don't shift when the network is updated.

Higher-resolution networks (optional)

The bundled network is Eurostat's 100 km marnet_plus. Eurostat also publishes finer resolutions, which give more accurate coastal routing and shorter-hop fidelity at the cost of a larger download and slightly slower first-route graph construction. Two moderate resolutions ship as subpath exports so you only pay for them if you import them:

server.ts
import { DEFAULT_MARNET } from 'searoute-ts/marnet-20km'; // or 'searoute-ts/marnet-50km'
import { seaRoute } from 'searoute-ts';

seaRoute(origin, destination, { network: DEFAULT_MARNET });

Like the bundled default, each variant ships once as a shared dist/data/marnet-<res>.cjs asset that both the CJS and ESM builds load at runtime, so importing a variant doesn't duplicate the network across builds.

ImportResolutionSegmentsJSON sizegzippedCoastal accuracy
searoute-ts (bundled default)100 km9,847~1.3 MB~0.18 MBBaseline β€” good for global routing
searoute-ts/marnet-50km50 km15,498~1.9 MB~0.27 MBModest step up
searoute-ts/marnet-20km20 km29,581~3.6 MB~0.51 MBNoticeably finer coastal hops
via loadNetwork (see below)10 km48,301~5.9 MB~0.84 MBHigh β€” larger download
via loadNetwork (see below)5 km72,478~9.0 MB~1.24 MBHighest β€” largest download

Reviews

No reviews yet β€” be the first to share how it worked for you.

Frequently Asked Questions about Searoute

searoute is an MCP server that provides shortest realistic sea routes between coordinates or UN/LOCODE ports, returning distance, route geometry, canal/strait information, and optional ETA data. It uses the 2025 Eurostat maritime network and supports GeoJSON output, route restrictions, vessel-draft gating, alternatives, and multi-leg itineraries.

Yes, searoute supports UN/LOCODE port identifiers such as CNSHA for Shanghai and NLRTM for Rotterdam. Port-code support is enabled through the searoute-ts/ports subpath, and codes can be used with coordinates in the same route request.

Yes, searoute returns route geometry as GeoJSON LineStrings, which can be used with mapping tools such as Leaflet, Mapbox, deck.gl, and MapLibre. Route properties also include distance units and, when requested, estimated duration.

Yes, searoute supports route restrictions for canals and straits. For example, restricting Suez and Bab-el-Mandeb routes a Shanghai-to-Rotterdam journey around the Cape of Good Hope during a Red Sea disruption.

Yes, searoute can use vessel draft to automatically block canals whose limits are exceeded, including Panama, Suez, Kiel, and Corinth. Providing speed in knots enables an estimated duration in hours.

Related MCP servers

Add a badge to your READMEShow it’s listed β€” live SVG, Markdown or HTML.

AllMCPs Directory Badge

Full Badge Customizer

Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.

Badge Style:
Live Dynamic SVG PreviewSearoute AllMCPs Directory Badge
Markdown (GitHub README)
[![AllMCPs](https://allmcps.com/api/badge/searoute?style=directory)](https://allmcps.com/mcp/searoute)
HTML Embed
<a href="https://allmcps.com/mcp/searoute"><img src="https://allmcps.com/api/badge/searoute?style=directory" alt="Searoute on AllMCPs" /></a>