@mseep/wanderlog-mcp 0.3.1

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.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +282 -0
  3. package/dist/cache/trip-cache.js +87 -0
  4. package/dist/cache/trip-cache.js.map +1 -0
  5. package/dist/config.js +38 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/context.js +12 -0
  8. package/dist/context.js.map +1 -0
  9. package/dist/errors.js +93 -0
  10. package/dist/errors.js.map +1 -0
  11. package/dist/formatters/trip-summary.js +296 -0
  12. package/dist/formatters/trip-summary.js.map +1 -0
  13. package/dist/http.js +165 -0
  14. package/dist/http.js.map +1 -0
  15. package/dist/index.js +48 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/ot/apply.js +282 -0
  18. package/dist/ot/apply.js.map +1 -0
  19. package/dist/resolvers/day.js +83 -0
  20. package/dist/resolvers/day.js.map +1 -0
  21. package/dist/resolvers/place-ref.js +194 -0
  22. package/dist/resolvers/place-ref.js.map +1 -0
  23. package/dist/server.js +164 -0
  24. package/dist/server.js.map +1 -0
  25. package/dist/tools/add-checklist.js +59 -0
  26. package/dist/tools/add-checklist.js.map +1 -0
  27. package/dist/tools/add-expense.js +127 -0
  28. package/dist/tools/add-expense.js.map +1 -0
  29. package/dist/tools/add-hotel.js +92 -0
  30. package/dist/tools/add-hotel.js.map +1 -0
  31. package/dist/tools/add-note.js +63 -0
  32. package/dist/tools/add-note.js.map +1 -0
  33. package/dist/tools/add-place.js +151 -0
  34. package/dist/tools/add-place.js.map +1 -0
  35. package/dist/tools/annotate-place.js +114 -0
  36. package/dist/tools/annotate-place.js.map +1 -0
  37. package/dist/tools/create-trip.js +85 -0
  38. package/dist/tools/create-trip.js.map +1 -0
  39. package/dist/tools/edit-note.js +217 -0
  40. package/dist/tools/edit-note.js.map +1 -0
  41. package/dist/tools/get-guide.js +42 -0
  42. package/dist/tools/get-guide.js.map +1 -0
  43. package/dist/tools/get-trip-url.js +52 -0
  44. package/dist/tools/get-trip-url.js.map +1 -0
  45. package/dist/tools/get-trip.js +43 -0
  46. package/dist/tools/get-trip.js.map +1 -0
  47. package/dist/tools/list-trips.js +32 -0
  48. package/dist/tools/list-trips.js.map +1 -0
  49. package/dist/tools/remove-note.js +107 -0
  50. package/dist/tools/remove-note.js.map +1 -0
  51. package/dist/tools/remove-place.js +95 -0
  52. package/dist/tools/remove-place.js.map +1 -0
  53. package/dist/tools/rename-day.js +64 -0
  54. package/dist/tools/rename-day.js.map +1 -0
  55. package/dist/tools/search-guides.js +172 -0
  56. package/dist/tools/search-guides.js.map +1 -0
  57. package/dist/tools/search-places.js +81 -0
  58. package/dist/tools/search-places.js.map +1 -0
  59. package/dist/tools/shared.js +216 -0
  60. package/dist/tools/shared.js.map +1 -0
  61. package/dist/tools/update-trip-dates.js +211 -0
  62. package/dist/tools/update-trip-dates.js.map +1 -0
  63. package/dist/transport/rest.js +152 -0
  64. package/dist/transport/rest.js.map +1 -0
  65. package/dist/transport/sharedb.js +323 -0
  66. package/dist/transport/sharedb.js.map +1 -0
  67. package/dist/types.js +7 -0
  68. package/dist/types.js.map +1 -0
  69. package/package.json +61 -0
