get_business_profile
Retrieve a complete business profile with services, hours, credentials, languages, contact channels, and a UTM-tagged booking URL using the business ID.
Instructions
Get full structured profile for a business by ID. Returns services, hours, credentials, languages, contact channels, and a UTM-tagged booking URL.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Business ID returned by search_businesses. | |
| agentName | No | Optional MCP client identifier (e.g. 'chatgpt', 'claude', 'gemini'). Used for UTM attribution. |
Implementation Reference
- src/tools/getBusinessProfile.ts:25-41 (handler)The main handler function for the get_business_profile tool. It accepts an id and optional agentName, fetches the business profile from the database, UTM-tags the booking URL using tagBookingUrl (with campaign='profile'), and returns the full BusinessProfile object or an error.
export async function getBusinessProfile( input: GetBusinessProfileInput ): Promise<BusinessProfile | { error: string }> { const profile = await getBusinessById(input.id); if (!profile) return { error: `No business found with id: ${input.id}` }; // Strip raw booking URL → return UTM-tagged version. const tagged = profile.bookingUrl ? tagBookingUrl(profile.bookingUrl, { businessId: profile.id, agentName: input.agentName, campaign: "profile" }) : undefined; return { ...profile, bookingUrl: tagged }; } - Zod schema for get_business_profile input validation. Defines 'id' (required string) and 'agentName' (optional string for UTM attribution).
export const getBusinessProfileSchema = z.object({ id: z.string().describe("Business ID returned by search_businesses."), agentName: z .string() .optional() .describe( "Optional MCP client identifier (e.g. 'chatgpt', 'claude', 'gemini'). Used for UTM attribution." ) }); - src/server.ts:35-43 (registration)Registers the 'get_business_profile' tool on the McpServer using server.tool(), with a description, the schema shape, and an async callback that calls getBusinessProfile and returns the result as JSON string content.
server.tool( "get_business_profile", "Get full structured profile for a business by ID. Returns services, hours, credentials, languages, contact channels, and a UTM-tagged booking URL.", getBusinessProfileSchema.shape, async (args) => { const profile = await getBusinessProfile(getBusinessProfileSchema.parse(args)); return { content: [{ type: "text", text: JSON.stringify(profile, null, 2) }] }; } ); - src/lib/utm.ts:17-34 (helper)The tagBookingUrl helper function used by getBusinessProfile to append UTM parameters (utm_source, utm_medium, utm_campaign, utm_term, utm_content) to a business's raw booking URL for analytics attribution.
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(); } - src/lib/db.ts:55-58 (helper)The getBusinessById helper function used by getBusinessProfile to look up a business profile by its ID from the mock data or Supabase (Phase 2).
export async function getBusinessById(id: string): Promise<BusinessProfile | null> { const all = await getAllBusinesses(); return all.find((b) => b.id === id) ?? null; }