get_latest_news
Retrieve news and updates for any AI ecosystem. Items include content age and freshness indicators; verify critical decisions against source URLs.
Instructions
Get the latest news and updates for an AI ecosystem. Pro tier receives real-time results. Free tier receives items older than 24 hours. Each item includes content_age_hours and data_freshness — check these before acting on time-sensitive information. Strata provides intelligence, not ground truth. Always verify critical decisions against the source_urls returned with each item.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ecosystem | Yes | ||
| limit | No |
Implementation Reference
- lib/mcp-tools.ts:229-275 (handler)The main handler function for 'get_latest_news'. Accepts ecosystem (required) and limit (optional, default 5, max 20). Queries the 'content_items' table filtered by ecosystem slug, category 'news', and non-quarantined. Free tier gets items older than 24h and non-pro-only. Returns items with freshness envelope (content_age_hours, last_verified_at, data_freshness).
if (name === 'get_latest_news') { const ecosystem = args.ecosystem as string const rawLimit = typeof args.limit === 'number' ? args.limit : 5 const limit = Math.min(Math.max(1, rawLimit), 20) const access = await checkEcosystemAccess(supabase, ecosystem, profile.tier) if (!access.ok) { await logApiRequest(supabase, { apiKey: profile.api_key, tool: 'news', ecosystem, statusCode: access.response.status }) return err('Error: Ecosystem not available on free tier. Upgrade at usestrata.dev/dashboard/billing', access.response.status) } let query = supabase .from('content_items') .select('id, title, body, source_url, published_at, last_verified_at, confidence, source_count') .eq('ecosystem_slug', access.slug) .eq('category', 'news') .eq('is_quarantined', false) .order('published_at', { ascending: false }) .limit(limit) if (profile.tier === 'free') { const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString() query = query.lt('published_at', cutoff).eq('is_pro_only', false) } const { data, error } = await query if (error) { await logApiRequest(supabase, { apiKey: profile.api_key, tool: 'news', ecosystem, statusCode: 500 }) return err('Error: Database error', 500) } type Row = { id: string; title: string; body: string; source_url: string | null; published_at: string; last_verified_at: string | null; confidence: string | null; source_count: number | null } const rows = (data ?? []) as Row[] const items = rows.map((row) => ({ id: row.id, title: row.title, body: row.body, source_urls: row.source_url ? [row.source_url] : [], confidence: row.confidence ?? 'medium', source_count: row.source_count ?? 1, published_at: row.published_at, ...freshnessEnvelope(row.published_at, row.last_verified_at), })) await logApiRequest(supabase, { apiKey: profile.api_key, tool: 'news', ecosystem, statusCode: 200 }) return ok({ ecosystem, tier: profile.tier, items }, rows.map(r => r.id)) } - lib/mcp-tools.ts:48-64 (schema)Input schema definition for 'get_latest_news' in the TOOL_DEFINITIONS array. Declares the tool name, description explaining tier behavior (Pro real-time, Free delayed 24h), and inputSchema with required 'ecosystem' (string) and optional 'limit' (number, min 5 max 20).
{ name: 'get_latest_news', description: 'Get the latest news and updates for an AI ecosystem. Pro tier receives real-time results. Free tier receives items older than 24 hours. ' + 'Each item includes content_age_hours and data_freshness — check these before acting on time-sensitive information. ' + EPISTEMIC_NOTICE, inputSchema: { type: 'object', properties: { ecosystem: { type: 'string', description: 'AI ecosystem slug' }, limit: { type: 'number', description: 'Number of results to return. Default 5, max 20', }, }, required: ['ecosystem'], }, - app/mcp/route.ts:35-42 (registration)Registration of 'get_latest_news' on the MCP server in the HTTP (POST) route handler. Uses McpServer.registerTool with Zod schema for ecosystem (required string) and limit (optional number), delegating to handleToolCall.
server.registerTool( 'get_latest_news', { description: TOOL_DEFINITIONS[1].description, inputSchema: { ecosystem: z.string(), limit: z.number().optional() }, }, (args) => handleToolCall('get_latest_news', args as Record<string, unknown>, req), ) - scripts/mcp-stdio.ts:43-50 (registration)Registration of 'get_latest_news' on the MCP server in the STDIO script (for local CLI usage). Same pattern: registerTool with Zod schema, delegates to handleToolCall with a mock Request.
server.registerTool( 'get_latest_news', { description: TOOL_DEFINITIONS[1].description, inputSchema: { ecosystem: z.string(), limit: z.number().optional() }, }, (args) => handleToolCall('get_latest_news', args as Record<string, unknown>, mockReq), ) - lib/freshness.ts:9-25 (helper)The freshnessEnvelope helper used by the get_latest_news handler to compute content_age_hours, last_verified_at, and data_freshness bucket (live/recent/stale/very_stale) for each news item.
export function freshnessEnvelope( publishedAt: string, lastVerifiedAt: string | null, ): FreshnessEnvelope { const ageMs = Date.now() - new Date(publishedAt).getTime() const ageHours = Math.round(ageMs / 3.6e6) const bucket: FreshnessBucket = ageHours < 12 ? 'live' : ageHours < 48 ? 'recent' : ageHours < 168 ? 'stale' : 'very_stale' return { content_age_hours: ageHours, last_verified_at: lastVerifiedAt ?? publishedAt, data_freshness: bucket, } }