package/dist/server.js ADDED
@@ -0,0 +1,164 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { addChecklist, addChecklistDescription, addChecklistInputSchema, } from "./tools/add-checklist.js";
3
+ import { addExpense, addExpenseDescription, addExpenseInputSchema, } from "./tools/add-expense.js";
4
+ import { annotatePlace, annotatePlaceDescription, annotatePlaceInputSchema, } from "./tools/annotate-place.js";
5
+ import { addHotel, addHotelDescription, addHotelInputSchema, } from "./tools/add-hotel.js";
6
+ import { addNote, addNoteDescription, addNoteInputSchema, } from "./tools/add-note.js";
7
+ import { addPlace, addPlaceDescription, addPlaceInputSchema, } from "./tools/add-place.js";
8
+ import { createTrip, createTripDescription, createTripInputSchema, } from "./tools/create-trip.js";
9
+ import { getTrip, getTripDescription, getTripInputSchema, } from "./tools/get-trip.js";
10
+ import { getTripUrl, getTripUrlDescription, getTripUrlInputSchema, } from "./tools/get-trip-url.js";
11
+ import { listTrips, listTripsDescription, listTripsInputSchema, } from "./tools/list-trips.js";
12
+ import { removePlace, removePlaceDescription, removePlaceInputSchema, } from "./tools/remove-place.js";
13
+ import { searchPlaces, searchPlacesDescription, searchPlacesInputSchema, } from "./tools/search-places.js";
14
+ import { updateTripDates, updateTripDatesDescription, updateTripDatesInputSchema, } from "./tools/update-trip-dates.js";
15
+ import { renameDay, renameDayDescription, renameDayInputSchema, } from "./tools/rename-day.js";
16
+ import { editNote, editNoteDescription, editNoteInputSchema, } from "./tools/edit-note.js";
17
+ import { removeNote, removeNoteDescription, removeNoteInputSchema, } from "./tools/remove-note.js";
18
+ import { searchGuides, searchGuidesDescription, searchGuidesInputSchema, } from "./tools/search-guides.js";
19
+ import { getGuide, getGuideDescription, getGuideInputSchema, } from "./tools/get-guide.js";
20
+ const AUTH_ERROR_RESPONSE = {
21
+ content: [
22
+ {
23
+ type: "text",
24
+ text: "Authentication required. Update WANDERLOG_COOKIE with a valid connect.sid cookie from wanderlog.com and restart the server.",
25
+ },
26
+ ],
27
+ isError: true,
28
+ };
29
+ function requireAuth(ctx, handler) {
30
+ return async (args) => {
31
+ if (!ctx.authenticated)
32
+ return AUTH_ERROR_RESPONSE;
33
+ return handler(args);
34
+ };
35
+ }
36
+ const SERVER_INSTRUCTIONS = `
37
+ You are connected to Wanderdog, an MCP server for building Wanderlog trip itineraries.
38
+
39
+ When a user asks you to create an itinerary or plan a trip, build it in full — not just a list
40
+ of places. A complete itinerary uses these building blocks:
41
+
42
+ 1. wanderlog_add_place — 3-5 places per day (attractions, restaurants, activities).
43
+ ALWAYS use the "note" parameter to attach practical context directly to the place: how to
44
+ get there, what to order, booking tips, opening hours. ALWAYS use "start_time" and
45
+ "end_time" to schedule each place (e.g. start_time: "09:00", end_time: "10:30").
46
+ This is one tool call instead of two — faster and the note lives on the place itself.
47
+ 2. wanderlog_add_note — use ONLY for freestanding commentary between places: neighborhood
48
+ context, multi-stop transit directions, or day-level tips not about a specific place.
49
+ Do NOT use add_note for per-place context — use the "note" param on add_place instead.
50
+ 3. wanderlog_add_hotel — one hotel block covering the full stay
51
+ 4. wanderlog_add_checklist — at least one pre-trip checklist (visa, currency, offline maps,
52
+ return ticket, travel insurance) and per-day checklists for days that need advance prep
53
+ 5. wanderlog_add_expense — add estimated costs for meals, entrance fees, transport passes.
54
+ Link each expense to its place for budget tracking.
55
+ 6. wanderlog_annotate_place — update an existing place with a note, start/end time, or both.
56
+ 7. wanderlog_search_guides + wanderlog_get_guide — when the user wants inspiration ("give
57
+ me an itinerary I can copy", "what guides exist for Vietnam"), call search_guides FIRST
58
+ to list curated user-written guides for the destination, then get_guide with the chosen
59
+ guide_key to read the full content. Use this for OTHER people's published guides; for
60
+ your own trips use wanderlog_get_trip.
61
+
62
+ Example add_place call with all features:
63
+ wanderlog_add_place(trip_key, place: "Sensō-ji", day: "day 1",
64
+ note: "Arrive before 9am to avoid crowds. Free entry. The Nakamise shopping street
65
+ leading to the temple is great for souvenirs and snacks.",
66
+ start_time: "08:30", end_time: "10:00")
67
+
68
+ Places without notes and times are just pins on a map. Rich places make an itinerary useful.
69
+ `.trim();
70
+ export function buildServer(ctx) {
71
+ const server = new McpServer({ name: "wanderlog-mcp", version: "0.2.0" }, { instructions: SERVER_INSTRUCTIONS });
72
+ server.registerTool("wanderlog_list_trips", {
73
+ title: "List Wanderlog trips",
74
+ description: listTripsDescription,
75
+ inputSchema: listTripsInputSchema,
76
+ }, requireAuth(ctx, async (args) => listTrips(ctx, args)));
77
+ server.registerTool("wanderlog_get_trip", {
78
+ title: "Get a Wanderlog trip",
79
+ description: getTripDescription,
80
+ inputSchema: getTripInputSchema,
81
+ }, requireAuth(ctx, async (args) => getTrip(ctx, args)));
82
+ server.registerTool("wanderlog_get_trip_url", {
83
+ title: "Get the wanderlog.com URL for a trip",
84
+ description: getTripUrlDescription,
85
+ inputSchema: getTripUrlInputSchema,
86
+ }, requireAuth(ctx, async (args) => getTripUrl(ctx, args)));
87
+ server.registerTool("wanderlog_search_places", {
88
+ title: "Search places near a Wanderlog trip",
89
+ description: searchPlacesDescription,
90
+ inputSchema: searchPlacesInputSchema,
91
+ }, requireAuth(ctx, async (args) => searchPlaces(ctx, args)));
92
+ server.registerTool("wanderlog_search_guides", {
93
+ title: "Search Wanderlog travel guides",
94
+ description: searchGuidesDescription,
95
+ inputSchema: searchGuidesInputSchema,
96
+ }, requireAuth(ctx, async (args) => searchGuides(ctx, args)));
97
+ server.registerTool("wanderlog_get_guide", {
98
+ title: "Read a Wanderlog travel guide",
99
+ description: getGuideDescription,
100
+ inputSchema: getGuideInputSchema,
101
+ }, requireAuth(ctx, async (args) => getGuide(ctx, args)));
102
+ server.registerTool("wanderlog_create_trip", {
103
+ title: "Create a Wanderlog trip",
104
+ description: createTripDescription,
105
+ inputSchema: createTripInputSchema,
106
+ }, requireAuth(ctx, async (args) => createTrip(ctx, args)));
107
+ server.registerTool("wanderlog_add_place", {
108
+ title: "Add a place to a Wanderlog trip",
109
+ description: addPlaceDescription,
110
+ inputSchema: addPlaceInputSchema,
111
+ }, requireAuth(ctx, async (args) => addPlace(ctx, args)));
112
+ server.registerTool("wanderlog_add_hotel", {
113
+ title: "Add a hotel booking to a Wanderlog trip",
114
+ description: addHotelDescription,
115
+ inputSchema: addHotelInputSchema,
116
+ }, requireAuth(ctx, async (args) => addHotel(ctx, args)));
117
+ server.registerTool("wanderlog_add_note", {
118
+ title: "Add a note to a Wanderlog trip",
119
+ description: addNoteDescription,
120
+ inputSchema: addNoteInputSchema,
121
+ }, requireAuth(ctx, async (args) => addNote(ctx, args)));
122
+ server.registerTool("wanderlog_add_checklist", {
123
+ title: "Add a checklist to a Wanderlog trip",
124
+ description: addChecklistDescription,
125
+ inputSchema: addChecklistInputSchema,
126
+ }, requireAuth(ctx, async (args) => addChecklist(ctx, args)));
127
+ server.registerTool("wanderlog_annotate_place", {
128
+ title: "Update a place with notes, times, or both",
129
+ description: annotatePlaceDescription,
130
+ inputSchema: annotatePlaceInputSchema,
131
+ }, requireAuth(ctx, async (args) => annotatePlace(ctx, args)));
132
+ server.registerTool("wanderlog_add_expense", {
133
+ title: "Add a budget expense to a Wanderlog trip",
134
+ description: addExpenseDescription,
135
+ inputSchema: addExpenseInputSchema,
136
+ }, requireAuth(ctx, async (args) => addExpense(ctx, args)));
137
+ server.registerTool("wanderlog_remove_place", {
138
+ title: "Remove a place from a Wanderlog trip",
139
+ description: removePlaceDescription,
140
+ inputSchema: removePlaceInputSchema,
141
+ }, requireAuth(ctx, async (args) => removePlace(ctx, args)));
142
+ server.registerTool("wanderlog_edit_note", {
143
+ title: "Edit note content in a Wanderlog trip",
144
+ description: editNoteDescription,
145
+ inputSchema: editNoteInputSchema,
146
+ }, requireAuth(ctx, async (args) => editNote(ctx, args)));
147
+ server.registerTool("wanderlog_remove_note", {
148
+ title: "Remove a note from a Wanderlog trip",
149
+ description: removeNoteDescription,
150
+ inputSchema: removeNoteInputSchema,
151
+ }, requireAuth(ctx, async (args) => removeNote(ctx, args)));
152
+ server.registerTool("wanderlog_update_trip_dates", {
153
+ title: "Update a Wanderlog trip's date range",
154
+ description: updateTripDatesDescription,
155
+ inputSchema: updateTripDatesInputSchema,
156
+ }, requireAuth(ctx, async (args) => updateTripDates(ctx, args)));
157
+ server.registerTool("wanderlog_rename_day", {
158
+ title: "Rename a day heading in a Wanderlog trip",
159
+ description: renameDayDescription,
160
+ inputSchema: renameDayInputSchema,
161
+ }, requireAuth(ctx, async (args) => renameDay(ctx, args)));
162
+ return server;
163
+ }
164
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { z } from "zod";
2
+ import { WanderlogError } from "../errors.js";
3
+ import { buildChecklistBlock, findTargetSection, requireUserId, submitOp, } from "./shared.js";
4
+ export const addChecklistInputSchema = {
5
+ trip_key: z
6
+ .string()
7
+ .min(1)
8
+ .describe("The trip to add the checklist to. Use wanderlog_list_trips if you don't know the key."),
9
+ items: z
10
+ .array(z.string().min(1))
11
+ .min(1)
12
+ .describe("Checklist items. Each string becomes one checkbox item, initially unchecked."),
13
+ title: z
14
+ .string()
15
+ .optional()
16
+ .describe("Optional title for the checklist (e.g. 'Packing list'). Omit for an untitled checklist."),
17
+ day: z
18
+ .string()
19
+ .optional()
20
+ .describe("Optional day to add the checklist to. Accepts 'day 2', 'May 4', or ISO '2026-05-04'. Omit to add to the 'Places to visit' list."),
21
+ };
22
+ export const addChecklistDescription = `
23
+ Adds a checklist to a Wanderlog trip. Each item starts unchecked and can be ticked off in the
24
+ Wanderlog app.
25
+
26
+ Add at least one checklist per trip. Common patterns:
27
+ - On the trip (no day): a packing list or "before departure" checklist
28
+ - On day 1: an arrival-day checklist ("pick up Oyster card", "check into hotel", "buy SIM")
29
+ - On specific days: day-of tasks ("bring swimsuit", "charge camera", "carry cash for market")
30
+
31
+ Returns a confirmation including the checklist title and item count.
32
+ `.trim();
33
+ export async function addChecklist(ctx, args) {
34
+ try {
35
+ const userId = requireUserId(ctx);
36
+ const entry = await ctx.tripCache.getEntry(args.trip_key);
37
+ const trip = entry.snapshot;
38
+ const target = findTargetSection(trip, args.day);
39
+ const block = buildChecklistBlock(args.items, args.title ?? "", userId);
40
+ const insertIndex = target.section.blocks.length;
41
+ const ops = [
42
+ {
43
+ p: ["itinerary", "sections", target.index, "blocks", insertIndex],
44
+ li: block,
45
+ },
46
+ ];
47
+ await submitOp(ctx, args.trip_key, ops);
48
+ const titlePart = args.title ? `"${args.title}" ` : "";
49
+ const text = `Added checklist ${titlePart}(${args.items.length} items) to ${target.label} in "${trip.title}".`;
50
+ return { content: [{ type: "text", text }] };
51
+ }
52
+ catch (err) {
53
+ const msg = err instanceof WanderlogError
54
+ ? err.toUserMessage()
55
+ : `Unexpected error: ${err.message}`;
56
+ return { content: [{ type: "text", text: msg }], isError: true };
57
+ }
58
+ }
59
+ //# sourceMappingURL=add-checklist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-checklist.js","sourceRoot":"","sources":["../../src/tools/add-checklist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,QAAQ,GACT,MAAM,aAAa,CAAC;AAErB,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,uFAAuF,CAAC;IACpG,KAAK,EAAE,CAAC;SACL,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACxB,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,8EAA8E,CAAC;IAC3F,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,yFAAyF,CAAC;IACtG,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,iIAAiI,CAClI;CACJ,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;CAUtC,CAAC,IAAI,EAAE,CAAC;AAST,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAe,EACf,IAAU;IAEV,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC;QAE5B,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAEjD,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;QACxE,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;QACjD,MAAM,GAAG,GAAc;YACrB;gBACE,CAAC,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC;gBACjE,EAAE,EAAE,KAAK;aACV;SACF,CAAC;QAEF,MAAM,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAExC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,mBAAmB,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,cAAc,MAAM,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC;QAC/G,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GACP,GAAG,YAAY,cAAc;YAC3B,CAAC,CAAC,GAAG,CAAC,aAAa,EAAE;YACrB,CAAC,CAAC,qBAAsB,GAAa,CAAC,OAAO,EAAE,CAAC;QACpD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACnE,CAAC;AACH,CAAC"}
@@ -0,0 +1,127 @@
1
+ import { z } from "zod";
2
+ import { WanderlogError } from "../errors.js";
3
+ import { resolvePlaceRef } from "../resolvers/place-ref.js";
4
+ import { isPlaceBlock } from "../types.js";
5
+ import { generateBlockId, requireUserId, submitOp } from "./shared.js";
6
+ export const addExpenseInputSchema = {
7
+ trip_key: z
8
+ .string()
9
+ .min(1)
10
+ .describe("The trip to add the expense to."),
11
+ amount: z
12
+ .number()
13
+ .positive()
14
+ .describe("Cost amount (e.g. 50, 12.50)."),
15
+ currency: z
16
+ .string()
17
+ .min(3)
18
+ .max(3)
19
+ .default("USD")
20
+ .describe("ISO 4217 currency code (e.g. 'USD', 'JPY', 'EUR'). Defaults to USD."),
21
+ category: z
22
+ .enum([
23
+ "food",
24
+ "drinks",
25
+ "groceries",
26
+ "publicTransit",
27
+ "carRental",
28
+ "gas",
29
+ "flights",
30
+ "lodging",
31
+ "sightseeing",
32
+ "activities",
33
+ "shopping",
34
+ "other",
35
+ ])
36
+ .default("other")
37
+ .describe("Expense category."),
38
+ description: z
39
+ .string()
40
+ .min(1)
41
+ .describe("What the expense is for (e.g. 'Lunch at Ichiran Ramen', 'Subway day pass')."),
42
+ place: z
43
+ .string()
44
+ .min(1)
45
+ .describe("Natural-language reference to link this expense to a place in the trip (e.g. 'Sensō-ji', 'the hotel'). Required — every expense must be linked to a place."),
46
+ date: z
47
+ .string()
48
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "must be YYYY-MM-DD")
49
+ .optional()
50
+ .describe("Date of the expense, YYYY-MM-DD. Defaults to today if omitted."),
51
+ };
52
+ export const addExpenseDescription = `
53
+ Adds a budget expense to a Wanderlog trip linked to a specific place. Expenses appear in the
54
+ trip's budget tracker on the linked place.
55
+
56
+ Use this after adding places to give the trip a cost dimension — estimated meal costs, entrance
57
+ fees, transport passes, etc. The place must already exist in the trip.
58
+
59
+ Returns confirmation with the expense amount and description.
60
+ `.trim();
61
+ export async function addExpense(ctx, args) {
62
+ try {
63
+ const userId = requireUserId(ctx);
64
+ const entry = await ctx.tripCache.getEntry(args.trip_key);
65
+ const trip = entry.snapshot;
66
+ // Every expense must be linked to a place — Wanderlog's UI crashes on
67
+ // unlinked expenses (blockId: null triggers an undefined .text access).
68
+ const result = resolvePlaceRef(trip, args.place);
69
+ if (result.kind === "ambiguous") {
70
+ const lines = result.candidates.map((c, i) => {
71
+ const name = isPlaceBlock(c.block) ? c.block.place.name : `block #${c.block.id}`;
72
+ const loc = c.section.date ? `day ${c.section.date}` : c.section.heading || "unscheduled";
73
+ return ` ${i + 1}. ${name} (${loc})`;
74
+ });
75
+ const text = `Multiple places match "${args.place}":\n${lines.join("\n")}\n\nRetry with a more specific reference.`;
76
+ return { content: [{ type: "text", text }] };
77
+ }
78
+ if (result.kind === "none") {
79
+ throw new WanderlogError(`No place matching "${args.place}" found in "${trip.title}"`, "place_ref_not_found", {
80
+ hint: "Add the place to the trip first with wanderlog_add_place, then add the expense.",
81
+ followUps: [
82
+ `Call wanderlog_get_trip with trip_key "${args.trip_key}" to see existing places.`,
83
+ ],
84
+ });
85
+ }
86
+ const blockId = result.match.block.id;
87
+ const associatedDate = result.match.section.date;
88
+ const expenseDate = args.date ?? new Date().toISOString().slice(0, 10);
89
+ // Build the expense object matching Wanderlog's schema
90
+ const expense = {
91
+ id: generateBlockId(),
92
+ amount: {
93
+ amount: args.amount,
94
+ currencyCode: args.currency.toUpperCase(),
95
+ },
96
+ category: args.category,
97
+ description: args.description,
98
+ date: expenseDate,
99
+ paidByUserId: userId,
100
+ paidByUser: { type: "registered", id: userId },
101
+ splitWith: { type: "individuals", users: [] },
102
+ blockId: blockId,
103
+ associatedDate: associatedDate ?? expenseDate,
104
+ };
105
+ // Find the current expenses array length to insert at the end
106
+ const budget = trip.itinerary.budget;
107
+ const expenses = budget?.expenses ?? [];
108
+ const insertIndex = expenses.length;
109
+ const ops = [
110
+ {
111
+ p: ["itinerary", "budget", "expenses", insertIndex],
112
+ li: expense,
113
+ },
114
+ ];
115
+ await submitOp(ctx, args.trip_key, ops);
116
+ const currencyLabel = args.currency.toUpperCase();
117
+ const text = `Added expense: ${currencyLabel} ${args.amount} for "${args.description}" (linked to ${args.place}) in "${trip.title}".`;
118
+ return { content: [{ type: "text", text }] };
119
+ }
120
+ catch (err) {
121
+ const msg = err instanceof WanderlogError
122
+ ? err.toUserMessage()
123
+ : `Unexpected error: ${err.message}`;
124
+ return { content: [{ type: "text", text: msg }], isError: true };
125
+ }
126
+ }
127
+ //# sourceMappingURL=add-expense.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-expense.js","sourceRoot":"","sources":["../../src/tools/add-expense.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ import { z } from "zod";
2
+ import { WanderlogError, WanderlogValidationError } from "../errors.js";
3
+ import { buildPlaceBlock, findHotelsSection, findTripCenter, requireUserId, submitOp, } from "./shared.js";
4
+ export const addHotelInputSchema = {
5
+ trip_key: z.string().min(1).describe("The trip to add the hotel to."),
6
+ hotel: z
7
+ .string()
8
+ .min(1)
9
+ .describe("Hotel name to search for. Examples: 'Park Hyatt Tokyo', 'the cheap hostel near the train station'. Matched against Google Places near the trip's destination."),
10
+ check_in: z
11
+ .string()
12
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "must be YYYY-MM-DD")
13
+ .describe("Check-in date, YYYY-MM-DD."),
14
+ check_out: z
15
+ .string()
16
+ .regex(/^\d{4}-\d{2}-\d{2}$/, "must be YYYY-MM-DD")
17
+ .describe("Check-out date, YYYY-MM-DD. Must be after check_in."),
18
+ };
19
+ export const addHotelDescription = `
20
+ Adds a hotel booking to a Wanderlog trip with check-in and check-out dates. If the trip does
21
+ not yet have a "Hotels and lodging" section, one is created automatically.
22
+
23
+ Returns confirmation with the resolved hotel name and the booking window.
24
+ `.trim();
25
+ export async function addHotel(ctx, args) {
26
+ try {
27
+ if (args.check_out <= args.check_in) {
28
+ throw new WanderlogValidationError(`check_out (${args.check_out}) must be after check_in (${args.check_in})`);
29
+ }
30
+ const userId = requireUserId(ctx);
31
+ const entry = await ctx.tripCache.getEntry(args.trip_key);
32
+ const trip = entry.snapshot;
33
+ const center = findTripCenter(trip, entry.geos);
34
+ if (!center) {
35
+ throw new WanderlogValidationError(`Cannot add hotel to "${trip.title}" because no location anchor is available`, "This trip has no associated geo and no existing places.");
36
+ }
37
+ const predictions = await ctx.rest.searchPlacesAutocomplete({
38
+ input: args.hotel,
39
+ sessionToken: crypto.randomUUID(),
40
+ location: { latitude: center.lat, longitude: center.lng },
41
+ radius: 15000,
42
+ });
43
+ if (predictions.length === 0) {
44
+ throw new WanderlogError(`No hotel found matching "${args.hotel}" near ${trip.title}`, "hotel_not_found", "Try a more specific name or check the spelling.");
45
+ }
46
+ const detail = await ctx.rest.getPlaceDetails(predictions[0].place_id);
47
+ const block = buildPlaceBlock(detail, userId, {
48
+ hotel: {
49
+ checkIn: args.check_in,
50
+ checkOut: args.check_out,
51
+ travelerNames: [],
52
+ confirmationNumber: null,
53
+ },
54
+ });
55
+ const existing = findHotelsSection(trip);
56
+ const ops = existing
57
+ ? [
58
+ {
59
+ p: ["itinerary", "sections", existing.index, "blocks", existing.section.blocks.length],
60
+ li: block,
61
+ },
62
+ ]
63
+ : [
64
+ {
65
+ // Insert a new hotels section after the Notes section (index 1).
66
+ // The existing sections shift down by 1.
67
+ p: ["itinerary", "sections", 1],
68
+ li: {
69
+ id: Math.floor(Math.random() * 1_000_000_000),
70
+ type: "hotels",
71
+ mode: "placeList",
72
+ heading: "Hotels and lodging",
73
+ date: null,
74
+ blocks: [block],
75
+ placeMarkerColor: "#7045af",
76
+ placeMarkerIcon: "bed",
77
+ text: { ops: [{ insert: "\n" }] },
78
+ },
79
+ },
80
+ ];
81
+ await submitOp(ctx, args.trip_key, ops);
82
+ const text = `Added ${detail.name} to "${trip.title}" · check-in ${args.check_in} → check-out ${args.check_out}.`;
83
+ return { content: [{ type: "text", text }] };
84
+ }
85
+ catch (err) {
86
+ const msg = err instanceof WanderlogError
87
+ ? err.toUserMessage()
88
+ : `Unexpected error: ${err.message}`;
89
+ return { content: [{ type: "text", text: msg }], isError: true };
90
+ }
91
+ }
92
+ //# sourceMappingURL=add-hotel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-hotel.js","sourceRoot":"","sources":["../../src/tools/add-hotel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import { z } from "zod";
2
+ import { WanderlogError } from "../errors.js";
3
+ import { buildNoteBlock, findTargetSection, requireUserId, submitOp, } from "./shared.js";
4
+ export const addNoteInputSchema = {
5
+ trip_key: z
6
+ .string()
7
+ .min(1)
8
+ .describe("The trip to add the note to. Use wanderlog_list_trips if you don't know the key."),
9
+ text: z
10
+ .string()
11
+ .min(1)
12
+ .describe("The note text. Plain text — can be multi-line."),
13
+ day: z
14
+ .string()
15
+ .optional()
16
+ .describe("Optional day to add the note to. Accepts 'day 2', 'May 4', or ISO '2026-05-04'. Omit to add to the 'Places to visit' list."),
17
+ };
18
+ export const addNoteDescription = `
19
+ Adds a text note to a Wanderlog trip. Notes appear inline between places in a day, acting as
20
+ the connective tissue of the itinerary. Every well-built day should have notes between stops.
21
+
22
+ When to add a note (do this after adding each place or group of places):
23
+ - How to get there: "Walk 15 min along the South Bank, or take the Jubilee line one stop"
24
+ - Practical tips: "Book tickets online at least 2 days ahead — sells out in summer"
25
+ - Food/drink recs: "Try the salt beef bagel at Beigel Bake — cash only, open 24hrs"
26
+ - Time guidance: "Budget 2-3 hours here. Open 10am-6pm, closed Tuesdays"
27
+ - Neighborhood context: "This area is great for wandering — no rush, just explore the lanes"
28
+
29
+ Returns a confirmation of where the note was added.
30
+ `.trim();
31
+ export async function addNote(ctx, args) {
32
+ try {
33
+ const userId = requireUserId(ctx);
34
+ const entry = await ctx.tripCache.getEntry(args.trip_key);
35
+ const trip = entry.snapshot;
36
+ const target = findTargetSection(trip, args.day);
37
+ // Step 1: Insert the note block with placeholder text
38
+ const block = buildNoteBlock(userId);
39
+ const insertIndex = target.section.blocks.length;
40
+ const blockPath = ["itinerary", "sections", target.index, "blocks", insertIndex];
41
+ const insertOps = [{ p: blockPath, li: block }];
42
+ await submitOp(ctx, args.trip_key, insertOps);
43
+ // Step 2: Set the note text via rich-text subtype op
44
+ const textOps = [
45
+ {
46
+ p: [...blockPath, "text"],
47
+ t: "rich-text",
48
+ o: [{ insert: `${args.text}\n` }],
49
+ },
50
+ ];
51
+ await submitOp(ctx, args.trip_key, textOps);
52
+ const preview = args.text.length > 60 ? `${args.text.slice(0, 57)}…` : args.text;
53
+ const text = `Added note "${preview}" to ${target.label} in "${trip.title}".`;
54
+ return { content: [{ type: "text", text }] };
55
+ }
56
+ catch (err) {
57
+ const msg = err instanceof WanderlogError
58
+ ? err.toUserMessage()
59
+ : `Unexpected error: ${err.message}`;
60
+ return { content: [{ type: "text", text: msg }], isError: true };
61
+ }
62
+ }
63
+ //# sourceMappingURL=add-note.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-note.js","sourceRoot":"","sources":["../../src/tools/add-note.ts"],"names":[],"mappings":"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"}