hn_comments
Retrieve comments for a Hacker News story by specifying its ID or index from the latest fetched story list for quick access to discussions.
Instructions
Get comments for a story (by story ID or index from last story list)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| story_id | No | The ID of the story to get comments for | |
| story_index | No | The index (1-based) of the story from the last fetched list |
Implementation Reference
- index.ts:208-225 (registration)Registration of the hn_comments tool including its name, description, and input schema in the ListToolsRequestSchema handler.{ name: "hn_comments", description: "Get comments for a story (by story ID or index from last story list)", inputSchema: { type: "object", properties: { story_id: { type: "number", description: "The ID of the story to get comments for" }, story_index: { type: "number", description: "The index (1-based) of the story from the last fetched list", minimum: 1 } } } }
- index.ts:329-383 (handler)The handler logic for hn_comments tool call, which resolves story ID, fetches story and comments, formats them, and returns text content.if (name === "hn_comments") { const storyId = typeof args?.story_id === 'number' ? args.story_id : NaN; const storyIndex = typeof args?.story_index === 'number' ? args.story_index : NaN; if (isNaN(storyId) && isNaN(storyIndex)) { throw new Error('Either a story ID or a story index is required'); } let targetStoryId: number; if (!isNaN(storyId)) { targetStoryId = storyId; } else if (!isNaN(storyIndex) && storyIndex > 0 && storyIndex <= lastStoriesList.length) { targetStoryId = lastStoriesList[storyIndex - 1].id; } else { throw new Error('Invalid story index or ID provided'); } if (isNaN(targetStoryId)) { throw new Error('Story ID must be a number'); } const story = await api.getItemDetails(targetStoryId) as Story | null; if (!story) { throw new Error(`Story with ID ${targetStoryId} not found`); } if (!story.kids || story.kids.length === 0) { return { content: [ { type: "text", text: `No comments found for story "${story.title}" (ID: ${story.id})` } ] }; } const comments = await api.getComments(story.kids); const formattedComments = comments.map(comment => ({ id: comment.id, by: comment.by, time: api.formatTime(comment.time), text: api.cleanText(comment.text), replies: comment.kids ? comment.kids.length : 0 })); return { content: [ { type: "text", text: formatCommentsAsText(story.title, formattedComments) } ] }; }
- index.ts:97-109 (helper)Helper method in HackerNewsAPI to fetch multiple comments by their IDs.async getComments(commentIds: number[] = []): Promise<Comment[]> { if (!commentIds || commentIds.length === 0) { return []; } try { const commentPromises = commentIds.map(id => this.getItemDetails(id)); const comments = await Promise.all(commentPromises); return comments.filter((comment): comment is Comment => comment !== null); } catch (error) { console.error('Failed to load comments:', error); return []; } }
- index.ts:428-443 (helper)Helper function to format the story title and list of comments into a readable text output.function formatCommentsAsText(storyTitle: string, comments: FormattedComment[]): string { if (!comments || comments.length === 0) { return "No comments found."; } const header = `Comments for "${storyTitle}" (Total: ${comments.length}):\n`; const formattedComments = comments.map((comment, index) => { return `${index + 1}. Comment by ${comment.by} at ${comment.time}: "${comment.text}" ${comment.replies > 0 ? `(${comment.replies} replies)` : '(no replies)'} ------------------------------`; }).join('\n\n'); return header + '\n' + formattedComments; }
- index.ts:214-223 (schema)Input schema definition for hn_comments tool parameters.story_id: { type: "number", description: "The ID of the story to get comments for" }, story_index: { type: "number", description: "The index (1-based) of the story from the last fetched list", minimum: 1 } }