Skip to main content
Glama

search_sitters

Find available pet sitters on Rover by location and service type, with ratings and pricing details for boarding, house sitting, dog walking, and other pet care services.

Instructions

Search for pet sitters on Rover by location and service type. Returns a list of available sitters with ratings and pricing.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
locationYesCity, neighborhood, or zip code to search in (e.g. 'Seattle, WA' or '98101')
serviceTypeYesType of pet care service
startDateNoStart date in YYYY-MM-DD format
endDateNoEnd date in YYYY-MM-DD format
petCountNoNumber of pets
petSizeNoSize of your pet

Implementation Reference

  • The core implementation of search_sitters - navigates to Rover search URL, scrapes sitter cards from the page using Playwright, and returns structured sitter results with name, location, rating, reviews, price, and profile URL.
    async searchSitters(params: SitterSearchParams): Promise<SitterResult[]> {
      const page = this.ensurePage();
      const serviceMap: Record<string, string> = {
        boarding: "boarding",
        house_sitting: "house-sitting",
        drop_in: "drop-in-visits",
        doggy_day_care: "doggy-day-care",
        dog_walking: "dog-walking",
      };
      const service = serviceMap[params.serviceType] || "boarding";
      const encodedLocation = encodeURIComponent(params.location);
      let url = `${this.BASE_URL}/search/results/?service_type=${service}&location=${encodedLocation}`;
    
      if (params.startDate) url += `&start_date=${params.startDate}`;
      if (params.endDate) url += `&end_date=${params.endDate}`;
      if (params.petCount) url += `&dog_count=${params.petCount}`;
    
      await page.goto(url);
      await page.waitForLoadState("networkidle");
    
      const sitters = await page.evaluate(() => {
        const results: Array<{
          id: string;
          name: string;
          location: string;
          rating: number;
          reviewCount: number;
          price: number;
          priceUnit: string;
          services: string[];
          profileUrl: string;
          avatarUrl: string | undefined;
          summary: string | undefined;
        }> = [];
    
        const cards = document.querySelectorAll(
          '[data-testid="sitter-card"], .sitter-card, article[class*="sitter"], [class*="SearchResult"]'
        );
    
        cards.forEach((card, index) => {
          if (index >= 20) return;
          const nameEl = card.querySelector(
            '[class*="sitter-name"], [class*="SitterName"], h3, h2'
          );
          const ratingEl = card.querySelector(
            '[class*="rating"], [aria-label*="rating"], [class*="Rating"]'
          );
          const reviewEl = card.querySelector('[class*="review"], [class*="Review"]');
          const priceEl = card.querySelector('[class*="price"], [class*="Price"]');
          const locationEl = card.querySelector('[class*="location"], [class*="Location"]');
          const linkEl = card.querySelector("a[href*='/sitters/'], a[href*='/dog-boarding/']");
          const imgEl = card.querySelector("img");
          const summaryEl = card.querySelector('[class*="summary"], [class*="Summary"], p');
    
          const ratingText = ratingEl?.textContent?.trim() || "0";
          const reviewText = reviewEl?.textContent?.replace(/[^\d]/g, "") || "0";
          const priceText = priceEl?.textContent?.replace(/[^\d.]/g, "") || "0";
    
          if (nameEl?.textContent?.trim()) {
            results.push({
              id: `sitter-${index}`,
              name: nameEl.textContent.trim(),
              location: locationEl?.textContent?.trim() || "",
              rating: parseFloat(ratingText) || 0,
              reviewCount: parseInt(reviewText, 10) || 0,
              price: parseFloat(priceText) || 0,
              priceUnit: "night",
              services: [],
              profileUrl: (linkEl as HTMLAnchorElement)?.href || "",
              avatarUrl: (imgEl as HTMLImageElement)?.src,
              summary: summaryEl?.textContent?.trim(),
            });
          }
        });
    
        return results;
      });
    
      return sitters.map((s, i) => ({
        ...s,
        id: s.id || `sitter-${i}`,
      }));
    }
  • The MCP tool handler for 'search_sitters' - validates input with SearchSittersSchema, calls browser.searchSitters(), and formats the results as markdown text content for the response.
    case "search_sitters": {
      const params = SearchSittersSchema.parse(args);
      const sitters = await browser.searchSitters(params);
      if (sitters.length === 0) {
        return {
          content: [{ type: "text", text: "No sitters found for the given criteria." }],
        };
      }
      const formatted = sitters
        .map(
          (s, i) =>
            `${i + 1}. **${s.name}** — ${s.location}\n` +
            `   Rating: ${s.rating}/5 (${s.reviewCount} reviews)\n` +
            `   Price: $${s.price}/${s.priceUnit}\n` +
            `   Profile: ${s.profileUrl}` +
            (s.summary ? `\n   "${s.summary}"` : "")
        )
        .join("\n\n");
      return {
        content: [
          {
            type: "text",
            text: `Found ${sitters.length} sitters in ${params.location}:\n\n${formatted}`,
          },
        ],
      };
    }
  • Zod validation schema for search_sitters parameters - defines required location and serviceType fields, plus optional date range, petCount, and petSize fields.
    const SearchSittersSchema = z.object({
      location: z.string().min(1),
      serviceType: z.enum(["boarding", "house_sitting", "drop_in", "doggy_day_care", "dog_walking"]),
      startDate: z.string().optional(),
      endDate: z.string().optional(),
      petCount: z.number().optional(),
      petSize: z.enum(["small", "medium", "large", "giant"]).optional(),
    });
  • src/index.ts:37-72 (registration)
    Tool registration for 'search_sitters' in the tools array - defines name, description, and JSON Schema inputSchema with all properties and required fields.
    {
      name: "search_sitters",
      description:
        "Search for pet sitters on Rover by location and service type. Returns a list of available sitters with ratings and pricing.",
      inputSchema: {
        type: "object",
        properties: {
          location: {
            type: "string",
            description: "City, neighborhood, or zip code to search in (e.g. 'Seattle, WA' or '98101')",
          },
          serviceType: {
            type: "string",
            enum: ["boarding", "house_sitting", "drop_in", "doggy_day_care", "dog_walking"],
            description: "Type of pet care service",
          },
          startDate: {
            type: "string",
            description: "Start date in YYYY-MM-DD format",
          },
          endDate: {
            type: "string",
            description: "End date in YYYY-MM-DD format",
          },
          petCount: {
            type: "number",
            description: "Number of pets",
          },
          petSize: {
            type: "string",
            enum: ["small", "medium", "large", "giant"],
            description: "Size of your pet",
          },
        },
        required: ["location", "serviceType"],
      },
  • TypeScript interface definitions for SitterSearchParams (input) and SitterResult (output) - defines the shape of parameters and results for the search_sitters tool.
    export interface SitterSearchParams {
      location: string;
      serviceType: "boarding" | "house_sitting" | "drop_in" | "doggy_day_care" | "dog_walking";
      startDate?: string;
      endDate?: string;
      petCount?: number;
      petSize?: "small" | "medium" | "large" | "giant";
    }
    
    export interface SitterResult {
      id: string;
      name: string;
      location: string;
      rating: number;
      reviewCount: number;
      price: number;
      priceUnit: string;
      services: string[];
      profileUrl: string;
      avatarUrl?: string;
      repeatClientCount?: number;
      yearsExperience?: number;
      summary?: string;
    }
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions the return format ('list of available sitters with ratings and pricing') but lacks critical details such as whether this is a read-only operation, potential rate limits, authentication requirements, pagination behavior, or error handling for invalid inputs. This is inadequate for a search tool with 6 parameters.

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?

The description is a single, well-structured sentence that efficiently conveys the tool's purpose and output without redundancy. It is front-loaded with the core action ('Search for pet sitters') and avoids unnecessary details, making it easy to parse.

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

Completeness3/5

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

Given the tool's moderate complexity (6 parameters, no output schema, no annotations), the description is incomplete. It adequately states the purpose but lacks usage guidelines, behavioral context (e.g., read-only nature, error cases), and output details beyond a high-level summary. The schema compensates for parameter documentation, but overall completeness is limited.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, providing clear documentation for all 6 parameters (e.g., location format, serviceType enums, date formats). The description adds minimal value beyond the schema by implying that location and serviceType are key filters, but it doesn't explain parameter interactions or constraints (e.g., how dates affect availability). Baseline 3 is appropriate given the comprehensive schema.

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?

The description clearly states the specific action ('Search for pet sitters'), resource ('on Rover'), and scope ('by location and service type'), with a distinct purpose from sibling tools like 'search_services' (which likely searches for services rather than sitters) and 'get_sitter_profile' (which retrieves a specific sitter's details).

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives like 'search_services' or 'get_sitter_profile', nor does it mention prerequisites (e.g., whether authentication is required) or exclusions (e.g., what happens if no sitters are found). It only states what the tool does without contextual usage advice.

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/markswendsen-code/mcp-rover'

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