Skip to main content
Glama
flying3615

Eventfinda MCP

by flying3615

list_events

Find events happening this week in your specified location using Eventfinda data.

Instructions

List all events within this week for a given location.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
locationYesThe location to search for events in.

Implementation Reference

  • The execute function implementing the list_events tool logic: searches for location ID, fetches events in the next week, retrieves detailed event info, extracts and enhances descriptions from event pages if available, processes ticket information, and returns a formatted JSON array of events.
    execute: async (args, { log }) => {
      const today = new Date();
      const nextWeek = new Date(
        today.getFullYear(),
        today.getMonth(),
        today.getDate() + 7
      );
    
      // Step 1: Find location ID from location name
      const locations = await fetchFromEventfinda('locations', {
        q: args.location,
      });
    
      if (!locations.locations.length) {
        throw new UserError(`Could not find location: ${args.location}`);
      }
      const locationId = locations.locations[0].id;
    
      // Step 2: Get events by location and date range
      const eventsResponse = await fetchFromEventfinda('events', {
        location: locationId,
        start_date: formatDateTime(today),
        end_date: formatDateTime(nextWeek),
        rows: '10', // Limit to 10 events to avoid rate limiting
      });
    
      log.debug(`Found ${eventsResponse.events.length} events`);
    
      // Step 3: Get detailed information for each event
      const eventDetails = await Promise.all(
        eventsResponse.events.map(async (event: any) => {
          try {
            // Get detailed event information using event ID
            return await fetchFromEventfinda(`events/${event.id}.json`, {});
          } catch (error) {
            log.error(`Error fetching details for event ${event.id}:`, error);
            // Return basic event info if detailed fetch fails
            return event;
          }
        })
      );
    
      // Step 4: Process each event to extract required information
      const processedEvents = await Promise.all(
        eventDetails.map(async (eventDetail: any) => {
          // Extract event from the response structure
          const event = eventDetail.event || eventDetail;
    
          // Extract and process description from API
          let description = 'No description available';
          if (event.description) {
            if (typeof event.description === 'string') {
              description = event.description;
            } else if (event.description.html) {
              description = event.description.html.replace(/<[^>]*>?/gm, '');
            }
          }
    
          // If we have a URL, try to fetch completed description from HTML
          if (event.url) {
            log.debug(
              `Fetching description from event page for event ${event.id}`
            );
            const htmlDescription = await fetchEventDescription(event.url, log);
            if (htmlDescription && htmlDescription.length > 0) {
              description = htmlDescription;
              log.debug(
                `Successfully extracted description from HTML for event ${event.id}`
              );
            }
          }
    
          // Check if event is free
          const isFree = Boolean(event.is_free);
          let ticketInfo = 'No ticket information available';
    
          // Process ticket information
          if (
            event.ticket_types &&
            Array.isArray(event.ticket_types.ticket_types) &&
            event.ticket_types.ticket_types.length > 0
          ) {
            ticketInfo = event.ticket_types.ticket_types.map((ticket: any) => ({
              name: ticket.name || 'Unnamed ticket',
              price: ticket.price,
              description: ticket.description,
              onsale_at: ticket.onsale_at,
            }));
          }
    
          return {
            id: event.id,
            title: event.name,
            description: description,
            url: event.url,
            datetime_start: event.datetime_start || event.datetime_summary,
            datetime_end: event.datetime_end || event.datetime_summary,
            address: event.address,
            is_free: isFree,
            ticket_info: isFree ? 'Free event' : ticketInfo,
            categories: event.category.name,
          };
        })
      );
    
      return JSON.stringify(processedEvents, null, 2);
    },
  • Zod schema defining the input parameter 'location' for the list_events tool.
    parameters: z.object({
      location: z.string().describe('The location to search for events in.'),
    }),
  • src/index.ts:87-89 (registration)
    Registration of the list_events tool with the FastMCP server, specifying name and description.
    server.addTool({
      name: 'list_events',
      description: 'List all events within this week for a given location.',
  • Helper function to fetch data from Eventfinda API with authentication and error handling, used by the list_events handler.
    async function fetchFromEventfinda(
      endpoint: string,
      params: Record<string, string>
    ) {
      const url = new URL(`https://api.eventfinda.co.nz/v2/${endpoint}.json`);
      Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
    
      const response = await fetch(url.toString(), {
        headers: {
          Authorization: auth,
        },
      });
    
      if (!response.ok) {
        throw new UserError(
          `Failed to fetch from Eventfinda API: ${response.statusText}`
        );
      }
    
      return await response.json();
    }
  • Helper function to scrape event description from the event webpage HTML, used to enhance event details in list_events.
    async function fetchEventDescription(
      eventUrl: string,
      log: any
    ): Promise<string | null> {
      try {
        const response = await fetch(eventUrl);
        if (!response.ok) {
          log.error(`Failed to fetch event page: ${response.statusText}`);
          return null;
        }
    
        const html = await response.text();
    
        // Simple HTML parsing to find element with id 'eventDescription'
        const descriptionMatch = html.match(
          /<div[^>]*id=['"]eventDescription['"][^>]*>([\s\S]*?)<\/div>/i
        );
        if (descriptionMatch && descriptionMatch[1]) {
          // Clean up HTML tags and decode HTML entities
          return descriptionMatch[1]
            .replace(/<[^>]*>?/gm, '') // Remove HTML tags
            .replace(/ /g, ' ') // Replace non-breaking spaces
            .replace(/&/g, '&') // Replace ampersands
            .replace(/</g, '<') // Replace less than
            .replace(/>/g, '>') // Replace greater than
            .replace(/"/g, '"') // Replace quotes
            .trim();
        }
        return null;
      } catch (error) {
        log.error(`Error fetching event description from URL: ${error}`);
        return null;
      }
    }
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/flying3615/eventfinda-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server