Skip to main content
Glama

Change a trip

write
Destructive

Change one trip: a batch of operations applied all or nothing (if one is refused, none apply), saved as one change in its history. It creates, updates and deletes that trip's records, only those this person may: items (place, goal, choice, stay, move, task, info), their own interest, notes, links, research, questions and answers, reminders, a friend's recommendations pad; the trip's details and its members (some only for the owner); and it removes files. An update overwrites the fields it sets: pass if_version from your read, and it's refused if the record changed since. This person can take a write back with undo, unless what it touched changed since or it changed who's in the trip, its owner or an offer of it, its join link or a pad's link. It can't delete the trip, add a file (upload_link, attach_file) or change another trip. It fetches the photos and links it saves from the web, to check them and show previews.

  • create item: {op:"create", type:"item", ref?, fields:{type, title, ...}}. type is place, goal, choice, stay, move, task or info.

  • set my interest: {op:"create", type:"interest", fields:{item, tier?, going?}}; tier is "no" (not interested), "maybe" or "yes" (really want it), going "yes", "no" or "maybe"; writing it again updates it. The others hear about my ratings and new notes, gathered once I pause.

  • a to-do: {op:"create", type:"item", fields:{type:"task", title, owner?, due?, important?}}; owner is a member or person id (they're notified); its due date reminds the owner (everyone, when there's none) 3 days before, on the day and the day after, at 9:00 their time; important:true when missing it costs money or the trip (everyone hears of it and its changes; see guide "todos"); done with {op:"update", id, set:{status:"done"}}.

  • a reminder Tripmo sends at its exact time (a notification on their devices, and an email), for a moment such as tickets going on sale; a due date needs none: {op:"create", type:"reminder", ref?, fields:{at:"2026-11-18T06:00", tz:"Asia/Singapore", to: "everyone" or [member ids], about?, text}}; at is local time in tz.

  • ask people a question: {op:"create", type:"ask", ref?, fields:{to: "everyone" or [member ids], about?, text, options?}}; close it {op:"update", id:"ask_…", set:{status:"closed"}} (only its author).

  • answer a question asked of you: {op:"create", type:"answer", fields:{ask, choice?, text?}}; writing it again changes your answer.

  • write a note (yours, attributed to you): {op:"create", type:"note", fields:{on, text}}; on is an item (or $ref), a finding (rsr_…), the trip's id, or a member id. Only you can change ({op:"update", id:"nte_…", set:{text}}) or delete yours.

  • save a link: {op:"create", type:"link", ref?, fields:{url, note?, items?}}; items are the places, goals or options it's about (ids or $refs); without items it waits in the inbox. Attach later with {op:"update", id:"lnk_…", set:{items:[…]}}.

  • save research (what you found out that isn't one place; shared, anyone's AI adds to it): {op:"create", type:"research", ref?, fields:{title, text, sources?, about?}}; text as short bullets, about the items it concerns. See guide "research".

  • a stay: {op:"create", type:"item", fields:{type:"stay", title, status?, where:{precision:"spot", name, address, city, lat, lng}, when:{precision:"days", start: check-in, end: check-out}}}; city on every stay, the city or town as people say it, never the ward or the prefecture ("Tokyo" for Oimachi, Shinagawa; "Ikaho", not Gunma; "Seoul", not Jung-gu): it heads the stay's group on the map. See guide "stays".

  • photos of a place, stay or option: fields photos:[{url, source, credit}], up to five pictures from the web, the best first, checked when written; refused ones come back in hints (photo_refused). See guide "photos".

  • who paid for something, and how: fields paid:[{by, amount, currency, method}]; method in a few words, the card by name ("Visa", "Mei's Visa", "Cash", "Bank transfer", "Citi Prestige points"), never its digits. A card on file charged later, on a day ("your card will be charged on 1 Nov"): charges:[{by, amount, currency, method, on}], not paid. See guide "money".

  • update: {op:"update", id, if_version?, set?, unset?}; keys may be dotted one level ("when.start"). Item types: place, goal (a want with candidates under it), choice (options under it: stays or moves with status "option"), stay, move, task, info.

  • delete: {op:"delete", id}; soft, kept in history. A choice takes its options and the to-dos about each with it (its result's with names them); undo brings back all of it. The trip and its members (ids from get_trip):

  • edit the trip: {op:"update", id:, set:{title?, brief?, dates?, budget?}}; anyone in the trip.

  • owner only: let someone in {op:"update", id:"mem_…", set:{status:"member"}}; if a let-in is refused because the trip is full, call add_seats; turn down or remove {op:"delete", id:"mem_…"}; offer the trip to another member {op:"update", id:, set:{owner:"mem_…"}}: it's theirs once they accept it, covering it as it is (their plan, or a Trip Pass and spots if it needs them); until then it's yours, and your own member id takes the offer back (offering it to someone else replaces it; it lapses after 14 days); new join link {op:"update", id:, set:{join_link:"new"}}.

  • a trip offered to you (get_trip's offer, with what taking it over needs): take it over {op:"update", id:, set:{owner:}}, using an unused Trip Pass of yours when it needs one; refused (payment_required) while something must be bought first, with buy_url for your human: once that's paid, it's theirs by itself. Turn it down: set owner to the owner's member id.

  • deleting the trip isn't a write: only its owner deletes it, on the web (Trip settings), so an AI's mistake can't lose one.

  • leave: delete your own member id (the owner first offers the trip to someone, who takes it over). Your profile (what you like, what you want in a stay: notes and data of your own): {op:"update", id:, set:{"profile.likes":"ramen, quiet temples"}}. Your currency is your account's, for every trip (get_trip's your_currency); "profile.currency" sets another for this trip alone (see guide "money"). Stop sharing your location: {op:"update", id:, set:{sharing_location:false}}. Returns the new ids and versions, the url of what changed (its card, the finding, or else the trip), not_on_map (what this write left with a location but no coordinates, to look up and send), hints (what it left looking like a common mistake, or what changing the trip's dates does to what's in it: things on relative days moving with its first day, things now outside its dates; to raise with your human), and your_currency when it set or took off your "profile.currency" (what's in use now, and a note to tell your human). Before writing a kind of thing for the first time, read its guide.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "trip": "<trip>",
      "reason": "<reason>",
      "ops": "<ops>"
    },
    "name": "write"
  }
}

Input Schema

