Skip to main content
Glama

mcp-rss

by buhe
index.ts4.26 kB
#!/usr/bin/env node import 'reflect-metadata'; import dotenv from 'dotenv'; import cron from 'node-cron'; import { initDatabase } from './config/database'; import { OpmlService } from './services/OpmlService'; import { RssService } from './services/RssService'; import { McpService } from './services/McpService'; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { ArticleStatus } from './entities/Article'; const server = new Server( { name: "rss_mcp", version: "1.1.0", }, { capabilities: { tools: {}, }, }, ); // 加载环境变量 dotenv.config(); // 获取环境变量 const opmlFilePath = process.env.OPML_FILE_PATH || './feeds.opml'; const updateInterval = process.env.RSS_UPDATE_INTERVAL || '1'; // 初始化服务 const opmlService = new OpmlService(); const rssService = new RssService(); const mcpService = new McpService(); server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "get_content", description: "Get articles by subscribing to RSS, status has only two values: normal, favorite, source is empty to indicate all sources, Sort by article time, with the latest at the front.", inputSchema: { type: "object", properties: { status: { type: "string" }, source: { type: "string" }, limit: { type: "number" } }, }, }, { name: "get_sources", description: "All sources of the article, the result is in array form. If you want to use the source parameter of get_content, which values ​​should be used, call it first", inputSchema: { type: "object", properties: { }, }, }, { name: "set_tag", description: "Set article tag, status has only two values: normal, favorite, articleId is article id", inputSchema: { type: "object", properties: { status: { type: "string" }, articleId: { type: "number" } } } } ], }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === "get_content") { const status = request.params.arguments?.status as string; const source = request.params.arguments?.source as string; const limit = request.params.arguments?.limit as number; const result = await mcpService.get_content(status as ArticleStatus, limit, source); return { content: [{ type: "text", text: JSON.stringify(result) }], isError: false, }; } if (request.params.name === "get_sources") { const result = await mcpService.get_sources(); return { content: [{ type: "text", text: JSON.stringify(result) }], isError: false, }; } if (request.params.name === "set_tag") { const status = request.params.arguments?.status as string; const articleId = request.params.arguments?.articleId as number; const result = await mcpService.set_tag(articleId, status as ArticleStatus); return { content: [{ type: "text", text: JSON.stringify(result) }], isError: false, }; } throw new Error(`Unknown tool: ${request.params.name}`); }); // console.log('MCP 启动成功') async function runServer() { await initDatabase(); // 设置定时任务,定期获取RSS更新 const cronExpression = `*/${updateInterval} * * * *`; // 每X分钟执行一次 // console.log(`设置定时任务: ${cronExpression}`); cron.schedule(cronExpression, async () => { // console.log(`定时任务执行: ${new Date().toISOString()}`); // 初始化数据库 // console.error('Fetch...'); // 解析OPML文件并保存订阅源 await opmlService.parseAndSaveFeeds(opmlFilePath); await rssService.fetchAllFeeds(); }); const transport = new StdioServerTransport(); await server.connect(transport); } runServer().catch(console.error);

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/buhe/mcp_rss'

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