guardian_search_by_length
Filter and search The Guardian articles by word count range, section, date, and sorting preferences to find content matching specific criteria.
Instructions
Search Guardian articles filtered by word count range
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| from_date | No | Start date (YYYY-MM-DD format) | |
| max_words | No | Maximum word count (default: unlimited) | |
| min_words | No | Minimum word count (default: 0) | |
| order_by | No | Sort order: 'newest', 'oldest', 'relevance' (default: 'newest') | |
| page_size | No | Results per page, max 200 (default: 20) | |
| query | No | Search terms (optional) | |
| section | No | Filter by section ID | |
| to_date | No | End date (YYYY-MM-DD format) |
Implementation Reference
- The core handler function that executes the tool: parses args with schema, builds Guardian API search params, fetches articles, filters by word count range, and formats results.export async function guardianSearchByLength(client: GuardianClient, args: any): Promise<string> { const params = SearchByLengthParamsSchema.parse(args); // Build search parameters const searchParams: Record<string, any> = { 'show-fields': 'headline,standfirst,byline,publication,firstPublicationDate,wordcount', 'order-by': params.order_by || 'newest', 'page-size': Math.min(params.page_size || 20, 200) // Get max for filtering }; if (params.query) { searchParams.q = params.query; } if (params.section) { searchParams.section = params.section; } 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; } const response = await client.search(searchParams); const articles = response.response.results; // Filter by word count const minWords = params.min_words || 0; const maxWords = params.max_words || Number.POSITIVE_INFINITY; const filteredArticles = articles.filter(article => { const wordCount = article.fields?.wordcount; if (wordCount && !isNaN(Number(wordCount))) { const count = Number(wordCount); return count >= minWords && count <= maxWords; } return false; }); if (filteredArticles.length > 0) { const maxWordsDisplay = maxWords === Number.POSITIVE_INFINITY ? '∞' : maxWords.toString(); let result = `Found ${filteredArticles.length} article(s) with ${minWords}-${maxWordsDisplay} words:\n\n`; filteredArticles.forEach((article, index) => { result += `**${index + 1}. ${article.webTitle || 'Untitled'}**\n`; if (article.fields) { const { fields } = article; if (fields.byline) { result += `By: ${fields.byline}\n`; } if (fields.firstPublicationDate) { const pubDate = fields.firstPublicationDate.substring(0, 10); result += `Published: ${pubDate}\n`; } if (fields.wordcount) { result += `Word count: ${fields.wordcount}\n`; } if (fields.standfirst) { result += `Summary: ${fields.standfirst}\n`; } } result += `Section: ${article.sectionName || 'Unknown'}\n`; result += `URL: ${article.webUrl || 'N/A'}\n\n`; }); return result; } else { const maxWordsDisplay = maxWords === Number.POSITIVE_INFINITY ? '∞' : maxWords.toString(); return `No articles found with word count between ${minWords} and ${maxWordsDisplay} words.`; } }
- src/types/guardian.ts:112-121 (schema)Zod schema for validating input parameters to the guardian_search_by_length tool, used in the handler for parsing args.export const SearchByLengthParamsSchema = z.object({ query: z.string().optional(), min_words: z.number().min(0).optional(), max_words: z.number().min(1).optional(), section: 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(), });
- src/tools/index.ts:30-30 (registration)Registers the guardianSearchByLength handler function under the 'guardian_search_by_length' key in the tools registry returned by registerTools.guardian_search_by_length: (args) => guardianSearchByLength(client, args),
- src/index.ts:261-305 (registration)MCP protocol registration of the tool in the ListTools response, including name, description, and JSON schema matching the Zod schema.name: 'guardian_search_by_length', description: 'Search Guardian articles filtered by word count range', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search terms (optional)', }, min_words: { type: 'integer', description: 'Minimum word count (default: 0)', minimum: 0, }, max_words: { type: 'integer', description: 'Maximum word count (default: unlimited)', minimum: 1, }, section: { type: 'string', description: 'Filter by section ID', }, 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: 'newest')", enum: ['newest', 'oldest', 'relevance'], }, page_size: { type: 'integer', description: 'Results per page, max 200 (default: 20)', minimum: 1, maximum: 200, }, }, }, },
- src/tools/index.ts:9-9 (registration)Import of the handler function into the tools index module.import { guardianSearchByLength } from './guardian-search-by-length.js';