Skip to main content
Glama
georgeck

Hacker News Companion MCP

by georgeck

get_hn_post_formatted_comments

Retrieve and format comments from a Hacker News discussion post to prepare them for summarization by an LLM using specific prompts.

Instructions

Retrieves and formats comments from a Hacker News discussion post for summarization by an LLM. Use the hacker_news_summarization_user_prompt prompts to generate a summary.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
post_urlYesThe URL or ID for the Hacker News post to analyze. Can be a full URL (https://news.ycombinator.com/item?id=43456723) or just the numeric post ID e.g. 43456723.

Implementation Reference

  • Main execution handler for the tool: validates post_url, extracts postId, fetches and formats comments, constructs response with content (formattedComments + userPrompt) and metadata.
    case "get_hn_post_formatted_comments": { const post_url = String(request.params.arguments?.post_url).trim(); if (!post_url) { throw new Error("PostURL is required"); } const postId = getPostId(post_url); if (!postId) { throw new Error("Invalid post URL"); } log(`Fetching comments for post ID: ${postId}`); const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 30_000); // 30 seconds timeout try { const postResponseData = await downloadPostComments(postId); let formattedComments = ''; postResponseData.postComments.forEach(comment => { formattedComments += `[${comment.path}] (score: ${comment.score}) <replies: ${comment.replies}> {downvotes: ${comment.downvotes}} ${comment.author}: ${comment.text}\n`; }); return { content: [ { type: "text", text: String(formattedComments), description: "'formattedComments' - Formatted comments for post ID", }, { type: "text", text: getSystemPrompt(), description: "'userPrompt' - Follow the instructions in the `userPrompt` on interpreting the 'formattedComments' data." } ], metadata: { postId: postId, commentCount: postResponseData.postComments.length, postUrl: `https://news.ycombinator.com/item?id=${postId}` } }; } catch (error) { console.error("Error downloading comments:", error); throw new Error(`Failed to download comment post: ${error.message}`); } finally { clearTimeout(timeoutId); controller.abort(); } }
  • Tool registration defining name, description, inputSchema (post_url required), and outputSchema (content array with text blocks, metadata object).
    { name: "get_hn_post_formatted_comments", description: "Retrieves and formats comments from a Hacker News discussion post for summarization by an LLM. Use the `hacker_news_summarization_user_prompt` prompts to generate a summary.", inputSchema: { type: "object", properties: { post_url: { type: "string", description: "The URL or ID for the Hacker News post to analyze. Can be a full URL (https://news.ycombinator.com/item?id=43456723) or just the numeric post ID e.g. 43456723.", } }, required: ["post_url"], }, outputSchema: { type: "object", properties: { content: { type: "array", description: "Contains the formatted comments ('formattedComments') and user prompt ('userPrompt') - Follow the instructions in the `userPrompt` on interpreting the formatted comments.", }, metadata: { type: "object", description: "Contains post ID (postId), comment count (commentCount), and original post URL (postUrl)." } } } }
  • Helper function getPostId: extracts numeric post ID from HN URL or validates direct ID string.
    export function getPostId(input) { // Check if input is a URL if (input.startsWith('http')) { return extractPostIdFromUrl(input); } // Check if input is a valid post ID if (isValidPostId(input)) { return input; } return null;
  • Core helper downloadPostComments: fetches post API and HTML, parses DOM comments, structures tree into flat list with paths, scores, replies, downvotes for formatting.
    export async function downloadPostComments(postId) { // Fetch post data from HN API const postResponse = await fetch(`https://hn.algolia.com/api/v1/items/${postId}`); if (!postResponse.ok) { throw new Error(`Failed to fetch post: ${postResponse.statusText}`); } const postData = await postResponse.json(); // Fetch post HTML to get comment structure const postHtmlResponse = await fetch(`https://news.ycombinator.com/item?id=${postId}`); if (!postHtmlResponse.ok) { throw new Error(`Failed to fetch post HTML: ${postHtmlResponse.statusText}`); } const postHtml = await postHtmlResponse.text(); // Get comments from DOM const commentsInDOM = await getCommentsFromDOM(postHtml); // Convert HNPostData to CommentTree and extract comments const postComments = extractComments(postData, commentsInDOM); return { post: { id: postId, title: postData.title }, postComments }; }

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/georgeck/hn-companion-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server