Skip to main content
Glama
devlimelabs

Meilisearch MCP Server

by devlimelabs

vector-search

Search Meilisearch indexes using vector embeddings to find semantically similar content, supporting hybrid text-vector searches and customizable filtering.

Instructions

Perform a vector search in a Meilisearch index

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
indexUidYesUnique identifier of the index
vectorYesJSON array representing the vector to search for
limitNoMaximum number of results to return (default: 20)
offsetNoNumber of results to skip (default: 0)
filterNoFilter to apply (e.g., 'genre = horror AND year > 2020')
embedderNoName of the embedder to use (if omitted, a 'vector' must be provided)
attributesNoAttributes to include in the vector search
queryNoText query to search for (if using 'embedder' instead of 'vector')
hybridNoWhether to perform a hybrid search (combining vector and text search)
hybridRatioNoRatio of vector vs text search in hybrid search (0-1, default: 0.5)

Implementation Reference

  • The async handler function that performs the vector search by parsing inputs, validating requirements (vector or embedder+query), building search parameters, and POSTing to Meilisearch's /indexes/{indexUid}/search endpoint.
    async ({ indexUid, vector, limit, offset, filter, embedder, attributes, query, hybrid, hybridRatio }) => {
      try {
        const searchParams: Record<string, any> = {};
        
        // Add required vector parameter
        if (vector) {
          try {
            searchParams.vector = JSON.parse(vector);
          } catch (parseError) {
            return {
              isError: true,
              content: [{ type: "text", text: "Vector must be a valid JSON array" }],
            };
          }
        }
        
        // Add embedder parameters
        if (embedder) {
          searchParams.embedder = embedder;
          
          if (query !== undefined) {
            searchParams.q = query;
          }
        }
        
        // Ensure we have either vector or (embedder + query)
        if (!vector && (!embedder || query === undefined)) {
          return {
            isError: true,
            content: [{ type: "text", text: "Either 'vector' or both 'embedder' and 'query' must be provided" }],
          };
        }
        
        // Add optional parameters
        if (limit !== undefined) searchParams.limit = limit;
        if (offset !== undefined) searchParams.offset = offset;
        if (filter) searchParams.filter = filter;
        if (attributes?.length) searchParams.attributes = attributes;
        if (hybrid !== undefined) searchParams.hybrid = hybrid;
        if (hybridRatio !== undefined) searchParams.hybridRatio = hybridRatio;
        
        const response = await apiClient.post(`/indexes/${indexUid}/search`, searchParams);
        return {
          content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }],
        };
      } catch (error) {
        return createErrorResponse(error);
      }
    }
  • Zod schema defining the input parameters for the vector-search tool.
    {
      indexUid: z.string().describe("Unique identifier of the index"),
      vector: z.string().describe("JSON array representing the vector to search for"),
      limit: z.number().min(1).max(1000).optional().describe("Maximum number of results to return (default: 20)"),
      offset: z.number().min(0).optional().describe("Number of results to skip (default: 0)"),
      filter: z.string().optional().describe("Filter to apply (e.g., 'genre = horror AND year > 2020')"),
      embedder: z.string().optional().describe("Name of the embedder to use (if omitted, a 'vector' must be provided)"),
      attributes: z.array(z.string()).optional().describe("Attributes to include in the vector search"),
      query: z.string().optional().describe("Text query to search for (if using 'embedder' instead of 'vector')"),
      hybrid: z.boolean().optional().describe("Whether to perform a hybrid search (combining vector and text search)"),
      hybridRatio: z.number().min(0).max(1).optional().describe("Ratio of vector vs text search in hybrid search (0-1, default: 0.5)"),
    },
  • Direct registration of the 'vector-search' tool on the MCP server using server.tool(), including description, input schema, and handler.
    server.tool(
      "vector-search",
      "Perform a vector search in a Meilisearch index",
      {
        indexUid: z.string().describe("Unique identifier of the index"),
        vector: z.string().describe("JSON array representing the vector to search for"),
        limit: z.number().min(1).max(1000).optional().describe("Maximum number of results to return (default: 20)"),
        offset: z.number().min(0).optional().describe("Number of results to skip (default: 0)"),
        filter: z.string().optional().describe("Filter to apply (e.g., 'genre = horror AND year > 2020')"),
        embedder: z.string().optional().describe("Name of the embedder to use (if omitted, a 'vector' must be provided)"),
        attributes: z.array(z.string()).optional().describe("Attributes to include in the vector search"),
        query: z.string().optional().describe("Text query to search for (if using 'embedder' instead of 'vector')"),
        hybrid: z.boolean().optional().describe("Whether to perform a hybrid search (combining vector and text search)"),
        hybridRatio: z.number().min(0).max(1).optional().describe("Ratio of vector vs text search in hybrid search (0-1, default: 0.5)"),
      },
      async ({ indexUid, vector, limit, offset, filter, embedder, attributes, query, hybrid, hybridRatio }) => {
        try {
          const searchParams: Record<string, any> = {};
          
          // Add required vector parameter
          if (vector) {
            try {
              searchParams.vector = JSON.parse(vector);
            } catch (parseError) {
              return {
                isError: true,
                content: [{ type: "text", text: "Vector must be a valid JSON array" }],
              };
            }
          }
          
          // Add embedder parameters
          if (embedder) {
            searchParams.embedder = embedder;
            
            if (query !== undefined) {
              searchParams.q = query;
            }
          }
          
          // Ensure we have either vector or (embedder + query)
          if (!vector && (!embedder || query === undefined)) {
            return {
              isError: true,
              content: [{ type: "text", text: "Either 'vector' or both 'embedder' and 'query' must be provided" }],
            };
          }
          
          // Add optional parameters
          if (limit !== undefined) searchParams.limit = limit;
          if (offset !== undefined) searchParams.offset = offset;
          if (filter) searchParams.filter = filter;
          if (attributes?.length) searchParams.attributes = attributes;
          if (hybrid !== undefined) searchParams.hybrid = hybrid;
          if (hybridRatio !== undefined) searchParams.hybridRatio = hybridRatio;
          
          const response = await apiClient.post(`/indexes/${indexUid}/search`, searchParams);
          return {
            content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }],
          };
        } catch (error) {
          return createErrorResponse(error);
        }
      }
    );
  • src/index.ts:68-68 (registration)
    Registers the vector tools module (including vector-search) on the main MCP server instance.
    registerVectorTools(server);
