extract_feed_content
Extract and format RSS feed content into markdown, text, HTML, or JSON. Include metadata for enhanced context and streamline feed data integration.
Instructions
Extract and format feed content for different use cases
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | Output format for the content | text |
| includeMetadata | No | If 'true', include item metadata (date, author, etc) in output | false |
| url | Yes | The RSS feed URL to extract content from |
Input Schema (JSON Schema)
{
"additionalProperties": false,
"properties": {
"format": {
"default": "text",
"description": "Output format for the content",
"enum": [
"markdown",
"text",
"html",
"json"
],
"type": "string"
},
"includeMetadata": {
"default": "false",
"description": "If 'true', include item metadata (date, author, etc) in output",
"type": "string"
},
"url": {
"description": "The RSS feed URL to extract content from",
"type": "string"
}
},
"required": [
"url"
],
"type": "object"
}
Implementation Reference
- src/index.ts:346-440 (handler)Execute handler for 'extract_feed_content' tool: fetches RSS feed from cache or network, formats each item's content in the requested format (markdown, html, text, json) with optional metadata, and returns structured JSON output.execute: async (args, context) => { logger.info( `Extracting content from: ${args.url} (format: ${args.format})` ); // Fetch feed let feed: FeedResult | null = feedCache.get(args.url); if (!feed) { feed = await rssReader.fetchFeed(args.url); feedCache.set(args.url, feed); } // Format content based on requested format const formatItem = (item: FeedItem): string | object => { const content = item.content || item.description || ""; const metadata = { title: item.title, author: item.author, published: item.published ? new Date(item.published).toISOString() : null, url: item.url, categories: item.categories, }; if (args.format === "json") { return args.includeMetadata === 'true' ? { ...metadata, content } : { content }; } const metadataText = args.includeMetadata === 'true' ? [ item.title ? `Title: ${item.title}` : "", item.author ? `Author: ${item.author}` : "", item.published ? `Published: ${new Date(item.published).toISOString()}` : "", item.url ? `URL: ${item.url}` : "", item.categories.length > 0 ? `Categories: ${item.categories.join(", ")}` : "", ] .filter(Boolean) .join("\n") : ""; switch (args.format) { case "markdown": const parts = []; if (item.title) parts.push(`# ${item.title}`); if (metadataText) parts.push(metadataText); if (content) parts.push(content); if (item.url) parts.push(`\n[Read more](${item.url})`); return parts.join("\n\n"); case "html": const htmlParts = []; if (item.title) htmlParts.push(`<h1>${item.title}</h1>`); if (metadataText) htmlParts.push( `<div class="metadata">${metadataText.replace( /\n/g, "<br>" )}</div>` ); if (content) htmlParts.push(`<div class="content">${content}</div>`); if (item.url) htmlParts.push(`<p><a href="${item.url}">Read more</a></p>`); return htmlParts.join("\n"); case "text": default: const textParts = []; if (item.title) textParts.push(item.title); if (metadataText) textParts.push(metadataText); if (content) textParts.push(content); return textParts.join("\n\n"); } }; const formattedItems = feed.items.map(formatItem); const output = { feedTitle: feed.info.title, feedUrl: args.url, itemCount: feed.items.length, format: args.format, extractedAt: Date.now(), extractedAtISO: new Date().toISOString(), content: formattedItems, }; logger.info(`Extracted content from ${feed.items.length} items`); return JSON.stringify(output, null, 2); }, });
- src/index.ts:328-340 (schema)Zod schema defining input parameters for the extract_feed_content tool: url (required), format (optional enum), includeMetadata (optional boolean as string).const ExtractFeedContentSchema = z.object({ url: z.string().describe("The RSS feed URL to extract content from"), format: z .enum(["markdown", "text", "html", "json"]) .optional() .default("text") .describe("Output format for the content"), includeMetadata: z .string() .optional() .default("false") .describe("If 'true', include item metadata (date, author, etc) in output"), });
- src/index.ts:342-440 (registration)Registration of the 'extract_feed_content' tool using server.addTool, specifying name, description, parameters schema, and execute handler.server.addTool({ name: "extract_feed_content", description: "Extract and format feed content for different use cases", parameters: ExtractFeedContentSchema, execute: async (args, context) => { logger.info( `Extracting content from: ${args.url} (format: ${args.format})` ); // Fetch feed let feed: FeedResult | null = feedCache.get(args.url); if (!feed) { feed = await rssReader.fetchFeed(args.url); feedCache.set(args.url, feed); } // Format content based on requested format const formatItem = (item: FeedItem): string | object => { const content = item.content || item.description || ""; const metadata = { title: item.title, author: item.author, published: item.published ? new Date(item.published).toISOString() : null, url: item.url, categories: item.categories, }; if (args.format === "json") { return args.includeMetadata === 'true' ? { ...metadata, content } : { content }; } const metadataText = args.includeMetadata === 'true' ? [ item.title ? `Title: ${item.title}` : "", item.author ? `Author: ${item.author}` : "", item.published ? `Published: ${new Date(item.published).toISOString()}` : "", item.url ? `URL: ${item.url}` : "", item.categories.length > 0 ? `Categories: ${item.categories.join(", ")}` : "", ] .filter(Boolean) .join("\n") : ""; switch (args.format) { case "markdown": const parts = []; if (item.title) parts.push(`# ${item.title}`); if (metadataText) parts.push(metadataText); if (content) parts.push(content); if (item.url) parts.push(`\n[Read more](${item.url})`); return parts.join("\n\n"); case "html": const htmlParts = []; if (item.title) htmlParts.push(`<h1>${item.title}</h1>`); if (metadataText) htmlParts.push( `<div class="metadata">${metadataText.replace( /\n/g, "<br>" )}</div>` ); if (content) htmlParts.push(`<div class="content">${content}</div>`); if (item.url) htmlParts.push(`<p><a href="${item.url}">Read more</a></p>`); return htmlParts.join("\n"); case "text": default: const textParts = []; if (item.title) textParts.push(item.title); if (metadataText) textParts.push(metadataText); if (content) textParts.push(content); return textParts.join("\n\n"); } }; const formattedItems = feed.items.map(formatItem); const output = { feedTitle: feed.info.title, feedUrl: args.url, itemCount: feed.items.length, format: args.format, extractedAt: Date.now(), extractedAtISO: new Date().toISOString(), content: formattedItems, }; logger.info(`Extracted content from ${feed.items.length} items`); return JSON.stringify(output, null, 2); }, });
- src/types.ts:101-105 (schema)TypeScript interface defining the input parameters for extract_feed_content, matching the Zod schema.export interface ExtractFeedContentParams { url: string; format?: 'markdown' | 'text' | 'html' | 'json'; includeMetadata?: 'true' | 'false'; }