getTopStories
Fetch the top stories from Hacker News, with options to specify the number of results (up to 50). Designed for AI tools to access live Hacker News data via MCP endpoints.
Instructions
Get top stories from Hacker News (up to 500 available)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Number of stories to return (default: 10, max: 50) |
Input Schema (JSON Schema)
{
"properties": {
"limit": {
"default": 10,
"description": "Number of stories to return (default: 10, max: 50)",
"type": "number"
}
},
"type": "object"
}
Implementation Reference
- src/tools.ts:27-69 (handler)The main execute handler for getTopStories tool, which fetches top story IDs from HN API, retrieves details for up to 50 stories, formats them with relative time, and returns a JSON string response.execute: async (args: any) => { const limit = Math.min(args.limit || 10, 50); const topIds = await fetchFromAPI<number[]>("/topstories"); if (!topIds) { return { content: [ { type: "text", text: JSON.stringify({ error: "Failed to fetch top stories" }), }, ], }; } const stories = await fetchMultipleItems(topIds, limit); const formattedStories = stories.map((story) => ({ id: story.id, title: story.title, url: story.url, score: story.score, author: story.by, comments: story.descendants || 0, time: story.time ? formatTime(story.time) : "unknown", hnUrl: `https://news.ycombinator.com/item?id=${story.id}`, })); return { content: [ { type: "text", text: JSON.stringify( { message: `Top ${limit} stories from Hacker News`, stories: formattedStories, }, null, 2 ), }, ], }; },
- src/tools.ts:17-26 (schema)Input schema defining the optional 'limit' parameter for the number of top stories to fetch.inputSchema: { type: "object", properties: { limit: { type: "number", description: "Number of stories to return (default: 10, max: 50)", default: 10, }, }, },
- src/tools.ts:14-70 (registration)The getTopStories tool object registered in the exported 'tools' array, which is imported and used by the MCP server.{ name: "getTopStories", description: "Get top stories from Hacker News (up to 500 available)", inputSchema: { type: "object", properties: { limit: { type: "number", description: "Number of stories to return (default: 10, max: 50)", default: 10, }, }, }, execute: async (args: any) => { const limit = Math.min(args.limit || 10, 50); const topIds = await fetchFromAPI<number[]>("/topstories"); if (!topIds) { return { content: [ { type: "text", text: JSON.stringify({ error: "Failed to fetch top stories" }), }, ], }; } const stories = await fetchMultipleItems(topIds, limit); const formattedStories = stories.map((story) => ({ id: story.id, title: story.title, url: story.url, score: story.score, author: story.by, comments: story.descendants || 0, time: story.time ? formatTime(story.time) : "unknown", hnUrl: `https://news.ycombinator.com/item?id=${story.id}`, })); return { content: [ { type: "text", text: JSON.stringify( { message: `Top ${limit} stories from Hacker News`, stories: formattedStories, }, null, 2 ), }, ], }; }, },
- src/fetch-actions.ts:30-44 (helper)Helper function used to fetch story details from multiple item IDs in parallel, filtering out deleted/dead items.export async function fetchMultipleItems( ids: number[], maxItems = 30 ): Promise<HackerNewsItem[]> { const limitedIds = ids.slice(0, maxItems); const promises = limitedIds.map((id) => fetchFromAPI<HackerNewsItem>(`/item/${id}`) ); const results = await Promise.all(promises); return results.filter( (item): item is HackerNewsItem => item !== null && !item.deleted && !item.dead ); }
- src/helpers.ts:23-35 (helper)Helper function to format Unix timestamps into human-readable relative time strings (e.g., '2h ago').export function formatTime(timestamp: number): string { const date = new Date(timestamp * 1000); const now = new Date(); const diff = now.getTime() - date.getTime(); const minutes = Math.floor(diff / (1000 * 60)); const hours = Math.floor(diff / (1000 * 60 * 60)); const days = Math.floor(diff / (1000 * 60 * 60 * 24)); if (minutes < 60) return `${minutes}m ago`; if (hours < 24) return `${hours}h ago`; return `${days}d ago`; }