Spark Feed MCP

Spark Feed MCP

OAuth-protected remote MCP server for Cloudflare Workers that exposes get_videos and get_articles tools to read configured RSS/Atom feeds filtered by date, returning entries and article previews.

Category
Visit Server

README

Spark Feed MCP

Spark Feed MCP is an OAuth-protected remote MCP server for Cloudflare Workers. It exposes two server-controlled tools:

  • get_videos reads the feeds hardcoded in VIDEO_OPML.
  • get_articles reads the feeds hardcoded in ARTICLE_OPML.

Both tools require a date argument in MM/DD/YYYY format and return entries published during that UTC calendar day. Article results additionally include the first 30 Unicode characters of the cleaned article body.

Project files

File Purpose
index.js Cloudflare Worker, MCP JSON-RPC endpoint, OAuth consent flow, OPML configuration, feed fetching, XML parsing, normalization, and date filtering.
package.json Dependency versions and Wrangler commands.
package-lock.json Reproducible npm dependency tree.
wrangler.jsonc Cloudflare Worker entry point and required OAuth KV binding.
.gitignore Prevents dependencies, local secrets, and generated output from being committed.

What index.js does

Hardcoded feeds

VIDEO_OPML and ARTICLE_OPML are XML string constants near the beginning of index.js. MCP callers cannot provide a feed URL, which keeps outbound requests limited to the feeds you configure on the server.

Each OPML list can contain one or more nested outline elements:

<outline
  text="Example feed"
  type="rss"
  xmlUrl="https://example.com/feed.xml"
/>

If a feed URL contains query parameters, XML-escape ampersands:

xmlUrl="https://example.com/feed.xml?topic=one&amp;format=rss"

MCP tools

Both tools take the same required input:

{
  "date": "12/12/2001"
}

get_videos returns:

{
  "items": [
    {
      "title": "Example video",
      "link": "https://example.com/video",
      "date": "2001-12-12T17:00:00.000Z"
    }
  ]
}

get_articles returns:

{
  "items": [
    {
      "title": "Example article",
      "link": "https://example.com/article",
      "date": "2001-12-12T18:00:00.000Z",
      "body": "The first thirty characters..."
    }
  ]
}

The date filter includes timestamps greater than or equal to midnight UTC and strictly earlier than midnight UTC on the following day. For 12/12/2001, that means:

2001-12-12T00:00:00.000Z <= timestamp < 2001-12-13T00:00:00.000Z

Entries with missing or unparseable publication dates are excluded.

Feed parsing

The Worker uses XMLParser from fast-xml-parser. It supports common:

  • RSS 2.0 channel.item feeds.
  • Atom feed.entry feeds.
  • RDF/RSS 1.0 feeds.

It recognizes common title, link, date, description, summary, and content fields. Dates are normalized to ISO 8601, duplicate entries are removed, and results are sorted newest first. HTML is removed from article bodies before the 30-character preview is created.

If one configured feed fails, the Worker logs that failure and still returns results from the remaining feeds. The tool returns an error only when every configured feed fails.

OAuth

OAuthProvider protects /mcp and supplies OAuth discovery, client registration, authorization-code exchange, token refresh, revocation, bearer validation, and OAuth storage.

The Worker implements its own /authorize consent page. Authorization requires the server-side OAUTH_ADMIN_PASSWORD secret. The secret is never placed in source control or wrangler.jsonc.

The public endpoints are:

Path Purpose
/ Basic service information.
/mcp OAuth-protected MCP endpoint.
/authorize Password-protected consent page.
/token OAuth token endpoint.
/register Dynamic client registration endpoint.

Prerequisites

  • A Cloudflare account with Workers and Workers KV available.
  • Node.js 22 or newer.
  • npm.

Check your versions:

node --version
npm --version

Setup

1. Install dependencies

From this project directory:

npm ci

npm ci uses the included lockfile and installs the exact tested versions.

2. Sign in to Cloudflare

npx wrangler login

Complete the authorization page Wrangler opens.

3. Create the OAuth KV namespace

npx wrangler kv namespace create OAUTH_KV

Copy the namespace ID printed by Wrangler. Open wrangler.jsonc and replace:

REPLACE_WITH_YOUR_OAUTH_KV_NAMESPACE_ID

with that ID. The binding name must remain exactly OAUTH_KV because the OAuth provider uses it for clients, grants, codes, access tokens, and refresh tokens.

