{"serverInfo":{"name":"vibeofthecity","title":"Vibe of the City","version":"1.0.0-beta"},"description":"Vibe of the City knows cities and the people who travel them: what is on this week and the weather, places and what stands at a spot, how a city fits a traveller's vibe, and — with the user's consent — their own trips, saved places and travel vibe, which an assistant can read and plan with.","documentationUrl":"https://www.vibeofthe.city/docs/mcp","websiteUrl":"https://www.vibeofthe.city","transport":{"type":"streamable-http","url":"https://www.vibeofthe.city/api/public/mcp"},"protocolVersions":["2025-11-25","2025-06-18","2025-03-26"],"authentication":{"required":true,"schemes":["oauth2","bearer"],"protectedResourceMetadata":"https://www.vibeofthe.city/.well-known/oauth-protected-resource","authorizationServerMetadata":"https://www.vibeofthe.city/.well-known/oauth-authorization-server","scopes":["public:read","me:read","me:write"],"apiKeys":"https://www.vibeofthe.city/en/account/api-keys"},"capabilities":{"tools":{"listChanged":false}},"tools":[{"name":"find_city","title":"Find a city","description":"Looks up the cities Vibe of the City covers by name and returns their city_slug. Call it first whenever another tool needs a city_slug.","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"City name, e.g. \"Lisbon\" or \"Málaga\".","minLength":2,"maxLength":80}},"required":["query"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"public:read"},{"name":"get_city_week","title":"City week","description":"The weather forecast from today and what is on in a city (concerts, markets, festivals) over the next days. Use it to answer \"what is on\", \"what will the weather be\" or to plan around rain.","inputSchema":{"type":"object","properties":{"city_slug":{"type":"string","description":"From find_city, e.g. \"lisbon-pt\".","minLength":2,"maxLength":80},"days":{"type":"integer","description":"How many days from today, 1 to 14. Default 7.","minimum":1,"maximum":14}},"required":["city_slug"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"public:read"},{"name":"get_host_guide","title":"Host guide","description":"A published host guide (a holiday flat, a hotel, a guide's page): check-in facts, house information and the host's own tips with coordinates.","inputSchema":{"type":"object","properties":{"host_slug":{"type":"string","description":"The slug in the guide's link, e.g. \"ferienwohnung-hindenburgstr-18\".","minLength":2,"maxLength":120}},"required":["host_slug"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"public:read"},{"name":"search_places","title":"Search places","description":"Finds places (cafés, museums, bars, parks, shops) or a street address by name or kind, optionally near a point or a town. Returns a place_ref for each place, which save_place and add_trip_idea take, and matching addresses with their coordinates. Pass near_lat/near_lng to rank by distance, e.g. to resolve \"the café next to X\": search X first, then search \"café\" near its coordinates.","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"Name or kind of place, or an address, e.g. \"Pergamonmuseum\", \"ramen\" or \"Calle Larios 4\".","minLength":2,"maxLength":100},"near_lat":{"type":"number","description":"Latitude to search around.","minimum":-90,"maximum":90},"near_lng":{"type":"number","description":"Longitude to search around.","minimum":-180,"maximum":180},"town":{"type":"string","description":"A town to search around, when no near_lat/near_lng is given, e.g. \"Ronda\".","minLength":2,"maxLength":80},"limit":{"type":"integer","description":"At most this many results, 1 to 10. Default 5.","minimum":1,"maximum":10}},"required":["query"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true},"requiredScope":"public:read"},{"name":"find_places_near","title":"Places at a spot","description":"The places right at a point, nearest first: cafés, bars, restaurants, sights and shops within a short walk. Use it to find which place a photo shows from the GPS it was taken at, or what is at coordinates the user gives. Returns a place_ref for the places we can pin (save_place, add_trip_idea, update_trip_idea); one without a place_ref can be added with add_new_place.","inputSchema":{"type":"object","properties":{"lat":{"type":"number","description":"Latitude of the spot.","minimum":-90,"maximum":90},"lng":{"type":"number","description":"Longitude of the spot.","minimum":-180,"maximum":180},"radius_m":{"type":"integer","description":"How far around, 50 to 500 metres. Default 150: a photo's GPS is rarely further off.","minimum":50,"maximum":500},"limit":{"type":"integer","description":"At most this many, 1 to 10. Default 8.","minimum":1,"maximum":10}},"required":["lat","lng"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true},"requiredScope":"public:read"},{"name":"list_my_trips","title":"My trips","description":"The user's trips (their own and ones they joined), with city and dates. Returns the trip_id get_trip and add_trip_idea take.","inputSchema":{"type":"object","properties":{"when":{"type":"string","description":"Which trips. Default \"upcoming\", which includes a trip happening now.","enum":["upcoming","past","all"]}},"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"me:read"},{"name":"get_trip","title":"Trip plan","description":"One trip's plan: the ideas scheduled per day (with time and place), ideas not yet on a day, and the shortlist of places. Use it for \"what's next\", \"what's on Saturday\" or before adding to a trip.","inputSchema":{"type":"object","properties":{"trip_id":{"type":"string","description":"From list_my_trips.","format":"uuid"}},"required":["trip_id"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"me:read"},{"name":"get_trip_balances","title":"Trip money","description":"Who paid what on a trip, who owes whom, and the fewest transfers that settle it. Read-only: expenses are added in the app. Use it for \"who owes what\" or \"how much have we spent\".","inputSchema":{"type":"object","properties":{"trip_id":{"type":"string","description":"From list_my_trips.","format":"uuid"}},"required":["trip_id"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"me:read"},{"name":"list_saved_places","title":"My saved places","description":"Places the user saved as want-to-go or marked as been, with their notes. Use it to recall \"that ramen place in Tokyo\" or to suggest from the user's own list first.","inputSchema":{"type":"object","properties":{"city_slug":{"type":"string","description":"Only this city, from find_city.","minLength":2,"maxLength":80},"state":{"type":"string","description":"Only want-to-go or only been. Default both.","enum":["want_to_go","been"]},"query":{"type":"string","description":"Only places whose name or note contains this.","minLength":2,"maxLength":80}},"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"me:read"},{"name":"save_place","title":"Save a place","description":"Saves a place to the user's want-to-go list or marks it as been, with an optional note. As when saving in the app, the user's contacts may see the save in their feed. Confirm the exact place with the user first. For a place_ref starting with \"osm:\", also pass the name, lat and lng search_places returned with it.","inputSchema":{"type":"object","properties":{"place_ref":{"type":"string","description":"From search_places or list_saved_places.","minLength":5,"maxLength":120},"state":{"type":"string","description":"Default want_to_go.","enum":["want_to_go","been"]},"note":{"type":"string","description":"The user's own words about it, up to 280 characters.","maxLength":280},"name":{"type":"string","description":"Required for an osm: place_ref.","minLength":1,"maxLength":160},"lat":{"type":"number","description":"Required for an osm: place_ref.","minimum":-90,"maximum":90},"lng":{"type":"number","description":"Required for an osm: place_ref.","minimum":-180,"maximum":180}},"required":["place_ref"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"me:write"},{"name":"add_trip_idea","title":"Add to a trip","description":"Adds an idea to a trip: something to do, optionally on a day and at a time, optionally pinned to a place (place_ref) or to an address from search_places (name, lat, lng without a place_ref). Everyone on the trip sees it and may get a notification. Confirm the wording, day and time with the user first.","inputSchema":{"type":"object","properties":{"trip_id":{"type":"string","description":"From list_my_trips.","format":"uuid"},"text":{"type":"string","description":"What to do, e.g. \"Dinner at Lode & Stijn\".","minLength":1,"maxLength":200},"date":{"type":"string","description":"The day, within the trip's dates.","format":"date"},"time":{"type":"string","description":"Start time, 24-hour.","format":"time"},"note":{"type":"string","description":"One line: booking number, meeting point, what to bring.","maxLength":280},"place_ref":{"type":"string","description":"The place to pin, from search_places or list_saved_places.","minLength":5,"maxLength":120},"name":{"type":"string","description":"Required for an osm: place_ref, and for an address pin.","minLength":1,"maxLength":160},"lat":{"type":"number","description":"Required for an osm: place_ref, and for an address pin.","minimum":-90,"maximum":90},"lng":{"type":"number","description":"Required for an osm: place_ref, and for an address pin.","minimum":-180,"maximum":180}},"required":["trip_id","text"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"requiredScope":"me:write"},{"name":"update_trip_idea","title":"Change a trip idea","description":"Changes something already on a trip's plan: its wording, day, time, note, or where it happens (a place_ref from search_places, or an address's name, lat and lng). Use it instead of add_trip_idea whenever the user means an item that is already there, e.g. \"set the location of the ATP match\"; get its idea_id from get_trip. Only set a time the user gave or a source confirmed. Everyone on the trip sees the change. Confirm it with the user first.","inputSchema":{"type":"object","properties":{"trip_id":{"type":"string","description":"From list_my_trips.","format":"uuid"},"idea_id":{"type":"string","description":"From get_trip.","format":"uuid"},"text":{"type":"string","description":"New wording.","minLength":1,"maxLength":200},"date":{"type":"string","description":"The day, within the trip's dates.","format":"date"},"time":{"type":"string","description":"Start time, 24-hour, only on a dated idea.","format":"time"},"note":{"type":"string","description":"One line: booking number, meeting point, what to bring.","maxLength":280},"place_ref":{"type":"string","description":"Where it happens, from search_places or list_saved_places.","minLength":5,"maxLength":120},"name":{"type":"string","description":"Required for an osm: place_ref, and for an address pin.","minLength":1,"maxLength":160},"lat":{"type":"number","description":"Required for an osm: place_ref, and for an address pin.","minimum":-90,"maximum":90},"lng":{"type":"number","description":"Required for an osm: place_ref, and for an address pin.","minimum":-180,"maximum":180}},"required":["trip_id","idea_id"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"me:write"},{"name":"set_trip_stay","title":"Add where the trip stays","description":"Records where the group sleeps on a trip: a hotel, a flat. Only the trip's members see it; it places their plan's distances. Use it when the user says where they stay or asks to add it, and confirm the name first.","inputSchema":{"type":"object","properties":{"trip_id":{"type":"string","description":"From list_my_trips.","format":"uuid"},"name":{"type":"string","description":"The stay's name, e.g. \"Hotel María Cristina\".","minLength":1,"maxLength":120},"address":{"type":"string","description":"Its address, when known.","maxLength":200},"lat":{"type":"number","description":"From search_places, with lng.","minimum":-90,"maximum":90},"lng":{"type":"number","description":"From search_places, with lat.","minimum":-180,"maximum":180}},"required":["trip_id","name"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"requiredScope":"me:write"},{"name":"add_trip_day_trip","title":"Add a day out","description":"Adds a day out to another town to a trip's route, optionally on one of its days. Everyone on the trip sees it. Confirm the town and the day with the user first.","inputSchema":{"type":"object","properties":{"trip_id":{"type":"string","description":"From list_my_trips.","format":"uuid"},"town":{"type":"string","description":"The town, e.g. \"Ronda\".","minLength":2,"maxLength":80},"country_code":{"type":"string","description":"ISO 3166-1 alpha-2, e.g. \"ES\", when the name is ambiguous.","minLength":2,"maxLength":2},"date":{"type":"string","description":"The day, within the trip's dates.","format":"date"}},"required":["trip_id","town"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":false},"requiredScope":"me:write"},{"name":"get_my_vibe","title":"My travel vibe","description":"The user's own travel vibe as they set it in Vibe of the City: the travel types they like or love, how they take crowds, heat and rain, who they travel with, budget, diet, what they seek, care about and avoid, the vibe dimensions they value most, and how far their profile is filled in. Read it before recommending cities or places, or when the user asks what their vibe is. It is the user's own data: describe it to them, never to others.","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"me:read"},{"name":"get_city_vibe","title":"City vibe","description":"What a city is like, on the vibe dimensions (calm, adventure, nature, food, sport, culture, social, family, romance, productivity, value, authenticity, safety, weather, beauty, sea): how strongly it delivers each over the year, a sentence of local knowledge where we have one, and classic places that prove it. Not personal; for how it fits the user, use explain_city_match.","inputSchema":{"type":"object","properties":{"city_slug":{"type":"string","description":"From find_city.","minLength":2,"maxLength":80}},"required":["city_slug"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"public:read"},{"name":"explain_city_match","title":"Why a city fits me","description":"How a city fits the user's travel vibe, and why: the match label, where what they value meets what the city delivers, where it falls short, what it offers beyond their priorities, and classic places that prove each point. Use it for \"why does Lisbon suit me?\" or \"why not Ibiza?\"; compare two cities by calling it for each. Say the match label in words; give a percent only when match_percent is not null.","inputSchema":{"type":"object","properties":{"city_slug":{"type":"string","description":"From find_city.","minLength":2,"maxLength":80}},"required":["city_slug"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"me:read"},{"name":"read_place_link","title":"Read a place from a link","description":"Reads a place from a link the user shares: a map link (Google Maps, Apple Maps, OpenStreetMap) or the place's own website. Returns its name, address and coordinates when the link carries them; needs_name when it can't be read, so ask the user for the name. Then search_places for it, and only if it isn't there, add_new_place.","inputSchema":{"type":"object","properties":{"url":{"type":"string","description":"The link, https.","minLength":8,"maxLength":2000}},"required":["url"],"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true},"requiredScope":"public:read"},{"name":"add_new_place","title":"Add a missing place","description":"Adds a place that is not on the map yet, and saves it for the user (want to go, or been). Only after search_places did not find it. The name must be the place's real name, never an address; the coordinates come from read_place_link, from an address search_places returned, or from the user. It becomes a place everyone can find, so confirm the name and where it is with the user first. Returns a place_ref for add_trip_idea and update_trip_idea.","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"The place's name, e.g. \"Bodega La Fuente\".","minLength":1,"maxLength":120},"lat":{"type":"number","description":"Where it is.","minimum":-90,"maximum":90},"lng":{"type":"number","description":"Where it is.","minimum":-180,"maximum":180},"category":{"type":"string","description":"One word for what it is, e.g. restaurant, cafe, bar, museum, viewpoint, beach, shop.","maxLength":40},"address":{"type":"string","description":"Its address, when known.","maxLength":200},"note":{"type":"string","description":"The user's own words about it.","maxLength":280},"state":{"type":"string","description":"Default want_to_go.","enum":["want_to_go","been"]}},"required":["name","lat","lng"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"me:write"},{"name":"get_app_help","title":"How the app works","description":"How Vibe of the City works and where things are: signing in, account and data, reporting and blocking, notifications and language, the travel vibe, the map, places, trips, tips, invites, Marvia, and how to reach a person. Read it before answering any question about the app, and answer only from it; when it doesn't say, say you aren't sure and offer report_problem or the contact address.","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"requiredScope":"public:read"},{"name":"report_problem","title":"Report a problem to the team","description":"Sends the Vibe of the City team a bug or problem the user ran into, in their words: what happened, what they expected, and where in the app. A person reads every report. Use it when the user reports something broken or wrong in the app, after summing it up back to them and getting their yes. Not for reporting a person or a message — that is the report option on their profile or thread.","inputSchema":{"type":"object","properties":{"summary":{"type":"string","description":"One line, e.g. \"The map opens on the wrong city after sign-in\".","minLength":5,"maxLength":200},"details":{"type":"string","description":"What happened, what they expected, where in the app, which city or trip.","maxLength":2000},"trip_id":{"type":"string","description":"The trip it happened on, when it did.","format":"uuid"}},"required":["summary"],"additionalProperties":false},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false,"openWorldHint":true},"requiredScope":"me:write"}]}