guardian_search
Search and filter Guardian newspaper articles from 1999 onward using queries, dates, sections, tags, and sorting options.
Instructions
Search Guardian articles with flexible filtering options
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Search terms (can be empty to browse all content) | |
| section | No | Filter by section ID (get available sections via guardian_get_sections) | |
| tag | No | Filter by tag (over 50,000 available tags) | |
| from_date | No | Start date (YYYY-MM-DD format) | |
| to_date | No | End date (YYYY-MM-DD format) | |
| order_by | No | Sort order: 'newest', 'oldest', 'relevance' (default: 'relevance') | |
| page_size | No | Results per page, max 200 (default: 20) | |
| page | No | Page number (default: 1) | |
| show_fields | No | Comma-separated fields to include (headline,standfirst,body,byline,thumbnail,publication) | |
| production_office | No | Filter by office: 'uk', 'us', 'au' | |
| detail_level | No | Response detail level: 'minimal' (fast), 'standard' (default), 'full' (complete) |
Implementation Reference
- src/tools/guardian-search.ts:5-73 (handler)Main handler function that parses input args using SearchParamsSchema, builds Guardian API search parameters based on options like query, section, dates, order, detail level, calls client.search(), and formats the response using formatArticleResponse.export async function guardianSearch(client: GuardianClient, args: any): Promise<string> { const params = SearchParamsSchema.parse(args); // Build search parameters for Guardian API const searchParams: Record<string, any> = {}; if (params.query) { searchParams.q = params.query; } if (params.section) { searchParams.section = params.section; } if (params.tag) { searchParams.tag = params.tag; } if (params.from_date) { const fromDate = validateDate(params.from_date); if (!fromDate) { throw new Error(`Invalid from_date format: ${params.from_date}. Use YYYY-MM-DD format.`); } searchParams['from-date'] = fromDate; } if (params.to_date) { const toDate = validateDate(params.to_date); if (!toDate) { throw new Error(`Invalid to_date format: ${params.to_date}. Use YYYY-MM-DD format.`); } searchParams['to-date'] = toDate; } searchParams['order-by'] = params.order_by || 'relevance'; searchParams['page-size'] = params.page_size || 20; searchParams.page = params.page || 1; // Handle detail_level for performance optimization const detailLevel = params.detail_level || 'minimal'; let showFields = params.show_fields; if (!showFields) { switch (detailLevel) { case 'minimal': showFields = 'headline,sectionName,webPublicationDate'; break; case 'standard': showFields = 'headline,standfirst,byline,publication,firstPublicationDate'; break; case 'full': showFields = 'headline,standfirst,body,byline,publication,firstPublicationDate,wordcount'; break; } } searchParams['show-fields'] = showFields; if (params.production_office) { searchParams['production-office'] = params.production_office; } const response = await client.search(searchParams); const articles = response.response.results; const pagination = response.response; // Apply truncation based on detail level const formatOptions = { truncate: detailLevel !== 'full', // Only show full content for 'full' detail level maxLength: 500 }; return formatArticleResponse(articles, pagination, formatOptions); }
- src/types/guardian.ts:65-77 (schema)Zod schema for validating and typing the input parameters to the guardian_search tool.export const SearchParamsSchema = z.object({ query: z.string().optional(), section: z.string().optional(), tag: z.string().optional(), from_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(), to_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(), order_by: z.enum(['newest', 'oldest', 'relevance']).optional(), page_size: z.number().min(1).max(200).optional(), page: z.number().min(1).optional(), show_fields: z.string().optional(), production_office: z.enum(['uk', 'us', 'au']).optional(), detail_level: z.enum(['minimal', 'standard', 'full']).optional(), });
- src/tools/index.ts:21-39 (registration)Function that registers all tools including guardian_search by mapping the name to the handler function wrapped with the GuardianClient.export function registerTools(client: GuardianClient): Record<string, ToolHandler> { return { guardian_search: (args) => guardianSearch(client, args), guardian_get_article: (args) => guardianGetArticle(client, args), guardian_longread: (args) => guardianLongread(client, args), guardian_lookback: (args) => guardianLookback(client, args), guardian_browse_section: (args) => guardianBrowseSection(client, args), guardian_get_sections: (args) => guardianGetSections(client, args), guardian_search_tags: (args) => guardianSearchTags(client, args), guardian_search_by_length: (args) => guardianSearchByLength(client, args), guardian_search_by_author: (args) => guardianSearchByAuthor(client, args), guardian_find_related: (args) => guardianFindRelated(client, args), guardian_get_article_tags: (args) => guardianGetArticleTags(client, args), guardian_content_timeline: (args) => guardianContentTimeline(client, args), guardian_author_profile: (args) => guardianAuthorProfile(client, args), guardian_topic_trends: (args) => guardianTopicTrends(client, args), guardian_top_stories_by_date: (args) => guardianTopStoriesByDate(client, args), guardian_recommend_longreads: (args) => guardianRecommendLongreads(client, args), };
- src/index.ts:61-118 (registration)MCP tool registration in the ListTools response, defining the name, description, and input schema for guardian_search.name: 'guardian_search', description: 'Search Guardian articles with flexible filtering options', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search terms (can be empty to browse all content)', }, section: { type: 'string', description: 'Filter by section ID (get available sections via guardian_get_sections)', }, tag: { type: 'string', description: 'Filter by tag (over 50,000 available tags)', }, from_date: { type: 'string', description: 'Start date (YYYY-MM-DD format)', }, to_date: { type: 'string', description: 'End date (YYYY-MM-DD format)', }, order_by: { type: 'string', description: "Sort order: 'newest', 'oldest', 'relevance' (default: 'relevance')", enum: ['newest', 'oldest', 'relevance'], }, page_size: { type: 'integer', description: 'Results per page, max 200 (default: 20)', minimum: 1, maximum: 200, }, page: { type: 'integer', description: 'Page number (default: 1)', minimum: 1, }, show_fields: { type: 'string', description: 'Comma-separated fields to include (headline,standfirst,body,byline,thumbnail,publication)', }, production_office: { type: 'string', description: "Filter by office: 'uk', 'us', 'au'", enum: ['uk', 'us', 'au'], }, detail_level: { type: 'string', description: "Response detail level: 'minimal' (fast), 'standard' (default), 'full' (complete)", enum: ['minimal', 'standard', 'full'], }, }, }, },