Skip to main content
Glama
kfrzr

FastMCP Boilerplate

by kfrzr

property_search

Read-only

Find real estate properties by location, price, size, and amenities using spatial, semantic, or hybrid search to match specific user criteria.

Instructions

Search for a real estate property via spatial, semantic, or hybrid search

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoThe maximum number of properties to return
max_priceNoMaximum price of properties to return
min_bathsNoReturn properties with a number of baths greater than or equal to this number
min_bedsNoReturn properties with a number of bedrooms greater than or equal to this number
min_sqftNoReturn properties with a square footage greater than or equal to this number
queryYesA short and concise description of desired apartment amenities and other intangibles. Don't include traits like number of bedrooms that are covered by other search parameters. Don't include amenities or intangibles the user wants to avoid.
search_center_latitudeNoOptional float latitude for search center. Should always be set if longitude is set
search_center_longitudeNoOptional float longitude for search center. Should always be set if latitude is set
search_radiusNoReturn properties within this distance (in miles) from the search center

Implementation Reference

  • The main handler function that executes the property search logic by validating parameters and making an HTTP request to the properties API endpoint.
    export async function searchProperties(
      params: PropertySearchParams,
    ): Promise<string> {
      // Validate that both latitude and longitude are provided together
      if (
        (params.search_center_latitude !== null) !==
        (params.search_center_longitude !== null)
      ) {
        throw new Error(
          "Must provide both search_center_latitude and search_center_longitude if either is set",
        );
      }
    
      try {
        const response = await axios.get(
          "http://0.0.0.0:3000/properties",
          {
            params: {
              limit: params.limit,
              max_price: params.max_price === Infinity ? null : params.max_price,
              min_baths: params.min_baths,
              min_beds: params.min_beds,
              min_sqft: params.min_sqft,
              query: params.query,
              search_center_latitude: params.search_center_latitude,
              search_center_longitude: params.search_center_longitude,
              search_radius: params.search_radius,
            },
            timeout: 30000, // 30 second timeout
          },
        );
    
        return JSON.stringify(response.data, null, 2);
      } catch (error) {
        if (axios.isAxiosError(error)) {
          if (error.response) {
            throw new Error(
              `API Error ${error.response.status}: ${error.response.statusText}`,
            );
          } else if (error.request) {
            throw new Error(
              "No response from API server.",
            );
          }
        }
        throw new Error(
          `Request failed: ${error instanceof Error ? error.message : String(error)}`,
        );
      }
    }
  • Zod schema defining the input parameters for the property_search tool, including limits, filters, and location-based search criteria.
    const PropertySearchSchema = z.object({
      limit: z
        .number()
        .positive()
        .default(20)
        .describe("The maximum number of properties to return"),
      max_price: z
        .number()
        .positive()
        .default(Infinity)
        .describe("Maximum price of properties to return"),
      min_baths: z
        .number()
        .min(0)
        .default(0)
        .describe(
          "Return properties with a number of baths greater than or equal to this number",
        ),
      min_beds: z
        .number()
        .min(0)
        .default(0)
        .describe(
          "Return properties with a number of bedrooms greater than or equal to this number",
        ),
      min_sqft: z
        .number()
        .min(0)
        .default(0)
        .describe(
          "Return properties with a square footage greater than or equal to this number",
        ),
      query: z
        .string()
        .describe(
          "A short and concise description of desired apartment amenities and other intangibles. Don't include traits like number of bedrooms that are covered by other search parameters. Don't include amenities or intangibles the user wants to avoid.",
        ),
      search_center_latitude: z
        .number()
        .nullable()
        .default(null)
        .describe(
          "Optional float latitude for search center. Should always be set if longitude is set",
        ),
      search_center_longitude: z
        .number()
        .nullable()
        .default(null)
        .describe(
          "Optional float longitude for search center. Should always be set if latitude is set",
        ),
      search_radius: z
        .number()
        .positive()
        .default(5)
        .describe(
          "Return properties within this distance (in miles) from the search center",
        ),
    });
  • src/server.ts:10-23 (registration)
    Registration of the 'property_search' tool using FastMCP's addTool method, specifying name, schema, description, annotations, and execute handler that delegates to searchProperties.
    server.addTool({
      annotations: {
        openWorldHint: true, // This tool interacts with external API
        readOnlyHint: true, // This tool doesn't modify anything
        title: "Property Search",
      },
      description:
        "Search for a real estate property via spatial, semantic, or hybrid search",
      execute: async (args) => {
        return await searchProperties(args);
      },
      name: "property_search",
      parameters: PropertySearchSchema,
    });
Behavior3/5

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

Annotations indicate readOnlyHint=true and openWorldHint=true, covering safety and data scope. The description adds value by specifying search types (spatial, semantic, hybrid), which provides context beyond annotations. However, it lacks details on rate limits, authentication needs, or result format.

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, efficient sentence that clearly states the tool's purpose without unnecessary words. It's front-loaded with the core action and resource, making it easy to understand quickly.

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?

For a search tool with 9 parameters, no output schema, and annotations covering read-only and open-world aspects, the description is minimally adequate. It specifies search types but lacks details on result structure, error handling, or performance characteristics that would enhance completeness.

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?

Schema description coverage is 100%, so the schema fully documents all 9 parameters. The description doesn't add any parameter-specific semantics beyond what's in the schema, such as explaining interactions between parameters or search type implications. Baseline 3 is appropriate when schema coverage is high.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Search for a real estate property') and the resource ('real estate property'), and specifies the search methods ('spatial, semantic, or hybrid search'). However, with no sibling tools mentioned, it cannot differentiate from alternatives, preventing a perfect score.

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, prerequisites, or exclusions. It mentions search types but doesn't explain when to choose one over another or contextual constraints.

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

Related 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/kfrzr/realtor_mcp'

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