Tutorial

How to Build a Trading Data MCP Server Combining Search and Financial Data

Build an MCP server that combines Scavio search for market news with financial data APIs. Serve real-time trading signals to any MCP-compatible AI agent.

Trading agents need two data streams: real-time market news and structured financial data. This tutorial builds an MCP server that combines Scavio search for breaking news and sentiment with a financial data API for prices and fundamentals, exposing both as tool calls any MCP-compatible agent can invoke.

Prerequisites

  • Python 3.11+
  • A Scavio API key from https://scavio.dev
  • A free financial data API key (Alpha Vantage or similar)
  • The mcp Python package (pip install mcp)

Walkthrough

Step 1: Set up the MCP server skeleton

Create the MCP server with the standard protocol handler. This server will expose three tools: market_news, stock_quote, and trading_signal.

Python
from mcp.server import Server
from mcp.types import Tool, TextContent
import httpx
import json
import os

SCAVIO_API_KEY = os.environ.get("SCAVIO_API_KEY", "your-api-key")
FINANCE_API_KEY = os.environ.get("FINANCE_API_KEY", "your-finance-key")

server = Server("trading-data")

@server.list_tools()
async def list_tools() -> list[Tool]:
    return [
        Tool(
            name="market_news",
            description="Search for breaking market news and analyst commentary on a stock or sector",
            inputSchema={
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "Stock ticker or sector to search"},
                    "num_results": {"type": "integer", "default": 5}
                },
                "required": ["query"]
            }
        ),
        Tool(
            name="stock_quote",
            description="Get current price, volume, and daily change for a stock ticker",
            inputSchema={
                "type": "object",
                "properties": {
                    "ticker": {"type": "string", "description": "Stock ticker symbol"}
                },
                "required": ["ticker"]
            }
        ),
        Tool(
            name="trading_signal",
            description="Combine news sentiment with price data to generate a trading signal",
            inputSchema={
                "type": "object",
                "properties": {
                    "ticker": {"type": "string"},
                    "timeframe": {"type": "string", "default": "1d"}
                },
                "required": ["ticker"]
            }
        )
    ]

Step 2: Implement the market news tool with Scavio search

The market_news tool searches for recent financial news, filters for market-relevant content, and returns structured summaries with source URLs.

Python
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    if name == "market_news":
        return await handle_market_news(arguments)
    elif name == "stock_quote":
        return await handle_stock_quote(arguments)
    elif name == "trading_signal":
        return await handle_trading_signal(arguments)
    return [TextContent(type="text", text=f"Unknown tool: {name}")]

async def handle_market_news(args: dict) -> list[TextContent]:
    query = args["query"]
    num_results = args.get("num_results", 5)

    async with httpx.AsyncClient(timeout=15) as client:
        resp = await client.post(
            "https://api.scavio.dev/api/v1/search",
            headers={"x-api-key": SCAVIO_API_KEY},
            json={
                "query": f"{query} stock market news 2026",
                "num_results": num_results
            }
        )
        resp.raise_for_status()
        results = resp.json().get("results", [])

    news = []
    for r in results:
        news.append({
            "title": r.get("title", ""),
            "url": r.get("url", ""),
            "summary": r.get("description", "")[:300],
            "source": r.get("url", "").split("/")[2] if r.get("url") else ""
        })

    return [TextContent(type="text", text=json.dumps({"news": news, "count": len(news)}, indent=2))]

Step 3: Implement the stock quote and trading signal tools

The stock_quote tool fetches price data from a financial API. The trading_signal tool combines news sentiment with price movement to produce a simple bullish/bearish/neutral signal.

Python
async def handle_stock_quote(args: dict) -> list[TextContent]:
    ticker = args["ticker"].upper()
    async with httpx.AsyncClient(timeout=10) as client:
        resp = await client.get(
            "https://www.alphavantage.co/query",
            params={
                "function": "GLOBAL_QUOTE",
                "symbol": ticker,
                "apikey": FINANCE_API_KEY
            }
        )
        resp.raise_for_status()
        data = resp.json().get("Global Quote", {})

    quote = {
        "ticker": ticker,
        "price": data.get("05. price", "N/A"),
        "change": data.get("09. change", "N/A"),
        "change_pct": data.get("10. change percent", "N/A"),
        "volume": data.get("06. volume", "N/A")
    }
    return [TextContent(type="text", text=json.dumps(quote, indent=2))]

async def handle_trading_signal(args: dict) -> list[TextContent]:
    ticker = args["ticker"].upper()

    # Get news
    news_result = await handle_market_news({"query": ticker, "num_results": 5})
    news_data = json.loads(news_result[0].text)

    # Get price
    quote_result = await handle_stock_quote({"ticker": ticker})
    quote_data = json.loads(quote_result[0].text)

    # Simple sentiment scoring from news titles
    positive_words = {"surge", "jump", "rally", "beat", "upgrade", "growth", "record", "gain"}
    negative_words = {"drop", "fall", "crash", "miss", "downgrade", "decline", "loss", "cut"}

    sentiment_score = 0
    for article in news_data.get("news", []):
        title_words = set(article["title"].lower().split())
        sentiment_score += len(title_words & positive_words)
        sentiment_score -= len(title_words & negative_words)

    # Combine with price change
    change_pct = quote_data.get("change_pct", "0%").replace("%", "")
    try:
        price_signal = float(change_pct)
    except ValueError:
        price_signal = 0.0

    # Generate signal
    combined = sentiment_score + (1 if price_signal > 0 else -1 if price_signal < 0 else 0)
    if combined >= 2:
        signal = "BULLISH"
    elif combined <= -2:
        signal = "BEARISH"
    else:
        signal = "NEUTRAL"

    result = {
        "ticker": ticker,
        "signal": signal,
        "sentiment_score": sentiment_score,
        "price_change": change_pct + "%",
        "news_count": len(news_data.get("news", [])),
        "confidence": "high" if abs(combined) >= 3 else "medium" if abs(combined) >= 2 else "low"
    }
    return [TextContent(type="text", text=json.dumps(result, indent=2))]

Step 4: Run the MCP server

Start the MCP server over stdio so any MCP-compatible client (Claude Desktop, Hermes, custom agents) can connect and invoke the trading tools.

Python
from mcp.server.stdio import stdio_server

async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream)

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

# MCP client config (add to mcp_config.json):
# {
#   "mcpServers": {
#     "trading-data": {
#       "command": "python",
#       "args": ["trading_mcp_server.py"],
#       "env": {
#         "SCAVIO_API_KEY": "your-api-key",
#         "FINANCE_API_KEY": "your-finance-key"
#       }
#     }
#   }
# }

Python Example

Python
import asyncio
import httpx
import json

SCAVIO_API_KEY = "your-api-key"

async def market_news(ticker: str) -> dict:
    async with httpx.AsyncClient(timeout=15) as client:
        resp = await client.post(
            "https://api.scavio.dev/api/v1/search",
            headers={"x-api-key": SCAVIO_API_KEY},
            json={"query": f"{ticker} stock market news 2026", "num_results": 5}
        )
        resp.raise_for_status()
        results = resp.json().get("results", [])
    return {
        "ticker": ticker,
        "articles": [{"title": r["title"], "url": r["url"]} for r in results],
        "count": len(results)
    }

async def main():
    news = await market_news("NVDA")
    print(f"Found {news['count']} articles for {news['ticker']}")
    for a in news["articles"]:
        print(f"  {a['title']}")

asyncio.run(main())

JavaScript Example

JavaScript
const SCAVIO_API_KEY = "your-api-key";

async function marketNews(ticker) {
  const resp = await fetch("https://api.scavio.dev/api/v1/search", {
    method: "POST",
    headers: { "x-api-key": SCAVIO_API_KEY, "Content-Type": "application/json" },
    body: JSON.stringify({ query: ticker + " stock market news 2026", num_results: 5 })
  });
  const data = await resp.json();
  return {
    ticker,
    articles: (data.results || []).map(r => ({ title: r.title, url: r.url })),
    count: (data.results || []).length
  };
}

async function main() {
  const news = await marketNews("NVDA");
  console.log(`Found ${news.count} articles for ${news.ticker}`);
  news.articles.forEach(a => console.log("  " + a.title));
}

main();

Expected Output

JSON
Found 5 articles for NVDA
  NVIDIA Q2 2026 Earnings Beat Expectations...
  NVDA Stock Surges on New AI Chip Announcement...

Related Tutorials

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.11+. A Scavio API key from https://scavio.dev. A free financial data API key (Alpha Vantage or similar). The mcp Python package (pip install mcp). A Scavio API key gives you 250 free credits per month.

Yes. The free tier includes 250 credits per month, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Start Building

Build an MCP server that combines Scavio search for market news with financial data APIs. Serve real-time trading signals to any MCP-compatible AI agent.