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 +184 -0
- package/dist/index.js +430 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# VesselAPI MCP Server
|
|
2
|
+
|
|
3
|
+
[](https://github.com/vessel-api/vesselapi-mcp/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/vesselapi-mcp)
|
|
5
|
+
[](https://www.npmjs.com/package/vesselapi-mcp)
|
|
6
|
+
[](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
|
+
}
|