pifini
Real events, reviewed places, and ticket checkout across the Caribbean and Latin America.
我該用這個嗎
品質與安全性
根據工具定義與協定合規性的自動化分析。
上下文成本
這是每次將伺服器的工具載入模型上下文時所消耗的約略 token 數量。數量越高,可用於其他工作的注意力就越少。
安裝
一鍵安裝
將以下內容加入你的 `claude_desktop_config.json` 檔案:
{
"mcpServers": {
"pifini": {
"url": "https://pifini.net/api/mcp"
}
}
}遠端端點
https://pifini.net/api/mcpstreamable-http它能做什麼
工具清單
工具(6)
🟢search_events(query, country, city, category, entry_model, ...)
Search upcoming events (festivals, carnivals, concerts, food + cultural events) across the Caribbean, Latin America, and beyond. Returns event names, dates, locations, category, price (when known), and page URLs. Strongest coverage: Barbados, Trinidad, Jamaica, Bahamas, Mexico.
輸入結構描述
{
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Free-text search over title and description"
},
"country": {
"type": "string",
"description": "ISO-3166 alpha-2 country code, e.g. BB, TT, JM"
},
"city": {
"type": "string",
"description": "City name filter"
},
"category": {
"type": "string",
"enum": [
"music",
"arts",
"culture",
"festival",
"sports",
"food",
"business",
"nightlife"
],
"description": "Filter by event category"
},
"entry_model": {
"type": "string",
"enum": [
"free",
"ticketed",
"external",
"mixed",
"unknown"
],
"description": "Filter by how someone gets in: 'free' = confirmed free entry, 'ticketed' = Pifini sells tickets, 'external' = paid but sold elsewhere, 'mixed' = umbrella event with both free and paid components, 'unknown' = not yet confirmed either way."
},
"starts_after": {
"type": "string",
"description": "Earliest start. A bare date ('2026-08-01') matches the event's LOCAL calendar date in its own timezone and is inclusive — this is what you want for 'what's on this weekend'. A full ISO timestamp ('2026-08-01T18:00:00Z') is compared as an exact UTC instant instead."
},
"starts_before": {
"type": "string",
"description": "Latest start, same rules as starts_after. A bare date is inclusive of that whole local day, so starts_after='2026-08-13' with starts_before='2026-08-13' returns everything happening on the 13th where it happens."
},
"include_past": {
"type": "boolean",
"description": "Include past events (default false)"
},
"near_lat": {
"type": "number",
"description": "Latitude to search near (pair with near_lng)"
},
"near_lng": {
"type": "number",
"description": "Longitude to search near (pair with near_lat)"
},
"radius_km": {
"type": "number",
"description": "Search radius in km around near_lat/near_lng (default 25, max 500)"
},
"limit": {
"type": "number",
"description": "Max results, 1-50 (default 10)"
},
"offset": {
"type": "number",
"description": "Skip this many matching results (for paging past the limit)"
}
}
}輸出結構描述
{
"type": "object",
"properties": {
"count": {
"type": "number",
"description": "Number of events in this page of results"
},
"total": {
"type": "number",
"description": "Total events matching the filters, across all pages. Use this before claiming how many exist."
},
"has_more": {
"type": "boolean",
"description": "True when more matches exist beyond this page."
},
"next_offset": {
"type": [
"number",
"null"
],
"description": "Pass as `offset` to fetch the next page. Null when this is the last page."
},
"events": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"slug": {
"type": "string"
},
"url": {
"type": "string"
},
"summary": {
"type": [
"string",
"null"
]
},
"starts_at": {
"type": "string",
"description": "Exact start instant, ISO-8601 UTC. Do NOT format this for a human — it is the wrong calendar day in most of the region. Use local_date / local_time."
},
"timezone": {
"type": [
"string",
"null"
],
"description": "IANA timezone of the venue, e.g. America/Mexico_City. Null when unknown."
},
"local_date": {
"type": "string",
"description": "The date the event actually happens where it happens, YYYY-MM-DD. Quote this one."
},
"local_time": {
"type": [
"string",
"null"
],
"description": "Local start time, HH:MM 24h. Null when start_time_known is false — say nothing about the time in that case."
},
"start_time_known": {
"type": "boolean",
"description": "False when only the date is known and the stored hour is a placeholder. Never present a start time when this is false."
},
"ends_at": {
"type": [
"string",
"null"
]
},
"city": {
"type": [
"string",
"null"
]
},
"country": {
"type": [
"string",
"null"
]
},
"category": {
"type": [
"string",
"null"
]
},
"entry_model": {
"type": "string"
},
"price": {
"type": [
"object",
"null"
],
"properties": {
"min": {
"type": "number"
},
"max": {
"type": [
"number",
"null"
]
},
"currency": {
"type": "string"
},
"note": {
"type": [
"string",
"null"
]
}
}
},
"organizer_name": {
"type": [
"string",
"null"
]
},
"cover_image_url": {
"type": [
"string",
"null"
]
},
"attendee_count": {
"type": "number"
},
"distance_km": {
"type": [
"number",
"null"
],
"description": "Only present when near_lat/near_lng were given"
}
}
}
}
},
"required": [
"count",
"total",
"has_more",
"events"
]
}🟢get_event(slug)
Full details for one event by slug: description, venue, date/time, and available ticket types with prices and remaining stock. Use the slug from search_events.
輸入結構描述
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"description": "Event slug from search_events"
}
},
"required": [
"slug"
]
}輸出結構描述
{
"type": "object",
"properties": {
"title": {
"type": "string"
},
"slug": {
"type": "string"
},
"url": {
"type": "string"
},
"summary": {
"type": [
"string",
"null"
]
},
"description": {
"type": [
"string",
"null"
]
},
"starts_at": {
"type": "string",
"description": "Exact start instant, ISO-8601 UTC. Do NOT format this for a human — it is the wrong calendar day in most of the region. Use local_date / local_time."
},
"timezone": {
"type": [
"string",
"null"
],
"description": "IANA timezone of the venue, e.g. America/Mexico_City. Null when unknown."
},
"local_date": {
"type": "string",
"description": "The date the event actually happens where it happens, YYYY-MM-DD. Quote this one."
},
"local_time": {
"type": [
"string",
"null"
],
"description": "Local start time, HH:MM 24h. Null when start_time_known is false — say nothing about the time in that case."
},
"start_time_known": {
"type": "boolean",
"description": "False when only the date is known and the stored hour is a placeholder. Never present a start time when this is false."
},
"ends_at": {
"type": [
"string",
"null"
]
},
"location_name": {
"type": [
"string",
"null"
]
},
"city": {
"type": [
"string",
"null"
]
},
"country": {
"type": [
"string",
"null"
]
},
"category": {
"type": [
"string",
"null"
]
},
"entry_model": {
"type": "string"
},
"price": {
"type": [
"object",
"null"
]
},
"organizer_name": {
"type": [
"string",
"null"
]
},
"organizer_url": {
"type": [
"string",
"null"
]
},
"cover_image_url": {
"type": [
"string",
"null"
]
},
"attendee_count": {
"type": "number"
},
"currency": {
"type": "string"
},
"website": {
"type": [
"string",
"null"
]
},
"ticket_types": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ticket_type_id": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": [
"string",
"null"
]
},
"price": {
"type": "number"
},
"currency": {
"type": "string"
},
"remaining": {
"type": [
"number",
"null"
]
},
"sales_end_at": {
"type": [
"string",
"null"
]
}
},
"required": [
"ticket_type_id",
"name",
"price",
"currency"
]
}
}
}
}🟢search_places(query, entity_type, category, country, city, ...)
Search Pifini's places directory across the Caribbean and Latin America — restaurants, bars, beaches, attractions, venues, hotels, tour operators, professionals, and services. Every result carries listing_type: 'curated' is a small, editorially reviewed set of flagship entries; 'directory' is the much larger set sourced from open map data (name, category, location, contact info) that has no reviews yet — say so rather than implying a recommendation the data doesn't back up. Category is a specific Overture taxonomy value (e.g. caribbean_restaurant, church_cathedral), not a broad bucket — call list_categories first if unsure of the exact value. Results marked is_sponsored are paid placements — disclose that when recommending.
輸入結構描述
{
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Free-text search over name and summary"
},
"entity_type": {
"type": "string",
"enum": [
"venue",
"place",
"attraction",
"business",
"professional",
"service",
"city",
"country",
"experience",
"government",
"region",
"transport"
],
"description": "Filter by broad type of place"
},
"category": {
"type": "string",
"description": "Filter by exact category value (e.g. 'caribbean_restaurant'). Use list_categories to discover valid values — there are 1,000+, not a small fixed set."
},
"country": {
"type": "string",
"description": "ISO-3166 alpha-2 country code"
},
"city": {
"type": "string",
"description": "City name filter"
},
"near_lat": {
"type": "number",
"description": "Latitude to search near (pair with near_lng)"
},
"near_lng": {
"type": "number",
"description": "Longitude to search near (pair with near_lat)"
},
"radius_km": {
"type": "number",
"description": "Search radius in km around near_lat/near_lng (default 25, max 500)"
},
"limit": {
"type": "number",
"description": "Max results, 1-50 (default 10)"
},
"offset": {
"type": "number",
"description": "Skip this many matching results (for paging past the limit)"
}
}
}輸出結構描述
{
"type": "object",
"properties": {
"count": {
"type": "number",
"description": "Number of places in this page of results"
},
"total": {
"type": "number",
"description": "Total places matching the filters, across all pages. Use this before claiming how many exist."
},
"has_more": {
"type": "boolean",
"description": "True when more matches exist beyond this page."
},
"next_offset": {
"type": [
"number",
"null"
],
"description": "Pass as `offset` to fetch the next page. Null when this is the last page."
},
"places": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"slug": {
"type": "string"
},
"type": {
"type": "string"
},
"listing_type": {
"type": "string",
"enum": [
"curated",
"directory"
]
},
"url": {
"type": "string"
},
"summary": {
"type": [
"string",
"null"
]
},
"city": {
"type": [
"string",
"null"
]
},
"country": {
"type": [
"string",
"null"
]
},
"category": {
"type": [
"string",
"null"
]
},
"price_tier": {
"type": [
"string",
"null"
]
},
"avg_rating": {
"type": [
"number",
"null"
]
},
"review_count": {
"type": "number"
},
"is_verified": {
"type": "boolean"
},
"is_sponsored": {
"type": "boolean"
},
"distance_km": {
"type": [
"number",
"null"
]
}
}
}
}
},
"required": [
"count",
"total",
"has_more",
"places"
]
}🟢get_place(slug)
Full details for one place by slug, including its most recent published reviews if any exist. listing_type distinguishes a curated entry from an unreviewed directory listing (see search_places) — recent_reviews is often an empty array, which means no reviews yet, not a low-quality place. Use the slug from search_places.
輸入結構描述
{
"type": "object",
"properties": {
"slug": {
"type": "string",
"description": "Place slug from search_places"
}
},
"required": [
"slug"
]
}輸出結構描述
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"slug": {
"type": "string"
},
"type": {
"type": "string"
},
"listing_type": {
"type": "string",
"enum": [
"curated",
"directory"
]
},
"url": {
"type": "string"
},
"summary": {
"type": [
"string",
"null"
]
},
"description": {
"type": [
"string",
"null"
]
},
"city": {
"type": [
"string",
"null"
]
},
"country": {
"type": [
"string",
"null"
]
},
"address": {
"type": [
"string",
"null"
]
},
"category": {
"type": [
"string",
"null"
]
},
"price_tier": {
"type": [
"string",
"null"
]
},
"website": {
"type": [
"string",
"null"
]
},
"avg_rating": {
"type": [
"number",
"null"
]
},
"review_count": {
"type": "number"
},
"is_verified": {
"type": "boolean"
},
"is_sponsored": {
"type": "boolean"
},
"recent_reviews": {
"type": "array",
"items": {
"type": "object",
"properties": {
"rating": {
"type": "number"
},
"title": {
"type": [
"string",
"null"
]
},
"body": {
"type": [
"string",
"null"
]
},
"verified_attendee": {
"type": "boolean"
},
"verification_basis": {
"type": "string",
"enum": [
"ticket_scan",
"transaction",
"rsvp",
"geo_checkin",
"manual",
"none"
],
"description": "How the reviewer's visit was established. ticket_scan and transaction are strong evidence, rsvp and geo_checkin are weaker, manual is self-declared and none is an unverified opinion. Describe the review accordingly."
},
"date": {
"type": "string"
}
},
"required": [
"rating",
"verified_attendee",
"date"
]
}
}
}
}🟢list_categories(query, country, limit)
Discover valid category values for search_places. Pifini's places directory uses Overture Maps' taxonomy — over 1,000 specific values like caribbean_restaurant, church_cathedral, landmark_and_historical_building — rather than broad buckets, so guessing a category string will usually miss. Call this first with a rough query (e.g. 'coffee' or 'beach') to find the exact value, then pass it to search_places' category parameter.
輸入結構描述
{
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Rough term to match against category values, e.g. 'coffee', 'beach'"
},
"country": {
"type": "string",
"description": "ISO-3166 alpha-2 country code — only return categories present in that country"
},
"limit": {
"type": "number",
"description": "Max results, 1-100 (default 30)"
}
}
}輸出結構描述
{
"type": "object",
"properties": {
"count": {
"type": "number"
},
"categories": {
"type": "array",
"items": {
"type": "object",
"properties": {
"category": {
"type": "string",
"description": "Exact value to pass to search_places' category parameter"
},
"label": {
"type": "string",
"description": "Human-readable label"
},
"count": {
"type": "number",
"description": "How many active places have this category"
}
}
}
}
},
"required": [
"count",
"categories"
]
}🟡create_ticket_checkout(event_slug, items, buyer_email, buyer_name)
Create a secure Stripe-hosted payment link for event tickets. Returns a checkout URL — give it to the human to complete payment themselves; each ticket is then emailed with its QR code and its own link, which opens on any phone and can be saved to WhatsApp. Get ticket_type_id values from get_event. Always confirm the exact tickets and total with the human before calling this.
輸入結構描述
{
"type": "object",
"properties": {
"event_slug": {
"type": "string",
"description": "Event slug"
},
"items": {
"type": "array",
"description": "Ticket selections",
"items": {
"type": "object",
"properties": {
"ticket_type_id": {
"type": "string",
"description": "Ticket type id from get_event"
},
"quantity": {
"type": "number",
"description": "1-20"
}
},
"required": [
"ticket_type_id",
"quantity"
]
}
},
"buyer_email": {
"type": "string",
"description": "Email to deliver tickets to (required — ask the human)"
},
"buyer_name": {
"type": "string",
"description": "Buyer's name (optional)"
}
},
"required": [
"event_slug",
"items",
"buyer_email"
]
}輸出結構描述
{
"type": "object",
"properties": {
"checkout_url": {
"type": "string"
},
"order_id": {
"type": "string"
},
"event": {
"type": "string"
},
"total": {
"type": "number"
},
"currency": {
"type": "string"
},
"instructions": {
"type": "string"
}
}
}建議的提示詞
search_eventssearch_eventsget_eventget_eventlist_categories社群
證據