Skip to main content

Overview

We are excited to introduce a new Bigdata Remote MCP server with search and fetch tools that comply with OpenAI Deep Research model standards. These tools allow you to leverage Bigata.com’s financial premium content to generate professional-grade research reports in under 30 minutes with full inline source attribution. This guide describes how to use the new Remote MCP server https://mcp.bigdata.com/deepresearch/ with OpenAI’s o3-deep-research model to produce comprehensive equity research reports in PDF.

GitHub Repository

Access the complete source code, requirements, and setup instructions.

Features

✅ Generates detailed equity research reports using Bigdata.com Search Service.
✅ Provides visibility into all MCP requests and responses.
✅ Displays a summary table of tool calls by type.
✅ Tracks total response time.
✅ Exports the final report as a professionally styled PDF.
Example output: Download the complete Micron Q2 FY2026 Earnings Preview PDF Micron Earnings Preview PDF

Prerequisites

  • Python 3.9 or higher
  • An OpenAI API key with access to the o3-deep-research-2025-06-26 model
  • A Bigdata.com API key

System Dependencies

WeasyPrint requires some system libraries for PDF generation.
sudo apt-get install libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf2.0-0

Setup

1

Clone the repository

git clone https://github.com/Bigdata-com/bigdata-docs-resources.git
cd bigdata-docs-resources/how_to_guides/mcp_deep_research_openai
2

Create a virtual environment (recommended)

python -m venv venv
Activate the virtual environment:
source venv/bin/activate
3

Install Python dependencies

pip install -r requirements.txt
4

Configure API Keys

Copy the .env_template file to .env:
cp .env_template .env
Open the .env file and replace the placeholder values with your actual API keys:
OPENAI_API_KEY=your_openai_api_key_here
BIGDATA_API_KEY=your_bigdata_api_key_here
You can obtain your API keys from:
Never commit your .env file to version control. Add it to your .gitignore file.

Usage

Run the script

python deep-research-mcp.py

Customizing the prompt

To change the prompt, edit the input parameter in the client.responses.create() call. The default prompt requests a Micron earnings preview.

Code

from dotenv import load_dotenv
from openai import OpenAI
import os
import json
import time
from datetime import datetime
from collections import Counter
import markdown
from weasyprint import HTML, CSS

load_dotenv()

# Read Bigdata API key from environment
BIGDATA_API_KEY = os.getenv("BIGDATA_API_KEY")

client = OpenAI()

# Track response time
start_time = time.time()

resp = client.responses.create(
    model="o3-deep-research-2025-06-26",
    input="""You are a senior equity analyst preparing for an upcoming earnings call. Please provide a comprehensive earnings preview and analysis for Micron.

Cover:
- Recent developments and initiatives
- Industry trends and sector dynamics
- Bull/bear cases
- Key metrics to watch

Deliverable Format: Present findings as a concise, actionable brief suitable for investment professionals. Focus on business fundamentals, avoid speculation, and highlight areas of uncertainty or debate. Be decisive in your assessments while acknowledging alternative viewpoints. Add inline source attribution and use the Bigdata MCP.""",
    tools=[
        {
            "type": "mcp",
            "server_label": "bigdata",
            "server_url": "https://mcp.bigdata.com/deepresearch/",
            "headers": {
                "x-api-key": BIGDATA_API_KEY
            },
            "require_approval": "never",
        }
    ]
)

end_time = time.time()
elapsed_time = end_time - start_time

# Display MCP tool calls and responses
print("=" * 80)
print("MCP REQUESTS AND RESPONSES")
print("=" * 80)

mcp_call_count = 0
tool_calls_counter = Counter()

