Tutorial

How to Build an MCP Meeting Notes to Actions Pipeline

Build an MCP pipeline that extracts action items from meeting notes and enriches them with search context. Automated follow-up generation.

Meeting notes contain action items that often need context: competitive research, pricing lookups, feature comparisons, or market data. An MCP pipeline can automatically extract action items from meeting transcripts and enrich each one with relevant search data, turning vague tasks into actionable briefs. This tutorial builds an MCP tool server with two tools: one that parses meeting notes into structured actions, and one that enriches each action with web search context. Search enrichment costs $0.005 per action item via Scavio.

Prerequisites

  • Python 3.10+ installed
  • mcp and openai packages installed
  • A Scavio API key from scavio.dev
  • An OpenAI API key for action extraction

Walkthrough

Step 1: Build the action extraction tool

Create an MCP tool that takes raw meeting notes and uses an LLM to extract structured action items with assignees, deadlines, and search queries.

Python
from mcp.server import Server
import json
from openai import OpenAI

server = Server('meeting-actions')
llm = OpenAI()

@server.tool()
async def extract_actions(meeting_notes: str) -> str:
    """Extract action items from meeting notes."""
    response = llm.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'system', 'content': '''Extract action items from meeting notes.
Return JSON array with: task, assignee, deadline, search_query (a web search
that would provide useful context for this task).'''},
            {'role': 'user', 'content': meeting_notes}],
        response_format={'type': 'json_object'},
        max_tokens=1000
    )
    return response.choices[0].message.content

Step 2: Build the search enrichment tool

Create a second MCP tool that takes an action item and enriches it with relevant web search data. This turns a bare task into a contextual brief.

Python
import requests, os

API_KEY = os.environ['SCAVIO_API_KEY']

@server.tool()
async def enrich_action(search_query: str, task_context: str = '') -> str:
    """Enrich an action item with web search context."""
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
        json={'query': search_query, 'country_code': 'us'})
    results = resp.json().get('organic_results', [])[:5]
    enrichment = {
        'query': search_query,
        'key_findings': [
            {'source': r['link'], 'title': r['title'],
             'insight': r.get('snippet', '')}
            for r in results
        ],
        'sources_count': len(results)
    }
    return json.dumps(enrichment, indent=2)

Step 3: Build the full pipeline tool

Create a combined tool that does both extraction and enrichment in one call. This is the main entry point for the meeting-to-actions pipeline.

Python
@server.tool()
async def meeting_to_actions(meeting_notes: str) -> str:
    """Extract action items from meeting notes and enrich each with search context."""
    # Step 1: Extract actions
    actions_json = await extract_actions(meeting_notes)
    actions = json.loads(actions_json).get('actions', [])
    # Step 2: Enrich each action
    enriched = []
    for action in actions:
        search_query = action.get('search_query', action.get('task', ''))
        enrichment_json = await enrich_action(search_query, action.get('task', ''))
        enrichment = json.loads(enrichment_json)
        enriched.append({
            **action,
            'enrichment': enrichment
        })
    result = {
        'total_actions': len(enriched),
        'credits_used': len(enriched),  # 1 search per action
        'cost': f'${len(enriched) * 0.005:.3f}',
        'actions': enriched
    }
    return json.dumps(result, indent=2)

Step 4: Run the MCP server

Start the server so it can be connected to Claude Desktop, Cursor, or any MCP client.

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())

# .mcp.json configuration:
# {
#   "mcpServers": {
#     "meeting-actions": {
#       "command": "python",
#       "args": ["meeting_actions_server.py"],
#       "env": {
#         "SCAVIO_API_KEY": "your_key",
#         "OPENAI_API_KEY": "your_key"
#       }
#     }
#   }
# }

Step 5: Test with sample meeting notes

Feed in a real meeting transcript and verify the pipeline extracts and enriches actions correctly.

Python
# Test the pipeline directly (without MCP client):
import asyncio

async def test():
    notes = """Product sync 2026-05-13:
- Sarah: Research competitor pricing for CRM tools, need comparison by Friday
- Mike: Look into TikTok API options for our influencer vetting feature
- Lisa: Find best practices for AI Overview optimization, present next week
- Team: Evaluate n8n vs Zapier for our lead gen automation"""
    result = await meeting_to_actions(notes)
    data = json.loads(result)
    print(f'Extracted {data["total_actions"]} actions (cost: {data["cost"]})')
    for a in data['actions']:
        print(f'\n  Task: {a["task"]}')
        print(f'  Assignee: {a.get("assignee", "unassigned")}')
        print(f'  Context: {len(a["enrichment"]["key_findings"])} sources found')

asyncio.run(test())

Python Example

Python
import os, json, requests
from openai import OpenAI

llm = OpenAI()
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']

def extract_actions(notes):
    resp = llm.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'system', 'content': 'Extract action items as JSON array with task, assignee, search_query fields.'},
                  {'role': 'user', 'content': notes}],
        response_format={'type': 'json_object'}, max_tokens=500)
    return json.loads(resp.choices[0].message.content).get('actions', [])

def enrich(query):
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
        json={'query': query, 'country_code': 'us'})
    return [r.get('snippet', '') for r in resp.json().get('organic_results', [])[:3]]

notes = 'Sarah: Research CRM pricing. Mike: Evaluate TikTok APIs.'
for action in extract_actions(notes):
    context = enrich(action.get('search_query', action['task']))
    print(f'{action["task"]}: {len(context)} sources')

JavaScript Example

JavaScript
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;

async function enrich(query) {
  const resp = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST',
    headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({ query, country_code: 'us' })
  });
  const data = await resp.json();
  return (data.organic_results || []).slice(0, 3)
    .map(r => ({ title: r.title, snippet: r.snippet || '' }));
}

async function main() {
  const actions = [
    { task: 'Research CRM pricing', query: 'CRM pricing comparison 2026' },
    { task: 'Evaluate TikTok APIs', query: 'TikTok API options developers 2026' }
  ];
  for (const a of actions) {
    const context = await enrich(a.query);
    console.log(`${a.task}: ${context.length} sources found`);
  }
}

main().catch(console.error);

Expected Output

JSON
Extracted 4 actions (cost: $0.020)

  Task: Research competitor CRM pricing comparison
  Assignee: Sarah
  Context: 5 sources found

  Task: Evaluate TikTok API options for influencer vetting
  Assignee: Mike
  Context: 5 sources found

  Task: Research AI Overview optimization best practices
  Assignee: Lisa
  Context: 5 sources found

  Task: Compare n8n vs Zapier for lead generation
  Assignee: Team
  Context: 5 sources found

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 and openai packages installed. A Scavio API key from scavio.dev. An OpenAI API key for action extraction. 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 pipeline that extracts action items from meeting notes and enriches them with search context. Automated follow-up generation.