build_search_query
Generate GraphQL search queries for Contentful content types to find specific text across searchable fields, returning query strings and required variables.
Instructions
Generate a GraphQL search query for a specific content type based on cached schema information. Returns the query string and variables needed to search text fields in the content type.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| contentType | Yes | The content type to build a search query for | |
| searchTerm | Yes | The term to search for | |
| fields | No | Optional: Specific fields to search (default: all searchable text fields) | |
| spaceId | No | Optional override for the space ID (defaults to SPACE_ID environment variable) | |
| environmentId | No | Optional override for the environment ID (defaults to ENVIRONMENT_ID environment variable or 'master') |
Implementation Reference
- Main handler function that builds a GraphQL search query for a given content type by identifying searchable text fields from the cached schema and constructing a query with OR conditions across those fields.buildSearchQuery: async (args: BuildSearchQueryArgs): Promise<ToolResponse> => { try { if (!isCacheAvailable()) { return { content: [ { type: "text", text: "Query builder requires cached metadata. Please wait for the cache to load.", }, ], isError: true, } } const schema = getCachedContentTypeSchema(args.contentType) if (!schema) { // Try with Collection suffix const collectionSchema = getCachedContentTypeSchema(`${args.contentType}Collection`) if (!collectionSchema) { return { content: [ { type: "text", text: `Content type "${args.contentType}" not found in cache. Use graphql_list_content_types to see available content types.`, }, ], isError: true, } } } const actualSchema = schema || getCachedContentTypeSchema(`${args.contentType}Collection`) const contentTypeName = actualSchema.contentType // Find the correct query name from cached content types const cachedContentTypes = getCachedContentTypes() const contentTypeInfo = cachedContentTypes?.find( (ct) => ct.name === args.contentType || ct.name === contentTypeName || ct.queryName === contentTypeName, ) const queryName = contentTypeInfo?.queryName || (contentTypeName.endsWith("Collection") ? contentTypeName : `${contentTypeName}Collection`) // Determine which fields to search let fieldsToSearch = actualSchema.fields.filter((field: any) => isSearchableTextField(field.type), ) if (args.fields && args.fields.length > 0) { // Use only specified fields that are also searchable fieldsToSearch = fieldsToSearch.filter((field: any) => args.fields!.includes(field.name)) } if (fieldsToSearch.length === 0) { return { content: [ { type: "text", text: `No searchable text fields found for content type "${args.contentType}". Available fields: ${actualSchema.fields.map((f: any) => f.name).join(", ")}`, }, ], isError: true, } } // Build search conditions const searchConditions = fieldsToSearch .map((field: any) => `{ ${field.name}_contains: $searchTerm }`) .join(", ") // Get all fields for selection (scalars only for simplicity) const scalarFields = actualSchema.fields .filter((field: any) => isScalarType(field.type)) .map((field: any) => field.name) const query = `query Search${contentTypeName.replace("Collection", "")}($searchTerm: String!) { ${queryName}(where: { OR: [${searchConditions}] }, limit: 10) { items { sys { id } ${scalarFields.map((field: any) => ` ${field}`).join("\n")} } } }` return { content: [ { type: "text", text: query, }, ], } } catch (error) { return { content: [ { type: "text", text: `Error building search query: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, } } },
- src/types/tools.ts:135-158 (schema)Input schema definition for the build_search_query tool, specifying parameters like contentType, searchTerm, and optional fields.BUILD_SEARCH_QUERY: { name: "build_search_query", description: "Generate a GraphQL search query for a specific content type based on cached schema information. Returns the query string and variables needed to search text fields in the content type.", inputSchema: getOptionalEnvProperties({ type: "object", properties: { contentType: { type: "string", description: "The content type to build a search query for", }, searchTerm: { type: "string", description: "The term to search for", }, fields: { type: "array", items: { type: "string" }, description: "Optional: Specific fields to search (default: all searchable text fields)", }, }, required: ["contentType", "searchTerm"], }), },
- src/index.ts:118-131 (registration)Registration of the build_search_query handler in the getHandler function which maps tool names to their handler functions.// eslint-disable-next-line @typescript-eslint/no-explicit-any function getHandler(name: string): ((args: any) => Promise<any>) | undefined { const cdaOnlyHandlers = { // Only GraphQL operations are allowed with just a CDA token graphql_query: graphqlHandlers.executeQuery, graphql_list_content_types: graphqlHandlers.listContentTypes, graphql_get_content_type_schema: graphqlHandlers.getContentTypeSchema, graphql_get_example: graphqlHandlers.getExample, smart_search: graphqlHandlers.smartSearch, build_search_query: graphqlHandlers.buildSearchQuery, } return cdaOnlyHandlers[name as keyof typeof cdaOnlyHandlers] }
- TypeScript interface defining the arguments for the buildSearchQuery handler.export interface BuildSearchQueryArgs { contentType: string searchTerm: string fields?: string[] // Optional specific fields to search spaceId?: string // Optional override for environment variable environmentId?: string // Optional override for environment variable }
- src/index.ts:45-46 (registration)Inclusion of BUILD_SEARCH_QUERY in the static tools list returned by getAllTools() for MCP capabilities.if (allStaticTools.BUILD_SEARCH_QUERY) staticTools.BUILD_SEARCH_QUERY = allStaticTools.BUILD_SEARCH_QUERY