Behavior2/5

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

With no annotations provided, the description carries full burden for behavioral disclosure but only states the basic function. It doesn't mention whether this is a read-only operation, potential performance characteristics, error conditions, authentication requirements, or what the output format looks like. For a complex 10-parameter tool with vector operations, this is insufficient behavioral context.

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 gets straight to the point with zero wasted words. It's perfectly front-loaded with the essential information and doesn't include any unnecessary elaboration or repetition.

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

Completeness2/5

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

For a complex vector search tool with 10 parameters, no annotations, and no output schema, the description is inadequate. It doesn't explain what vector search means in this context, how results are returned, what the relationship is between 'vector' and 'embedder' parameters, or how this differs from regular search. The agent would struggle to use this tool effectively without significant external knowledge.

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 already documents all parameters thoroughly. The description doesn't add any parameter-specific information beyond what's in the schema. However, it does establish the core concept of 'vector search' which provides context for why certain parameters like 'vector' and 'embedder' exist.

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 ('Perform a vector search') and resource ('in a Meilisearch index'), making the purpose immediately understandable. However, it doesn't differentiate this tool from the sibling 'search' tool, which appears to be a general text search, leaving some ambiguity about when to choose vector search over regular search.

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?

No guidance is provided about when to use this tool versus alternatives like the 'search' sibling tool. The description doesn't mention prerequisites, context requirements, or typical use cases for vector search versus other search methods available in the system.

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/devlimelabs/meilisearch-ts-mcp'

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