4. Configure the Worker URL

Near the beginning of index.js, set PUBLIC_ORIGIN to the exact public origin that Cloudflare will assign to this Worker:

const PUBLIC_ORIGIN =
  "https://spark-feed-mcp.YOUR-WORKERS-SUBDOMAIN.workers.dev";

Do not include a trailing slash. The value must match the deployed Worker URL because it is used in OAuth resource and authorization-server metadata.

5. Configure the feeds

Replace the example xmlUrl in VIDEO_OPML with your video feed URL or URLs. Replace the example xmlUrl in ARTICLE_OPML with your article feed URL or URLs.

Example with multiple feeds:

<body>
  <outline text="Feed one" type="rss" xmlUrl="https://one.example/feed.xml" />
  <outline text="Feed two" type="rss" xmlUrl="https://two.example/atom.xml" />
</body>

Do not leave the example.com placeholder feeds in production.

6. Create the production authorization password

npx wrangler secret put OAUTH_ADMIN_PASSWORD

Enter a long, unique password at the prompt. Do not add this password to wrangler.jsonc, package.json, or Git.

7. Validate the build

npm run check

This performs a Wrangler dry-run bundle without deploying.

8. Deploy

npm run deploy

After deployment, confirm the printed URL exactly matches PUBLIC_ORIGIN. If it differs, correct PUBLIC_ORIGIN and deploy again.

9. Confirm the service

Open the Worker root URL or run:

curl https://spark-feed-mcp.YOUR-WORKERS-SUBDOMAIN.workers.dev/

The JSON response should list get_videos, get_articles, and the OAuth endpoints. An unauthenticated request to /mcp should receive an OAuth bearer challenge rather than tool data.

10. Connect Gemini

In the Gemini agent configuration that accepts a remote MCP server:

  1. Use https://spark-feed-mcp.YOUR-WORKERS-SUBDOMAIN.workers.dev/mcp as the MCP server URL.
  2. Select OAuth authorization if the interface asks for an authentication method.
  3. Allow the client-registration and authorization flow to open.
  4. Enter OAUTH_ADMIN_PASSWORD on the consent page and approve access.
  5. Verify that Gemini discovers get_videos and get_articles.

The exact Gemini controls can vary by product surface, but the MCP URL always ends in /mcp; the root Worker URL is not the MCP endpoint.

Local development

Create a .dev.vars file for local-only secrets:

OAUTH_ADMIN_PASSWORD=replace-with-a-local-test-password

Then run:

npm run dev

.dev.vars is ignored by Git. Never commit real production credentials.

Local OAuth redirects still depend on PUBLIC_ORIGIN. For a complete local OAuth test, temporarily use the local origin Wrangler prints, then restore the production origin before deployment.

Tool behavior and limits

  • Date input must be a real calendar date in zero-padded MM/DD/YYYY form.
  • Filtering uses UTC, regardless of the offset originally present in the feed.
  • Feed requests time out after 10 seconds.
  • Each feed is limited to 2 MB.
  • At most four feeds are requested concurrently.
  • Feed URLs must use HTTP or HTTPS.
  • Results contain no feed metadata beyond the requested item fields.
  • Article body previews contain at most 30 Unicode characters and no ellipsis is appended.

Troubleshooting

None of the configured feeds could be read

  • Confirm that the placeholder example.com URLs were replaced.
  • Open each feed URL directly and verify it returns RSS, Atom, or RDF XML.
  • Check Worker logs for the URL and HTTP status of the failed feed.

OAuth or authorization fails

  • Confirm OAUTH_KV exists in wrangler.jsonc and contains the correct namespace ID.
  • Confirm OAUTH_ADMIN_PASSWORD was created with wrangler secret put.
  • Confirm PUBLIC_ORIGIN exactly matches the deployed HTTPS origin.
  • Use the /mcp URL in Gemini, not / or /authorize.

The tools return an empty items array

  • Confirm the requested date is in UTC and in MM/DD/YYYY format.
  • Confirm the feed entries contain a parseable publication or update date.
  • Remember that an entry displayed as December 12 in a negative UTC offset may fall on December 13 after conversion to UTC.

Article bodies are empty

The feed must provide article text in a common field such as content:encoded, content, summary, or description. Some feeds expose only titles and links.

Updating dependencies

The dependency versions are intentionally pinned. To update them later:

npm outdated
npm update
npm run check

Commit both package.json and package-lock.json after testing an update.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured