Skip to main content
Glama

get_booking_options

Retrieve UTM-tagged booking URL, accepted payment methods, and business hours for direct client booking without sharing customer data.

Instructions

Get UTM-tagged booking URL plus accepted methods and hours for a business. The user books directly with the SMB; we never see customer data.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYesBusiness ID.
agentNameNoMCP client identifier for UTM attribution.

Implementation Reference

  • The main handler function for get_booking_options. Looks up a business by ID, collects accepted booking methods (online, phone, email, walk_in), resolves fallback contact, and returns UTM-tagged booking URL, hours, timezone, and fallback contact info.
    export async function getBookingOptions(
      input: GetBookingOptionsInput
    ): Promise<BookingOptions | { error: string }> {
      const b = await getBusinessById(input.id);
      if (!b) return { error: `No business found with id: ${input.id}` };
    
      const acceptedMethods: BookingOptions["acceptedMethods"] = [];
      if (b.bookingUrl) acceptedMethods.push("online");
      for (const c of b.contactChannels) {
        if (c.type === "phone") acceptedMethods.push("phone");
        if (c.type === "email") acceptedMethods.push("email");
      }
      // Always include walk-in by default for medical / realtor / insurance offices.
      acceptedMethods.push("walk_in");
    
      const fallback: ContactChannel =
        b.contactChannels.find((c) => c.preferred) ??
        b.contactChannels[0] ?? { type: "website", value: b.socials.website ?? "" };
    
      return {
        businessId: b.id,
        bookingUrl: b.bookingUrl
          ? tagBookingUrl(b.bookingUrl, { businessId: b.id, agentName: input.agentName, campaign: "booking" })
          : "",
        acceptedMethods: Array.from(new Set(acceptedMethods)),
        hours: b.hours,
        timezone: b.timezone,
        fallbackContact: fallback
      };
    }
  • Zod schema defining the tool input: required business ID string and optional agentName string for UTM attribution.
    export const getBookingOptionsSchema = z.object({
      id: z.string().describe("Business ID."),
      agentName: z.string().optional().describe("MCP client identifier for UTM attribution.")
    });
  • src/server.ts:45-53 (registration)
    Registration of the tool with the MCP server using server.tool(), connecting the schema and handler.
    server.tool(
      "get_booking_options",
      "Get UTM-tagged booking URL plus accepted methods and hours for a business. The user books directly with the SMB; we never see customer data.",
      getBookingOptionsSchema.shape,
      async (args) => {
        const opts = await getBookingOptions(getBookingOptionsSchema.parse(args));
        return { content: [{ type: "text", text: JSON.stringify(opts, null, 2) }] };
      }
    );
  • Helper function that looks up a business by ID from the data store (mock JSON fallback or Supabase).
    export async function getBusinessById(id: string): Promise<BusinessProfile | null> {
      const all = await getAllBusinesses();
      return all.find((b) => b.id === id) ?? null;
    }
    
    export async function getCategories(countryCode?: string): Promise<CategoryEntry[]> {
      if (DATA_SOURCE === "supabase") {
        throw new Error("Supabase data source not yet wired.");
      }
      const cats = loadMockCategories();
      if (!countryCode) return cats;
      return cats.filter((c) => c.availableInCountries.includes(countryCode));
    }
  • Helper that appends UTM tracking parameters (source, medium, campaign, term, content) to the business's raw booking URL.
    export function tagBookingUrl(rawUrl: string, ctx: UtmContext): string {
      if (!rawUrl) return rawUrl;
      let url: URL;
      try {
        url = new URL(rawUrl);
      } catch {
        // not a valid URL — return as-is rather than corrupting it
        return rawUrl;
      }
    
      url.searchParams.set("utm_source", SOURCE);
      url.searchParams.set("utm_medium", MEDIUM);
      if (ctx.campaign) url.searchParams.set("utm_campaign", ctx.campaign);
      if (ctx.agentName) url.searchParams.set("utm_term", ctx.agentName);
      url.searchParams.set("utm_content", ctx.businessId);
    
      return url.toString();
    }
Behavior3/5

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

With no annotations, the description carries the full burden. It discloses the 'UTM-tagged' nature and the privacy aspect of not seeing customer data, but does not reveal additional behaviors such as caching, rate limits, or whether the URL is always returned. Some behavioral traits remain implicit.

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

Conciseness5/5

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

Two sentences with no wasted words. The first sentence front-loads the core functionality, and the second adds a relevant privacy caveat. Every sentence contributes value.

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

Completeness4/5

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

The description lists the key outputs (booking URL, accepted methods, hours). Since there is no output schema, it would benefit from explicitly stating the response structure. However, for a simple tool with two parameters, it is reasonably complete.

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?

Schema coverage is 100%, so baseline is 3. The description adds meaning by explaining that agentName is for 'UTM attribution,' clarifying its purpose beyond the schema's 'MCP client identifier for UTM attribution.' This extra context justifies a 4.

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?

Description clearly states the tool retrieves a UTM-tagged booking URL along with accepted methods and hours for a business. The verb 'Get' is specific, and the resource 'booking options' is distinct from sibling tools like get_business_profile, get_categories, search_businesses, and search_by_query.

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

Usage Guidelines3/5

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

The description implies usage when needing booking details but does not explicitly state when to use this tool versus alternatives or when not to use it. The privacy note 'we never see customer data' provides some context but no direct guidance on selection.

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

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/mutamiri-sudo/ailistmybusiness'

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