getTopStories
Fetch top stories from Hacker News using the MCP Hacker News server. Retrieve up to 50 stories to access trending tech news and discussions.
Instructions
Get top stories from Hacker News (up to 500 available)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Number of stories to return (default: 10, max: 50) |
Implementation Reference
- src/tools.ts:27-69 (handler)The async execute handler function for the getTopStories tool. It fetches the top story IDs from Hacker News API, limits and fetches the story details using helper functions, formats the output including time and HN URLs, and returns a structured JSON 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)The input schema for getTopStories tool, defining an optional 'limit' parameter (number, default 10).inputSchema: { type: "object", properties: { limit: { type: "number", description: "Number of stories to return (default: 10, max: 50)", default: 10, }, }, },
- src/index.ts:52-65 (registration)MCP server registration and invocation logic for all tools, including getTopStories. Finds the tool by name from the imported tools array and executes its handler.if (json.method === "tools/call") { const tool = tools.find((tool) => tool.name === json.params.name); if (tool) { const toolResponse = await tool.execute(json.params.arguments); sendResponse(json.id, toolResponse); } else { sendResponse(json.id, { error: { code: -32602, message: `MCP error -32602: Tool ${json.params.name} not found`, }, }); } }
- src/fetch-actions.ts:30-44 (helper)Helper function used in getTopStories to fetch multiple story items by IDs in parallel, filtering out deleted or 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 used 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`; }