Overview
Retail investors miss market-moving news because they check manually or rely on delayed feeds. This workflow monitors your stock watchlist through Scavio's MCP server: search for each ticker daily, detect earnings announcements, analyst rating changes, and SEC filings, and send a morning briefing before market open. All through MCP so it integrates directly with your AI assistant.
Trigger
Daily at 6:30 AM ET, before market open.
Schedule
Daily 6:30 AM
Workflow Steps
Load Stock Watchlist
Read the list of tickers to monitor from config. Include company names for better search results.
Search for Each Ticker via MCP
Call Scavio MCP search for each ticker with news-focused queries: earnings, analyst, SEC filing.
Classify News Events
Categorize results: EARNINGS, ANALYST_RATING, SEC_FILING, GENERAL_NEWS based on title and snippet keywords.
Score Market Impact
Assign impact scores: earnings surprises and analyst upgrades/downgrades get high scores.
Send Morning Briefing
Format the top events into a briefing and send via Slack, email, or display in your AI assistant.
Python Implementation
import requests, os, json
from datetime import date
API_KEY = os.environ["SCAVIO_API_KEY"]
MCP_URL = "https://mcp.scavio.dev/mcp"
MH = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
WATCHLIST = [
{"ticker": "AAPL", "name": "Apple"},
{"ticker": "NVDA", "name": "NVIDIA"},
{"ticker": "MSFT", "name": "Microsoft"},
{"ticker": "GOOGL", "name": "Alphabet"},
]
EVENT_KEYWORDS = {
"EARNINGS": ["earnings", "revenue", "quarterly", "beat", "miss", "eps"],
"ANALYST": ["upgrade", "downgrade", "price target", "analyst", "rating"],
"SEC_FILING": ["sec filing", "10-k", "10-q", "8-k", "proxy"],
"GENERAL": [],
}
def mcp_search(query: str) -> dict:
payload = {
"jsonrpc": "2.0", "id": 1,
"method": "tools/call",
"params": {"name": "search", "arguments": {"query": query, "country_code": "us"}}
}
resp = requests.post(MCP_URL, headers=MH, json=payload, timeout=15)
return resp.json().get("result", {})
def classify_event(title: str) -> str:
title_lower = title.lower()
for event_type, keywords in EVENT_KEYWORDS.items():
if any(kw in title_lower for kw in keywords):
return event_type
return "GENERAL"
def monitor_stocks():
briefing = []
for stock in WATCHLIST:
query = f"{stock['ticker']} {stock['name']} stock news {date.today()}"
data = mcp_search(query)
results = data.get("organic_results", [])[:5] if isinstance(data, dict) else []
for r in results:
title = r.get("title", "")
event_type = classify_event(title)
briefing.append({
"ticker": stock["ticker"],
"event": event_type,
"title": title,
"url": r.get("link", ""),
"snippet": r.get("snippet", ""),
})
briefing.sort(key=lambda x: 0 if x["event"] in ["EARNINGS", "ANALYST"] else 1)
return briefing
news = monitor_stocks()
print(f"Stock briefing for {date.today()}: {len(news)} items")
for n in news[:10]:
print(f" [{n['ticker']}] [{n['event']}] {n['title']}")JavaScript Implementation
const MCP_URL = 'https://mcp.scavio.dev/mcp';
const MH = {'Authorization': 'Bearer '+process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'};
const WATCHLIST = [
{ticker:'AAPL', name:'Apple'},
{ticker:'NVDA', name:'NVIDIA'},
{ticker:'MSFT', name:'Microsoft'},
{ticker:'GOOGL', name:'Alphabet'},
];
const EVENT_KEYWORDS = {EARNINGS:['earnings','revenue','quarterly','beat','miss','eps'], ANALYST:['upgrade','downgrade','price target','analyst','rating'], SEC_FILING:['sec filing','10-k','10-q','8-k','proxy']};
async function mcpSearch(query) {
const payload = {jsonrpc:'2.0', id:1, method:'tools/call', params:{name:'search', arguments:{query, country_code:'us'}}};
const r = await fetch(MCP_URL, {method:'POST', headers:MH, body:JSON.stringify(payload)});
return (await r.json()).result || {};
}
function classifyEvent(title) {
const t = title.toLowerCase();
for (const [type, kws] of Object.entries(EVENT_KEYWORDS)) {
if (kws.some(kw=>t.includes(kw))) return type;
}
return 'GENERAL';
}
async function monitorStocks() {
const briefing = [];
const today = new Date().toISOString().split('T')[0];
for (const stock of WATCHLIST) {
const data = await mcpSearch(stock.ticker+' '+stock.name+' stock news '+today);
const results = (data.organic_results || []).slice(0,5);
for (const r of results) {
briefing.push({ticker:stock.ticker, event:classifyEvent(r.title||''), title:r.title||'', url:r.link||'', snippet:r.snippet||''});
}
}
briefing.sort((a,b)=>(['EARNINGS','ANALYST'].includes(a.event)?0:1)-(['EARNINGS','ANALYST'].includes(b.event)?0:1));
return briefing;
}
const news = await monitorStocks();
console.log('Stock briefing: '+news.length+' items');
for (const n of news.slice(0,10)) console.log(' ['+n.ticker+'] ['+n.event+'] '+n.title);Platforms Used
Web search with knowledge graph, PAA, and AI overviews