Unified Search MCP Server
Unified Search MCP Server ๐
ํ๋ก๋์ ๋ ๋ฒจ MCP (Model Context Protocol) ์๋ฒ๋ก Google Scholar, Google Web Search, YouTube๋ฅผ ํตํฉ ๊ฒ์ํ ์ ์์ต๋๋ค.
๐ ์ฃผ์ ๊ธฐ๋ฅ
ํต์ฌ ๊ฒ์ ๊ธฐ๋ฅ
๐ Google Scholar: ํ์ ๋ ผ๋ฌธ ๊ฒ์ (์ ์, ์ฐ๋ ํํฐ๋ง)
๐ Google Web Search: Google Custom Search API๋ฅผ ์ฌ์ฉํ ์น ๊ฒ์
๐บ YouTube Search: ๋์์ ๊ฒ์ (๊ธธ์ด, ์ ๋ก๋ ๋ ์ง, ์ ๋ ฌ ์ต์ )
๐ ํตํฉ ๊ฒ์: ๋ชจ๋ ์์ค์์ ๋์ ๊ฒ์
์ํฐํ๋ผ์ด์ฆ ๊ธฐ๋ฅ
๐ ๋ณด์: API ํค ์ํธํ, ์ ๋ ฅ๊ฐ ๊ฒ์ฆ, XSS/SQL ์ธ์ ์ ๋ฐฉ์ง
๐พ ๋ถ์ฐ ์บ์ฑ: Redis ๊ธฐ๋ฐ ์บ์ฑ ๋ฐ TTL ๊ด๋ฆฌ
โก Rate Limiting: Redis ๋ฐฑ์๋ ๊ธฐ๋ฐ ์ค์ ๊ฐ๋ฅํ rate limit
๐ ๋ชจ๋ํฐ๋ง: Prometheus ๋ฉํธ๋ฆญ, ํฌ์ค ์ฒดํฌ, ๊ตฌ์กฐํ๋ ๋ก๊น
๐ ๋ณต์๋ ฅ: ์ฌ์๋ ๋ก์ง, ์ํท ๋ธ๋ ์ด์ปค, ์ฐ์ํ ์ฑ๋ฅ ์ ํ
๐ ๊ฐ์ฌ ๋ก๊น : ๊ท์ ์ค์๋ฅผ ์ํ ํฌ๊ด์ ์ธ ๊ฐ์ฌ ์ถ์
๐ ์๊ตฌ ์ฌํญ
Python 3.11+
Redis (์ ํ์ฌํญ, ๋ถ์ฐ ๊ธฐ๋ฅ์ฉ)
API ํค:
Google Custom Search API (์น ๊ฒ์์ฉ)
YouTube Data API v3 (YouTube ๊ฒ์์ฉ)
๐ ๏ธ ์ค์น
Smithery๋ฅผ ํตํ ๋น ๋ฅธ ์ค์น
Smithery ํ๋ซํผ์ ํตํด ์ง์ ๋ฐฐํฌํ๋ฉด ์๋์ผ๋ก ์ค์ ๋ฉ๋๋ค.
์๋ ์ค์น
์ ์ฅ์ ํด๋ก :
git clone https://github.com/JDeun/unified-search-mcp-server.git
cd unified-search-mcp-server๊ฐ์ ํ๊ฒฝ ์์ฑ:
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate์์กด์ฑ ์ค์น:
pip install -r requirements.txtํ๊ฒฝ ์ค์ :
cp .env.example .env
# .env ํ์ผ์ ํธ์งํ์ฌ API ํค์ ์ค์ ์
๋ ฅโ๏ธ ์ค์
ํ๊ฒฝ ๋ณ์
# API ํค
GOOGLE_API_KEY=your-google-api-key
GOOGLE_CUSTOM_SEARCH_ENGINE_ID=your-cse-id
YOUTUBE_API_KEY=your-youtube-api-key
# ๋ณด์
MCP_ENCRYPTION_KEY=your-256-bit-key
MCP_RATE_LIMIT_SECRET=your-secret
# Redis (์ ํ์ฌํญ)
MCP_REDIS_URL=redis://localhost:6379/0
# ์ค์
MCP_ENV=production
MCP_LOG_LEVEL=INFO
MCP_CACHE_TTL=3600API ํค ๋ฐ๊ธ ๋ฐฉ๋ฒ
Google Custom Search API:
Google Cloud Console ์ ์
"Custom Search API" ํ์ฑํ
์ธ์ฆ ์ ๋ณด ์์ฑ (API ํค)
cse.google.com์์ Custom Search Engine ์์ฑ
YouTube Data API v3:
๋์ผํ Google Cloud Console ํ๋ก์ ํธ ์ฌ์ฉ
"YouTube Data API v3" ํ์ฑํ
๋์ผํ API ํค ์ฌ์ฉ ๋๋ ์๋ก ์์ฑ
๐ ์ฌ์ฉ๋ฒ
์๋ฒ ์คํ
# ๊ฐ๋ฐ ๋ชจ๋ (stdio)
python unified_search_server.py
# ํ๋ก๋์
๋ชจ๋ (HTTP)
python unified_search_server.py --transport streamable-http
# ์ปค์คํ
ํฌํธ
MCP_PORT=8080 python unified_search_server.py --transport streamable-httpDocker ๋ฐฐํฌ
# ์ด๋ฏธ์ง ๋น๋
docker build -t unified-search-mcp .
# ์ปจํ
์ด๋ ์คํ
docker run -p 8000:8000 \
-e GOOGLE_API_KEY=your-key \
-e GOOGLE_CUSTOM_SEARCH_ENGINE_ID=your-cse \
-e YOUTUBE_API_KEY=your-key \
unified-search-mcpClaude Desktop ํตํฉ
claude_desktop_config.json์ ์ถ๊ฐ:
{
"mcpServers": {
"unified-search": {
"command": "python",
"args": ["/path/to/unified_search_server.py"],
"env": {
"GOOGLE_API_KEY": "your-key",
"GOOGLE_CUSTOM_SEARCH_ENGINE_ID": "your-cse",
"YOUTUBE_API_KEY": "your-key"
}
}
}
}๐ ์ฌ์ฉ ๊ฐ๋ฅํ ๋๊ตฌ
unified_search
๋ชจ๋ ์์ค์์ ๋์์ ๊ฒ์ํฉ๋๋ค.
results = await unified_search(
query="์ธ๊ณต์ง๋ฅ",
sources=["scholar", "web", "youtube"],
num_results=10
)search_google_scholar
ํ์ ๋ ผ๋ฌธ์ ๊ฒ์ํฉ๋๋ค.
results = await search_google_scholar(
query="๋จธ์ ๋ฌ๋",
author="Yann LeCun",
year_start=2020,
year_end=2024,
num_results=10
)search_google_web
์น์ ๊ฒ์ํฉ๋๋ค.
results = await search_google_web(
query="ChatGPT",
language="ko",
safe_search="medium",
num_results=10
)search_youtube
YouTube ๋์์์ ๊ฒ์ํฉ๋๋ค.
results = await search_youtube(
query="ํ์ด์ฌ ํํ ๋ฆฌ์ผ",
video_duration="medium",
upload_date="month",
order="viewCount",
num_results=20
)get_author_info
Google Scholar์์ ์ ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
info = await get_author_info("Geoffrey Hinton")clear_cache
์บ์๋ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ์ญ์ ํฉ๋๋ค.
await clear_cache(source="web") # ๋๋ None์ผ๋ก ์ ์ฒด ์ญ์ get_api_usage_stats
API ์ฌ์ฉ๋๊ณผ ์ ํ์ ๋ชจ๋ํฐ๋งํฉ๋๋ค.
stats = await get_api_usage_stats()๐๏ธ ์ํคํ ์ฒ
๋ชจ๋์ ์ค๊ณ
src/
โโโ config/ # ์ค์ ๋ฐ ๋ณด์
โโโ models/ # ๋ฐ์ดํฐ ๋ชจ๋ธ ๋ฐ ๊ฒ์ฆ
โโโ services/ # ๊ฒ์ ์๋น์ค ๊ตฌํ
โโโ cache/ # ์บ์ฑ ๋ ์ด์ด
โโโ utils/ # ์ ํธ๋ฆฌํฐ (๋ก๊น
, rate limiting)
โโโ monitoring/ # ๋ฉํธ๋ฆญ ๋ฐ ํฌ์ค ์ฒดํฌ
โโโ mcp_server.py # ๋ฉ์ธ ์๋ฒ ๊ตฌํ๋ณด์ ๋ ์ด์ด
์ ๋ ฅ๊ฐ ๊ฒ์ฆ ๋ฐ ์ด๊ท
API ํค ์ํธํ ์ ์ฅ
ํด๋ผ์ด์ธํธ/์๋ํฌ์ธํธ๋ณ rate limiting
๊ท์ ์ค์๋ฅผ ์ํ ๊ฐ์ฌ ๋ก๊น
CORS ๋ฐ ์์ฒญ ID ์ถ์
์ฑ๋ฅ ์ต์ ํ
Redis ๊ธฐ๋ฐ ๋ถ์ฐ ์บ์ฑ
HTTP ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ ํ๋ง
๋์ ๊ฒ์ ์คํ
์ง์ ๋ฐฑ์คํ๋ฅผ ํตํ ์ค๋งํธ ์ฌ์๋
์ธ๋ถ API์ฉ ์ํท ๋ธ๋ ์ด์ปค
๐ ๋ชจ๋ํฐ๋ง
ํฌ์ค ์ฒดํฌ ์๋ํฌ์ธํธ
๋ฆฌ์์ค: health://status๋ฉํธ๋ฆญ ์๋ํฌ์ธํธ
๋ฆฌ์์ค: metrics://stats์ฃผ์ ๋ฉํธ๋ฆญ
๊ฒ์ ์์ฒญ ์ ๋ฐ ์ง์ฐ ์๊ฐ
์บ์ ํํธ์จ
API ํ ๋น๋ ์ฌ์ฉ๋
์์ค๋ณ ์ค๋ฅ์จ
Rate limit ์๋ฐ
๐ ๋ณด์
๋ชจ๋ฒ ์ฌ๋ก
๋ชจ๋ API ํค Fernet์ผ๋ก ์ํธํ
XSS/SQL ์ธ์ ์ ๋ฐฉ์ง๋ฅผ ์ํ ์ ๋ ฅ ๊ฒ์ฆ
๋จ์ฉ ๋ฐฉ์ง๋ฅผ ์ํ rate limiting
๋ฏผ๊ฐํ ๋ฐ์ดํฐ ์๋ ๊ตฌ์กฐํ๋ ๋ก๊น
์ ๊ธฐ์ ์ธ ๋ณด์ ์ ๋ฐ์ดํธ
๊ท์ ์ค์
PII ์ ์ฅ ์๋ GDPR ์ค๋น
๋ชจ๋ ๊ฒ์์ ๋ํ ๊ฐ์ฌ ์ถ์
์ค์ ๊ฐ๋ฅํ ๋ฐ์ดํฐ ๋ณด์กด
API ์ฌ์ฉ๋ ์ถ์
๐งช ํ ์คํธ
ํ ์คํธ ์คํ:
pytest tests/ -v --cov=src๐ค ๊ธฐ์ฌ
์ ์ฅ์ ํฌํฌ
๊ธฐ๋ฅ ๋ธ๋์น ์์ฑ (
git checkout -b feature/amazing)๋ณ๊ฒฝ ์ฌํญ ์ปค๋ฐ (
git commit -m 'Add feature')๋ธ๋์น์ ํธ์ (
git push origin feature/amazing)Pull Request ์ด๊ธฐ
๐ ๋ผ์ด์ ์ค
MIT ๋ผ์ด์ ์ค - ์์ธํ ๋ด์ฉ์ LICENSE ํ์ผ ์ฐธ์กฐ
๐ ๊ฐ์ฌ์ ๋ง
โ ๏ธ ์ค์ ์ฌํญ
API ์ ํ
Google Web Search: 100 ์ฟผ๋ฆฌ/์ผ (๋ฌด๋ฃ ํฐ์ด)
YouTube API: 10,000 ์ ๋/์ผ (์ฝ 100 ๊ฒ์)
Google Scholar: ๊ณต์ API ์์, rate ์ ํ ์์
ํ๋ก๋์ ๊ณ ๋ ค์ฌํญ
๋ถ์ฐ ๋ฐฐํฌ๋ฅผ ์ํด Redis ์ฌ์ฉ
์ ์ ํ API ํค ๋กํ ์ด์ ์ค์
Rate limit ๋ฐ ํ ๋น๋ ๋ชจ๋ํฐ๋ง
API ์ค๋ฅ์ ๋ํ ์๋ฆผ ์ค์
์ ๊ธฐ์ ์ธ ์ค์ ๋ฐฑ์
๐ ์ง์
๋ฌธ์ ๋ฐ ์ง๋ฌธ:
GitHub Issues: ์ด์ ์์ฑ
Smithery ์ง์: ๋ฐฐํฌ ๊ด๋ จ ๋ฌธ์
MCP ์ปค๋ฎค๋ํฐ๋ฅผ ์ํด โค๏ธ๋ก ์ ์