AI 주식 비서 시스템: Gemini 2.5 Pro와 MCP로 자동화 리포트 받아보기
🧠 "AI로 만드는 실시간 주식 리포트 시스템"
Google Gemini 2.5 Pro와 MCP(Model Context Protocol)를 이용해 "어제 인기 주식 TOP 10"의 종목명, 주가 변화 추이, 관련 기업 정보를 수집하고 Gmail로 자동 전송하는 시스템을 만드는 예시입니다.
✳️ 전체 아키텍처 개요
[사용자]
│
▼ (자연어 입력: "어제 인기 주식 알려줘")
[클라이언트 코드 (Python)]
│
├─ Gemini 2.5 Pro API → 사용자 의도 분석
│
├─ MCP 서버 통해 툴 자동 선택
│ ├─ MCP-Stock-Rank: 인기 주식 TOP10 조회
│ ├─ MCP-Stock-Detail: 개별 종목 상세 정보 조회
│ └─ MCP-Gmail-Sender: 리포트 이메일 발송
│
▼
[Gmail 전송 완료: 주식 리포트]
1️⃣ 준비 사항
항목 | 설명 |
---|---|
Python | 3.8 이상 |
API 키 | Google Gemini API 키 |
주식 API 키 | 예: Yahoo Finance, Alpha Vantage, 또는 Naver/Daum 금융 크롤링 |
이메일 | Gmail SMTP 사용: Gmail 주소와 앱 비밀번호 필요 |
MCP 구성 | mcp-stock-search , mcp-stock-detail , mcp-gmail-sender 구성 필요 |
2️⃣ 가상환경 및 라이브러리 설치
python -m venv venv
source venv/bin/activate
pip install google-genai mcp yfinance smtplib jinja2
3️⃣ 환경 변수 설정 (.env)
export GEMINI_API_KEY="your-google-api-key"
export GMAIL_ADDRESS="your@gmail.com"
export GMAIL_APP_PASSWORD="your-gmail-app-password"
4️⃣ MCP 툴 구성
✔ MCP 서버 1: mcp-stock-search
- 인기 종목 Top 10 반환 (크롤링 또는 yfinance 사용)
# tool_stock_search.py def search_trending_stocks(): import yfinance as yf tickers = ["AAPL", "MSFT", "NVDA", "TSLA", "AMZN", "META", "GOOGL", "NFLX", "AMD", "INTC"] # 예시 return {"top_tickers": tickers}
✔ MCP 서버 2: mcp-stock-detail
- 각 종목에 대한 가격변동 + 기업정보 수집
def get_stock_details(ticker: str): import yfinance as yf info = yf.Ticker(ticker).info history = yf.Ticker(ticker).history(period="5d").to_dict() return { "ticker": ticker, "name": info.get("longName"), "sector": info.get("sector"), "summary": info.get("longBusinessSummary"), "price_trend": history.get("Close") }
✔ MCP 서버 3: mcp-gmail-sender
- 리포트를 메일로 전송
def send_email_report(recipient: str, subject: str, html_body: str): import smtplib from email.mime.text import MIMEText msg = MIMEText(html_body, 'html') msg['Subject'] = subject msg['From'] = os.getenv("GMAIL_ADDRESS") msg['To'] = recipient with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server: server.login(os.getenv("GMAIL_ADDRESS"), os.getenv("GMAIL_APP_PASSWORD")) server.send_message(msg)
5️⃣ Gemini + MCP 통합 클라이언트 구성
import os
from google import genai
from google.genai import types
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
server_params = StdioServerParameters(
command="mcp-stock-server", # MCP 툴 통합 서버
args=["--connection_type", "stdio"],
env={
"GMAIL_ADDRESS": os.getenv("GMAIL_ADDRESS"),
"GMAIL_APP_PASSWORD": os.getenv("GMAIL_APP_PASSWORD")
}
)
async def run():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
mcp_tools = await session.list_tools()
tools = [
types.Tool(function_declarations=[{
"name": tool.name,
"description": tool.description,
"parameters": {k: v for k, v in tool.inputSchema.items()}
}]) for tool in mcp_tools.tools
]
prompt = "어제 인기 주식 10개와 각각의 변화 추이 및 기업 정보를 보고서로 만들어 이메일로 보내줘"
response = client.models.generate_content(
model="gemini-2.5-pro-exp-03-25",
contents=prompt,
config=types.GenerateContentConfig(
temperature=0.2,
tools=tools
)
)
call = response.candidates[0].content.parts[0].function_call
result = await session.call_tool(call.name, dict(call.args))
print(result)
6️⃣ 이메일 리포트 템플릿 (Jinja2)
<h2>📊 어제의 인기 주식 리포트</h2>
{% for stock in stocks %}
<hr/>
<h3>{{ stock.name }} ({{ stock.ticker }})</h3>
<p><b>업종:</b> {{ stock.sector }}</p>
<p><b>기업 개요:</b> {{ stock.summary }}</p>
<p><b>최근 주가 추이:</b> {{ stock.price_trend | safe }}</p>
{% endfor %}
7️⃣ 자동화 실행 예시
python daily_stock_report.py
or crontab에 등록하여 매일 오전 9시에 실행
0 9 * * * /home/user/daily_stock_report.sh
역할 기반 MCP 모듈 정리
역할 | MCP 툴명 | 기능 설명 |
---|---|---|
주식 랭킹 수집 | mcp-stock-search |
어제 인기 주식 TOP10 수집 |
종목 상세 수집 | mcp-stock-detail |
개별 주식 정보, 최근 가격 추이, 기업 개요 |
이메일 발송 | mcp-gmail-sender |
수집된 정보를 이메일로 보고서 전송 |
보안 및 운영 가이드
- API 키는
.env
혹은 Secret Manager로 보호 - Gmail 앱 비밀번호를 사용하고, 계정 보호 설정 필요
- MCP 서버는
stdout
기반의stdio
로 설정, 실시간 디버깅 가능 - 리포트 HTML은 외부 링크 차단, 이미지 대신 텍스트/차트 URL로 처리
이 시스템은 "자연어로 종목 요청 → AI가 MCP 툴을 선택 → 실시간 데이터 수집 → 보고서 생성 → 이메일 전송"이라는 일련의 과정을 자동화하며, 향후 메시지 전송, PDF 저장, 음성 안내 등으로 확장할 수 있습니다.
아래는 Gemini 2.5 Pro
가 MCP 툴을 호출하고 결과를 통합하는 서버 코드(mcp_stock_server.py
)입니다.
# MCP 모듈 템플릿 및 완성 코드
# 📦 MCP 툴 서버: mcp_stock_server.py
import os
import asyncio
from mcp.fast import FastMCP, tool
import yfinance as yf
import smtplib
from email.mime.text import MIMEText
from jinja2 import Template
mcp = FastMCP("mcp-stock-server")
# 🔹 툴 1: 인기 주식 조회
top_tickers = ["AAPL", "MSFT", "NVDA", "TSLA", "AMZN", "META", "GOOGL", "NFLX", "AMD", "INTC"]
@mcp.tool("mcp-stock-search")
def search_trending_stocks():
return {"top_tickers": top_tickers}
# 🔹 툴 2: 종목 상세 정보 수집
@mcp.tool("mcp-stock-detail")
def get_stock_details(ticker: str):
t = yf.Ticker(ticker)
info = t.info
trend = t.history(period="5d")['Close'].to_dict()
return {
"ticker": ticker,
"name": info.get("longName"),
"sector": info.get("sector"),
"summary": info.get("longBusinessSummary"),
"price_trend": trend
}
# 🔹 툴 3: 이메일 리포트 전송
@mcp.tool("mcp-gmail-sender")
def send_email_report(recipient: str, subject: str, stocks: list):
template = Template('''
<h2>📊 어제의 인기 주식 리포트</h2>
{% for stock in stocks %}
<hr/>
<h3>{{ stock.name }} ({{ stock.ticker }})</h3>
<p><b>업종:</b> {{ stock.sector }}</p>
<p><b>기업 개요:</b> {{ stock.summary }}</p>
<p><b>최근 주가 추이:</b> {{ stock.price_trend | safe }}</p>
{% endfor %}
''')
html_body = template.render(stocks=stocks)
msg = MIMEText(html_body, 'html')
msg['Subject'] = subject
msg['From'] = os.getenv("GMAIL_ADDRESS")
msg['To'] = recipient
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
server.login(os.getenv("GMAIL_ADDRESS"), os.getenv("GMAIL_APP_PASSWORD"))
server.send_message(msg)
return {"status": "success"}
# 🔁 실행
if __name__ == "__main__":
asyncio.run(mcp.serve())
- MCP 서버 통합 모듈 (
mcp-stock-server
) - 3개의 MCP 툴
mcp-stock-search
: 인기 주식 Top10 반환mcp-stock-detail
: 주가 추이 및 기업 정보 수집mcp-gmail-sender
: 이메일로 리포트 전송
- Jinja2 기반 이메일 HTML 템플릿 포함
다음은 Gemini와 연결하는 클라이언트 코드(client.py
)입니다.
# 🚀 클라이언트 코드: client.py
import os
import asyncio
from google import genai
from google.genai import types
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
server_params = StdioServerParameters(
command="python",
args=["mcp_stock_server.py", "--connection_type", "stdio"],
env={
"GMAIL_ADDRESS": os.getenv("GMAIL_ADDRESS"),
"GMAIL_APP_PASSWORD": os.getenv("GMAIL_APP_PASSWORD")
}
)
async def run():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
mcp_tools = await session.list_tools()
tools = [
types.Tool(function_declarations=[{
"name": tool.name,
"description": tool.description,
"parameters": {
k: v for k, v in tool.inputSchema.items()
}
}]) for tool in mcp_tools.tools
]
# 자연어 쿼리 → Gemini → 구조화된 함수 호출
prompt = "어제 인기 주식 10개와 각각의 변화 추이 및 기업 정보를 보고서로 만들어 이메일로 보내줘"
response = client.models.generate_content(
model="gemini-2.5-pro-exp-03-25",
contents=prompt,
config=types.GenerateContentConfig(
temperature=0.2,
tools=tools
)
)
call = response.candidates[0].content.parts[0].function_call
result = await session.call_tool(call.name, dict(call.args))
print("[최종 결과]", result)
if __name__ == "__main__":
asyncio.run(run())
항목 | 설명 |
---|---|
genai.Client() |
Google Gemini 2.5 Pro API와의 연결 |
stdio_client() |
MCP 서버와 표준 입력/출력 기반 연결 |
session.initialize() |
MCP 세션 초기화 및 툴 목록 로딩 |
generate_content() |
자연어 → 함수 호출 자동 변환 |
call_tool() |
MCP 툴 실행 및 결과 수신 |
실행 시 Gemini가 자연어 명령을 분석하고, MCP 툴을 자동 호출하여 주식 데이터 및 보고서를 이메일로 전송합니다.
MCP + Gemini 기반 주식 리포트 자동화 시스템을 로컬에서 테스트할 수 있는 구성 템플릿은 아래 파일 구조, 코드, 설정입니다.
📁 폴더 구조
mcp_stock_report/
├── .env ← 환경 변수 파일
├── client.py ← Gemini + MCP 클라이언트
├── server/
│ ├── __init__.py
│ ├── mcp_server.py ← MCP 통합 서버 진입점
│ ├── stock_search.py ← 인기 종목 Top10 추출 툴
│ ├── stock_detail.py ← 종목별 상세 정보 수집
│ └── gmail_sender.py ← 이메일 리포트 전송 툴
└── templates/
└── email_template.html ← HTML 리포트 템플릿
🛠 1. 환경 변수 설정 (.env)
GEMINI_API_KEY=your-gemini-api-key
GMAIL_ADDRESS=your@gmail.com
GMAIL_APP_PASSWORD=your-app-password
Gmail 2단계 인증을 사용하는 경우 앱 비밀번호를 생성해야 합니다.
💡 2. MCP 툴 - 구현
🔹 stock_search.py
# server/stock_search.py
def search_trending_stocks():
return {
"top_tickers": [
"AAPL", "MSFT", "NVDA", "TSLA", "AMZN",
"META", "GOOGL", "NFLX", "AMD", "INTC"
]
}
🔹 stock_detail.py
# server/stock_detail.py
import yfinance as yf
def get_stock_details(ticker: str):
info = yf.Ticker(ticker).info
history = yf.Ticker(ticker).history(period="5d")["Close"]
return {
"ticker": ticker,
"name": info.get("longName"),
"sector": info.get("sector"),
"summary": info.get("longBusinessSummary"),
"price_trend": history.to_dict()
}
🔹 gmail_sender.py
# server/gmail_sender.py
import os
import smtplib
from email.mime.text import MIMEText
def send_email_report(to: str, subject: str, html_body: str):
msg = MIMEText(html_body, 'html')
msg['Subject'] = subject
msg['From'] = os.getenv("GMAIL_ADDRESS")
msg['To'] = to
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login(os.getenv("GMAIL_ADDRESS"), os.getenv("GMAIL_APP_PASSWORD"))
smtp.send_message(msg)
return {"status": "success"}
🚀 3. MCP 서버 진입점
# server/mcp_server.py
from mcp.fastmcp import FastMCPServer
from server import stock_search, stock_detail, gmail_sender
tools = [
{
"name": "search_trending_stocks",
"description": "어제 인기 주식 10개를 반환합니다.",
"parameters": {},
"function": stock_search.search_trending_stocks,
},
{
"name": "get_stock_details",
"description": "주식 종목 상세 정보를 반환합니다.",
"parameters": {
"ticker": {"type": "string", "description": "주식 종목 코드"}
},
"function": stock_detail.get_stock_details,
},
{
"name": "send_email_report",
"description": "HTML 이메일 보고서를 전송합니다.",
"parameters": {
"to": {"type": "string"},
"subject": {"type": "string"},
"html_body": {"type": "string"}
},
"function": gmail_sender.send_email_report,
}
]
if __name__ == "__main__":
FastMCPServer(tools=tools).run_stdio()
📨 4. 이메일 템플릿 (templates/email_template.html)
<h2>📊 어제의 인기 주식 리포트</h2>
{% for stock in stocks %}
<hr/>
<h3>{{ stock.name }} ({{ stock.ticker }})</h3>
<p><b>업종:</b> {{ stock.sector }}</p>
<p><b>개요:</b> {{ stock.summary }}</p>
<p><b>5일간 주가:</b> {{ stock.price_trend }}</p>
{% endfor %}
Python에서 Jinja2를 사용해 html_body = template.render(stocks=data)로 채웁니다.
🤖 5. 클라이언트 코드 (client.py)
import os
from dotenv import load_dotenv
from google import genai
from google.genai import types
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
load_dotenv()
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
server_params = StdioServerParameters(
command="python3 server/mcp_server.py",
args=["--connection_type", "stdio"],
env={
"GMAIL_ADDRESS": os.getenv("GMAIL_ADDRESS"),
"GMAIL_APP_PASSWORD": os.getenv("GMAIL_APP_PASSWORD")
}
)
async def run():
prompt = "어제 인기 주식 10개와 각각의 주가 추이 및 기업정보를 종합해 보고서로 만들어 이메일로 보내줘"
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
gemini_tools = [
types.Tool(function_declarations=[{
"name": t.name,
"description": t.description,
"parameters": {k: v for k, v in t.inputSchema.items()}
}]) for t in tools.tools
]
response = client.models.generate_content(
model="gemini-2.5-pro-exp-03-25",
contents=prompt,
config=types.GenerateContentConfig(
temperature=0.2,
tools=gemini_tools
)
)
call = response.candidates[0].content.parts[0].function_call
result = await session.call_tool(call.name, dict(call.args))
print("📧 결과:", result)
⚙️ 설치 & 실행
# 1. 환경 구성
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# 2. 실행
python3 client.py
📌 requirements.txt 예시
google-genai
mcp
yfinance
smtplib
jinja2
python-dotenv
✅ 테스트 성공 조건
- Gmail로 📩 제목이 "어제의 인기 주식 리포트"인 메일 수신
- 각 종목의 이름, 업종, 주가 추이, 개요 포함된 HTML 리포트
- Gemini가 자연어 프롬프트 기반으로 MCP 툴을 자동 호출