search-posts
Search HackerNews posts using keywords, tags, and numeric filters to find relevant content sorted by relevance, points, and comments.
Instructions
Search HackerNews posts by relevance (sorted by relevance, then points, then number of comments)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| hitsPerPage | No | Number of results per page (default: 20) | |
| numericFilters | No | Numeric filters (e.g., "points>100", "created_at_i>1672531200") | |
| page | No | Page number for pagination (default: 0) | |
| query | Yes | Search query text | |
| tags | No | Filter tags (e.g., "story", "comment", "poll", "show_hn", "ask_hn", "front_page", "author_USERNAME", "story_ID") |
Implementation Reference
- src/index.ts:46-61 (handler)The handler function for the 'search-posts' tool. It constructs query parameters from inputs, calls the HackerNews Algolia /search endpoint via the fetchHN helper, and returns the results as both text and structured content.async ({ query, tags, numericFilters, page, hitsPerPage }) => { const params = new URLSearchParams(); if (query) params.append('query', query); if (tags) params.append('tags', tags); if (numericFilters) params.append('numericFilters', numericFilters); if (page !== undefined) params.append('page', page.toString()); if (hitsPerPage !== undefined) params.append('hitsPerPage', hitsPerPage.toString()); const endpoint = `/search?${params.toString()}`; const result = await fetchHN(endpoint); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], structuredContent: result }; }
- src/index.ts:28-45 (schema)The inputSchema and outputSchema definitions using Zod for validating parameters and response of the 'search-posts' tool.{ title: 'Search HackerNews Posts', description: 'Search HackerNews posts by relevance (sorted by relevance, then points, then number of comments)', inputSchema: { query: z.string().describe('Search query text'), tags: z.string().optional().describe('Filter tags (e.g., "story", "comment", "poll", "show_hn", "ask_hn", "front_page", "author_USERNAME", "story_ID")'), numericFilters: z.string().optional().describe('Numeric filters (e.g., "points>100", "created_at_i>1672531200")'), page: z.number().optional().describe('Page number for pagination (default: 0)'), hitsPerPage: z.number().optional().describe('Number of results per page (default: 20)') }, outputSchema: { hits: z.array(z.any()), nbHits: z.number(), nbPages: z.number(), page: z.number(), hitsPerPage: z.number() } },
- src/index.ts:26-62 (registration)The complete registration of the 'search-posts' tool using McpServer.registerTool, including name, schema, and handler.server.registerTool( 'search-posts', { title: 'Search HackerNews Posts', description: 'Search HackerNews posts by relevance (sorted by relevance, then points, then number of comments)', inputSchema: { query: z.string().describe('Search query text'), tags: z.string().optional().describe('Filter tags (e.g., "story", "comment", "poll", "show_hn", "ask_hn", "front_page", "author_USERNAME", "story_ID")'), numericFilters: z.string().optional().describe('Numeric filters (e.g., "points>100", "created_at_i>1672531200")'), page: z.number().optional().describe('Page number for pagination (default: 0)'), hitsPerPage: z.number().optional().describe('Number of results per page (default: 20)') }, outputSchema: { hits: z.array(z.any()), nbHits: z.number(), nbPages: z.number(), page: z.number(), hitsPerPage: z.number() } }, async ({ query, tags, numericFilters, page, hitsPerPage }) => { const params = new URLSearchParams(); if (query) params.append('query', query); if (tags) params.append('tags', tags); if (numericFilters) params.append('numericFilters', numericFilters); if (page !== undefined) params.append('page', page.toString()); if (hitsPerPage !== undefined) params.append('hitsPerPage', hitsPerPage.toString()); const endpoint = `/search?${params.toString()}`; const result = await fetchHN(endpoint); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], structuredContent: result }; } );
- src/index.ts:11-17 (helper)Shared helper function fetchHN used by the 'search-posts' handler (and other tools) to make API calls to the HackerNews Algolia API.async function fetchHN(endpoint: string): Promise<any> { const response = await fetch(`${HN_API_BASE}${endpoint}`); if (!response.ok) { throw new Error(`HN API error: ${response.status} ${response.statusText}`); } return await response.json(); }