vesselapi-mcp 1.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/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # VesselAPI MCP Server
2
+
3
+ [![CI](https://github.com/vessel-api/vesselapi-mcp/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/vessel-api/vesselapi-mcp/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/vesselapi-mcp.svg)](https://www.npmjs.com/package/vesselapi-mcp)
5
+ [![Node](https://img.shields.io/node/v/vesselapi-mcp.svg)](https://www.npmjs.com/package/vesselapi-mcp)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+
8
+ An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that exposes maritime data from the [VesselAPI](https://vesselapi.com) to AI assistants like Claude Desktop, Cursor, Windsurf, and Claude Code.
9
+
10
+ ## Prerequisites
11
+
12
+ 1. Sign up at [dashboard.vesselapi.com](https://dashboard.vesselapi.com)
13
+ 2. Create an API token in your dashboard
14
+ 3. Use the token as `VESSELAPI_API_KEY` in the configuration below
15
+
16
+ **Resources**: [Documentation](https://vesselapi.com/docs) | [API Explorer](https://vesselapi.com/api-reference) | [Dashboard](https://dashboard.vesselapi.com) | [Contact Support](mailto:support@vesselapi.com)
17
+
18
+ ## Features
19
+
20
+ - **16 tools** covering vessels, ports, location search, and maritime safety
21
+ - Vessel search, positions, ETA, classification, ownership, emissions, inspections, and casualties
22
+ - Port search, details, and port events (arrivals/departures)
23
+ - Geographic vessel search (bounding box and radius)
24
+ - NAVTEX maritime safety messages
25
+ - Manual pagination to control API quota usage
26
+
27
+ ## Quick Start
28
+
29
+ No installation required — just configure your AI client with `npx`:
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "vesselapi": {
35
+ "command": "npx",
36
+ "args": ["-y", "vesselapi-mcp"],
37
+ "env": {
38
+ "VESSELAPI_API_KEY": "your-api-key"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ ## Configuration
46
+
47
+ ### Claude Desktop
48
+
49
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
50
+
51
+ ```json
52
+ {
53
+ "mcpServers": {
54
+ "vesselapi": {
55
+ "command": "npx",
56
+ "args": ["-y", "vesselapi-mcp"],
57
+ "env": {
58
+ "VESSELAPI_API_KEY": "your-api-key"
59
+ }
60
+ }
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### Cursor
66
+
67
+ Add to `.cursor/mcp.json` in your project or `~/.cursor/mcp.json` globally:
68
+
69
+ ```json
70
+ {
71
+ "mcpServers": {
72
+ "vesselapi": {
73
+ "command": "npx",
74
+ "args": ["-y", "vesselapi-mcp"],
75
+ "env": {
76
+ "VESSELAPI_API_KEY": "your-api-key"
77
+ }
78
+ }
79
+ }
80
+ }
81
+ ```
82
+
83
+ ### Claude Code
84
+
85
+ Add to `.claude/settings.json` in your project or `~/.claude/settings.json` globally:
86
+
87
+ ```json
88
+ {
89
+ "mcpServers": {
90
+ "vesselapi": {
91
+ "command": "npx",
92
+ "args": ["-y", "vesselapi-mcp"],
93
+ "env": {
94
+ "VESSELAPI_API_KEY": "your-api-key"
95
+ }
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ ### Windsurf
102
+
103
+ Add to `~/.codeium/windsurf/mcp_config.json`:
104
+
105
+ ```json
106
+ {
107
+ "mcpServers": {
108
+ "vesselapi": {
109
+ "command": "npx",
110
+ "args": ["-y", "vesselapi-mcp"],
111
+ "env": {
112
+ "VESSELAPI_API_KEY": "your-api-key"
113
+ }
114
+ }
115
+ }
116
+ }
117
+ ```
118
+
119
+ ## Tools
120
+
121
+ ### Vessel Tools
122
+
123
+ | Tool | Description |
124
+ |---|---|
125
+ | `search_vessels` | Search vessels by name, IMO, MMSI, flag, type, or callsign |
126
+ | `get_vessel` | Get detailed vessel information |
127
+ | `get_vessel_position` | Get current vessel position (lat/lon, speed, heading) |
128
+ | `get_vessel_eta` | Get vessel estimated time of arrival |
129
+ | `get_vessel_classification` | Get classification details (class society, surveys, hull) |
130
+ | `get_vessel_ownership` | Get ownership details (owner, manager, operator) |
131
+ | `get_vessel_emissions` | Get emissions data (CO2, fuel consumption) |
132
+ | `get_vessel_inspections` | Get port state control inspections |
133
+ | `get_vessel_casualties` | Get marine casualty records |
134
+
135
+ ### Port Tools
136
+
137
+ | Tool | Description |
138
+ |---|---|
139
+ | `search_ports` | Search ports by name, country, type, or region |
140
+ | `get_port` | Get port details by UN/LOCODE |
141
+ | `get_port_events` | Get arrivals/departures for a port |
142
+ | `get_port_events_by_vessel` | Get port events for a vessel |
143
+
144
+ ### Location Tools
145
+
146
+ | Tool | Description |
147
+ |---|---|
148
+ | `get_vessels_in_area` | Find vessels in a bounding box |
149
+ | `get_vessels_in_radius` | Find vessels within a radius of a point |
150
+
151
+ ### Safety Tools
152
+
153
+ | Tool | Description |
154
+ |---|---|
155
+ | `get_navtex_messages` | Get NAVTEX maritime safety messages |
156
+
157
+ ## Pagination
158
+
159
+ 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.
160
+
161
+ ## Development
162
+
163
+ ```bash
164
+ git clone https://github.com/vessel-api/vesselapi-mcp.git
165
+ cd vesselapi-mcp
166
+ npm install
167
+ npm run build
168
+ ```
169
+
170
+ ```bash
171
+ npm run build # Build the server
172
+ npm run typecheck # Type-check without emitting
173
+ npm run clean # Remove build artifacts
174
+ ```
175
+
176
+ ### Testing with MCP Inspector
177
+
178
+ ```bash
179
+ VESSELAPI_API_KEY=your-key npx @modelcontextprotocol/inspector node dist/index.js
180
+ ```
181
+
182
+ ## License
183
+
184
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,430 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { VesselClient } from "vesselapi";
7
+
8
+ // src/tools/location.ts
9
+ import { z } from "zod";
10
+
11
+ // src/errors.ts
12
+ import {
13
+ VesselAPIError,
14
+ VesselAuthError,
15
+ VesselNotFoundError,
16
+ VesselRateLimitError,
17
+ VesselServerError
18
+ } from "vesselapi";
19
+ function formatResult(data) {
20
+ return {
21
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
22
+ };
23
+ }
24
+ function handleToolError(error) {
25
+ let message;
26
+ if (error instanceof VesselAuthError) {
27
+ message = "Authentication failed. Check your VESSELAPI_API_KEY.";
28
+ } else if (error instanceof VesselNotFoundError) {
29
+ message = "Resource not found. Verify the ID or parameters.";
30
+ } else if (error instanceof VesselRateLimitError) {
31
+ message = "Rate limit exceeded. Try again later or reduce request frequency.";
32
+ } else if (error instanceof VesselServerError) {
33
+ message = `Server error: ${error.message}`;
34
+ } else if (error instanceof VesselAPIError) {
35
+ message = `API error: ${error.message}`;
36
+ } else if (error instanceof Error) {
37
+ message = error.message;
38
+ } else {
39
+ message = String(error);
40
+ }
41
+ return {
42
+ isError: true,
43
+ content: [{ type: "text", text: message }]
44
+ };
45
+ }
46
+
47
+ // src/tools/location.ts
48
+ function registerLocationTools(server2, client2) {
49
+ server2.tool(
50
+ "get_vessels_in_area",
51
+ "Find all vessels within a rectangular bounding box (latitude/longitude)",
52
+ {
53
+ latMin: z.number().describe("Southern boundary latitude"),
54
+ latMax: z.number().describe("Northern boundary latitude"),
55
+ lonMin: z.number().describe("Western boundary longitude"),
56
+ lonMax: z.number().describe("Eastern boundary longitude"),
57
+ limit: z.number().optional().describe("Max results per page"),
58
+ nextToken: z.string().optional().describe("Pagination token from previous response")
59
+ },
60
+ async (params) => {
61
+ try {
62
+ const data = await client2.location.vesselsBoundingBox({
63
+ latMin: params.latMin,
64
+ latMax: params.latMax,
65
+ lonMin: params.lonMin,
66
+ lonMax: params.lonMax,
67
+ paginationLimit: params.limit,
68
+ paginationNextToken: params.nextToken
69
+ });
70
+ return formatResult(data);
71
+ } catch (error) {
72
+ return handleToolError(error);
73
+ }
74
+ }
75
+ );
76
+ server2.tool(
77
+ "get_vessels_in_radius",
78
+ "Find all vessels within a radius (in nautical miles) of a point",
79
+ {
80
+ latitude: z.number().describe("Center latitude"),
81
+ longitude: z.number().describe("Center longitude"),
82
+ radius: z.number().describe("Radius in nautical miles"),
83
+ limit: z.number().optional().describe("Max results per page"),
84
+ nextToken: z.string().optional().describe("Pagination token from previous response")
85
+ },
86
+ async (params) => {
87
+ try {
88
+ const data = await client2.location.vesselsRadius({
89
+ latitude: params.latitude,
90
+ longitude: params.longitude,
91
+ radius: params.radius,
92
+ paginationLimit: params.limit,
93
+ paginationNextToken: params.nextToken
94
+ });
95
+ return formatResult(data);
96
+ } catch (error) {
97
+ return handleToolError(error);
98
+ }
99
+ }
100
+ );
101
+ }
102
+
103
+ // src/tools/ports.ts
104
+ import { z as z2 } from "zod";
105
+ function registerPortTools(server2, client2) {
106
+ server2.tool(
107
+ "search_ports",
108
+ "Search for ports by name, country, type, or region",
109
+ {
110
+ name: z2.string().optional().describe("Port name (partial match)"),
111
+ country: z2.string().optional().describe("Country (ISO code)"),
112
+ portType: z2.string().optional().describe("Port type"),
113
+ region: z2.string().optional().describe("Geographic region"),
114
+ limit: z2.number().optional().describe("Max results per page"),
115
+ nextToken: z2.string().optional().describe("Pagination token from previous response")
116
+ },
117
+ async (params) => {
118
+ try {
119
+ const data = await client2.search.ports({
120
+ filterName: params.name,
121
+ filterCountry: params.country,
122
+ filterPortType: params.portType,
123
+ filterRegion: params.region,
124
+ paginationLimit: params.limit,
125
+ paginationNextToken: params.nextToken
126
+ });
127
+ return formatResult(data);
128
+ } catch (error) {
129
+ return handleToolError(error);
130
+ }
131
+ }
132
+ );
133
+ server2.tool(
134
+ "get_port",
135
+ "Get detailed information about a specific port by UN/LOCODE",
136
+ {
137
+ unlocode: z2.string().describe("UN/LOCODE of the port (e.g. NLRTM for Rotterdam)")
138
+ },
139
+ async (params) => {
140
+ try {
141
+ const data = await client2.ports.get(params.unlocode);
142
+ return formatResult(data);
143
+ } catch (error) {
144
+ return handleToolError(error);
145
+ }
146
+ }
147
+ );
148
+ server2.tool(
149
+ "get_port_events",
150
+ "Get port events (arrivals/departures) for a specific port",
151
+ {
152
+ unlocode: z2.string().describe("UN/LOCODE of the port"),
153
+ limit: z2.number().optional().describe("Max results per page"),
154
+ nextToken: z2.string().optional().describe("Pagination token from previous response")
155
+ },
156
+ async (params) => {
157
+ try {
158
+ const data = await client2.portEvents.byPort(params.unlocode, {
159
+ paginationLimit: params.limit,
160
+ paginationNextToken: params.nextToken
161
+ });
162
+ return formatResult(data);
163
+ } catch (error) {
164
+ return handleToolError(error);
165
+ }
166
+ }
167
+ );
168
+ server2.tool(
169
+ "get_port_events_by_vessel",
170
+ "Get port events (arrivals/departures) for a specific vessel",
171
+ {
172
+ vesselId: z2.string().describe("Vessel identifier (IMO number by default)"),
173
+ idType: z2.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId"),
174
+ eventType: z2.string().optional().describe("Filter by event type (arrival, departure)"),
175
+ timeFrom: z2.string().optional().describe("Start time (ISO 8601 format)"),
176
+ timeTo: z2.string().optional().describe("End time (ISO 8601 format)"),
177
+ limit: z2.number().optional().describe("Max results per page"),
178
+ nextToken: z2.string().optional().describe("Pagination token from previous response")
179
+ },
180
+ async (params) => {
181
+ try {
182
+ const data = await client2.portEvents.byVessel(params.vesselId, {
183
+ filterIdType: params.idType,
184
+ filterEventType: params.eventType,
185
+ timeFrom: params.timeFrom,
186
+ timeTo: params.timeTo,
187
+ paginationLimit: params.limit,
188
+ paginationNextToken: params.nextToken
189
+ });
190
+ return formatResult(data);
191
+ } catch (error) {
192
+ return handleToolError(error);
193
+ }
194
+ }
195
+ );
196
+ }
197
+
198
+ // src/tools/safety.ts
199
+ import { z as z3 } from "zod";
200
+ function registerSafetyTools(server2, client2) {
201
+ server2.tool(
202
+ "get_navtex_messages",
203
+ "Get NAVTEX maritime safety messages (navigational warnings, weather forecasts)",
204
+ {
205
+ timeFrom: z3.string().optional().describe("Start time (ISO 8601 format)"),
206
+ timeTo: z3.string().optional().describe("End time (ISO 8601 format)"),
207
+ limit: z3.number().optional().describe("Max results per page"),
208
+ nextToken: z3.string().optional().describe("Pagination token from previous response")
209
+ },
210
+ async (params) => {
211
+ try {
212
+ const data = await client2.navtex.list({
213
+ timeFrom: params.timeFrom,
214
+ timeTo: params.timeTo,
215
+ paginationLimit: params.limit,
216
+ paginationNextToken: params.nextToken
217
+ });
218
+ return formatResult(data);
219
+ } catch (error) {
220
+ return handleToolError(error);
221
+ }
222
+ }
223
+ );
224
+ }
225
+
226
+ // src/tools/vessels.ts
227
+ import { z as z4 } from "zod";
228
+ function registerVesselTools(server2, client2) {
229
+ server2.tool(
230
+ "search_vessels",
231
+ "Search for vessels by name, IMO, MMSI, flag, type, or callsign",
232
+ {
233
+ name: z4.string().optional().describe("Vessel name (partial match)"),
234
+ imo: z4.string().optional().describe("IMO number"),
235
+ mmsi: z4.string().optional().describe("MMSI number"),
236
+ flag: z4.string().optional().describe("Flag state (ISO country code)"),
237
+ vesselType: z4.string().optional().describe("Vessel type"),
238
+ callsign: z4.string().optional().describe("Radio callsign"),
239
+ limit: z4.number().optional().describe("Max results per page"),
240
+ nextToken: z4.string().optional().describe("Pagination token from previous response")
241
+ },
242
+ async (params) => {
243
+ try {
244
+ const data = await client2.search.vessels({
245
+ filterName: params.name,
246
+ filterImo: params.imo,
247
+ filterMmsi: params.mmsi,
248
+ filterFlag: params.flag,
249
+ filterVesselType: params.vesselType,
250
+ filterCallsign: params.callsign,
251
+ paginationLimit: params.limit,
252
+ paginationNextToken: params.nextToken
253
+ });
254
+ return formatResult(data);
255
+ } catch (error) {
256
+ return handleToolError(error);
257
+ }
258
+ }
259
+ );
260
+ server2.tool(
261
+ "get_vessel",
262
+ "Get detailed information about a specific vessel",
263
+ {
264
+ vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
265
+ idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
266
+ },
267
+ async (params) => {
268
+ try {
269
+ const data = await client2.vessels.get(params.vesselId, {
270
+ filterIdType: params.idType
271
+ });
272
+ return formatResult(data);
273
+ } catch (error) {
274
+ return handleToolError(error);
275
+ }
276
+ }
277
+ );
278
+ server2.tool(
279
+ "get_vessel_position",
280
+ "Get the current position of a vessel (latitude, longitude, speed, heading)",
281
+ {
282
+ vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
283
+ idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
284
+ },
285
+ async (params) => {
286
+ try {
287
+ const data = await client2.vessels.position(params.vesselId, {
288
+ filterIdType: params.idType
289
+ });
290
+ return formatResult(data);
291
+ } catch (error) {
292
+ return handleToolError(error);
293
+ }
294
+ }
295
+ );
296
+ server2.tool(
297
+ "get_vessel_eta",
298
+ "Get the estimated time of arrival for a vessel",
299
+ {
300
+ vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
301
+ idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
302
+ },
303
+ async (params) => {
304
+ try {
305
+ const data = await client2.vessels.eta(params.vesselId, {
306
+ filterIdType: params.idType
307
+ });
308
+ return formatResult(data);
309
+ } catch (error) {
310
+ return handleToolError(error);
311
+ }
312
+ }
313
+ );
314
+ server2.tool(
315
+ "get_vessel_classification",
316
+ "Get the classification details for a vessel (class society, surveys, hull info)",
317
+ {
318
+ vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
319
+ idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
320
+ },
321
+ async (params) => {
322
+ try {
323
+ const data = await client2.vessels.classification(params.vesselId, {
324
+ filterIdType: params.idType
325
+ });
326
+ return formatResult(data);
327
+ } catch (error) {
328
+ return handleToolError(error);
329
+ }
330
+ }
331
+ );
332
+ server2.tool(
333
+ "get_vessel_ownership",
334
+ "Get the ownership details for a vessel (owner, manager, operator)",
335
+ {
336
+ vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
337
+ idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId")
338
+ },
339
+ async (params) => {
340
+ try {
341
+ const data = await client2.vessels.ownership(params.vesselId, {
342
+ filterIdType: params.idType
343
+ });
344
+ return formatResult(data);
345
+ } catch (error) {
346
+ return handleToolError(error);
347
+ }
348
+ }
349
+ );
350
+ server2.tool(
351
+ "get_vessel_emissions",
352
+ "Get emissions data for a vessel (CO2, fuel consumption)",
353
+ {
354
+ vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
355
+ idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId"),
356
+ limit: z4.number().optional().describe("Max results per page"),
357
+ nextToken: z4.string().optional().describe("Pagination token from previous response")
358
+ },
359
+ async (params) => {
360
+ try {
361
+ const data = await client2.vessels.emissions(params.vesselId, {
362
+ filterIdType: params.idType,
363
+ paginationLimit: params.limit,
364
+ paginationNextToken: params.nextToken
365
+ });
366
+ return formatResult(data);
367
+ } catch (error) {
368
+ return handleToolError(error);
369
+ }
370
+ }
371
+ );
372
+ server2.tool(
373
+ "get_vessel_inspections",
374
+ "Get port state control inspections for a vessel",
375
+ {
376
+ vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
377
+ idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId"),
378
+ limit: z4.number().optional().describe("Max results per page"),
379
+ nextToken: z4.string().optional().describe("Pagination token from previous response")
380
+ },
381
+ async (params) => {
382
+ try {
383
+ const data = await client2.vessels.inspections(params.vesselId, {
384
+ filterIdType: params.idType,
385
+ paginationLimit: params.limit,
386
+ paginationNextToken: params.nextToken
387
+ });
388
+ return formatResult(data);
389
+ } catch (error) {
390
+ return handleToolError(error);
391
+ }
392
+ }
393
+ );
394
+ server2.tool(
395
+ "get_vessel_casualties",
396
+ "Get marine casualty records for a vessel",
397
+ {
398
+ vesselId: z4.string().describe("Vessel identifier (IMO number by default)"),
399
+ idType: z4.string().optional().describe("Identifier type: imo (default), mmsi, or vesselId"),
400
+ limit: z4.number().optional().describe("Max results per page"),
401
+ nextToken: z4.string().optional().describe("Pagination token from previous response")
402
+ },
403
+ async (params) => {
404
+ try {
405
+ const data = await client2.vessels.casualties(params.vesselId, {
406
+ filterIdType: params.idType,
407
+ paginationLimit: params.limit,
408
+ paginationNextToken: params.nextToken
409
+ });
410
+ return formatResult(data);
411
+ } catch (error) {
412
+ return handleToolError(error);
413
+ }
414
+ }
415
+ );
416
+ }
417
+
418
+ // src/index.ts
419
+ var client = new VesselClient();
420
+ var server = new McpServer({
421
+ name: "vesselapi",
422
+ version: "1.0.0"
423
+ });
424
+ registerVesselTools(server, client);
425
+ registerPortTools(server, client);
426
+ registerLocationTools(server, client);
427
+ registerSafetyTools(server, client);
428
+ var transport = new StdioServerTransport();
429
+ await server.connect(transport);
430
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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 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 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 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 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, or region\",\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\"),\n region: z.string().optional().describe(\"Geographic region\"),\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 filterRegion: params.region,\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_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 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 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 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, or callsign\",\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 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 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"],"mappings":"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","names":["server","client","z","server","client","z","z","server","client","z","z","server","client","z"]}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "vesselapi-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for the VesselAPI — maritime vessel tracking, port events, emissions, and navigation data",
5
+ "license": "MIT",
6
+ "author": "VesselAPI",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/vessel-api/vesselapi-mcp.git"
10
+ },
11
+ "homepage": "https://vesselapi.com",
12
+ "bugs": {
13
+ "url": "https://github.com/vessel-api/vesselapi-mcp/issues"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "model-context-protocol",
18
+ "vesselapi",
19
+ "maritime",
20
+ "vessel",
21
+ "shipping",
22
+ "ais",
23
+ "vessel-tracking",
24
+ "port-events",
25
+ "emissions"
26
+ ],
27
+ "type": "module",
28
+ "bin": {
29
+ "vesselapi-mcp": "./dist/index.js"
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "scripts": {
35
+ "prepublishOnly": "npm run build",
36
+ "build": "tsup",
37
+ "typecheck": "tsc --noEmit",
38
+ "clean": "rm -rf dist"
39
+ },
40
+ "engines": {
41
+ "node": ">=18"
42
+ },
43
+ "dependencies": {
44
+ "vesselapi": "^1.0.0",
45
+ "@modelcontextprotocol/sdk": "^1.12.0",
46
+ "zod": "^3.24.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^25.3.0",
50
+ "tsup": "^8.0.0",
51
+ "typescript": "^5.5.0"
52
+ }
53
+ }