wanderlog-mcp 0.1.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/LICENSE +21 -0
- package/README.md +256 -0
- package/dist/cache/trip-cache.js +87 -0
- package/dist/cache/trip-cache.js.map +1 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/context.js +12 -0
- package/dist/context.js.map +1 -0
- package/dist/errors.js +86 -0
- package/dist/errors.js.map +1 -0
- package/dist/formatters/trip-summary.js +280 -0
- package/dist/formatters/trip-summary.js.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/ot/apply.js +282 -0
- package/dist/ot/apply.js.map +1 -0
- package/dist/resolvers/day.js +83 -0
- package/dist/resolvers/day.js.map +1 -0
- package/dist/resolvers/place-ref.js +192 -0
- package/dist/resolvers/place-ref.js.map +1 -0
- package/dist/server.js +100 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/add-checklist.js +59 -0
- package/dist/tools/add-checklist.js.map +1 -0
- package/dist/tools/add-hotel.js +92 -0
- package/dist/tools/add-hotel.js.map +1 -0
- package/dist/tools/add-note.js +63 -0
- package/dist/tools/add-note.js.map +1 -0
- package/dist/tools/add-place.js +98 -0
- package/dist/tools/add-place.js.map +1 -0
- package/dist/tools/create-trip.js +85 -0
- package/dist/tools/create-trip.js.map +1 -0
- package/dist/tools/get-trip-url.js +52 -0
- package/dist/tools/get-trip-url.js.map +1 -0
- package/dist/tools/get-trip.js +43 -0
- package/dist/tools/get-trip.js.map +1 -0
- package/dist/tools/list-trips.js +32 -0
- package/dist/tools/list-trips.js.map +1 -0
- package/dist/tools/remove-place.js +95 -0
- package/dist/tools/remove-place.js.map +1 -0
- package/dist/tools/search-places.js +81 -0
- package/dist/tools/search-places.js.map +1 -0
- package/dist/tools/shared.js +194 -0
- package/dist/tools/shared.js.map +1 -0
- package/dist/tools/update-trip-dates.js +208 -0
- package/dist/tools/update-trip-dates.js.map +1 -0
- package/dist/transport/rest.js +125 -0
- package/dist/transport/rest.js.map +1 -0
- package/dist/transport/sharedb.js +313 -0
- package/dist/transport/sharedb.js.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
import { WanderlogAuthError, WanderlogError } from "../errors.js";
|
|
4
|
+
/**
|
|
5
|
+
* ShareDB JSONv0 client bound to a single trip key.
|
|
6
|
+
* Exposes subscribe() for the initial snapshot, submit() for outgoing ops
|
|
7
|
+
* (with version tracking and ack waiting), and a `remoteOp` event for ops
|
|
8
|
+
* pushed by the server from other clients.
|
|
9
|
+
*/
|
|
10
|
+
export class ShareDBClient extends EventEmitter {
|
|
11
|
+
config;
|
|
12
|
+
tripKey;
|
|
13
|
+
ws;
|
|
14
|
+
sessionId;
|
|
15
|
+
handshakeComplete = false;
|
|
16
|
+
closedByUser = false;
|
|
17
|
+
reconnectAttempts = 0;
|
|
18
|
+
seqCounter = 0;
|
|
19
|
+
snapshot;
|
|
20
|
+
_version = 0;
|
|
21
|
+
subscribed = false;
|
|
22
|
+
subscribePending;
|
|
23
|
+
pendingOps = new Map();
|
|
24
|
+
connectPromise;
|
|
25
|
+
constructor(config, tripKey) {
|
|
26
|
+
super();
|
|
27
|
+
this.config = config;
|
|
28
|
+
this.tripKey = tripKey;
|
|
29
|
+
}
|
|
30
|
+
get version() {
|
|
31
|
+
return this._version;
|
|
32
|
+
}
|
|
33
|
+
get currentSnapshot() {
|
|
34
|
+
return this.snapshot;
|
|
35
|
+
}
|
|
36
|
+
get isSubscribed() {
|
|
37
|
+
return this.subscribed;
|
|
38
|
+
}
|
|
39
|
+
url() {
|
|
40
|
+
return `${this.config.wsBaseUrl}/api/tripPlans/wsOverall/${encodeURIComponent(this.tripKey)}?clientSchemaVersion=2`;
|
|
41
|
+
}
|
|
42
|
+
async connect() {
|
|
43
|
+
if (this.handshakeComplete)
|
|
44
|
+
return;
|
|
45
|
+
if (this.connectPromise)
|
|
46
|
+
return this.connectPromise;
|
|
47
|
+
this.connectPromise = this.doConnect();
|
|
48
|
+
try {
|
|
49
|
+
await this.connectPromise;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
this.connectPromise = undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
doConnect() {
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
const ws = new WebSocket(this.url(), {
|
|
58
|
+
headers: {
|
|
59
|
+
Cookie: this.config.cookieHeader,
|
|
60
|
+
Origin: this.config.baseUrl,
|
|
61
|
+
"User-Agent": this.config.userAgent,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
this.ws = ws;
|
|
65
|
+
this.handshakeComplete = false;
|
|
66
|
+
const handshakeTimeout = setTimeout(() => {
|
|
67
|
+
reject(new WanderlogError("ShareDB handshake timeout", "ws_timeout"));
|
|
68
|
+
ws.close();
|
|
69
|
+
}, 10_000);
|
|
70
|
+
ws.on("open", () => {
|
|
71
|
+
this.send({ a: "hs", id: null, protocol: 1, protocolMinor: 2 });
|
|
72
|
+
});
|
|
73
|
+
ws.on("message", (raw) => {
|
|
74
|
+
const text = raw.toString();
|
|
75
|
+
let msg;
|
|
76
|
+
try {
|
|
77
|
+
msg = JSON.parse(text);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (!msg || typeof msg !== "object")
|
|
83
|
+
return;
|
|
84
|
+
this.handleFrame(msg, handshakeTimeout, resolve);
|
|
85
|
+
});
|
|
86
|
+
ws.on("close", (code) => {
|
|
87
|
+
clearTimeout(handshakeTimeout);
|
|
88
|
+
const wasSubscribed = this.subscribed;
|
|
89
|
+
this.handshakeComplete = false;
|
|
90
|
+
this.subscribed = false;
|
|
91
|
+
this.failAllPending(new WanderlogError("WebSocket closed", "ws_closed"));
|
|
92
|
+
this.emit("closed", code);
|
|
93
|
+
if (!this.closedByUser && code !== 1000) {
|
|
94
|
+
this.scheduleReconnect(wasSubscribed);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
ws.on("unexpected-response", (_req, res) => {
|
|
98
|
+
clearTimeout(handshakeTimeout);
|
|
99
|
+
if (res.statusCode === 401 || res.statusCode === 403) {
|
|
100
|
+
reject(new WanderlogAuthError());
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
reject(new WanderlogError(`WebSocket upgrade failed: ${res.statusCode}`, "ws_upgrade_failed"));
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
ws.on("error", (err) => {
|
|
107
|
+
clearTimeout(handshakeTimeout);
|
|
108
|
+
if (!this.handshakeComplete)
|
|
109
|
+
reject(err);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
handleFrame(frame, handshakeTimeout, connectResolve) {
|
|
114
|
+
if (frame.error) {
|
|
115
|
+
const err = frame.error;
|
|
116
|
+
const errMsg = typeof err === "string" ? err : err.message ?? "unknown";
|
|
117
|
+
// If the error frame carries a seq, it belongs to a specific submit.
|
|
118
|
+
// Fail only that one pending op, so concurrent/queued submits are not
|
|
119
|
+
// collateral damage.
|
|
120
|
+
if (typeof frame.seq === "number" && this.pendingOps.has(frame.seq)) {
|
|
121
|
+
const pending = this.pendingOps.get(frame.seq);
|
|
122
|
+
this.pendingOps.delete(frame.seq);
|
|
123
|
+
clearTimeout(pending.timer);
|
|
124
|
+
pending.reject(new WanderlogError(errMsg, "ws_error"));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// No seq, or unknown seq — fall back to failing everything, since we
|
|
128
|
+
// can't safely attribute the error.
|
|
129
|
+
this.failAllPending(new WanderlogError(errMsg, "ws_error"));
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (frame.a === "init") {
|
|
133
|
+
this.sessionId = frame.id;
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (frame.a === "hs" && !this.handshakeComplete) {
|
|
137
|
+
this.handshakeComplete = true;
|
|
138
|
+
clearTimeout(handshakeTimeout);
|
|
139
|
+
this.reconnectAttempts = 0;
|
|
140
|
+
const hs = frame;
|
|
141
|
+
if (!this.sessionId && hs.id)
|
|
142
|
+
this.sessionId = hs.id;
|
|
143
|
+
connectResolve();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (frame.a === "s") {
|
|
147
|
+
const pending = this.subscribePending;
|
|
148
|
+
if (pending) {
|
|
149
|
+
this.subscribePending = undefined;
|
|
150
|
+
pending.resolve(frame);
|
|
151
|
+
}
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (frame.a === "op") {
|
|
155
|
+
this.handleOpFrame(frame);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
handleOpFrame(frame) {
|
|
159
|
+
const isOurAck = frame.src === this.sessionId &&
|
|
160
|
+
frame.seq !== undefined &&
|
|
161
|
+
this.pendingOps.has(frame.seq);
|
|
162
|
+
if (isOurAck) {
|
|
163
|
+
const pending = this.pendingOps.get(frame.seq);
|
|
164
|
+
this.pendingOps.delete(frame.seq);
|
|
165
|
+
clearTimeout(pending.timer);
|
|
166
|
+
this._version = frame.v + 1;
|
|
167
|
+
pending.resolve();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (frame.op && frame.op.length > 0) {
|
|
171
|
+
this._version = frame.v + 1;
|
|
172
|
+
this.emit("remoteOp", frame.op, this._version);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
failAllPending(err) {
|
|
176
|
+
if (this.subscribePending) {
|
|
177
|
+
this.subscribePending.reject(err);
|
|
178
|
+
this.subscribePending = undefined;
|
|
179
|
+
}
|
|
180
|
+
for (const [seq, pending] of this.pendingOps) {
|
|
181
|
+
clearTimeout(pending.timer);
|
|
182
|
+
pending.reject(err);
|
|
183
|
+
this.pendingOps.delete(seq);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
scheduleReconnect(resubscribe) {
|
|
187
|
+
const delay = Math.min(1000 * 2 ** this.reconnectAttempts, 30_000);
|
|
188
|
+
this.reconnectAttempts += 1;
|
|
189
|
+
setTimeout(() => {
|
|
190
|
+
if (this.closedByUser)
|
|
191
|
+
return;
|
|
192
|
+
this.doConnect()
|
|
193
|
+
.then(() => {
|
|
194
|
+
if (resubscribe) {
|
|
195
|
+
void this.subscribe().then(() => this.emit("reconnected"));
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
this.emit("reconnected");
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
.catch(() => this.scheduleReconnect(resubscribe));
|
|
202
|
+
}, delay);
|
|
203
|
+
}
|
|
204
|
+
send(obj) {
|
|
205
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
206
|
+
throw new WanderlogError("WebSocket is not open — cannot send frame", "ws_not_open");
|
|
207
|
+
}
|
|
208
|
+
this.ws.send(JSON.stringify(obj));
|
|
209
|
+
}
|
|
210
|
+
async subscribe() {
|
|
211
|
+
await this.connect();
|
|
212
|
+
if (this.subscribed && this.snapshot)
|
|
213
|
+
return this.snapshot;
|
|
214
|
+
const ack = await new Promise((resolve, reject) => {
|
|
215
|
+
this.subscribePending = { resolve, reject };
|
|
216
|
+
this.send({ a: "s", c: "TripPlans", d: this.tripKey });
|
|
217
|
+
setTimeout(() => {
|
|
218
|
+
if (this.subscribePending) {
|
|
219
|
+
this.subscribePending = undefined;
|
|
220
|
+
reject(new WanderlogError("Subscribe timeout", "subscribe_timeout"));
|
|
221
|
+
}
|
|
222
|
+
}, 10_000);
|
|
223
|
+
});
|
|
224
|
+
if (!ack.data) {
|
|
225
|
+
throw new WanderlogError("Subscribe ack missing snapshot", "subscribe_failed");
|
|
226
|
+
}
|
|
227
|
+
this.snapshot = ack.data.data;
|
|
228
|
+
this._version = ack.data.v;
|
|
229
|
+
this.subscribed = true;
|
|
230
|
+
return this.snapshot;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Submit a JSON0 op array to the server. Resolves when the server acks.
|
|
234
|
+
* Throws if not subscribed, if the WebSocket is closed, or on ack timeout.
|
|
235
|
+
*
|
|
236
|
+
* On successful ack, the local version is bumped to `frame.v + 1`.
|
|
237
|
+
*/
|
|
238
|
+
async submit(ops) {
|
|
239
|
+
if (!this.subscribed) {
|
|
240
|
+
throw new WanderlogError("Cannot submit op before subscribing to the trip", "not_subscribed");
|
|
241
|
+
}
|
|
242
|
+
if (ops.length === 0) {
|
|
243
|
+
throw new WanderlogError("Cannot submit an empty op array", "empty_op");
|
|
244
|
+
}
|
|
245
|
+
this.seqCounter += 1;
|
|
246
|
+
const seq = this.seqCounter;
|
|
247
|
+
const frame = {
|
|
248
|
+
a: "op",
|
|
249
|
+
c: "TripPlans",
|
|
250
|
+
d: this.tripKey,
|
|
251
|
+
v: this._version,
|
|
252
|
+
seq,
|
|
253
|
+
x: {},
|
|
254
|
+
op: ops,
|
|
255
|
+
};
|
|
256
|
+
return new Promise((resolve, reject) => {
|
|
257
|
+
const timer = setTimeout(() => {
|
|
258
|
+
if (this.pendingOps.has(seq)) {
|
|
259
|
+
this.pendingOps.delete(seq);
|
|
260
|
+
reject(new WanderlogError("Submit op timeout", "submit_timeout"));
|
|
261
|
+
}
|
|
262
|
+
}, 10_000);
|
|
263
|
+
this.pendingOps.set(seq, { resolve, reject, timer });
|
|
264
|
+
try {
|
|
265
|
+
this.send(frame);
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
// Send failed (e.g. WS closed between the isSubscribed check and now).
|
|
269
|
+
// Clean up the pending entry and propagate immediately rather than
|
|
270
|
+
// waiting 10s for the timeout to fire.
|
|
271
|
+
this.pendingOps.delete(seq);
|
|
272
|
+
clearTimeout(timer);
|
|
273
|
+
reject(err);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
close() {
|
|
278
|
+
this.closedByUser = true;
|
|
279
|
+
this.subscribed = false;
|
|
280
|
+
this.failAllPending(new WanderlogError("Client closed", "ws_closed"));
|
|
281
|
+
this.ws?.close();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Pool of ShareDBClient instances keyed by trip key. A single MCP server
|
|
286
|
+
* session may subscribe to multiple trips concurrently; each gets its own
|
|
287
|
+
* WebSocket (required, since the URL embeds the trip key).
|
|
288
|
+
*/
|
|
289
|
+
export class ShareDBPool {
|
|
290
|
+
config;
|
|
291
|
+
clients = new Map();
|
|
292
|
+
constructor(config) {
|
|
293
|
+
this.config = config;
|
|
294
|
+
}
|
|
295
|
+
get(tripKey) {
|
|
296
|
+
let client = this.clients.get(tripKey);
|
|
297
|
+
if (!client) {
|
|
298
|
+
client = new ShareDBClient(this.config, tripKey);
|
|
299
|
+
this.clients.set(tripKey, client);
|
|
300
|
+
}
|
|
301
|
+
return client;
|
|
302
|
+
}
|
|
303
|
+
has(tripKey) {
|
|
304
|
+
return this.clients.has(tripKey);
|
|
305
|
+
}
|
|
306
|
+
closeAll() {
|
|
307
|
+
for (const client of this.clients.values()) {
|
|
308
|
+
client.close();
|
|
309
|
+
}
|
|
310
|
+
this.clients.clear();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=sharedb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sharedb.js","sourceRoot":"","sources":["../../src/transport/sharedb.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA0HA,MAAM,UAAU,YAAY,CAAC,KAAY;IACvC,OAAO,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,IAAI,KAAK,IAAI,CAAC,CAAE,KAAoB,CAAC,KAAK,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAY;IAC3C,OAAO,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,IAAI,KAAK,CAAC;AACxD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wanderlog-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Wanderlog — let Claude build and edit your trip itineraries through conversation",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"wanderlog-mcp": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=22"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"wanderlog",
|
|
20
|
+
"travel",
|
|
21
|
+
"itinerary",
|
|
22
|
+
"claude",
|
|
23
|
+
"llm",
|
|
24
|
+
"ai-agent"
|
|
25
|
+
],
|
|
26
|
+
"author": "shaikhspeare",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/shaikhspeare/wanderlog-mcp.git"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/shaikhspeare/wanderlog-mcp#readme",
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc",
|
|
35
|
+
"dev": "tsx --env-file=.env src/index.ts",
|
|
36
|
+
"probe": "node --env-file=.env probe.mjs",
|
|
37
|
+
"test": "vitest run tests/unit",
|
|
38
|
+
"test:watch": "vitest tests/unit",
|
|
39
|
+
"test:integration": "node --env-file=.env ./node_modules/vitest/vitest.mjs run tests/integration",
|
|
40
|
+
"test:all": "npm run test && npm run test:integration",
|
|
41
|
+
"typecheck": "tsc --noEmit",
|
|
42
|
+
"eval": "node --env-file=.env --import tsx evals/run.ts"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
46
|
+
"ws": "^8.18.0",
|
|
47
|
+
"zod": "^3.23.8"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@anthropic-ai/sdk": "^0.40.0",
|
|
51
|
+
"@types/node": "^22.10.2",
|
|
52
|
+
"@types/ws": "^8.5.13",
|
|
53
|
+
"tsx": "^4.19.2",
|
|
54
|
+
"typescript": "^5.7.2",
|
|
55
|
+
"vitest": "^2.1.8"
|
|
56
|
+
}
|
|
57
|
+
}
|