for item in resp.output:
    item_type = getattr(item, 'type', None)
    
    # MCP tool calls (requests to MCP server)
    if item_type == 'mcp_call':
        mcp_call_count += 1
        tool_name = getattr(item, 'name', 'N/A')
        tool_calls_counter[tool_name] += 1
        print(f"\n[MCP CALL #{mcp_call_count}]")
        print(f"  Server: {getattr(item, 'server_label', 'N/A')}")
        print(f"  Tool: {tool_name}")
        print(f"  Call ID: {getattr(item, 'id', 'N/A')}")
        if hasattr(item, 'arguments'):
            print(f"  Arguments: {item.arguments}")
    
    # MCP tool results (responses from MCP server)
    elif item_type == 'mcp_call_output':
        print(f"\n[MCP RESPONSE for call: {getattr(item, 'call_id', 'N/A')}]")
        output = getattr(item, 'output', None)
        if output:
            # Try to pretty-print if it's JSON
            try:
                parsed = json.loads(output) if isinstance(output, str) else output
                print(f"  Output: {json.dumps(parsed, indent=4)[:2000]}...")
            except (json.JSONDecodeError, TypeError):
                print(f"  Output: {str(output)[:2000]}...")
    
    # MCP list tools response
    elif item_type == 'mcp_list_tools':
        print(f"\n[MCP LIST TOOLS - Server: {getattr(item, 'server_label', 'N/A')}]")
        tools = getattr(item, 'tools', [])
        for tool in tools:
            tool_name = getattr(tool, 'name', 'N/A')
            tool_desc = getattr(tool, 'description', '')[:100]
            print(f"  - {tool_name}: {tool_desc}")

# Display summary with table
print(f"\n{'=' * 80}")
print("MCP CALLS SUMMARY")
print("=" * 80)

# Format elapsed time
if elapsed_time >= 60:
    minutes = int(elapsed_time // 60)
    seconds = elapsed_time % 60
    time_str = f"{minutes}m {seconds:.2f}s"
else:
    time_str = f"{elapsed_time:.2f}s"

print(f"\nTotal Response Time: {time_str}")
print(f"\nTotal MCP Calls: {mcp_call_count}")

if tool_calls_counter:
    print("\nCalls per Tool:")
    print("-" * 40)
    print(f"{'Tool Name':<30} {'Calls':>8}")
    print("-" * 40)
    for tool_name, count in tool_calls_counter.most_common():
        print(f"{tool_name:<30} {count:>8}")
    print("-" * 40)
    print(f"{'TOTAL':<30} {mcp_call_count:>8}")

print("=" * 80)

# Display final output
print("\n" + "=" * 80)
print("FINAL OUTPUT")
print("=" * 80)
print(resp.output_text)

# Convert markdown to PDF
print("\n" + "=" * 80)
print("GENERATING PDF")
print("=" * 80)

# Convert markdown to HTML
html_content = markdown.markdown(
    resp.output_text,
    extensions=['tables', 'fenced_code', 'toc']
)

# Add CSS styling for professional look
css_style = CSS(string='''
    @page {
        margin: 1in;
        size: letter;
    }
    body {
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
        font-size: 11pt;
        line-height: 1.6;
        color: #333;
    }
    h1 {
        color: #1a1a1a;
        border-bottom: 2px solid #333;
        padding-bottom: 0.3em;
        font-size: 24pt;
    }
    h2 {
        color: #2c2c2c;
        border-bottom: 1px solid #ccc;
        padding-bottom: 0.2em;
        font-size: 18pt;
        margin-top: 1.5em;
    }
    h3 {
        color: #444;
        font-size: 14pt;
        margin-top: 1.2em;
    }
    table {
        border-collapse: collapse;
        width: 100%;
        margin: 1em 0;
    }
    th, td {
        border: 1px solid #ddd;
        padding: 8px;
        text-align: left;
    }
    th {
        background-color: #f5f5f5;
        font-weight: bold;
    }
    tr:nth-child(even) {
        background-color: #fafafa;
    }
    code {
        background-color: #f4f4f4;
        padding: 2px 6px;
        border-radius: 3px;
        font-family: "Courier New", monospace;
        font-size: 10pt;
    }
    pre {
        background-color: #f4f4f4;
        padding: 1em;
        border-radius: 5px;
        overflow-x: auto;
    }
    blockquote {
        border-left: 4px solid #ccc;
        margin: 1em 0;
        padding-left: 1em;
        color: #666;
    }
    ul, ol {
        margin: 0.5em 0;
        padding-left: 2em;
    }
    li {
        margin: 0.3em 0;
    }
''')

# Wrap HTML content with proper document structure
full_html = f'''
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Research Report</title>
</head>
<body>
{html_content}
</body>
</html>
'''

# Generate PDF filename with timestamp
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
pdf_filename = f"research_report_{timestamp}.pdf"

# Create PDF
HTML(string=full_html).write_pdf(pdf_filename, stylesheets=[css_style])

print(f"\nPDF generated: {pdf_filename}")