Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/web/public/.well-known/openmcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"list_authors",
"get_author",
"directory_stats",
"trending_topics",
"submit_feed",
"get_openprofile",
"update_openprofile",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/lib/llms.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export async function llmsTxt(opts = {}) {
'',
'The same capabilities as the endpoints below, as tools an agent can call:',
'search, list_feeds, get_feed, list_topics, get_topic, topic_posts, read_post,',
'random_feed, directory_stats and submit_feed. Point an MCP client at',
'random_feed, directory_stats, trending_topics and submit_feed. Point an MCP client at',
`\`${base}/mcp\` — it answers both the current protocol revision and the`,
'older handshake-based ones. Documentation for humans is at the same URL in a',
`browser: ${base}/mcp`,
Expand Down
23 changes: 22 additions & 1 deletion apps/web/src/lib/mcp/tools.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { q, newId, authors as people, webrings } from '@rssamplifier/db';
import { q, newId, authors as people, trends, webrings } from '@rssamplifier/db';
import { topicSlug } from '@rssamplifier/feed';
import { submitCatalogue, hashIp, EXPRESS_MAX } from '@rssamplifier/ingest';
import { submitFeedTool } from '@profullstack/submit-feed/core';
Expand Down Expand Up @@ -652,6 +652,27 @@ export const TOOLS = [
},
},

{
name: 'trending_topics',
title: 'What the open web is writing about more than last week',
description:
'Subjects English blogs and news sites used in headlines more than the week before, ranked. `count` is feeds, not posts, in a one in four sample, so it measures movement rather than coverage, and `prior_count` is the same figure for the week before. Updated daily. An empty list means the rollup has not got two days to compare yet.',
inputSchema: {
type: 'object',
properties: {
window: { type: 'integer', minimum: 1, maximum: 14, description: 'Days per side of the comparison. Default 7.' },
limit: { type: 'integer', minimum: 1, maximum: 200, description: 'Default 50.' },
},
},
annotations: { readOnlyHint: true, openWorldHint: true },
async run({ window = 7, limit = 50 } = {}) {
const size = Math.min(14, Math.max(1, Math.round(Number(window)) || 7));
const top = Math.min(200, Math.max(1, Math.round(Number(limit)) || 50));
const result = await trends.trendingTerms(db(), { window: size, limit: top });
return { window_days: size, generated_at: result.generatedAt, documents: result.feeds, topics: result.topics };
},
},

{
name: 'list_rings',
title: 'List the webrings this site hosts',
Expand Down
Loading