vesselapi-mcp 1.3.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,65 @@
1
+ # Changelog
2
+
3
+ All notable changes to this server are documented here.
4
+ This project follows [Semantic Versioning](https://semver.org/).
5
+
6
+ ## [2.0.0] - 2026-08-13
7
+
8
+ Vessel ownership, classification and inspection data, and NAVTEX messages were
9
+ retired from the VesselAPI service on **10 August 2026**. There is no
10
+ replacement for them.
11
+
12
+ ### Removed (breaking)
13
+
14
+ - `get_vessel_classification`
15
+ - `get_vessel_ownership`
16
+ - `get_vessel_inspections`
17
+ - `get_vessel_inspection_detail`
18
+ - `get_navtex_messages`
19
+
20
+ `search_vessels` no longer accepts `classSociety` or `owner`. The API rejects
21
+ both with HTTP 400.
22
+
23
+ **19 tools remain**, down from 24.
24
+
25
+ ### Added
26
+
27
+ - **`q` on `search_vessels`.** Free-text search across name, IMO, MMSI, ENI and
28
+ callsign. The response reports which fields matched.
29
+ - **`eni` on `search_vessels`**, for inland waterway vessels.
30
+ - **`sat` on `get_vessel_position`.** Falls back to a satellite position when no
31
+ recent terrestrial one exists. Charged per call against a prepaid balance.
32
+ - **`timeFrom` and `timeTo` on `get_port_events`, `search_port_events_by_port`
33
+ and `search_port_events_by_vessel`.** Without them the service returns only
34
+ the last 2 hours.
35
+
36
+ ### Fixed
37
+
38
+ - **`get_vessels_in_radius` asked for the radius in nautical miles.** The API
39
+ takes metres, so a request for 20 nautical miles searched 20 metres and
40
+ returned nothing.
41
+ - **`get_port_inbound` required an ETA window.** It is now optional, and the
42
+ service defaults to the next 72 hours.
43
+ - **`idType` offered `vesselId`, which the API rejects with HTTP 400.** It now
44
+ accepts `imo` and `mmsi` only.
45
+ - **402 and 403 reported as generic API errors.** Out of satellite credits, a
46
+ suspended key and a feature outside the plan are now distinct conditions,
47
+ none worth retrying unchanged.
48
+ - **A missing `VESSELAPI_API_KEY` killed the process with a stack trace during
49
+ startup.** It now prints one line naming the variable.
50
+ - **Two version mismatches.** `server.json` declared 1.0.1 while the package was
51
+ 1.3.0, and the server reported 1.0.0 in the MCP handshake whatever the
52
+ installed version.
53
+ - **Tool schemas now match what the API accepts.** `idType`, `eventType` and
54
+ `sortOrder` are enumerations, `limit` is bounded to 1 to 50, and the area
55
+ tools state the 4 hour maximum window.
56
+
57
+ ### Requires
58
+
59
+ `vesselapi` 2.0.0 or later.
60
+
61
+ ### Attribution
62
+
63
+ Emissions and casualty data: © European Union. Source: European Maritime Safety
64
+ Agency (EMSA), THETIS-MRV (EU MRV, Regulation (EU) 2015/757) and the European
65
+ Marine Casualty Information Platform (EMCIP). See the README.
package/README.md CHANGED
@@ -21,16 +21,19 @@ An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that
21
21
 
22
22
  ## Features
23
23
 
24
- - **23 tools** covering vessels, ports, location search, emissions, and maritime safety
25
- - Vessel search, positions (single and batch), ETA, classification, ownership, emissions, inspections, and casualties
24
+ - **19 tools** covering vessels, ports, location search, and emissions
25
+ - Vessel search, positions (single and batch), ETA, emissions, and casualties
26
26
  - Port search, details, port events (arrivals/departures), and global port event search
27
27
  - Geographic vessel search (bounding box and radius)
28
- - NAVTEX maritime safety messages
29
28
  - Manual pagination to control API quota usage
30
29
 
30
+ ## Hosted deployment
31
+
32
+ A hosted deployment is available on [Fronteir AI](https://fronteir.ai/mcp/vessel-api-vesselapi-mcp).
33
+
31
34
  ## Quick Start
32
35
 
33
- No installation required — just configure your AI client with `npx`:
36
+ No installation required. Configure your AI client with `npx`:
34
37
 
35
38
  ```json
36
39
  {
@@ -54,7 +57,7 @@ Add the JSON above to the config file for your client:
54
57
  |---|---|
55
58
  | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows) |
56
59
  | Cursor | `.cursor/mcp.json` or `~/.cursor/mcp.json` |
57
- | Claude Code | `.claude/settings.json` or `~/.claude/settings.json` |
60
+ | Claude Code | `claude mcp add`, which writes `.mcp.json` in the project or `~/.claude.json` for user scope |
58
61
  | Windsurf | `~/.codeium/windsurf/mcp_config.json` |
59
62
 
60
63
  ## Tools
@@ -63,16 +66,12 @@ Add the JSON above to the config file for your client:
63
66
 
64
67
  | Tool | Description |
65
68
  |---|---|
66
- | `search_vessels` | Search vessels by name, IMO, MMSI, flag, type, callsign, year built, class society, or owner |
69
+ | `search_vessels` | Search vessels by name, IMO, MMSI, flag, type, callsign, or year built |
67
70
  | `get_vessel` | Get detailed vessel information |
68
71
  | `get_vessel_position` | Get current vessel position (lat/lon, speed, heading) |
69
72
  | `get_vessel_eta` | Get vessel estimated time of arrival |
70
- | `get_vessel_classification` | Get classification details (class society, surveys, hull) |
71
- | `get_vessel_ownership` | Get ownership details (owner, manager, operator) |
72
73
  | `get_vessel_emissions` | Get emissions data (CO2, fuel consumption) |
73
- | `get_vessel_inspections` | Get port state control inspections |
74
74
  | `get_vessel_casualties` | Get marine casualty records |
75
- | `get_vessel_inspection_detail` | Get detailed information about a specific inspection |
76
75
  | `get_vessel_positions_batch` | Get positions for multiple vessels at once (with optional time range) |
77
76
 
78
77
  ### Port Tools
@@ -81,6 +80,7 @@ Add the JSON above to the config file for your client:
81
80
  |---|---|
82
81
  | `search_ports` | Search ports by name, country, type, size, region, harbor size, or harbor use |
83
82
  | `get_port` | Get port details by UN/LOCODE |
83
+ | `get_port_inbound` | Get vessels inbound to a port within an ETA window |
84
84
  | `get_port_events` | Get arrivals/departures for a port |
85
85
  | `get_port_events_by_vessel` | Get port events for a vessel |
86
86
  | `list_port_events` | List port events globally with filters for time, country, port, vessel, or event type |
@@ -101,15 +101,10 @@ Add the JSON above to the config file for your client:
101
101
  | `get_vessels_in_area` | Find vessels in a bounding box (with optional time range) |
102
102
  | `get_vessels_in_radius` | Find vessels within a radius of a point (with optional time range) |
103
103
 
104
- ### Safety Tools
105
-
106
- | Tool | Description |
107
- |---|---|
108
- | `get_navtex_messages` | Get NAVTEX maritime safety messages |
109
104
 
110
105
  ## Pagination
111
106
 
112
- All list endpoints support `limit` and `nextToken` parameters for manual pagination. When more results exist, the response includes a `nextToken` — pass it in the next call to get the next page.
107
+ All list endpoints support `limit` and `nextToken` parameters for manual pagination. When more results exist, the response includes a `nextToken`. Pass it in the next call to get the next page.
113
108
 
114
109
  ## Development
115
110
 
@@ -132,6 +127,15 @@ npm run clean # Remove build artifacts
132
127
  VESSELAPI_API_KEY=your-key npx @modelcontextprotocol/inspector node dist/index.js
133
128
  ```
134
129
 
130
+ ## Data Sources & Attribution
131
+
132
+ Emissions and casualty data: © European Union. Source: European Maritime Safety Agency
133
+ (EMSA): THETIS-MRV (EU MRV, Regulation (EU) 2015/757) and the European Marine Casualty
134
+ Information Platform (EMCIP). Reused under the European Commission reuse notice
135
+ (Commission Decision 2011/833/EU), which authorises reuse for commercial and
136
+ non-commercial purposes with acknowledgement of the source. Data may be transformed and
137
+ combined; EMSA does not endorse this service.
138
+
135
139
  ## License
136
140
 
137
141
  MIT
package/dist/index.js CHANGED
@@ -5,6 +5,9 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
6
  import { VesselClient } from "vesselapi";
7
7
 
8
+ // src/version.ts
9
+ var VERSION = "2.0.0";
10
+
8
11
  // src/tools/location.ts
9
12
  import { z } from "zod";
10
13
 
@@ -12,7 +15,9 @@ import { z } from "zod";
12
15
  import {
13
16
  VesselAPIError,
14
17
  VesselAuthError,
18
+ VesselForbiddenError,
15
19
  VesselNotFoundError,
20
+ VesselPaymentRequiredError,
16
21
  VesselRateLimitError,
17
22
  VesselServerError
18
23
  } from "vesselapi";
@@ -24,15 +29,21 @@ function formatResult(data) {
24
29
  function handleToolError(error) {
25
30
  let message;
26
31
  if (error instanceof VesselAuthError) {
27
- message = "Authentication failed. Check your VESSELAPI_API_KEY.";
32
+ message = "Authentication failed. Check your VESSELAPI_API_KEY. Do not retry.";
33
+ } else if (error instanceof VesselPaymentRequiredError) {
34
+ message = "Out of satellite credits, and no stored position was available to fall back on. Retry without the satellite option to use stored data, or top up the balance at https://dashboard.vesselapi.com. Retrying the same request will not help.";
35
+ } else if (error instanceof VesselForbiddenError) {
36
+ message = error.code === "feature_not_available" ? "This endpoint is not included in the current plan. Do not retry; a different plan is required." : "The API key is suspended, usually for sustained quota abuse. Do not retry; check the account at https://dashboard.vesselapi.com.";
28
37
  } else if (error instanceof VesselNotFoundError) {
29
- message = "Resource not found. Verify the ID or parameters.";
38
+ message = `Resource not found. Verify the ID or parameters. ${error.message}`;
30
39
  } else if (error instanceof VesselRateLimitError) {
31
- message = "Rate limit exceeded. Try again later or reduce request frequency.";
40
+ message = "Rate limit exceeded. Retrying later may succeed; reduce request frequency.";
32
41
  } else if (error instanceof VesselServerError) {
33
- message = `Server error: ${error.message}`;
42
+ message = `Server error, retrying later may succeed: ${error.message}`;
34
43
  } else if (error instanceof VesselAPIError) {
35
- message = `API error: ${error.message}`;
44
+ const code = error.code ? ` (code: ${error.code})` : "";
45
+ const retry = error.statusCode >= 400 && error.statusCode < 500 ? " Do not retry without changing the request." : "";
46
+ message = `Request rejected${code}: ${error.message}.${retry}`;
36
47
  } else if (error instanceof Error) {
37
48
  message = error.message;
38
49
  } else {
@@ -54,9 +65,9 @@ function registerLocationTools(server2, client2) {
54
65
  latMax: z.number().describe("Northern boundary latitude"),
55
66
  lonMin: z.number().describe("Western boundary longitude"),
56
67
  lonMax: z.number().describe("Eastern boundary longitude"),
57
- timeFrom: z.string().optional().describe("Start time filter in RFC3339 format (defaults to 2 hours ago)"),
58
- timeTo: z.string().optional().describe("End time filter in RFC3339 format (defaults to current time)"),
59
- limit: z.number().optional().describe("Max results per page"),
68
+ timeFrom: z.string().optional().describe("Start of the time window, RFC3339. Defaults to 2 hours ago. The window may not exceed 4 hours."),
69
+ timeTo: z.string().optional().describe("End of the time window, RFC3339. Defaults to now. The window may not exceed 4 hours."),
70
+ limit: z.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
60
71
  nextToken: z.string().optional().describe("Pagination token from previous response")
61
72
  },
62
73
  async (params) => {
@@ -79,14 +90,14 @@ function registerLocationTools(server2, client2) {
79
90
  );
80
91
  server2.tool(
81
92
  "get_vessels_in_radius",
82
- "Find all vessels within a radius (in nautical miles) of a point",
93
+ "Find all vessels within a radius of a point. The radius is in METRES, not nautical miles or kilometres.",
83
94
  {
84
95
  latitude: z.number().describe("Center latitude"),
85
96
  longitude: z.number().describe("Center longitude"),
86
- radius: z.number().describe("Radius in nautical miles"),
87
- timeFrom: z.string().optional().describe("Start time filter in RFC3339 format (defaults to 2 hours ago)"),
88
- timeTo: z.string().optional().describe("End time filter in RFC3339 format (defaults to current time)"),
89
- limit: z.number().optional().describe("Max results per page"),
97
+ radius: z.number().describe("Search radius in METRES, maximum 100000 (100 km). One nautical mile is 1852 metres."),
98
+ timeFrom: z.string().optional().describe("Start of the time window, RFC3339. Defaults to 2 hours ago. The window may not exceed 4 hours."),
99
+ timeTo: z.string().optional().describe("End of the time window, RFC3339. Defaults to now. The window may not exceed 4 hours."),
100
+ limit: z.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
90
101
  nextToken: z.string().optional().describe("Pagination token from previous response")
91
102
  },
92
103
  async (params) => {
@@ -122,7 +133,7 @@ function registerPortTools(server2, client2) {
122
133
  region: z2.string().optional().describe("Geographic region (partial match)"),
123
134
  harborSize: z2.string().optional().describe("Harbor size classification"),
124
135
  harborUse: z2.string().optional().describe("Primary harbor use"),
125
- limit: z2.number().optional().describe("Max results per page"),
136
+ limit: z2.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
126
137
  nextToken: z2.string().optional().describe("Pagination token from previous response")
127
138
  },
128
139
  async (params) => {
@@ -164,11 +175,11 @@ function registerPortTools(server2, client2) {
164
175
  "Get vessels heading to a specific port within an ETA arrival window",
165
176
  {
166
177
  unlocode: z2.string().describe("UN/LOCODE of the destination port (e.g. NLRTM for Rotterdam)"),
167
- etaFrom: z2.string().describe("Start of ETA arrival window (RFC3339 format, e.g. 2026-03-07T00:00:00Z)"),
168
- etaTo: z2.string().describe("End of ETA arrival window (RFC3339 format, e.g. 2026-03-14T00:00:00Z)"),
178
+ etaFrom: z2.string().optional().describe("Start of ETA arrival window (RFC3339). Omit to default to now."),
179
+ etaTo: z2.string().optional().describe("End of ETA arrival window (RFC3339). Omit to default to 72 hours ahead."),
169
180
  timeFrom: z2.string().optional().describe("AIS position time range start (RFC3339 format)"),
170
181
  timeTo: z2.string().optional().describe("AIS position time range end (RFC3339 format)"),
171
- limit: z2.number().optional().describe("Max results per page"),
182
+ limit: z2.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
172
183
  nextToken: z2.string().optional().describe("Pagination token from previous response")
173
184
  },
174
185
  async (params) => {
@@ -189,15 +200,19 @@ function registerPortTools(server2, client2) {
189
200
  );
190
201
  server2.tool(
191
202
  "get_port_events",
192
- "Get port events (arrivals/departures) for a specific port",
203
+ "Get port events (arrivals/departures) for a specific port. Covers only the last 2 hours unless timeFrom is given.",
193
204
  {
194
205
  unlocode: z2.string().describe("UN/LOCODE of the port"),
195
- limit: z2.number().optional().describe("Max results per page"),
206
+ timeFrom: z2.string().optional().describe("Start of the time window, RFC3339. Without it the service returns only the last 2 hours."),
207
+ timeTo: z2.string().optional().describe("End of the time window, RFC3339. Defaults to now."),
208
+ limit: z2.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
196
209
  nextToken: z2.string().optional().describe("Pagination token from previous response")
197
210
  },
198
211
  async (params) => {
199
212
  try {
200
213
  const data = await client2.portEvents.byPort(params.unlocode, {
214
+ timeFrom: params.timeFrom,
215
+ timeTo: params.timeTo,
201
216
  paginationLimit: params.limit,
202
217
  paginationNextToken: params.nextToken
203
218
  });
@@ -212,12 +227,12 @@ function registerPortTools(server2, client2) {
212
227
  "Get port events (arrivals/departures) for a specific vessel",
213
228
  {
214
229
  vesselId: z2.string().describe("Vessel identifier (IMO number by default)"),
215
- idType: z2.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId"),
216
- eventType: z2.string().optional().describe("Filter by event type (arrival, departure)"),
217
- sortOrder: z2.string().optional().describe("Sort order by timestamp (asc or desc)"),
230
+ idType: z2.enum(["imo", "mmsi"]).optional().describe("Identifier type: imo (default) or mmsi"),
231
+ eventType: z2.enum(["arrival", "departure", "all"]).optional().describe("Filter by event type. Omit for both arrivals and departures"),
232
+ sortOrder: z2.enum(["asc", "desc"]).optional().describe("Sort order by timestamp"),
218
233
  timeFrom: z2.string().optional().describe("Start time (ISO 8601 format)"),
219
234
  timeTo: z2.string().optional().describe("End time (ISO 8601 format)"),
220
- limit: z2.number().optional().describe("Max results per page"),
235
+ limit: z2.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
221
236
  nextToken: z2.string().optional().describe("Pagination token from previous response")
222
237
  },
223
238
  async (params) => {
@@ -245,10 +260,10 @@ function registerPortTools(server2, client2) {
245
260
  timeTo: z2.string().optional().describe("End time (RFC3339 format)"),
246
261
  country: z2.string().optional().describe("Filter by port country (case-insensitive)"),
247
262
  unlocode: z2.string().optional().describe("Filter by port UN/LOCODE"),
248
- eventType: z2.string().optional().describe("Filter by event type (arrival, departure)"),
263
+ eventType: z2.enum(["arrival", "departure", "all"]).optional().describe("Filter by event type. Omit for both arrivals and departures"),
249
264
  vesselName: z2.string().optional().describe("Filter by vessel name (full-text search)"),
250
265
  portName: z2.string().optional().describe("Filter by port name (full-text search)"),
251
- limit: z2.number().optional().describe("Max results per page"),
266
+ limit: z2.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
252
267
  nextToken: z2.string().optional().describe("Pagination token from previous response")
253
268
  },
254
269
  async (params) => {
@@ -272,16 +287,20 @@ function registerPortTools(server2, client2) {
272
287
  );
273
288
  server2.tool(
274
289
  "search_port_events_by_port",
275
- "Search port events by port name",
290
+ "Search port events by port name. Covers only the last 2 hours unless timeFrom is given.",
276
291
  {
277
292
  portName: z2.string().describe("Port name to search for"),
278
- limit: z2.number().optional().describe("Max results per page"),
293
+ timeFrom: z2.string().optional().describe("Start of the time window, RFC3339. Without it the service returns only the last 2 hours."),
294
+ timeTo: z2.string().optional().describe("End of the time window, RFC3339. Defaults to now."),
295
+ limit: z2.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
279
296
  nextToken: z2.string().optional().describe("Pagination token from previous response")
280
297
  },
281
298
  async (params) => {
282
299
  try {
283
300
  const data = await client2.portEvents.byPorts({
284
301
  filterPortName: params.portName,
302
+ timeFrom: params.timeFrom,
303
+ timeTo: params.timeTo,
285
304
  paginationLimit: params.limit,
286
305
  paginationNextToken: params.nextToken
287
306
  });
@@ -293,16 +312,20 @@ function registerPortTools(server2, client2) {
293
312
  );
294
313
  server2.tool(
295
314
  "search_port_events_by_vessel",
296
- "Search port events by vessel name",
315
+ "Search port events by vessel name. Covers only the last 2 hours unless timeFrom is given.",
297
316
  {
298
317
  vesselName: z2.string().describe("Vessel name to search for"),
299
- limit: z2.number().optional().describe("Max results per page"),
318
+ timeFrom: z2.string().optional().describe("Start of the time window, RFC3339. Without it the service returns only the last 2 hours."),
319
+ timeTo: z2.string().optional().describe("End of the time window, RFC3339. Defaults to now."),
320
+ limit: z2.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
300
321
  nextToken: z2.string().optional().describe("Pagination token from previous response")
301
322
  },
302
323
  async (params) => {
303
324
  try {
304
325
  const data = await client2.portEvents.byVessels({
305
326
  filterVesselName: params.vesselName,
327
+ timeFrom: params.timeFrom,
328
+ timeTo: params.timeTo,
306
329
  paginationLimit: params.limit,
307
330
  paginationNextToken: params.nextToken
308
331
  });
@@ -317,7 +340,7 @@ function registerPortTools(server2, client2) {
317
340
  "Get the most recent port event (arrival or departure) for a vessel",
318
341
  {
319
342
  vesselId: z2.string().describe("Vessel identifier (IMO number by default)"),
320
- idType: z2.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
343
+ idType: z2.enum(["imo", "mmsi"]).optional().describe("Identifier type: imo (default) or mmsi")
321
344
  },
322
345
  async (params) => {
323
346
  try {
@@ -335,7 +358,7 @@ function registerPortTools(server2, client2) {
335
358
  "List global vessel emissions data with optional year filter",
336
359
  {
337
360
  period: z2.number().optional().describe("Reporting year filter (e.g. 2024)"),
338
- limit: z2.number().optional().describe("Max results per page"),
361
+ limit: z2.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
339
362
  nextToken: z2.string().optional().describe("Pagination token from previous response")
340
363
  },
341
364
  async (params) => {
@@ -353,57 +376,31 @@ function registerPortTools(server2, client2) {
353
376
  );
354
377
  }
355
378
 
356
- // src/tools/safety.ts
357
- import { z as z3 } from "zod";
358
- function registerSafetyTools(server2, client2) {
359
- server2.tool(
360
- "get_navtex_messages",
361
- "Get NAVTEX maritime safety messages (navigational warnings, weather forecasts)",
362
- {
363
- timeFrom: z3.string().optional().describe("Start time (ISO 8601 format)"),
364
- timeTo: z3.string().optional().describe("End time (ISO 8601 format)"),
365
- limit: z3.number().optional().describe("Max results per page"),
366
- nextToken: z3.string().optional().describe("Pagination token from previous response")
367
- },
368
- async (params) => {
369
- try {
370
- const data = await client2.navtex.list({
371
- timeFrom: params.timeFrom,
372
- timeTo: params.timeTo,
373
- paginationLimit: params.limit,
374
- paginationNextToken: params.nextToken
375
- });
376
- return formatResult(data);
377
- } catch (error) {
378
- return handleToolError(error);
379
- }
380
- }
381
- );
382
- }
383
-
384
379
  // src/tools/vessels.ts
385
- import { z as z4 } from "zod";
380
+ import { z as z3 } from "zod";
386
381
  function registerVesselTools(server2, client2) {
387
382
  server2.tool(
388
383
  "search_vessels",
389
- "Search for vessels by name, IMO, MMSI, flag, type, callsign, year built, class society, or owner",
384
+ "Search for vessels. Use q when you have an identifier but do not know which kind it is; use the specific filters to narrow a fleet.",
390
385
  {
391
- name: z4.string().optional().describe("Vessel name (partial match)"),
392
- imo: z4.string().optional().describe("IMO number"),
393
- mmsi: z4.string().optional().describe("MMSI number"),
394
- flag: z4.string().optional().describe("Flag state (ISO country code)"),
395
- vesselType: z4.string().optional().describe("Vessel type"),
396
- callsign: z4.string().optional().describe("Radio callsign"),
397
- yearBuiltMin: z4.number().optional().describe("Minimum year built"),
398
- yearBuiltMax: z4.number().optional().describe("Maximum year built"),
399
- classSociety: z4.string().optional().describe("Classification society (case-insensitive)"),
400
- owner: z4.string().optional().describe("Owner name (partial match, case-insensitive)"),
401
- limit: z4.number().optional().describe("Max results per page"),
402
- nextToken: z4.string().optional().describe("Pagination token from previous response")
386
+ q: z3.string().optional().describe("Free-text search across name, IMO, MMSI, ENI and callsign. Use this when the type of identifier is unknown."),
387
+ name: z3.string().optional().describe("Vessel name (partial match)"),
388
+ imo: z3.string().optional().describe("IMO number"),
389
+ mmsi: z3.string().optional().describe("MMSI number"),
390
+ eni: z3.string().optional().describe("ENI number, used for inland waterway vessels"),
391
+ flag: z3.string().optional().describe("Flag state (ISO country code)"),
392
+ vesselType: z3.string().optional().describe("Vessel type"),
393
+ callsign: z3.string().optional().describe("Radio callsign"),
394
+ yearBuiltMin: z3.number().optional().describe("Minimum year built"),
395
+ yearBuiltMax: z3.number().optional().describe("Maximum year built"),
396
+ limit: z3.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
397
+ nextToken: z3.string().optional().describe("Pagination token from previous response")
403
398
  },
404
399
  async (params) => {
405
400
  try {
406
401
  const data = await client2.search.vessels({
402
+ q: params.q,
403
+ filterEni: params.eni,
407
404
  filterName: params.name,
408
405
  filterImo: params.imo,
409
406
  filterMmsi: params.mmsi,
@@ -412,8 +409,6 @@ function registerVesselTools(server2, client2) {
412
409
  filterCallsign: params.callsign,
413
410
  filterYearBuiltMin: params.yearBuiltMin,
414
411
  filterYearBuiltMax: params.yearBuiltMax,
415
- filterClassSociety: params.classSociety,
416
- filterOwner: params.owner,
417
412
  paginationLimit: params.limit,
418
413
  paginationNextToken: params.nextToken
419
414
  });
@@ -427,8 +422,8 @@ function registerVesselTools(server2, client2) {
427
422
  "get_vessel",
428
423
  "Get detailed information about a specific vessel",
429
424
  {
430
- vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
431
- idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
425
+ vesselId: z3.string().describe("Vessel identifier (IMO number by default)"),
426
+ idType: z3.enum(["imo", "mmsi"]).optional().describe("Identifier type: imo (default) or mmsi")
432
427
  },
433
428
  async (params) => {
434
429
  try {
@@ -445,12 +440,14 @@ function registerVesselTools(server2, client2) {
445
440
  "get_vessel_position",
446
441
  "Get the current position of a vessel (latitude, longitude, speed, heading)",
447
442
  {
448
- vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
449
- idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
443
+ vesselId: z3.string().describe("Vessel identifier (IMO number by default)"),
444
+ idType: z3.enum(["imo", "mmsi"]).optional().describe("Identifier type: imo (default) or mmsi"),
445
+ sat: z3.boolean().optional().describe("Fall back to a satellite position when no recent terrestrial one exists. Charged per call against a prepaid balance, so use it only when a stored position is genuinely insufficient.")
450
446
  },
451
447
  async (params) => {
452
448
  try {
453
449
  const data = await client2.vessels.position(params.vesselId, {
450
+ filterSat: params.sat,
454
451
  filterIdType: params.idType
455
452
  });
456
453
  return formatResult(data);
@@ -463,8 +460,8 @@ function registerVesselTools(server2, client2) {
463
460
  "get_vessel_eta",
464
461
  "Get the estimated time of arrival for a vessel",
465
462
  {
466
- vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
467
- idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
463
+ vesselId: z3.string().describe("Vessel identifier (IMO number by default)"),
464
+ idType: z3.enum(["imo", "mmsi"]).optional().describe("Identifier type: imo (default) or mmsi")
468
465
  },
469
466
  async (params) => {
470
467
  try {
@@ -477,50 +474,14 @@ function registerVesselTools(server2, client2) {
477
474
  }
478
475
  }
479
476
  );
480
- server2.tool(
481
- "get_vessel_classification",
482
- "Get the classification details for a vessel (class society, surveys, hull info)",
483
- {
484
- vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
485
- idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
486
- },
487
- async (params) => {
488
- try {
489
- const data = await client2.vessels.classification(params.vesselId, {
490
- filterIdType: params.idType
491
- });
492
- return formatResult(data);
493
- } catch (error) {
494
- return handleToolError(error);
495
- }
496
- }
497
- );
498
- server2.tool(
499
- "get_vessel_ownership",
500
- "Get the ownership details for a vessel (owner, manager, operator)",
501
- {
502
- vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
503
- idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
504
- },
505
- async (params) => {
506
- try {
507
- const data = await client2.vessels.ownership(params.vesselId, {
508
- filterIdType: params.idType
509
- });
510
- return formatResult(data);
511
- } catch (error) {
512
- return handleToolError(error);
513
- }
514
- }
515
- );
516
477
  server2.tool(
517
478
  "get_vessel_emissions",
518
479
  "Get emissions data for a vessel (CO2, fuel consumption)",
519
480
  {
520
- vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
521
- idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId"),
522
- limit: z4.number().optional().describe("Max results per page"),
523
- nextToken: z4.string().optional().describe("Pagination token from previous response")
481
+ vesselId: z3.string().describe("Vessel identifier (IMO number by default)"),
482
+ idType: z3.enum(["imo", "mmsi"]).optional().describe("Identifier type: imo (default) or mmsi"),
483
+ limit: z3.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
484
+ nextToken: z3.string().optional().describe("Pagination token from previous response")
524
485
  },
525
486
  async (params) => {
526
487
  try {
@@ -535,36 +496,14 @@ function registerVesselTools(server2, client2) {
535
496
  }
536
497
  }
537
498
  );
538
- server2.tool(
539
- "get_vessel_inspections",
540
- "Get port state control inspections for a vessel",
541
- {
542
- vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
543
- idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId"),
544
- limit: z4.number().optional().describe("Max results per page"),
545
- nextToken: z4.string().optional().describe("Pagination token from previous response")
546
- },
547
- async (params) => {
548
- try {
549
- const data = await client2.vessels.inspections(params.vesselId, {
550
- filterIdType: params.idType,
551
- paginationLimit: params.limit,
552
- paginationNextToken: params.nextToken
553
- });
554
- return formatResult(data);
555
- } catch (error) {
556
- return handleToolError(error);
557
- }
558
- }
559
- );
560
499
  server2.tool(
561
500
  "get_vessel_casualties",
562
501
  "Get marine casualty records for a vessel",
563
502
  {
564
- vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
565
- idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId"),
566
- limit: z4.number().optional().describe("Max results per page"),
567
- nextToken: z4.string().optional().describe("Pagination token from previous response")
503
+ vesselId: z3.string().describe("Vessel identifier (IMO number by default)"),
504
+ idType: z3.enum(["imo", "mmsi"]).optional().describe("Identifier type: imo (default) or mmsi"),
505
+ limit: z3.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
506
+ nextToken: z3.string().optional().describe("Pagination token from previous response")
568
507
  },
569
508
  async (params) => {
570
509
  try {
@@ -579,35 +518,16 @@ function registerVesselTools(server2, client2) {
579
518
  }
580
519
  }
581
520
  );
582
- server2.tool(
583
- "get_vessel_inspection_detail",
584
- "Get detailed information about a specific vessel inspection",
585
- {
586
- vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
587
- detailId: z4.string().describe("Inspection detail ID"),
588
- idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
589
- },
590
- async (params) => {
591
- try {
592
- const data = await client2.vessels.inspectionDetail(params.vesselId, params.detailId, {
593
- filterIdType: params.idType
594
- });
595
- return formatResult(data);
596
- } catch (error) {
597
- return handleToolError(error);
598
- }
599
- }
600
- );
601
521
  server2.tool(
602
522
  "get_vessel_positions_batch",
603
523
  "Get positions for multiple vessels at once by MMSI or IMO numbers",
604
524
  {
605
- ids: z4.string().describe("Comma-separated list of MMSI or IMO numbers"),
606
- idType: z4.string().optional().describe("Identifier type: imo (default) or mmsi"),
607
- timeFrom: z4.string().optional().describe("Start time filter in RFC3339 format (defaults to 2 hours ago)"),
608
- timeTo: z4.string().optional().describe("End time filter in RFC3339 format (defaults to current time)"),
609
- limit: z4.number().optional().describe("Max results per page"),
610
- nextToken: z4.string().optional().describe("Pagination token from previous response")
525
+ ids: z3.string().describe("Comma-separated list of MMSI or IMO numbers"),
526
+ idType: z3.enum(["imo", "mmsi"]).optional().describe("Identifier type: imo (default) or mmsi"),
527
+ timeFrom: z3.string().optional().describe("Start time filter in RFC3339 format (defaults to 2 hours ago)"),
528
+ timeTo: z3.string().optional().describe("End time filter in RFC3339 format (defaults to current time)"),
529
+ limit: z3.number().int().min(1).max(50).optional().describe("Results per page, 1 to 50. Defaults to 20."),
530
+ nextToken: z3.string().optional().describe("Pagination token from previous response")
611
531
  },
612
532
  async (params) => {
613
533
  try {
@@ -628,15 +548,20 @@ function registerVesselTools(server2, client2) {
628
548
  }
629
549
 
630
550
  // src/index.ts
631
- var client = new VesselClient();
551
+ if (!process.env.VESSELAPI_API_KEY) {
552
+ process.stderr.write(
553
+ "vesselapi-mcp: VESSELAPI_API_KEY is not set. Add it to the env block of your MCP client configuration. Keys are issued at https://dashboard.vesselapi.com\n"
554
+ );
555
+ process.exit(1);
556
+ }
557
+ var client = new VesselClient(void 0, { userAgent: `vesselapi-mcp/${VERSION}` });
632
558
  var server = new McpServer({
633
559
  name: "vesselapi",
634
- version: "1.0.0"
560
+ version: VERSION
635
561
  });
636
562
  registerVesselTools(server, client);
637
563
  registerPortTools(server, client);
638
564
  registerLocationTools(server, client);
639
- registerSafetyTools(server, client);
640
565
  var transport = new StdioServerTransport();
641
566
  await server.connect(transport);
642
567
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/tools/location.ts","../src/errors.ts","../src/tools/ports.ts","../src/tools/safety.ts","../src/tools/vessels.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { VesselClient } from \"vesselapi\";\nimport { registerLocationTools } from \"./tools/location.js\";\nimport { registerPortTools } from \"./tools/ports.js\";\nimport { registerSafetyTools } from \"./tools/safety.js\";\nimport { registerVesselTools } from \"./tools/vessels.js\";\n\nconst client = new VesselClient();\n\nconst server = new McpServer({\n name: \"vesselapi\",\n version: \"1.0.0\",\n});\n\nregisterVesselTools(server, client);\nregisterPortTools(server, client);\nregisterLocationTools(server, client);\nregisterSafetyTools(server, client);\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { VesselClient } from \"vesselapi\";\nimport { z } from \"zod\";\nimport { formatResult, handleToolError } from \"../errors.js\";\n\nexport function registerLocationTools(server: McpServer, client: VesselClient): void {\n server.tool(\n \"get_vessels_in_area\",\n \"Find all vessels within a rectangular bounding box (latitude/longitude)\",\n {\n latMin: z.number().describe(\"Southern boundary latitude\"),\n latMax: z.number().describe(\"Northern boundary latitude\"),\n lonMin: z.number().describe(\"Western boundary longitude\"),\n lonMax: z.number().describe(\"Eastern boundary longitude\"),\n timeFrom: z.string().optional().describe(\"Start time filter in RFC3339 format (defaults to 2 hours ago)\"),\n timeTo: z.string().optional().describe(\"End time filter in RFC3339 format (defaults to current time)\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.location.vesselsBoundingBox({\n latMin: params.latMin,\n latMax: params.latMax,\n lonMin: params.lonMin,\n lonMax: params.lonMax,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessels_in_radius\",\n \"Find all vessels within a radius (in nautical miles) of a point\",\n {\n latitude: z.number().describe(\"Center latitude\"),\n longitude: z.number().describe(\"Center longitude\"),\n radius: z.number().describe(\"Radius in nautical miles\"),\n timeFrom: z.string().optional().describe(\"Start time filter in RFC3339 format (defaults to 2 hours ago)\"),\n timeTo: z.string().optional().describe(\"End time filter in RFC3339 format (defaults to current time)\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.location.vesselsRadius({\n latitude: params.latitude,\n longitude: params.longitude,\n radius: params.radius,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n}\n","import {\n VesselAPIError,\n VesselAuthError,\n VesselNotFoundError,\n VesselRateLimitError,\n VesselServerError,\n} from \"vesselapi\";\n\nexport function formatResult(data: unknown): { content: { type: \"text\"; text: string }[] } {\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n}\n\nexport function handleToolError(error: unknown): { isError: true; content: { type: \"text\"; text: string }[] } {\n let message: string;\n\n if (error instanceof VesselAuthError) {\n message = \"Authentication failed. Check your VESSELAPI_API_KEY.\";\n } else if (error instanceof VesselNotFoundError) {\n message = \"Resource not found. Verify the ID or parameters.\";\n } else if (error instanceof VesselRateLimitError) {\n message = \"Rate limit exceeded. Try again later or reduce request frequency.\";\n } else if (error instanceof VesselServerError) {\n message = `Server error: ${error.message}`;\n } else if (error instanceof VesselAPIError) {\n message = `API error: ${error.message}`;\n } else if (error instanceof Error) {\n message = error.message;\n } else {\n message = String(error);\n }\n\n return {\n isError: true,\n content: [{ type: \"text\", text: message }],\n };\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { VesselClient } from \"vesselapi\";\nimport { z } from \"zod\";\nimport { formatResult, handleToolError } from \"../errors.js\";\n\nexport function registerPortTools(server: McpServer, client: VesselClient): void {\n server.tool(\n \"search_ports\",\n \"Search for ports by name, country, type, size, region, harbor size, or harbor use\",\n {\n name: z.string().optional().describe(\"Port name (partial match)\"),\n country: z.string().optional().describe(\"Country (ISO code)\"),\n portType: z.string().optional().describe(\"Port type classification\"),\n size: z.string().optional().describe(\"Port size classification\"),\n region: z.string().optional().describe(\"Geographic region (partial match)\"),\n harborSize: z.string().optional().describe(\"Harbor size classification\"),\n harborUse: z.string().optional().describe(\"Primary harbor use\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.search.ports({\n filterName: params.name,\n filterCountry: params.country,\n filterPortType: params.portType,\n filterSize: params.size,\n filterRegion: params.region,\n filterHarborSize: params.harborSize,\n filterHarborUse: params.harborUse,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_port\",\n \"Get detailed information about a specific port by UN/LOCODE\",\n {\n unlocode: z.string().describe(\"UN/LOCODE of the port (e.g. NLRTM for Rotterdam)\"),\n },\n async (params) => {\n try {\n const data = await client.ports.get(params.unlocode);\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_port_inbound\",\n \"Get vessels heading to a specific port within an ETA arrival window\",\n {\n unlocode: z.string().describe(\"UN/LOCODE of the destination port (e.g. NLRTM for Rotterdam)\"),\n etaFrom: z.string().describe(\"Start of ETA arrival window (RFC3339 format, e.g. 2026-03-07T00:00:00Z)\"),\n etaTo: z.string().describe(\"End of ETA arrival window (RFC3339 format, e.g. 2026-03-14T00:00:00Z)\"),\n timeFrom: z.string().optional().describe(\"AIS position time range start (RFC3339 format)\"),\n timeTo: z.string().optional().describe(\"AIS position time range end (RFC3339 format)\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.ports.inbound(params.unlocode, {\n filterEtaFrom: params.etaFrom,\n filterEtaTo: params.etaTo,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_port_events\",\n \"Get port events (arrivals/departures) for a specific port\",\n {\n unlocode: z.string().describe(\"UN/LOCODE of the port\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.byPort(params.unlocode, {\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_port_events_by_vessel\",\n \"Get port events (arrivals/departures) for a specific vessel\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default), mmsi, or vesselId\"),\n eventType: z.string().optional().describe(\"Filter by event type (arrival, departure)\"),\n sortOrder: z.string().optional().describe(\"Sort order by timestamp (asc or desc)\"),\n timeFrom: z.string().optional().describe(\"Start time (ISO 8601 format)\"),\n timeTo: z.string().optional().describe(\"End time (ISO 8601 format)\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.byVessel(params.vesselId, {\n filterIdType: params.idType,\n filterEventType: params.eventType,\n filterSortOrder: params.sortOrder,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"list_port_events\",\n \"List port events (arrivals/departures) globally with optional filters for time, country, port, vessel, or event type\",\n {\n timeFrom: z.string().optional().describe(\"Start time (RFC3339 format)\"),\n timeTo: z.string().optional().describe(\"End time (RFC3339 format)\"),\n country: z.string().optional().describe(\"Filter by port country (case-insensitive)\"),\n unlocode: z.string().optional().describe(\"Filter by port UN/LOCODE\"),\n eventType: z.string().optional().describe(\"Filter by event type (arrival, departure)\"),\n vesselName: z.string().optional().describe(\"Filter by vessel name (full-text search)\"),\n portName: z.string().optional().describe(\"Filter by port name (full-text search)\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.list({\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n filterCountry: params.country,\n filterUnlocode: params.unlocode,\n filterEventType: params.eventType,\n filterVesselName: params.vesselName,\n filterPortName: params.portName,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"search_port_events_by_port\",\n \"Search port events by port name\",\n {\n portName: z.string().describe(\"Port name to search for\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.byPorts({\n filterPortName: params.portName,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"search_port_events_by_vessel\",\n \"Search port events by vessel name\",\n {\n vesselName: z.string().describe(\"Vessel name to search for\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.byVessels({\n filterVesselName: params.vesselName,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_last_port_event\",\n \"Get the most recent port event (arrival or departure) for a vessel\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default), mmsi, or vesselId\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.lastByVessel(params.vesselId, {\n filterIdType: params.idType,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"list_emissions\",\n \"List global vessel emissions data with optional year filter\",\n {\n period: z.number().optional().describe(\"Reporting year filter (e.g. 2024)\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.emissions.list({\n filterPeriod: params.period,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { VesselClient } from \"vesselapi\";\nimport { z } from \"zod\";\nimport { formatResult, handleToolError } from \"../errors.js\";\n\nexport function registerSafetyTools(server: McpServer, client: VesselClient): void {\n server.tool(\n \"get_navtex_messages\",\n \"Get NAVTEX maritime safety messages (navigational warnings, weather forecasts)\",\n {\n timeFrom: z.string().optional().describe(\"Start time (ISO 8601 format)\"),\n timeTo: z.string().optional().describe(\"End time (ISO 8601 format)\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.navtex.list({\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { VesselClient } from \"vesselapi\";\nimport { z } from \"zod\";\nimport { formatResult, handleToolError } from \"../errors.js\";\n\nexport function registerVesselTools(server: McpServer, client: VesselClient): void {\n server.tool(\n \"search_vessels\",\n \"Search for vessels by name, IMO, MMSI, flag, type, callsign, year built, class society, or owner\",\n {\n name: z.string().optional().describe(\"Vessel name (partial match)\"),\n imo: z.string().optional().describe(\"IMO number\"),\n mmsi: z.string().optional().describe(\"MMSI number\"),\n flag: z.string().optional().describe(\"Flag state (ISO country code)\"),\n vesselType: z.string().optional().describe(\"Vessel type\"),\n callsign: z.string().optional().describe(\"Radio callsign\"),\n yearBuiltMin: z.number().optional().describe(\"Minimum year built\"),\n yearBuiltMax: z.number().optional().describe(\"Maximum year built\"),\n classSociety: z.string().optional().describe(\"Classification society (case-insensitive)\"),\n owner: z.string().optional().describe(\"Owner name (partial match, case-insensitive)\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.search.vessels({\n filterName: params.name,\n filterImo: params.imo,\n filterMmsi: params.mmsi,\n filterFlag: params.flag,\n filterVesselType: params.vesselType,\n filterCallsign: params.callsign,\n filterYearBuiltMin: params.yearBuiltMin,\n filterYearBuiltMax: params.yearBuiltMax,\n filterClassSociety: params.classSociety,\n filterOwner: params.owner,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel\",\n \"Get detailed information about a specific vessel\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default), mmsi, or vesselId\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.get(params.vesselId, {\n filterIdType: params.idType,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_position\",\n \"Get the current position of a vessel (latitude, longitude, speed, heading)\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default), mmsi, or vesselId\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.position(params.vesselId, {\n filterIdType: params.idType,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_eta\",\n \"Get the estimated time of arrival for a vessel\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default), mmsi, or vesselId\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.eta(params.vesselId, {\n filterIdType: params.idType,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_classification\",\n \"Get the classification details for a vessel (class society, surveys, hull info)\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default), mmsi, or vesselId\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.classification(params.vesselId, {\n filterIdType: params.idType,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_ownership\",\n \"Get the ownership details for a vessel (owner, manager, operator)\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default), mmsi, or vesselId\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.ownership(params.vesselId, {\n filterIdType: params.idType,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_emissions\",\n \"Get emissions data for a vessel (CO2, fuel consumption)\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default), mmsi, or vesselId\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.emissions(params.vesselId, {\n filterIdType: params.idType,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_inspections\",\n \"Get port state control inspections for a vessel\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default), mmsi, or vesselId\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.inspections(params.vesselId, {\n filterIdType: params.idType,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_casualties\",\n \"Get marine casualty records for a vessel\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default), mmsi, or vesselId\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.casualties(params.vesselId, {\n filterIdType: params.idType,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_inspection_detail\",\n \"Get detailed information about a specific vessel inspection\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n detailId: z.string().describe(\"Inspection detail ID\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default), mmsi, or vesselId\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.inspectionDetail(params.vesselId, params.detailId, {\n filterIdType: params.idType,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_positions_batch\",\n \"Get positions for multiple vessels at once by MMSI or IMO numbers\",\n {\n ids: z.string().describe(\"Comma-separated list of MMSI or IMO numbers\"),\n idType: z.string().optional().describe(\"Identifier type: imo (default) or mmsi\"),\n timeFrom: z.string().optional().describe(\"Start time filter in RFC3339 format (defaults to 2 hours ago)\"),\n timeTo: z.string().optional().describe(\"End time filter in RFC3339 format (defaults to current time)\"),\n limit: z.number().optional().describe(\"Max results per page\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.positions({\n filterIds: params.ids,\n filterIdType: params.idType,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n}\n"],"mappings":"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","names":["server","client","z","server","client","z","z","server","client","z","z","server","client","z"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/version.ts","../src/tools/location.ts","../src/errors.ts","../src/tools/ports.ts","../src/tools/vessels.ts"],"sourcesContent":["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { VesselClient } from \"vesselapi\";\n\nimport { VERSION } from \"./version.js\";\nimport { registerLocationTools } from \"./tools/location.js\";\nimport { registerPortTools } from \"./tools/ports.js\";\nimport { registerVesselTools } from \"./tools/vessels.js\";\n\n// Fail with a readable line rather than a stack trace. Without a key the client\n// throws while this module is still evaluating, so the transport never connects\n// and the calling application sees the process die mid-handshake with no reason.\nif (!process.env.VESSELAPI_API_KEY) {\n process.stderr.write(\n \"vesselapi-mcp: VESSELAPI_API_KEY is not set. Add it to the env block of your \" +\n \"MCP client configuration. Keys are issued at https://dashboard.vesselapi.com\\n\",\n );\n process.exit(1);\n}\n\nconst client = new VesselClient(undefined, { userAgent: `vesselapi-mcp/${VERSION}` });\n\nconst server = new McpServer({\n name: \"vesselapi\",\n version: VERSION,\n});\n\nregisterVesselTools(server, client);\nregisterPortTools(server, client);\nregisterLocationTools(server, client);\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n","// Version advertised by the McpServer handshake. package.json and server.json\n// carry their own copies and are NOT derived from this — keep all three in step\n// when bumping.\nexport const VERSION = \"2.0.0\";\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { VesselClient } from \"vesselapi\";\nimport { z } from \"zod\";\nimport { formatResult, handleToolError } from \"../errors.js\";\n\nexport function registerLocationTools(server: McpServer, client: VesselClient): void {\n server.tool(\n \"get_vessels_in_area\",\n \"Find all vessels within a rectangular bounding box (latitude/longitude)\",\n {\n latMin: z.number().describe(\"Southern boundary latitude\"),\n latMax: z.number().describe(\"Northern boundary latitude\"),\n lonMin: z.number().describe(\"Western boundary longitude\"),\n lonMax: z.number().describe(\"Eastern boundary longitude\"),\n timeFrom: z.string().optional().describe(\"Start of the time window, RFC3339. Defaults to 2 hours ago. The window may not exceed 4 hours.\"),\n timeTo: z.string().optional().describe(\"End of the time window, RFC3339. Defaults to now. The window may not exceed 4 hours.\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.location.vesselsBoundingBox({\n latMin: params.latMin,\n latMax: params.latMax,\n lonMin: params.lonMin,\n lonMax: params.lonMax,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessels_in_radius\",\n \"Find all vessels within a radius of a point. The radius is in METRES, not nautical miles or kilometres.\",\n {\n latitude: z.number().describe(\"Center latitude\"),\n longitude: z.number().describe(\"Center longitude\"),\n radius: z.number().describe(\"Search radius in METRES, maximum 100000 (100 km). One nautical mile is 1852 metres.\"),\n timeFrom: z.string().optional().describe(\"Start of the time window, RFC3339. Defaults to 2 hours ago. The window may not exceed 4 hours.\"),\n timeTo: z.string().optional().describe(\"End of the time window, RFC3339. Defaults to now. The window may not exceed 4 hours.\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.location.vesselsRadius({\n latitude: params.latitude,\n longitude: params.longitude,\n radius: params.radius,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n}\n","import {\n VesselAPIError,\n VesselAuthError,\n VesselForbiddenError,\n VesselNotFoundError,\n VesselPaymentRequiredError,\n VesselRateLimitError,\n VesselServerError,\n} from \"vesselapi\";\n\nexport function formatResult(data: unknown): { content: { type: \"text\"; text: string }[] } {\n return {\n content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }],\n };\n}\n\n/**\n * Turn an SDK error into something a model can act on.\n *\n * The distinction that matters to a caller is whether retrying can ever help.\n * A 4xx is the request's fault and will fail identically until the caller\n * changes something, so each one says what to change. Only 429 and 5xx are\n * worth trying again. Where the API supplies a machine-readable `code` it is\n * included, since the prose message is free-form and may be reworded.\n */\nexport function handleToolError(error: unknown): { isError: true; content: { type: \"text\"; text: string }[] } {\n let message: string;\n\n if (error instanceof VesselAuthError) {\n message = \"Authentication failed. Check your VESSELAPI_API_KEY. Do not retry.\";\n } else if (error instanceof VesselPaymentRequiredError) {\n message =\n \"Out of satellite credits, and no stored position was available to fall back on. \" +\n \"Retry without the satellite option to use stored data, or top up the balance at \" +\n \"https://dashboard.vesselapi.com. Retrying the same request will not help.\";\n } else if (error instanceof VesselForbiddenError) {\n message =\n error.code === \"feature_not_available\"\n ? \"This endpoint is not included in the current plan. Do not retry; a different plan is required.\"\n : \"The API key is suspended, usually for sustained quota abuse. Do not retry; \" +\n \"check the account at https://dashboard.vesselapi.com.\";\n } else if (error instanceof VesselNotFoundError) {\n message = `Resource not found. Verify the ID or parameters. ${error.message}`;\n } else if (error instanceof VesselRateLimitError) {\n message = \"Rate limit exceeded. Retrying later may succeed; reduce request frequency.\";\n } else if (error instanceof VesselServerError) {\n message = `Server error, retrying later may succeed: ${error.message}`;\n } else if (error instanceof VesselAPIError) {\n // Remaining 4xx: the request itself is wrong. Name the code so the model can\n // tell an unparseable time range from an out-of-range coordinate.\n const code = error.code ? ` (code: ${error.code})` : \"\";\n const retry = error.statusCode >= 400 && error.statusCode < 500 ? \" Do not retry without changing the request.\" : \"\";\n message = `Request rejected${code}: ${error.message}.${retry}`;\n } else if (error instanceof Error) {\n message = error.message;\n } else {\n message = String(error);\n }\n\n return {\n isError: true,\n content: [{ type: \"text\", text: message }],\n };\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { VesselClient } from \"vesselapi\";\nimport { z } from \"zod\";\nimport { formatResult, handleToolError } from \"../errors.js\";\n\nexport function registerPortTools(server: McpServer, client: VesselClient): void {\n server.tool(\n \"search_ports\",\n \"Search for ports by name, country, type, size, region, harbor size, or harbor use\",\n {\n name: z.string().optional().describe(\"Port name (partial match)\"),\n country: z.string().optional().describe(\"Country (ISO code)\"),\n portType: z.string().optional().describe(\"Port type classification\"),\n size: z.string().optional().describe(\"Port size classification\"),\n region: z.string().optional().describe(\"Geographic region (partial match)\"),\n harborSize: z.string().optional().describe(\"Harbor size classification\"),\n harborUse: z.string().optional().describe(\"Primary harbor use\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.search.ports({\n filterName: params.name,\n filterCountry: params.country,\n filterPortType: params.portType,\n filterSize: params.size,\n filterRegion: params.region,\n filterHarborSize: params.harborSize,\n filterHarborUse: params.harborUse,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_port\",\n \"Get detailed information about a specific port by UN/LOCODE\",\n {\n unlocode: z.string().describe(\"UN/LOCODE of the port (e.g. NLRTM for Rotterdam)\"),\n },\n async (params) => {\n try {\n const data = await client.ports.get(params.unlocode);\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_port_inbound\",\n \"Get vessels heading to a specific port within an ETA arrival window\",\n {\n unlocode: z.string().describe(\"UN/LOCODE of the destination port (e.g. NLRTM for Rotterdam)\"),\n etaFrom: z.string().optional().describe(\"Start of ETA arrival window (RFC3339). Omit to default to now.\"),\n etaTo: z.string().optional().describe(\"End of ETA arrival window (RFC3339). Omit to default to 72 hours ahead.\"),\n timeFrom: z.string().optional().describe(\"AIS position time range start (RFC3339 format)\"),\n timeTo: z.string().optional().describe(\"AIS position time range end (RFC3339 format)\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.ports.inbound(params.unlocode, {\n filterEtaFrom: params.etaFrom,\n filterEtaTo: params.etaTo,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_port_events\",\n \"Get port events (arrivals/departures) for a specific port. Covers only the last 2 hours unless timeFrom is given.\",\n {\n unlocode: z.string().describe(\"UN/LOCODE of the port\"),\n timeFrom: z.string().optional().describe(\"Start of the time window, RFC3339. Without it the service returns only the last 2 hours.\"),\n timeTo: z.string().optional().describe(\"End of the time window, RFC3339. Defaults to now.\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.byPort(params.unlocode, {\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_port_events_by_vessel\",\n \"Get port events (arrivals/departures) for a specific vessel\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.enum([\"imo\", \"mmsi\"]).optional().describe(\"Identifier type: imo (default) or mmsi\"),\n eventType: z.enum([\"arrival\", \"departure\", \"all\"]).optional().describe(\"Filter by event type. Omit for both arrivals and departures\"),\n sortOrder: z.enum([\"asc\", \"desc\"]).optional().describe(\"Sort order by timestamp\"),\n timeFrom: z.string().optional().describe(\"Start time (ISO 8601 format)\"),\n timeTo: z.string().optional().describe(\"End time (ISO 8601 format)\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.byVessel(params.vesselId, {\n filterIdType: params.idType,\n filterEventType: params.eventType,\n filterSortOrder: params.sortOrder,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"list_port_events\",\n \"List port events (arrivals/departures) globally with optional filters for time, country, port, vessel, or event type\",\n {\n timeFrom: z.string().optional().describe(\"Start time (RFC3339 format)\"),\n timeTo: z.string().optional().describe(\"End time (RFC3339 format)\"),\n country: z.string().optional().describe(\"Filter by port country (case-insensitive)\"),\n unlocode: z.string().optional().describe(\"Filter by port UN/LOCODE\"),\n eventType: z.enum([\"arrival\", \"departure\", \"all\"]).optional().describe(\"Filter by event type. Omit for both arrivals and departures\"),\n vesselName: z.string().optional().describe(\"Filter by vessel name (full-text search)\"),\n portName: z.string().optional().describe(\"Filter by port name (full-text search)\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.list({\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n filterCountry: params.country,\n filterUnlocode: params.unlocode,\n filterEventType: params.eventType,\n filterVesselName: params.vesselName,\n filterPortName: params.portName,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"search_port_events_by_port\",\n \"Search port events by port name. Covers only the last 2 hours unless timeFrom is given.\",\n {\n portName: z.string().describe(\"Port name to search for\"),\n timeFrom: z.string().optional().describe(\"Start of the time window, RFC3339. Without it the service returns only the last 2 hours.\"),\n timeTo: z.string().optional().describe(\"End of the time window, RFC3339. Defaults to now.\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.byPorts({\n filterPortName: params.portName,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"search_port_events_by_vessel\",\n \"Search port events by vessel name. Covers only the last 2 hours unless timeFrom is given.\",\n {\n vesselName: z.string().describe(\"Vessel name to search for\"),\n timeFrom: z.string().optional().describe(\"Start of the time window, RFC3339. Without it the service returns only the last 2 hours.\"),\n timeTo: z.string().optional().describe(\"End of the time window, RFC3339. Defaults to now.\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.byVessels({\n filterVesselName: params.vesselName,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_last_port_event\",\n \"Get the most recent port event (arrival or departure) for a vessel\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.enum([\"imo\", \"mmsi\"]).optional().describe(\"Identifier type: imo (default) or mmsi\"),\n },\n async (params) => {\n try {\n const data = await client.portEvents.lastByVessel(params.vesselId, {\n filterIdType: params.idType,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"list_emissions\",\n \"List global vessel emissions data with optional year filter\",\n {\n period: z.number().optional().describe(\"Reporting year filter (e.g. 2024)\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.emissions.list({\n filterPeriod: params.period,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { VesselClient } from \"vesselapi\";\nimport { z } from \"zod\";\nimport { formatResult, handleToolError } from \"../errors.js\";\n\nexport function registerVesselTools(server: McpServer, client: VesselClient): void {\n server.tool(\n \"search_vessels\",\n \"Search for vessels. Use q when you have an identifier but do not know which kind it is; use the specific filters to narrow a fleet.\",\n {\n q: z.string().optional().describe(\"Free-text search across name, IMO, MMSI, ENI and callsign. Use this when the type of identifier is unknown.\"),\n name: z.string().optional().describe(\"Vessel name (partial match)\"),\n imo: z.string().optional().describe(\"IMO number\"),\n mmsi: z.string().optional().describe(\"MMSI number\"),\n eni: z.string().optional().describe(\"ENI number, used for inland waterway vessels\"),\n flag: z.string().optional().describe(\"Flag state (ISO country code)\"),\n vesselType: z.string().optional().describe(\"Vessel type\"),\n callsign: z.string().optional().describe(\"Radio callsign\"),\n yearBuiltMin: z.number().optional().describe(\"Minimum year built\"),\n yearBuiltMax: z.number().optional().describe(\"Maximum year built\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.search.vessels({\n q: params.q,\n filterEni: params.eni,\n filterName: params.name,\n filterImo: params.imo,\n filterMmsi: params.mmsi,\n filterFlag: params.flag,\n filterVesselType: params.vesselType,\n filterCallsign: params.callsign,\n filterYearBuiltMin: params.yearBuiltMin,\n filterYearBuiltMax: params.yearBuiltMax,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel\",\n \"Get detailed information about a specific vessel\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.enum([\"imo\", \"mmsi\"]).optional().describe(\"Identifier type: imo (default) or mmsi\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.get(params.vesselId, {\n filterIdType: params.idType,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_position\",\n \"Get the current position of a vessel (latitude, longitude, speed, heading)\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.enum([\"imo\", \"mmsi\"]).optional().describe(\"Identifier type: imo (default) or mmsi\"),\n sat: z.boolean().optional().describe(\"Fall back to a satellite position when no recent terrestrial one exists. Charged per call against a prepaid balance, so use it only when a stored position is genuinely insufficient.\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.position(params.vesselId, {\n filterSat: params.sat,\n filterIdType: params.idType,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_eta\",\n \"Get the estimated time of arrival for a vessel\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.enum([\"imo\", \"mmsi\"]).optional().describe(\"Identifier type: imo (default) or mmsi\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.eta(params.vesselId, {\n filterIdType: params.idType,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_emissions\",\n \"Get emissions data for a vessel (CO2, fuel consumption)\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.enum([\"imo\", \"mmsi\"]).optional().describe(\"Identifier type: imo (default) or mmsi\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.emissions(params.vesselId, {\n filterIdType: params.idType,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_casualties\",\n \"Get marine casualty records for a vessel\",\n {\n vesselId: z.string().describe(\"Vessel identifier (IMO number by default)\"),\n idType: z.enum([\"imo\", \"mmsi\"]).optional().describe(\"Identifier type: imo (default) or mmsi\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.casualties(params.vesselId, {\n filterIdType: params.idType,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n\n server.tool(\n \"get_vessel_positions_batch\",\n \"Get positions for multiple vessels at once by MMSI or IMO numbers\",\n {\n ids: z.string().describe(\"Comma-separated list of MMSI or IMO numbers\"),\n idType: z.enum([\"imo\", \"mmsi\"]).optional().describe(\"Identifier type: imo (default) or mmsi\"),\n timeFrom: z.string().optional().describe(\"Start time filter in RFC3339 format (defaults to 2 hours ago)\"),\n timeTo: z.string().optional().describe(\"End time filter in RFC3339 format (defaults to current time)\"),\n limit: z.number().int().min(1).max(50).optional().describe(\"Results per page, 1 to 50. Defaults to 20.\"),\n nextToken: z.string().optional().describe(\"Pagination token from previous response\"),\n },\n async (params) => {\n try {\n const data = await client.vessels.positions({\n filterIds: params.ids,\n filterIdType: params.idType,\n timeFrom: params.timeFrom,\n timeTo: params.timeTo,\n paginationLimit: params.limit,\n paginationNextToken: params.nextToken,\n });\n return formatResult(data);\n } catch (error) {\n return handleToolError(error);\n }\n },\n );\n}\n"],"mappings":"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","names":["server","client","z","server","client","z","z","server","client","z"]}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "vesselapi-mcp",
3
- "version": "1.3.0",
3
+ "version": "2.0.0",
4
4
  "mcpName": "io.github.vessel-api/vesselapi-mcp",
5
- "description": "MCP server for the VesselAPI — maritime vessel tracking, port events, emissions, and navigation data",
5
+ "description": "MCP server for the VesselAPI: maritime vessel tracking, port events and emissions",
6
6
  "license": "MIT",
7
7
  "author": "VesselAPI",
8
8
  "repository": {
@@ -30,7 +30,8 @@
30
30
  "vesselapi-mcp": "./dist/index.js"
31
31
  },
32
32
  "files": [
33
- "dist"
33
+ "dist",
34
+ "CHANGELOG.md"
34
35
  ],
35
36
  "scripts": {
36
37
  "prepublishOnly": "npm run build",
@@ -42,9 +43,9 @@
42
43
  "node": ">=18"
43
44
  },
44
45
  "dependencies": {
45
- "vesselapi": "^1.2.0",
46
46
  "@modelcontextprotocol/sdk": "^1.12.0",
47
- "zod": "^3.24.0"
47
+ "vesselapi": "^2.0.0",
48
+ "zod": "^3.25.0"
48
49
  },
49
50
  "devDependencies": {
50
51
  "@types/node": "^25.3.0",