NameRequiredDescriptionDefault
opsYes
tripYesThe trip id, e.g. "trp_8Kd2…", from list_trips.
reasonYesWhy, in a sentence the rest of the group will read.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / ops / items / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "amenities": {
      -            "items": {
      -              "maxLength": 80,
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "maxItems": 20,
      -            "type": "array"
      -          },
      -          "best_time": {
      -            "maxLength": 200,
      -            "type": "string"
      -          },
      -          "booking": {
      -            "additionalProperties": false,
      -            "properties": {
      -              "booked_by": {
      -                "type": "string"
      -              },
      -              "booker": {
      -                "type": "string"
      -              },
      -              "cancellation": {
      -                "additionalProperties": false,
      -                "properties": {
      -                  "steps": {
      -                    "items": {
      -                      "additionalProperties": false,
      -                      "properties": {
      -                        "refund": {
      -                          "anyOf": [
      -                            {
      -                              "const": "full",
      -                              "type": "string"
      -                            },
      -                            {
      -                              "additionalProperties": false,
      -                              "properties": {
      -                                "percent": {
      -                                  "maximum": 100,
      -                                  "minimum": 0,
      -                                  "type": "number"
      -                                }
      -                              },
      -                              "required": [
      -                                "percent"
      -                              ],
      -                              "type": "object"
      -                            },
      -                            {
      -                              "additionalProperties": false,
      -                              "properties": {
      -                                "amount": {
      -                                  "minimum": 0,
      -                                  "type": "number"
      -                                },
      -                                "currency": {
      -                                  "pattern": "^[A-Z]{3}$",
      -                                  "type": "string"
      -                                }
      -                              },
      -                              "required": [
      -                                "amount",
      -                                "currency"
      -                              ],
      -                              "type": "object"
      -                            }
      -                          ]
      -                        },
      -                        "until": {
      -                          "anyOf": [
      -                            {
      -                              "format": "date",
      -                              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      -                              "type": "string"
      -                            },
      -                            {
      -                              "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      -                              "type": "string"
      -                            }
      -                          ]
      -                        }
      -                      },
      -                      "required": [
      -                        "until",
      -                        "refund"
      -                      ],
      -                      "type": "object"
      -                    },
      -                    "maxItems": 10,
      -                    "type": "array"
      -                  },
      -                  "text": {
      -                    "maxLength": 1000,
      -                    "type": "string"
      -                  }
      -                },
      -                "required": [
      -                  "steps"
      -                ],
      -                "type": "object"
      -              },
      -              "cancelled_on": {
      -                "format": "date",
      -                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      -                "type": "string"
      -              },
      -              "for": {
      -                "items": {
      -                  "type": "string"
      -                },
      -                "type": "array"
      -              },
      -              "provider": {
      -                "maxLength": 100,
      -                "type": "string"
      -              },
      -              "ref": {
      -                "maxLength": 100,
      -                "type": "string"
      -              },
      -              "url": {
      -                "format": "uri",
      -                "type": "string"
      -              }
      -            },
      -            "type": "object"
      -          },
      -          "booking_needed": {
      -            "type": "boolean"
      -          },
      -          "books_from": {
      -            "anyOf": [
      -              {
      -                "format": "date",
      -                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      -                "type": "string"
      -              },
      -              {
      -                "additionalProperties": false,
      -                "properties": {
      -                  "days_before": {
      -                    "maximum": 400,
      -                    "minimum": 1,
      -                    "type": "integer"
      -                  }
      -                },
      -                "required": [
      -                  "days_before"
      -                ],
      -                "type": "object"
      -              }
      -            ]
      -          },
      -          "category": {
      -            "maxLength": 40,
      -            "type": "string"
      -          },
      -          "charges": {
      -            "description": "What a card on file will be charged later, on a day: [{by, amount, currency, method, on}]. See guide { topic: \"money\" }.",
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "amount": {
      -                  "exclusiveMinimum": 0,
      -                  "type": "number"
      -                },
      -                "by": {
      -                  "description": "Whose card it goes on: their member id (mem_…) or person id.",
      -                  "minLength": 1,
      -                  "type": "string"
      -                },
      -                "currency": {
      -                  "pattern": "^[A-Z]{3}$",
      -                  "type": "string"
      -                },
      -                "method": {
      -                  "description": "Which card, in a few words: \"Mastercard 8682\". Only a card's last 4 digits, never its whole number.",
      -                  "maxLength": 60,
      -                  "minLength": 1,
      -                  "type": "string"
      -                },
      -                "on": {
      -                  "description": "The day the card is charged, in the booking's own time zone.",
      -                  "format": "date",
      -                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "by",
      -                "amount",
      -                "currency",
      -                "on"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "closed": {
      -            "maxLength": 100,
      -            "type": "string"
      -          },
      -          "cons": {
      -            "items": {
      -              "maxLength": 200,
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "maxItems": 12,
      -            "type": "array"
      -          },
      -          "contact": {
      -            "additionalProperties": false,
      -            "properties": {
      -              "email": {
      -                "format": "email",
      -                "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
      -                "type": "string"
      -              },
      -              "phone": {
      -                "pattern": "^\\+?[\\d\\s().-]{5,30}$",
      -                "type": "string"
      -              },
      -              "social": {
      -                "description": "Its Instagram or other pages.",
      -                "items": {
      -                  "format": "uri",
      -                  "type": "string"
      -                },
      -                "maxItems": 5,
      -                "type": "array"
      -              },
      -              "website": {
      -                "format": "uri",
      -                "type": "string"
      -              }
      -            },
      -            "type": "object"
      -          },
      -          "cost": {
      -            "additionalProperties": false,
      -            "properties": {
      -              "amount": {
      -                "minimum": 0,
      -                "type": "number"
      -              },
      -              "category": {
      -                "enum": [
      -                  "stays",
      -                  "transport",
      -                  "food",
      -                  "activities",
      -                  "other"
      -                ],
      -                "type": "string"
      -              },
      -              "currency": {
      -                "pattern": "^[A-Z]{3}$",
      -                "type": "string"
      -              },
      -              "estimate": {
      -                "type": "boolean"
      -              },
      -              "per": {
      -                "enum": [
      -                  "person",
      -                  "group"
      -                ],
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "amount",
      -              "currency"
      -            ],
      -            "type": "object"
      -          },
      -          "data": {
      -            "additionalProperties": {},
      -            "propertyNames": {
      -              "type": "string"
      -            },
      -            "type": "object"
      -          },
      -          "due": {
      -            "format": "date",
      -            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      -            "type": "string"
      -          },
      -          "duration": {
      -            "maxLength": 40,
      -            "type": "string"
      -          },
      -          "from": {
      -            "additionalProperties": false,
      -            "properties": {
      -              "address": {
      -                "maxLength": 300,
      -                "type": "string"
      -              },
      -              "city": {
      -                "description": "The city or town it's in, as people say it, never the ward or the prefecture: \"Tokyo\" for Oimachi, Shinagawa; \"Ikaho\", not Gunma; \"Seoul\", not Jung-gu. On every stay: it heads the stay's group on the map.",
      -                "maxLength": 60,
      -                "minLength": 1,
      -                "type": "string"
      -              },
      -              "lat": {
      -                "maximum": 90,
      -                "minimum": -90,
      -                "type": "number"
      -              },
      -              "lng": {
      -                "maximum": 180,
      -                "minimum": -180,
      -                "type": "number"
      -              },
      -              "name": {
      -                "maxLength": 200,
      -                "type": "string"
      -              },
      -              "precision": {
      -                "enum": [
      -                  "spot",
      -                  "area",
      -                  "city",
      -                  "region",
      -                  "country",
      -                  "none"
      -                ],
      -                "type": "string"
      -              },
      -              "radius_m": {
      -                "exclusiveMinimum": 0,
      -                "maximum": 1000000,
      -                "type": "number"
      -              },
      -              "ref": {
      -                "maxLength": 500,
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "precision"
      -            ],
      -            "type": "object"
      -          },
      -          "getting_around": {
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "how": {
      -                  "description": "walk, bus, train, taxi, shuttle… (walk if not said)",
      -                  "maxLength": 40,
      -                  "type": "string"
      -                },
      -                "minutes": {
      -                  "maximum": 600,
      -                  "minimum": 0,
      -                  "type": "integer"
      -                },
      -                "note": {
      -                  "maxLength": 200,
      -                  "type": "string"
      -                },
      -                "to": {
      -                  "description": "Where to: \"Nagano Station (JR, Shinkansen)\", \"Haneda Airport\".",
      -                  "maxLength": 120,
      -                  "minLength": 1,
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "to"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 10,
      -            "type": "array"
      -          },
      -          "good_to_know": {
      -            "items": {
      -              "maxLength": 200,
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "maxItems": 10,
      -            "type": "array"
      -          },
      -          "hours": {
      -            "maxLength": 300,
      -            "type": "string"
      -          },
      -          "important": {
      -            "description": "Tasks: missing it costs money or the trip (a visa, a deposit, tickets that sell out). Everyone in the trip hears when it's done, moved, reassigned or removed.",
      -            "type": "boolean"
      -          },
      -          "links": {
      -            "items": {
      -              "format": "uri",
      -              "type": "string"
      -            },
      -            "maxItems": 20,
      -            "type": "array"
      -          },
      -          "nearby": {
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "minutes": {
      -                  "description": "Minutes' walk.",
      -                  "maximum": 120,
      -                  "minimum": 0,
      -                  "type": "integer"
      -                },
      -                "name": {
      -                  "maxLength": 120,
      -                  "minLength": 1,
      -                  "type": "string"
      -                },
      -                "note": {
      -                  "maxLength": 200,
      -                  "type": "string"
      -                },
      -                "what": {
      -                  "description": "food, shops, convenience store, sight…",
      -                  "maxLength": 60,
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "name"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 15,
      -            "type": "array"
      -          },
      -          "notes": {
      -            "maxLength": 4000,
      -            "type": "string"
      -          },
      -          "order": {
      -            "type": "number"
      -          },
      -          "origin": {
      -            "additionalProperties": false,
      -            "properties": {
      -              "by": {
      -                "description": "Which AI; Tripmo fills it in from the connection.",
      -                "maxLength": 100,
      -                "type": "string"
      -              },
      -              "kind": {
      -                "const": "ai",
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "kind"
      -            ],
      -            "type": "object"
      -          },
      -          "owner": {
      -            "type": "string"
      -          },
      -          "paid": {
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "amount": {
      -                  "exclusiveMinimum": 0,
      -                  "type": "number"
      -                },
      -                "by": {
      -                  "description": "The person who paid: their member id (mem_…) or person id.",
      -                  "minLength": 1,
      -                  "type": "string"
      -                },
      -                "currency": {
      -                  "pattern": "^[A-Z]{3}$",
      -                  "type": "string"
      -                },
      -                "method": {
      -                  "description": "How it was paid, in a few words: \"Mastercard 8682\", \"Cash\", \"Citi Prestige points\", \"Bank transfer\". Only a card's last 4 digits, never its whole number.",
      -                  "maxLength": 60,
      -                  "minLength": 1,
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "by",
      -                "amount",
      -                "currency"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "parent": {
      -            "type": "string"
      -          },
      -          "photos": {
      -            "description": "Up to five pictures of it from the web, the best first, references only. See guide { topic: \"photos\" }.",
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "credit": {
      -                  "description": "Who to credit: the site's or the photographer's name (\"Wikimedia Commons\", \"Kyoto City\").",
      -                  "maxLength": 100,
      -                  "minLength": 1,
      -                  "type": "string"
      -                },
      -                "source": {
      -                  "description": "The page it was found on; tapping the credit opens it.",
      -                  "format": "uri",
      -                  "maxLength": 2000,
      -                  "type": "string"
      -                },
      -                "url": {
      -                  "description": "The image itself (https), a mid-size version: Wikimedia's /960px- thumbnail, say.",
      -                  "format": "uri",
      -                  "maxLength": 2000,
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "url",
      -                "source",
      -                "credit"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 5,
      -            "type": "array"
      -          },
      -          "pros": {
      -            "items": {
      -              "maxLength": 200,
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "maxItems": 12,
      -            "type": "array"
      -          },
      -          "recommended_by": {
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "name": {
      -                  "description": "The friend's name, spelled as the trip already spells it.",
      -                  "maxLength": 100,
      -                  "minLength": 1,
      -                  "type": "string"
      -                },
      -                "pad": {
      -                  "description": "The pad it came through, when it did.",
      -                  "type": "string"
      -                },
      -                "said": {
      -                  "description": "Their own words, never rewritten.",
      -                  "maxLength": 1000,
      -                  "minLength": 1,
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "name"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 20,
      -            "type": "array"
      -          },
      -          "refunds": {
      -            "items": {
      -              "additionalProperties": false,
      -              "properties": {
      -                "amount": {
      -                  "exclusiveMinimum": 0,
      -                  "type": "number"
      -                },
      -                "currency": {
      -                  "pattern": "^[A-Z]{3}$",
      -                  "type": "string"
      -                },
      -                "received": {
      -                  "format": "date",
      -                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      -                  "type": "string"
      -                },
      -                "to": {
      -                  "description": "The person it goes back to: their member id (mem_…) or person id.",
      -                  "minLength": 1,
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "to",
      -                "amount",
      -                "currency"
      -              ],
      -              "type": "object"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "status": {
      -            "enum": [
      -              "idea",
      -              "planned",
      -              "booked",
      -              "cancelled",
      -              "done",
      -              "skipped",
      -              "missed",
      -              "dropped",
      -              "todo",
      -              "option",
      -              "not_chosen"
      -            ],
      -            "type": "string"
      -          },
      -          "tags": {
      -            "items": {
      -              "maxLength": 40,
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "maxItems": 20,
      -            "type": "array"
      -          },
      -          "title": {
      -            "maxLength": 200,
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "to": {
      -            "additionalProperties": false,
      -            "properties": {
      -              "address": {
      -                "maxLength": 300,
      -                "type": "string"
      -              },
      -              "city": {
      -                "description": "The city or town it's in, as people say it, never the ward or the prefecture: \"Tokyo\" for Oimachi, Shinagawa; \"Ikaho\", not Gunma; \"Seoul\", not Jung-gu. On every stay: it heads the stay's group on the map.",
      -                "maxLength": 60,
      -                "minLength": 1,
      -                "type": "string"
      -              },
      -              "lat": {
      -                "maximum": 90,
      -                "minimum": -90,
      -                "type": "number"
      -              },
      -              "lng": {
      -                "maximum": 180,
      -                "minimum": -180,
      -                "type": "number"
      -              },
      -              "name": {
      -                "maxLength": 200,
      -                "type": "string"
      -              },
      -              "precision": {
      -                "enum": [
      -                  "spot",
      -                  "area",
      -                  "city",
      -                  "region",
      -                  "country",
      -                  "none"
      -                ],
      -                "type": "string"
      -              },
      -              "radius_m": {
      -                "exclusiveMinimum": 0,
      -                "maximum": 1000000,
      -                "type": "number"
      -              },
      -              "ref": {
      -                "maxLength": 500,
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "precision"
      -            ],
      -            "type": "object"
      -          },
      -          "type": {
      -            "enum": [
      -              "place",
      -              "goal",
      -              "choice",
      -              "stay",
      -              "move",
      -              "task",
      -              "info"
      -            ],
      -            "type": "string"
      -          },
      -          "when": {
      -            "oneOf": [
      -              {
      -                "additionalProperties": false,
      -                "properties": {
      -                  "precision": {
      -                    "const": "none",
      -                    "type": "string"
      -                  }
      -                },
      -                "required": [
      -                  "precision"
      -                ],
      -                "type": "object"
      -              },
      -              {
      -                "additionalProperties": false,
      -                "properties": {
      -                  "end": {
      -                    "anyOf": [
      -                      {
      -                        "format": "date",
      -                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      -                        "type": "string"
      -                      },
      -                      {
      -                        "pattern": "^day [1-9]\\d{0,2}$",
      -                        "type": "string"
      -                      }
      -                    ]
      -                  },
      -                  "precision": {
      -                    "const": "days",
      -                    "type": "string"
      -                  },
      -                  "start": {
      -                    "anyOf": [
      -                      {
      -                        "format": "date",
      -                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      -                        "type": "string"
      -                      },
      -                      {
      -                        "pattern": "^day [1-9]\\d{0,2}$",
      -                        "type": "string"
      -                      }
      -                    ]
      -                  }
      -                },
      -                "required": [
      -                  "precision",
      -                  "start",
      -                  "end"
      -                ],
      -                "type": "object"
      -              },
      -              {
      -                "additionalProperties": false,
      -                "properties": {
      -                  "day": {
      -                    "anyOf": [
      -                      {
      -                        "format": "date",
      -                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      -                        "type": "string"
      -                      },
      -                      {
      -                        "pattern": "^day [1-9]\\d{0,2}$",
      -                        "type": "string"
      -                      }
      -                    ]
      -                  },
      -                  "precision": {
      -                    "const": "day",
      -                    "type": "string"
      -                  }
      -                },
      -                "required": [
      -                  "precision",
      -                  "day"
      -                ],
      -                "type": "object"
      -              },
      -              {
      -                "additionalProperties": false,
      -                "properties": {
      -                  "day": {
      -                    "anyOf": [
      -                      {
      -                        "format": "date",
      -                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      -                        "type": "string"
      -                      },
      -                      {
      -                        "pattern": "^day [1-9]\\d{0,2}$",
      -                        "type": "string"
      -                      }
      -                    ]
      -                  },
      -                  "part": {
      -                    "enum": [
      -                      "morning",
      -                      "afternoon",
      -                      "evening",
      -                      "night"
      -                    ],
      -                    "type": "string"
      -                  },
      -                  "precision": {
      -                    "const": "part",
      -                    "type": "string"
      -                  }
      -                },
      -                "required": [
      -                  "precision",
      -                  "part"
      -                ],
      -                "type": "object"
      -              },
      -              {
      -                "additionalProperties": false,
      -                "properties": {
      -                  "end": {
      -                    "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      -                    "type": "string"
      -                  },
      -                  "precision": {
      -                    "const": "window",
      -                    "type": "string"
      -                  },
      -                  "start": {
      -                    "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      -                    "type": "string"
      -                  },
      -                  "tz": {
      -                    "type": "string"
      -                  }
      -                },
      -                "required": [
      -                  "precision",
      -                  "start",
      -                  "end",
      -                  "tz"
      -                ],
      -                "type": "object"
      -              },
      -              {
      -                "additionalProperties": false,
      -                "properties": {
      -                  "end": {
      -                    "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      -                    "type": "string"
      -                  },
      -                  "end_tz": {
      -                    "type": "string"
      -                  },
      -                  "precision": {
      -                    "const": "exact",
      -                    "type": "string"
      -                  },
      -                  "start": {
      -                    "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      -                    "type": "string"
      -                  },
      -                  "tz": {
      -                    "type": "string"
      -                  }
      -                },
      -                "required": [
      -                  "precision",
      -                  "start",
      -                  "tz"
      -                ],
      -                "type": "object"
      -              }
      -            ]
      -          },
      -          "where": {
      -            "additionalProperties": false,
      -            "properties": {
      -              "address": {
      -                "maxLength": 300,
      -                "type": "string"
      -              },
      -              "city": {
      -                "description": "The city or town it's in, as people say it, never the ward or the prefecture: \"Tokyo\" for Oimachi, Shinagawa; \"Ikaho\", not Gunma; \"Seoul\", not Jung-gu. On every stay: it heads the stay's group on the map.",
      -                "maxLength": 60,
      -                "minLength": 1,
      -                "type": "string"
      -              },
      -              "lat": {
      -                "maximum": 90,
      -                "minimum": -90,
      -                "type": "number"
      -              },
      -              "lng": {
      -                "maximum": 180,
      -                "minimum": -180,
      -                "type": "number"
      -              },
      -              "name": {
      -                "maxLength": 200,
      -                "type": "string"
      -              },
      -              "precision": {
      -                "enum": [
      -                  "spot",
      -                  "area",
      -                  "city",
      -                  "region",
      -                  "country",
      -                  "none"
      -                ],
      -                "type": "string"
      -              },
      -              "radius_m": {
      -                "exclusiveMinimum": 0,
      -                "maximum": 1000000,
      -                "type": "number"
      -              },
      -              "ref": {
      -                "maxLength": 500,
      -                "type": "string"
      -              }
      -            },
      -            "required": [
      -              "precision"
      -            ],
      -            "type": "object"
      -          }
      -        },
      -        "required": [
      -          "type",
      -          "title"
      -        ],
      -        "type": "object"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "ref": {
      -        "description": "A name for this new item; later operations in the same batch can use it as $name.",
      -        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "item",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "type",
      -      "fields"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "going": {
      -            "enum": [
      -              "yes",
      -              "no",
      -              "maybe"
      -            ],
      -            "type": "string"
      -          },
      -          "item": {
      -            "description": "The item's id, or $ref of an item created earlier in this batch.",
      -            "type": "string"
      -          },
      -          "tier": {
      -            "description": "\"no\" (not interested), \"maybe\" or \"yes\" (really want it).",
      -            "enum": [
      -              "no",
      -              "maybe",
      -              "yes"
      -            ],
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "item"
      -        ],
      -        "type": "object"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "interest",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "type",
      -      "fields"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "items": {
      -            "description": "The ids (or $refs) of the places, goals or options it's about; none leaves it in the inbox.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "note": {
      -            "maxLength": 1000,
      -            "type": "string"
      -          },
      -          "url": {
      -            "format": "uri",
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "url"
      -        ],
      -        "type": "object"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "ref": {
      -        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "link",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "type",
      -      "fields"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "for": {
      -            "description": "The friend's name.",
      -            "maxLength": 100,
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "name": {
      -            "maxLength": 100,
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "prompt": {
      -            "description": "What we'd like tips on.",
      -            "maxLength": 500,
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "name",
      -          "for"
      -        ],
      -        "type": "object"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "ref": {
      -        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "pad",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "type",
      -      "fields"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "on": {
      -            "description": "What it's on: an item (or $ref), research (rsr_…), the trip's id, or a member id (mem_…).",
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "text": {
      -            "maxLength": 4000,
      -            "minLength": 1,
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "on",
      -          "text"
      -        ],
      -        "type": "object"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "ref": {
      -        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "note",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "type",
      -      "fields"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "about": {
      -            "description": "The item it's about, if any (an id or $ref).",
      -            "type": "string"
      -          },
      -          "options": {
      -            "items": {
      -              "maxLength": 100,
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "maxItems": 10,
      -            "minItems": 2,
      -            "type": "array"
      -          },
      -          "text": {
      -            "maxLength": 1000,
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "to": {
      -            "anyOf": [
      -              {
      -                "const": "everyone",
      -                "type": "string"
      -              },
      -              {
      -                "items": {
      -                  "minLength": 1,
      -                  "type": "string"
      -                },
      -                "maxItems": 50,
      -                "minItems": 1,
      -                "type": "array"
      -              }
      -            ],
      -            "description": "\"everyone\", or the people asked: member ids (mem_…) or person ids."
      -          }
      -        },
      -        "required": [
      -          "to",
      -          "text"
      -        ],
      -        "type": "object"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "ref": {
      -        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "ask",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "type",
      -      "fields"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "ask": {
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "choice": {
      -            "maxLength": 100,
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "text": {
      -            "maxLength": 2000,
      -            "minLength": 1,
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "ask"
      -        ],
      -        "type": "object"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "answer",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "type",
      -      "fields"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "about": {
      -            "description": "The item it's about, if any (an id or $ref).",
      -            "type": "string"
      -          },
      -          "at": {
      -            "description": "Local time at the place, e.g. 2026-11-18T09:00.",
      -            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      -            "type": "string"
      -          },
      -          "text": {
      -            "maxLength": 500,
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "to": {
      -            "anyOf": [
      -              {
      -                "const": "everyone",
      -                "type": "string"
      -              },
      -              {
      -                "items": {
      -                  "minLength": 1,
      -                  "type": "string"
      -                },
      -                "maxItems": 50,
      -                "minItems": 1,
      -                "type": "array"
      -              }
      -            ],
      -            "description": "\"everyone\", or the people to remind: member ids (mem_…) or person ids."
      -          },
      -          "tz": {
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "at",
      -          "tz",
      -          "to",
      -          "text"
      -        ],
      -        "type": "object"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "ref": {
      -        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "reminder",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "type",
      -      "fields"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "details": {
      -            "additionalProperties": {
      -              "anyOf": [
      -                {
      -                  "maxLength": 500,
      -                  "type": "string"
      -                },
      -                {
      -                  "type": "number"
      -                },
      -                {
      -                  "type": "boolean"
      -                }
      -              ]
      -            },
      -            "description": "Number, issuer, reference, anything else: only its owner and those it's shared with see these.",
      -            "propertyNames": {
      -              "maxLength": 60,
      -              "minLength": 1,
      -              "type": "string"
      -            },
      -            "type": "object"
      -          },
      -          "expires": {
      -            "description": "Seen by the trip.",
      -            "format": "date",
      -            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      -            "type": "string"
      -          },
      -          "kind": {
      -            "description": "passport, visa, insurance, licence, vaccination, or another kind.",
      -            "maxLength": 40,
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "shared_with": {
      -            "anyOf": [
      -              {
      -                "const": "everyone",
      -                "type": "string"
      -              },
      -              {
      -                "items": {
      -                  "minLength": 1,
      -                  "type": "string"
      -                },
      -                "maxItems": 50,
      -                "type": "array"
      -              }
      -            ],
      -            "description": "Who else sees the details: \"everyone\" in the trip, or member ids. Nobody when left out."
      -          },
      -          "status": {
      -            "description": "Seen by the trip: \"valid\", \"applied\", \"approved\"...",
      -            "maxLength": 60,
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "title": {
      -            "maxLength": 200,
      -            "minLength": 1,
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "kind",
      -          "title"
      -        ],
      -        "type": "object"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "ref": {
      -        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "document",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "type",
      -      "fields"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "fields": {
      -        "additionalProperties": false,
      -        "properties": {
      -          "about": {
      -            "description": "The ids (or $refs) of the items it's about; none for the trip in general.",
      -            "items": {
      -              "type": "string"
      -            },
      -            "maxItems": 50,
      -            "type": "array"
      -          },
      -          "sources": {
      -            "items": {
      -              "format": "uri",
      -              "type": "string"
      -            },
      -            "maxItems": 20,
      -            "type": "array"
      -          },
      -          "text": {
      -            "description": "The answer as short labelled bullets (\"- **Single tickets:** ¥41,000\").",
      -            "maxLength": 4000,
      -            "minLength": 1,
      -            "type": "string"
      -          },
      -          "title": {
      -            "description": "The question: \"JR Pass vs single tickets\".",
      -            "maxLength": 200,
      -            "minLength": 1,
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "title",
      -          "text"
      -        ],
      -        "type": "object"
      -      },
      -      "op": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "ref": {
      -        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "research",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "type",
      -      "fields"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "id": {
      -        "type": "string"
      -      },
      -      "if_version": {
      -        "description": "Fail unless the record is still at this version.",
      -        "exclusiveMinimum": 0,
      -        "maximum": 9007199254740991,
      -        "type": "integer"
      -      },
      -      "op": {
      -        "const": "update",
      -        "type": "string"
      -      },
      -      "set": {
      -        "additionalProperties": {},
      -        "description": "Fields to set. Keys are field names or dotted paths one level deep, e.g. \"when.start\".",
      -        "propertyNames": {
      -          "type": "string"
      -        },
      -        "type": "object"
      -      },
      -      "unset": {
      -        "description": "Fields to remove, same keys as set.",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "id": {
      -        "type": "string"
      -      },
      -      "op": {
      -        "const": "delete",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "op",
      -      "id"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "fields": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "amenities": {
      +            "items": {
      +              "maxLength": 80,
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "maxItems": 20,
      +            "type": "array"
      +          },
      +          "best_time": {
      +            "maxLength": 200,
      +            "type": "string"
      +          },
      +          "booking": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "booked_by": {
      +                "type": "string"
      +              },
      +              "booker": {
      +                "type": "string"
      +              },
      +              "cancellation": {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "steps": {
      +                    "items": {
      +                      "additionalProperties": false,
      +                      "properties": {
      +                        "refund": {
      +                          "anyOf": [
      +                            {
      +                              "const": "full",
      +                              "type": "string"
      +                            },
      +                            {
      +                              "additionalProperties": false,
      +                              "properties": {
      +                                "percent": {
      +                                  "maximum": 100,
      +                                  "minimum": 0,
      +                                  "type": "number"
      +                                }
      +                              },
      +                              "required": [
      +                                "percent"
      +                              ],
      +                              "type": "object"
      +                            },
      +                            {
      +                              "additionalProperties": false,
      +                              "properties": {
      +                                "amount": {
      +                                  "minimum": 0,
      +                                  "type": "number"
      +                                },
      +                                "currency": {
      +                                  "pattern": "^[A-Z]{3}$",
      +                                  "type": "string"
      +                                }
      +                              },
      +                              "required": [
      +                                "amount",
      +                                "currency"
      +                              ],
      +                              "type": "object"
      +                            }
      +                          ]
      +                        },
      +                        "until": {
      +                          "anyOf": [
      +                            {
      +                              "format": "date",
      +                              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +                              "type": "string"
      +                            },
      +                            {
      +                              "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      +                              "type": "string"
      +                            }
      +                          ]
      +                        }
      +                      },
      +                      "required": [
      +                        "until",
      +                        "refund"
      +                      ],
      +                      "type": "object"
      +                    },
      +                    "maxItems": 10,
      +                    "type": "array"
      +                  },
      +                  "text": {
      +                    "maxLength": 1000,
      +                    "type": "string"
      +                  }
      +                },
      +                "required": [
      +                  "steps"
      +                ],
      +                "type": "object"
      +              },
      +              "cancelled_on": {
      +                "format": "date",
      +                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +                "type": "string"
      +              },
      +              "for": {
      +                "items": {
      +                  "type": "string"
      +                },
      +                "type": "array"
      +              },
      +              "provider": {
      +                "maxLength": 100,
      +                "type": "string"
      +              },
      +              "ref": {
      +                "maxLength": 100,
      +                "type": "string"
      +              },
      +              "url": {
      +                "format": "uri",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "booking_needed": {
      +            "type": "boolean"
      +          },
      +          "books_from": {
      +            "anyOf": [
      +              {
      +                "format": "date",
      +                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +                "type": "string"
      +              },
      +              {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "days_before": {
      +                    "maximum": 400,
      +                    "minimum": 1,
      +                    "type": "integer"
      +                  }
      +                },
      +                "required": [
      +                  "days_before"
      +                ],
      +                "type": "object"
      +              }
      +            ]
      +          },
      +          "category": {
      +            "maxLength": 40,
      +            "type": "string"
      +          },
      +          "charges": {
      +            "description": "What a card on file will be charged later, on a day: [{by, amount, currency, method, on}]. See guide { topic: \"money\" }.",
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "amount": {
      +                  "exclusiveMinimum": 0,
      +                  "type": "number"
      +                },
      +                "by": {
      +                  "description": "Whose card it goes on: their member id (mem_…) or person id.",
      +                  "minLength": 1,
      +                  "type": "string"
      +                },
      +                "currency": {
      +                  "pattern": "^[A-Z]{3}$",
      +                  "type": "string"
      +                },
      +                "method": {
      +                  "description": "Which card, by name: \"Mei's Visa\". Never its digits.",
      +                  "maxLength": 60,
      +                  "minLength": 1,
      +                  "type": "string"
      +                },
      +                "on": {
      +                  "description": "The day the card is charged, in the booking's own time zone.",
      +                  "format": "date",
      +                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "by",
      +                "amount",
      +                "currency",
      +                "on"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "closed": {
      +            "maxLength": 100,
      +            "type": "string"
      +          },
      +          "cons": {
      +            "items": {
      +              "maxLength": 200,
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "maxItems": 12,
      +            "type": "array"
      +          },
      +          "contact": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "email": {
      +                "format": "email",
      +                "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
      +                "type": "string"
      +              },
      +              "phone": {
      +                "pattern": "^\\+?[\\d\\s().-]{5,30}$",
      +                "type": "string"
      +              },
      +              "social": {
      +                "description": "Its Instagram or other pages.",
      +                "items": {
      +                  "format": "uri",
      +                  "type": "string"
      +                },
      +                "maxItems": 5,
      +                "type": "array"
      +              },
      +              "website": {
      +                "format": "uri",
      +                "type": "string"
      +              }
      +            },
      +            "type": "object"
      +          },
      +          "cost": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "amount": {
      +                "minimum": 0,
      +                "type": "number"
      +              },
      +              "category": {
      +                "enum": [
      +                  "stays",
      +                  "transport",
      +                  "food",
      +                  "activities",
      +                  "other"
      +                ],
      +                "type": "string"
      +              },
      +              "currency": {
      +                "pattern": "^[A-Z]{3}$",
      +                "type": "string"
      +              },
      +              "estimate": {
      +                "type": "boolean"
      +              },
      +              "per": {
      +                "enum": [
      +                  "person",
      +                  "group"
      +                ],
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "amount",
      +              "currency"
      +            ],
      +            "type": "object"
      +          },
      +          "data": {
      +            "additionalProperties": {},
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          },
      +          "due": {
      +            "format": "date",
      +            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +            "type": "string"
      +          },
      +          "duration": {
      +            "maxLength": 40,
      +            "type": "string"
      +          },
      +          "from": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "address": {
      +                "maxLength": 300,
      +                "type": "string"
      +              },
      +              "city": {
      +                "description": "The city or town it's in, as people say it, never the ward or the prefecture: \"Tokyo\" for Oimachi, Shinagawa; \"Ikaho\", not Gunma; \"Seoul\", not Jung-gu. On every stay: it heads the stay's group on the map.",
      +                "maxLength": 60,
      +                "minLength": 1,
      +                "type": "string"
      +              },
      +              "lat": {
      +                "maximum": 90,
      +                "minimum": -90,
      +                "type": "number"
      +              },
      +              "lng": {
      +                "maximum": 180,
      +                "minimum": -180,
      +                "type": "number"
      +              },
      +              "name": {
      +                "maxLength": 200,
      +                "type": "string"
      +              },
      +              "precision": {
      +                "enum": [
      +                  "spot",
      +                  "area",
      +                  "city",
      +                  "region",
      +                  "country",
      +                  "none"
      +                ],
      +                "type": "string"
      +              },
      +              "radius_m": {
      +                "exclusiveMinimum": 0,
      +                "maximum": 1000000,
      +                "type": "number"
      +              },
      +              "ref": {
      +                "maxLength": 500,
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "precision"
      +            ],
      +            "type": "object"
      +          },
      +          "getting_around": {
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "how": {
      +                  "description": "walk, bus, train, taxi, shuttle… (walk if not said)",
      +                  "maxLength": 40,
      +                  "type": "string"
      +                },
      +                "minutes": {
      +                  "maximum": 600,
      +                  "minimum": 0,
      +                  "type": "integer"
      +                },
      +                "note": {
      +                  "maxLength": 200,
      +                  "type": "string"
      +                },
      +                "to": {
      +                  "description": "Where to: \"Nagano Station (JR, Shinkansen)\", \"Haneda Airport\".",
      +                  "maxLength": 120,
      +                  "minLength": 1,
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "to"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 10,
      +            "type": "array"
      +          },
      +          "good_to_know": {
      +            "items": {
      +              "maxLength": 200,
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "maxItems": 10,
      +            "type": "array"
      +          },
      +          "hours": {
      +            "maxLength": 300,
      +            "type": "string"
      +          },
      +          "important": {
      +            "description": "Tasks: missing it costs money or the trip (a visa, a deposit, tickets that sell out). Everyone in the trip hears when it's done, moved, reassigned or removed.",
      +            "type": "boolean"
      +          },
      +          "links": {
      +            "items": {
      +              "format": "uri",
      +              "type": "string"
      +            },
      +            "maxItems": 20,
      +            "type": "array"
      +          },
      +          "nearby": {
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "minutes": {
      +                  "description": "Minutes' walk.",
      +                  "maximum": 120,
      +                  "minimum": 0,
      +                  "type": "integer"
      +                },
      +                "name": {
      +                  "maxLength": 120,
      +                  "minLength": 1,
      +                  "type": "string"
      +                },
      +                "note": {
      +                  "maxLength": 200,
      +                  "type": "string"
      +                },
      +                "what": {
      +                  "description": "food, shops, convenience store, sight…",
      +                  "maxLength": 60,
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "name"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 15,
      +            "type": "array"
      +          },
      +          "notes": {
      +            "maxLength": 4000,
      +            "type": "string"
      +          },
      +          "order": {
      +            "type": "number"
      +          },
      +          "origin": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "by": {
      +                "description": "Which AI; Tripmo fills it in from the connection.",
      +                "maxLength": 100,
      +                "type": "string"
      +              },
      +              "kind": {
      +                "const": "ai",
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "kind"
      +            ],
      +            "type": "object"
      +          },
      +          "owner": {
      +            "type": "string"
      +          },
      +          "paid": {
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "amount": {
      +                  "exclusiveMinimum": 0,
      +                  "type": "number"
      +                },
      +                "by": {
      +                  "description": "The person who paid: their member id (mem_…) or person id.",
      +                  "minLength": 1,
      +                  "type": "string"
      +                },
      +                "currency": {
      +                  "pattern": "^[A-Z]{3}$",
      +                  "type": "string"
      +                },
      +                "method": {
      +                  "description": "How it was paid, in a few words, the card by name: \"Visa\", \"Mei's Visa\", \"Cash\", \"Bank transfer\", \"Citi Prestige points\". Never its digits.",
      +                  "maxLength": 60,
      +                  "minLength": 1,
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "by",
      +                "amount",
      +                "currency"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "parent": {
      +            "type": "string"
      +          },
      +          "photos": {
      +            "description": "Up to five pictures of it from the web, the best first, references only. See guide { topic: \"photos\" }.",
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "credit": {
      +                  "description": "Who to credit: the site's or the photographer's name (\"Wikimedia Commons\", \"Kyoto City\").",
      +                  "maxLength": 100,
      +                  "minLength": 1,
      +                  "type": "string"
      +                },
      +                "source": {
      +                  "description": "The page it was found on; tapping the credit opens it.",
      +                  "format": "uri",
      +                  "maxLength": 2000,
      +                  "type": "string"
      +                },
      +                "url": {
      +                  "description": "The image itself (https), a mid-size version: Wikimedia's /960px- thumbnail, say.",
      +                  "format": "uri",
      +                  "maxLength": 2000,
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "url",
      +                "source",
      +                "credit"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 5,
      +            "type": "array"
      +          },
      +          "pros": {
      +            "items": {
      +              "maxLength": 200,
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "maxItems": 12,
      +            "type": "array"
      +          },
      +          "recommended_by": {
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "name": {
      +                  "description": "The friend's name, spelled as the trip already spells it.",
      +                  "maxLength": 100,
      +                  "minLength": 1,
      +                  "type": "string"
      +                },
      +                "pad": {
      +                  "description": "The pad it came through, when it did.",
      +                  "type": "string"
      +                },
      +                "said": {
      +                  "description": "Their own words, never rewritten.",
      +                  "maxLength": 1000,
      +                  "minLength": 1,
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "name"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 20,
      +            "type": "array"
      +          },
      +          "refunds": {
      +            "items": {
      +              "additionalProperties": false,
      +              "properties": {
      +                "amount": {
      +                  "exclusiveMinimum": 0,
      +                  "type": "number"
      +                },
      +                "currency": {
      +                  "pattern": "^[A-Z]{3}$",
      +                  "type": "string"
      +                },
      +                "received": {
      +                  "format": "date",
      +                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +                  "type": "string"
      +                },
      +                "to": {
      +                  "description": "The person it goes back to: their member id (mem_…) or person id.",
      +                  "minLength": 1,
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "to",
      +                "amount",
      +                "currency"
      +              ],
      +              "type": "object"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "status": {
      +            "enum": [
      +              "idea",
      +              "planned",
      +              "booked",
      +              "cancelled",
      +              "done",
      +              "skipped",
      +              "missed",
      +              "dropped",
      +              "todo",
      +              "option",
      +              "not_chosen"
      +            ],
      +            "type": "string"
      +          },
      +          "tags": {
      +            "items": {
      +              "maxLength": 40,
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "maxItems": 20,
      +            "type": "array"
      +          },
      +          "title": {
      +            "maxLength": 200,
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "to": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "address": {
      +                "maxLength": 300,
      +                "type": "string"
      +              },
      +              "city": {
      +                "description": "The city or town it's in, as people say it, never the ward or the prefecture: \"Tokyo\" for Oimachi, Shinagawa; \"Ikaho\", not Gunma; \"Seoul\", not Jung-gu. On every stay: it heads the stay's group on the map.",
      +                "maxLength": 60,
      +                "minLength": 1,
      +                "type": "string"
      +              },
      +              "lat": {
      +                "maximum": 90,
      +                "minimum": -90,
      +                "type": "number"
      +              },
      +              "lng": {
      +                "maximum": 180,
      +                "minimum": -180,
      +                "type": "number"
      +              },
      +              "name": {
      +                "maxLength": 200,
      +                "type": "string"
      +              },
      +              "precision": {
      +                "enum": [
      +                  "spot",
      +                  "area",
      +                  "city",
      +                  "region",
      +                  "country",
      +                  "none"
      +                ],
      +                "type": "string"
      +              },
      +              "radius_m": {
      +                "exclusiveMinimum": 0,
      +                "maximum": 1000000,
      +                "type": "number"
      +              },
      +              "ref": {
      +                "maxLength": 500,
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "precision"
      +            ],
      +            "type": "object"
      +          },
      +          "type": {
      +            "enum": [
      +              "place",
      +              "goal",
      +              "choice",
      +              "stay",
      +              "move",
      +              "task",
      +              "info"
      +            ],
      +            "type": "string"
      +          },
      +          "when": {
      +            "oneOf": [
      +              {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "precision": {
      +                    "const": "none",
      +                    "type": "string"
      +                  }
      +                },
      +                "required": [
      +                  "precision"
      +                ],
      +                "type": "object"
      +              },
      +              {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "end": {
      +                    "anyOf": [
      +                      {
      +                        "format": "date",
      +                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +                        "type": "string"
      +                      },
      +                      {
      +                        "pattern": "^day [1-9]\\d{0,2}$",
      +                        "type": "string"
      +                      }
      +                    ]
      +                  },
      +                  "precision": {
      +                    "const": "days",
      +                    "type": "string"
      +                  },
      +                  "start": {
      +                    "anyOf": [
      +                      {
      +                        "format": "date",
      +                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +                        "type": "string"
      +                      },
      +                      {
      +                        "pattern": "^day [1-9]\\d{0,2}$",
      +                        "type": "string"
      +                      }
      +                    ]
      +                  }
      +                },
      +                "required": [
      +                  "precision",
      +                  "start",
      +                  "end"
      +                ],
      +                "type": "object"
      +              },
      +              {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "day": {
      +                    "anyOf": [
      +                      {
      +                        "format": "date",
      +                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +                        "type": "string"
      +                      },
      +                      {
      +                        "pattern": "^day [1-9]\\d{0,2}$",
      +                        "type": "string"
      +                      }
      +                    ]
      +                  },
      +                  "precision": {
      +                    "const": "day",
      +                    "type": "string"
      +                  }
      +                },
      +                "required": [
      +                  "precision",
      +                  "day"
      +                ],
      +                "type": "object"
      +              },
      +              {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "day": {
      +                    "anyOf": [
      +                      {
      +                        "format": "date",
      +                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
      +                        "type": "string"
      +                      },
      +                      {
      +                        "pattern": "^day [1-9]\\d{0,2}$",
      +                        "type": "string"
      +                      }
      +                    ]
      +                  },
      +                  "part": {
      +                    "enum": [
      +                      "morning",
      +                      "afternoon",
      +                      "evening",
      +                      "night"
      +                    ],
      +                    "type": "string"
      +                  },
      +                  "precision": {
      +                    "const": "part",
      +                    "type": "string"
      +                  }
      +                },
      +                "required": [
      +                  "precision",
      +                  "part"
      +                ],
      +                "type": "object"
      +              },
      +              {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "end": {
      +                    "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      +                    "type": "string"
      +                  },
      +                  "precision": {
      +                    "const": "window",
      +                    "type": "string"
      +                  },
      +                  "start": {
      +                    "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      +                    "type": "string"
      +                  },
      +                  "tz": {
      +                    "type": "string"
      +                  }
      +                },
      +                "required": [
      +                  "precision",
      +                  "start",
      +                  "end",
      +                  "tz"
      +                ],
      +                "type": "object"
      +              },
      +              {
      +                "additionalProperties": false,
      +                "properties": {
      +                  "end": {
      +                    "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      +                    "type": "string"
      +                  },
      +                  "end_tz": {
      +                    "type": "string"
      +                  },
      +                  "precision": {
      +                    "const": "exact",
      +                    "type": "string"
      +                  },
      +                  "start": {
      +                    "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      +                    "type": "string"
      +                  },
      +                  "tz": {
      +                    "type": "string"
      +                  }
      +                },
      +                "required": [
      +                  "precision",
      +                  "start",
      +                  "tz"
      +                ],
      +                "type": "object"
      +              }
      +            ]
      +          },
      +          "where": {
      +            "additionalProperties": false,
      +            "properties": {
      +              "address": {
      +                "maxLength": 300,
      +                "type": "string"
      +              },
      +              "city": {
      +                "description": "The city or town it's in, as people say it, never the ward or the prefecture: \"Tokyo\" for Oimachi, Shinagawa; \"Ikaho\", not Gunma; \"Seoul\", not Jung-gu. On every stay: it heads the stay's group on the map.",
      +                "maxLength": 60,
      +                "minLength": 1,
      +                "type": "string"
      +              },
      +              "lat": {
      +                "maximum": 90,
      +                "minimum": -90,
      +                "type": "number"
      +              },
      +              "lng": {
      +                "maximum": 180,
      +                "minimum": -180,
      +                "type": "number"
      +              },
      +              "name": {
      +                "maxLength": 200,
      +                "type": "string"
      +              },
      +              "precision": {
      +                "enum": [
      +                  "spot",
      +                  "area",
      +                  "city",
      +                  "region",
      +                  "country",
      +                  "none"
      +                ],
      +                "type": "string"
      +              },
      +              "radius_m": {
      +                "exclusiveMinimum": 0,
      +                "maximum": 1000000,
      +                "type": "number"
      +              },
      +              "ref": {
      +                "maxLength": 500,
      +                "type": "string"
      +              }
      +            },
      +            "required": [
      +              "precision"
      +            ],
      +            "type": "object"
      +          }
      +        },
      +        "required": [
      +          "type",
      +          "title"
      +        ],
      +        "type": "object"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "ref": {
      +        "description": "A name for this new item; later operations in the same batch can use it as $name.",
      +        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "item",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "type",
      +      "fields"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "fields": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "going": {
      +            "enum": [
      +              "yes",
      +              "no",
      +              "maybe"
      +            ],
      +            "type": "string"
      +          },
      +          "item": {
      +            "description": "The item's id, or $ref of an item created earlier in this batch.",
      +            "type": "string"
      +          },
      +          "tier": {
      +            "description": "\"no\" (not interested), \"maybe\" or \"yes\" (really want it).",
      +            "enum": [
      +              "no",
      +              "maybe",
      +              "yes"
      +            ],
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "item"
      +        ],
      +        "type": "object"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "interest",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "type",
      +      "fields"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "fields": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "items": {
      +            "description": "The ids (or $refs) of the places, goals or options it's about; none leaves it in the inbox.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "note": {
      +            "maxLength": 1000,
      +            "type": "string"
      +          },
      +          "url": {
      +            "format": "uri",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "url"
      +        ],
      +        "type": "object"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "ref": {
      +        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "link",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "type",
      +      "fields"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "fields": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "for": {
      +            "description": "The friend's name.",
      +            "maxLength": 100,
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "name": {
      +            "maxLength": 100,
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "prompt": {
      +            "description": "What we'd like tips on.",
      +            "maxLength": 500,
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "name",
      +          "for"
      +        ],
      +        "type": "object"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "ref": {
      +        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "pad",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "type",
      +      "fields"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "fields": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "on": {
      +            "description": "What it's on: an item (or $ref), research (rsr_…), the trip's id, or a member id (mem_…).",
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "text": {
      +            "maxLength": 4000,
      +            "minLength": 1,
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "on",
      +          "text"
      +        ],
      +        "type": "object"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "ref": {
      +        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "note",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "type",
      +      "fields"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "fields": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "about": {
      +            "description": "The item it's about, if any (an id or $ref).",
      +            "type": "string"
      +          },
      +          "options": {
      +            "items": {
      +              "maxLength": 100,
      +              "minLength": 1,
      +              "type": "string"
      +            },
      +            "maxItems": 10,
      +            "minItems": 2,
      +            "type": "array"
      +          },
      +          "text": {
      +            "maxLength": 1000,
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "to": {
      +            "anyOf": [
      +              {
      +                "const": "everyone",
      +                "type": "string"
      +              },
      +              {
      +                "items": {
      +                  "minLength": 1,
      +                  "type": "string"
      +                },
      +                "maxItems": 50,
      +                "minItems": 1,
      +                "type": "array"
      +              }
      +            ],
      +            "description": "\"everyone\", or the people asked: member ids (mem_…) or person ids."
      +          }
      +        },
      +        "required": [
      +          "to",
      +          "text"
      +        ],
      +        "type": "object"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "ref": {
      +        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "ask",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "type",
      +      "fields"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "fields": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "ask": {
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "choice": {
      +            "maxLength": 100,
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "text": {
      +            "maxLength": 2000,
      +            "minLength": 1,
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "ask"
      +        ],
      +        "type": "object"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "answer",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "type",
      +      "fields"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "fields": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "about": {
      +            "description": "The item it's about, if any (an id or $ref).",
      +            "type": "string"
      +          },
      +          "at": {
      +            "description": "Local time at the place, e.g. 2026-11-18T09:00.",
      +            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2})?$",
      +            "type": "string"
      +          },
      +          "text": {
      +            "maxLength": 500,
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "to": {
      +            "anyOf": [
      +              {
      +                "const": "everyone",
      +                "type": "string"
      +              },
      +              {
      +                "items": {
      +                  "minLength": 1,
      +                  "type": "string"
      +                },
      +                "maxItems": 50,
      +                "minItems": 1,
      +                "type": "array"
      +              }
      +            ],
      +            "description": "\"everyone\", or the people to remind: member ids (mem_…) or person ids."
      +          },
      +          "tz": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "at",
      +          "tz",
      +          "to",
      +          "text"
      +        ],
      +        "type": "object"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "ref": {
      +        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "reminder",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "type",
      +      "fields"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "fields": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "about": {
      +            "description": "The ids (or $refs) of the items it's about; none for the trip in general.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "maxItems": 50,
      +            "type": "array"
      +          },
      +          "sources": {
      +            "items": {
      +              "format": "uri",
      +              "type": "string"
      +            },
      +            "maxItems": 20,
      +            "type": "array"
      +          },
      +          "text": {
      +            "description": "The answer as short labelled bullets (\"- **Single tickets:** ¥41,000\").",
      +            "maxLength": 4000,
      +            "minLength": 1,
      +            "type": "string"
      +          },
      +          "title": {
      +            "description": "The question: \"JR Pass vs single tickets\".",
      +            "maxLength": 200,
      +            "minLength": 1,
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "title",
      +          "text"
      +        ],
      +        "type": "object"
      +      },
      +      "op": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "ref": {
      +        "pattern": "^[A-Za-z0-9_-]{1,40}$",
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "research",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "type",
      +      "fields"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "id": {
      +        "type": "string"
      +      },
      +      "if_version": {
      +        "description": "Fail unless the record is still at this version.",
      +        "exclusiveMinimum": 0,
      +        "maximum": 9007199254740991,
      +        "type": "integer"
      +      },
      +      "op": {
      +        "const": "update",
      +        "type": "string"
      +      },
      +      "set": {
      +        "additionalProperties": {},
      +        "description": "Fields to set. Keys are field names or dotted paths one level deep, e.g. \"when.start\".",
      +        "propertyNames": {
      +          "type": "string"
      +        },
      +        "type": "object"
      +      },
      +      "unset": {
      +        "description": "Fields to remove, same keys as set.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "id": {
      +        "type": "string"
      +      },
      +      "op": {
      +        "const": "delete",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "op",
      +      "id"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. First observed

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds rich behavioral detail beyond the annotations: all-or-nothing application, soft deletes retained in history, conditional overwrite via if_version, undo limitations, permission gating for member actions, web fetching for photos and links, and what the tool returns including hints and not_on_map. This is exactly the kind of context annotations alone cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the key atomic-batch and permission summary, then organizes detail into bullets. However, it is extremely long and dense, duplicating information that is also available in the schema and in referenced guides such as 'todos', 'research', 'stays', 'photos', and 'money'. It is useful but not concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a highly complex mutation tool with no output schema, the description is complete enough to call correctly: it explains the batch model, permissions, versioning, undo, return values, and many operation-specific field expectations. The remaining gaps are minor relative to the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema description coverage at 67%, the description compensates strongly by explaining operation shapes for create, update, and delete, giving concrete examples for items, interests, tasks, reminders, asks, answers, notes, links, research, stays, photos, payments, and membership changes. Some schema fields, such as booking, refunds, and contact details, are not explored in the description, but the core parameter semantics are well covered.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Change one trip: a batch of operations applied all or nothing'. It clearly distinguishes this tool from siblings like undo, upload_link, attach_file, and add_seats by explicitly noting what it cannot do or when a sibling is required.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives substantial usage context: it explains atomic batch semantics, permission boundaries, undo limitations, and when to use alternatives such as undo, add_seats, upload_link, and attach_file. It does not provide a general 'use this instead of query when...' rule for every case, but the operational guidance is extensive and clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources