Tutorial

How to Build an MCP Multi-Tool Agent in 2026

Build an MCP agent with multiple tool servers including web search, file access, and database queries. Full Python setup guide with working code.

The Model Context Protocol (MCP) lets AI agents call external tools through a standardized interface. A multi-tool MCP agent can combine web search, file system access, database queries, and custom APIs in a single conversation. This tutorial builds an MCP agent with a search tool backed by the Scavio API, a file tool, and a calculator tool. The pattern scales to any number of tools. Search calls cost $0.005 each via Scavio.

Prerequisites

  • Python 3.10+ installed
  • mcp package installed (pip install mcp)
  • A Scavio API key from scavio.dev
  • Basic understanding of tool-use patterns

Walkthrough

Step 1: Define the MCP search tool server

Create an MCP tool server that exposes a web_search function. This server handles the API call and returns structured results to the agent.

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

server = Server('search-tools')
API_KEY = os.environ['SCAVIO_API_KEY']

@server.tool()
async def web_search(query: str, country: str = 'us') -> str:
    """Search the web for current information."""
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
        json={'query': query, 'country_code': country})
    results = resp.json().get('organic_results', [])[:5]
    return json.dumps([{'title': r['title'], 'url': r['link'],
        'snippet': r.get('snippet', '')} for r in results], indent=2)

Step 2: Add a TikTok search tool to the same server

Add a second tool that searches TikTok. Both tools share the same MCP server, so the agent can use either one in a single session.

Python
@server.tool()
async def tiktok_search(keyword: str, count: int = 10) -> str:
    """Search TikTok for videos about a topic."""
    resp = requests.post('https://api.scavio.dev/api/v1/tiktok/search/videos',
        headers={'Authorization': f'Bearer {API_KEY}',
                 'Content-Type': 'application/json'},
        json={'keyword': keyword, 'count': count, 'cursor': 0})
    videos = resp.json().get('data', {}).get('videos', [])
    return json.dumps([{'author': v.get('author', {}).get('nickname', ''),
        'desc': v.get('desc', ''), 'plays': v.get('stats', {}).get('playCount', 0)}
        for v in videos], indent=2)

Step 3: Add a calculator and file reader tool

Demonstrate the multi-tool pattern by adding non-search tools. The agent decides which tool to use based on the user query.

Python
import math

@server.tool()
async def calculate(expression: str) -> str:
    """Evaluate a mathematical expression safely."""
    allowed = set('0123456789+-*/.() ')
    if not all(c in allowed for c in expression):
        return 'Error: only numeric expressions allowed'
    try:
        result = eval(expression)
        return str(result)
    except Exception as e:
        return f'Error: {e}'

@server.tool()
async def read_file(path: str) -> str:
    """Read a local text file."""
    try:
        with open(path, 'r') as f:
            content = f.read(10000)  # limit to 10KB
        return content
    except FileNotFoundError:
        return f'File not found: {path}'

Step 4: Configure the MCP server manifest

Create the .mcp.json configuration file that tells the MCP client where to find your tool server and what tools are available.

JSON
// .mcp.json
{
  "mcpServers": {
    "search-tools": {
      "command": "python",
      "args": ["search_tools_server.py"],
      "env": {
        "SCAVIO_API_KEY": "your_scavio_api_key"
      }
    }
  }
}
// The server exposes: web_search, tiktok_search, calculate, read_file

Step 5: Run the MCP server

Start the server with stdio transport. Any MCP-compatible client (Claude Desktop, Cursor, custom agents) can now connect and use all four tools.

Python
import asyncio
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__':
    asyncio.run(main())

# Test manually:
# echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | python search_tools_server.py
# Should list: web_search, tiktok_search, calculate, read_file

Python Example

Python
from mcp.server import Server
from mcp.server.stdio import stdio_server
import requests, os, json, asyncio

server = Server('search-tools')
API_KEY = os.environ['SCAVIO_API_KEY']

@server.tool()
async def web_search(query: str, country: str = 'us') -> str:
    """Search the web for current information."""
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
        json={'query': query, 'country_code': country})
    results = resp.json().get('organic_results', [])[:5]
    return json.dumps([{'title': r['title'], 'snippet': r.get('snippet', '')} for r in results])

@server.tool()
async def tiktok_search(keyword: str, count: int = 10) -> str:
    """Search TikTok videos."""
    resp = requests.post('https://api.scavio.dev/api/v1/tiktok/search/videos',
        headers={'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'},
        json={'keyword': keyword, 'count': count, 'cursor': 0})
    return json.dumps(resp.json().get('data', {}).get('videos', [])[:5])

async def main():
    async with stdio_server() as (read, write):
        await server.run(read, write)

if __name__ == '__main__':
    asyncio.run(main())

JavaScript Example

JavaScript
// MCP servers are typically Python; this shows a JS HTTP wrapper
const API_KEY = process.env.SCAVIO_API_KEY;

const tools = {
  async web_search({ query, country = 'us' }) {
    const resp = await fetch('https://api.scavio.dev/api/v1/search', {
      method: 'POST',
      headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
      body: JSON.stringify({ query, country_code: country })
    });
    const data = await resp.json();
    return (data.organic_results || []).slice(0, 5)
      .map(r => ({ title: r.title, snippet: r.snippet || '' }));
  },
  async tiktok_search({ keyword, count = 10 }) {
    const resp = await fetch('https://api.scavio.dev/api/v1/tiktok/search/videos', {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
      body: JSON.stringify({ keyword, count, cursor: 0 })
    });
    return (await resp.json()).data?.videos || [];
  }
};

async function main() {
  const results = await tools.web_search({ query: 'MCP protocol 2026' });
  console.log(JSON.stringify(results, null, 2));
}

main().catch(console.error);

Expected Output

JSON
Available tools:
- web_search: Search the web for current information
- tiktok_search: Search TikTok for videos about a topic
- calculate: Evaluate a mathematical expression
- read_file: Read a local text file

[
  {"title": "MCP Protocol Documentation", "snippet": "The Model Context Protocol..."}
  {"title": "Building MCP Agents in 2026", "snippet": "A guide to creating..."}
]

Cost: $0.005 per web_search call, $0.005 per tiktok_search call

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.10+ installed. mcp package installed (pip install mcp). A Scavio API key from scavio.dev. Basic understanding of tool-use patterns. 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 agent with multiple tool servers including web search, file access, and database queries. Full Python setup guide with working code.