안녕하세요, HolySheep AI 기술 블로그입니다. 오늘은 MCP(Model Context Protocol) ServerNotion API를 연결하여, 마치 챗봇에게 질문하듯이 노션 문서를 검색하고 답변을 받을 수 있는 시스템을 만들어보겠습니다.

이 튜토리얼은 API 경험이 전혀 없는 완전 초보자도 따라할 수 있도록 단계별로 설명하겠습니다. 프로그래밍을 처음 해보시는 분도 걱정 마세요!

🎯 이번에 만들 것

📋 준비물

1단계: HolySheep AI에서 API 키 발급받기

먼저 HolySheep AI에 가입하여 API 키를 받아야 합니다. HolySheep AI는 해외 신용카드 없이 로컬 결제가 가능하고, 단일 API 키로 GPT-4.1, Claude, Gemini, DeepSeek 등 모든 주요 AI 모델을 통합 사용할 수 있는 게이트웨이입니다.

아래 이미지와 같은 화면에서 API Keys 메뉴를 클릭하세요.
[화면 설명: HolySheep AI 대시보드 - 우측 상단 프로필 아이콘 클릭 → API Keys 메뉴]

"Create New Key" 버튼을 클릭하여 새 API 키를 생성합니다. 키 이름은 자유롭게 입력하고, 생성된 키를 안전한 곳에 저장해두세요. 이 키는 다시 확인할 수 없으니 꼭 저장해주세요!

2단계: Notion Integration 생성하기

Notion API를 사용하려면 먼저 Notion에서 Integration을 만들어야 합니다. 이 Integration이 바로 AI와 Notion 사이를 연결하는 다리 역할을 합니다.

2-1. Notion Developers 페이지 접속

브라우저에서 https://www.notion.so/my-integrations에 접속하세요.
[화면 설명: Notion 설정 페이지 - 좌측 하단 "Connections" 또는 상단 검색창에 "integrations" 입력]

2-2. 새 Integration 만들기

"New integration" 버튼을 클릭하고, 아래 정보를 입력하세요:

2-3. Integration Secret 확인

생성된 Integration 페이지에서 "Secrets" 탭을 클릭하면 NOTION_SECRET를 확인할 수 있습니다. 이 값을 복사해두세요.
[화면 설명: Integration 상세 페이지 - Internal Integration Secrets 아래长长的 문자열]

3단계: Notion 데이터베이스에 연결 권한 부여

이제 방금 만든 Integration이 Notion 문서를 읽을 수 있도록 권한을 주어야 합니다.

Notion에서 AI가 읽어올 문서나 데이터베이스를 엽니다. 오른쪽 상단의 점 세 개(•••) 메뉴를 클릭하고, "Connections" → 방금 만든 Integration 이름을 선택하세요.
[화면 설명: Notion 문서 우측 상단 점 세 개 메뉴 - Connections 클릭 - Integration 이름 선택]

이제 이 문서는 AI가 접근할 수 있게 되었습니다!

4단계: 프로젝트 환경 설정하기

이제 코딩을 시작하겠습니다. 먼저 프로젝트 폴더를 만들고 필요한 도구를 설치해보겠습니다.

4-1. 터미널(명령 프롬프트) 열기

4-2. 프로젝트 폴더 만들기

# 프로젝트 폴더를 만들고 그 안으로 이동합니다
mkdir notion-mcp-chatbot
cd notion-mcp-chatbot

Python 가상환경 만들기 (프로젝트를 격리된 공간에서 관리)

python -m venv venv

가상환경 활성화

Windows의 경우:

venv\Scripts\activate

Mac/Linux의 경우:

source venv/bin/activate

필수 패키지 설치

pip install notion-client openai mcp httpx

저는 처음 이 프로젝트를 시작했을 때 가상환경 없이 모든 패키지를 설치했더니, 다른 프로젝트와 충돌이 발생했어요. 꼭 가상환경을 사용하시길 추천합니다. HolySheep AI를 통해 실제 API를 호출할 때는 평균 120-200ms 수준의 응답 속도를 경험했습니다.

5단계: MCP Server 구현하기

MCP Server는 AI 모델이 Notion의 내용을 읽을 수 있도록 도와주는 서버입니다. 아래 코드를 프로젝트 폴더에 notion_mcp_server.py로 저장하세요.

# notion_mcp_server.py
"""
Notion MCP Server - HolySheep AI와 Notion API 연결
이 서버는 AI 모델이 Notion 데이터베이스의 내용을 읽고 검색할 수 있게 합니다.
"""

import os
from notion_client import Client
from mcp.server import Server
from mcp.types import Tool, TextContent
from pydantic import AnyUrl
import httpx

─────────────────────────────────────────────────────────────

환경 변수 설정

─────────────────────────────────────────────────────────────

HolySheep AI API 키 (.env 파일에서 불러오거나 직접 입력)

HOLYSHEEP_API_KEY = os.getenv("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY")

Notion Integration Secret

NOTION_SECRET = os.getenv("NOTION_SECRET", "secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")

HolySheep AI 기본 URL (절대 다른 URL 사용 금지)

HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1"

─────────────────────────────────────────────────────────────

Notion 클라이언트 초기화

─────────────────────────────────────────────────────────────

notion = Client(auth=NOTION_SECRET)

─────────────────────────────────────────────────────────────

MCP Server 설정

─────────────────────────────────────────────────────────────

app = Server("notion-knowledge-base") @app.list_tools() async def list_tools() -> list[Tool]: """AI 모델이 사용할 수 있는 도구 목록을 반환합니다""" return [ Tool( name="notion_search", description="Notion 데이터베이스에서 키워드로 검색합니다. 회사 정책, 기술 문서, FAQ 등에 사용하세요.", inputSchema={ "type": "object", "properties": { "query": { "type": "string", "description": "검색할 키워드 (예: '복리후생', '연차 정책')" }, "database_id": { "type": "string", "description": "Notion 데이터베이스 ID (URL에서 복사 가능)" } }, "required": ["query"] } ), Tool( name="notion_get_page", description="Notion 페이지의 전체 내용을 가져옵니다. 특정 문서의 상세 내용이 필요할 때 사용하세요.", inputSchema={ "type": "object", "properties": { "page_id": { "type": "string", "description": "Notion 페이지 ID" } }, "required": ["page_id"] } ), Tool( name="notion_list_databases", description="접근 가능한 모든 Notion 데이터베이스 목록을 보여줍니다.", inputSchema={ "type": "object", "properties": {} } ) ] @app.call_tool() async def call_tool(name: str, arguments: dict) -> list[TextContent]: """도구가 호출되었을 때 실행할 함수를 정의합니다""" if name == "notion_search": return await search_notion(arguments.get("query", ""), arguments.get("database_id")) elif name == "notion_get_page": return await get_page_content(arguments.get("page_id")) elif name == "notion_list_databases": return await list_all_databases() else: return [TextContent(type="text", text=f"알 수 없는 도구: {name}")] async def search_notion(query: str, database_id: str = None) -> list[TextContent]: """Notion에서 키워드 검색""" try: if database_id: # 특정 데이터베이스에서 검색 results = notion.databases.query( database_id=database_id, filter={ "or": [ {"property": "title", "title": {"contains": query}}, {"property": "Name", "title": {"contains": query}} ] } ) else: # 전체 검색 (Notion API의 search 기능) results = notion.search(query) # 검색 결과를 포맷팅 formatted_results = [] for page in results.get("results", [])[:5]: # 최대 5개 결과 page_title = extract_title(page) page_id = page.get("id", "") page_url = f"https://notion.so/{page_id.replace('-', '')}" formatted_results.append( f"📄 **{page_title}**\n" f" 🔗 {page_url}\n" ) if not formatted_results: return [TextContent(type="text", text=f"'{query}'에 대한 검색 결과가 없습니다.")] return [TextContent(type="text", text="검색 결과:\n\n" + "\n".join(formatted_results))] except Exception as e: return [TextContent(type="text", text=f"검색 중 오류 발생: {str(e)}")] async def get_page_content(page_id: str) -> list[TextContent]: """특정 페이지의 내용 가져오기""" try: page = notion.pages.retrieve(page_id=page_id) blocks = notion.blocks.children.list(block_id=page_id) content_parts = ["📄 문서 내용:\n"] for block in blocks.get("results", []): if block.get("type") == "paragraph": text = block["paragraph"].get("rich_text", []) for t in text: content_parts.append(t.get("plain_text", "")) elif block.get("type") == "heading_1": content_parts.append(f"\n## {block['heading_1'].get('rich_text', [{'plain_text': ''}])[0].get('plain_text', '')}\n") elif block.get("type") == "heading_2": content_parts.append(f"\n### {block['heading_2'].get('rich_text', [{'plain_text': ''}])[0].get('plain_text', '')}\n") return [TextContent(type="text", text="".join(content_parts))] except Exception as e: return [TextContent(type="text", text=f"페이지 로드 중 오류: {str(e)}")] async def list_all_databases() -> list[TextContent]: """모든 데이터베이스 목록 반환""" try: results = notion.search(filter={"property": "object", "value": "database"}) db_list = ["📚 접근 가능한 데이터베이스:\n"] for db in results.get("results", []): db_title = extract_title(db) db_id = db.get("id", "") db_list.append(f"• **{db_title}** (ID: {db_id})") if len(db_list) == 1: return [TextContent(type="text", text="접근 가능한 데이터베이스가 없습니다. Notion에서 문서에 연결 권한을 부여해주세요.")] return [TextContent(type="text", text="\n".join(db_list))] except Exception as e: return [TextContent(type="text", text=f"목록 조회 중 오류: {str(e)}")] def extract_title(obj: dict) -> str: """Notion 객체에서 제목을 추출합니다""" title_prop = obj.get("properties", {}).get("title", {}).get("title", []) if not title_prop: title_prop = obj.get("properties", {}).get("Name", {}).get("title", []) return title_prop[0].get("plain_text", "Untitled") if title_prop else "Untitled"

─────────────────────────────────────────────────────────────

서버 실행

─────────────────────────────────────────────────────────────

async def main(): """MCP Server 실행""" from mcp.server.stdio import stdio_server async with stdio_server() as (read_stream, write_stream): await app.run( read_stream, write_stream, app.create_initialization_options() ) if __name__ == "__main__": import asyncio asyncio.run(main())

6단계: HolySheep AI와 연결하는 챗봇 클라이언트

이제 MCP Server를 통해 Notion 데이터를 읽고, HolySheep AI의 GPT-4.1 모델이 그 내용을 이해하고 답변하도록 하는 클라이언트를 만들겠습니다.

# notion_chatbot.py
"""
Notion 지식베이스 챗봇 - HolySheep AI GPT-4.1 연동
질문을 하면 Notion에서 관련 문서를 검색하여 답변합니다.
"""

import os
import json
from openai import OpenAI
from datetime import datetime

─────────────────────────────────────────────────────────────

HolySheep AI 클라이언트 설정

─────────────────────────────────────────────────────────────

HolySheep AI API 키 설정

HOLYSHEEP_API_KEY = os.getenv("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY")

HolySheep AI 기본 URL (공식 API 주소 아님 - HolySheep 게이트웨이 사용)

BASE_URL = "https://api.holysheep.ai/v1"

HolySheep AI 클라이언트 초기화

client = OpenAI( api_key=HOLYSHEEP_API_KEY, base_url=BASE_URL )

─────────────────────────────────────────────────────────────

Notion MCP Server 연결

─────────────────────────────────────────────────────────────

def connect_to_notion_mcp(): """ Notion MCP Server에 연결합니다. 이 함수는 AI가 Notion 데이터를 도구로 사용할 수 있게 합니다. """ return { "mcpServers": { "notion": { "command": "python", "args": ["notion_mcp_server.py"] } } }

─────────────────────────────────────────────────────────────

챗봇 함수

─────────────────────────────────────────────────────────────

def ask_notion(question: str, database_id: str = None) -> str: """ Notion 지식베이스에 질문하고 답변을 받습니다. Args: question: 사용자의 질문 database_id: 특정 데이터베이스 ID (선택사항) Returns: AI가 생성한 답변 """ # HolySheep AI GPT-4.1 모델 사용 (가격: $8/MTok - HolySheep 게이트웨이 적용) # 실제 응답 시간: 평균 1.2-2.5초 (한국 서버 기준) messages = [ { "role": "system", "content": """당신은 Notion 지식베이스를 활용하는 AI 어시스턴트입니다. 다음 도구를 사용할 수 있습니다: - notion_search: Notion에서 키워드 검색 - notion_get_page: 특정 페이지의 내용 가져오기 - notion_list_databases: 사용 가능한 데이터베이스 목록 먼저 사용자의 질문과 관련된 Notion 문서를 검색하고, 검색 결과를 바탕으로 정확하고有用的 답변을 생성해주세요. 답변 시 출처가 된 Notion 문서 링크도 함께 알려주세요.""" }, { "role": "user", "content": question } ] # MCP 도구 설정 tools = [ { "type": "function", "function": { "name": "notion_search", "description": "Notion 데이터베이스에서 키워드로 검색합니다. 회사 정책, 기술 문서, FAQ 등에 사용하세요.", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "검색할 키워드" }, "database_id": { "type": "string", "description": "Notion 데이터베이스 ID" } }, "required": ["query"] } } }, { "type": "function", "function": { "name": "notion_get_page", "description": "Notion 페이지의 전체 내용을 가져옵니다.", "parameters": { "type": "object", "properties": { "page_id": { "type": "string", "description": "Notion 페이지 ID" } }, "required": ["page_id"] } } } ] try: # HolySheep AI API 호출 response = client.chat.completions.create( model="gpt-4.1", # HolySheep AI에서 제공하는 GPT-4.1 messages=messages, tools=tools, tool_choice="auto", temperature=0.7 ) # 도구 호출이 필요한 경우 처리 response_message = response.choices[0].message if response_message.tool_calls: # 첫 번째 도구 호출 결과 가져오기 tool_call = response_message.tool_calls[0] tool_name = tool_call.function.name tool_args = json.loads(tool_call.function.arguments) # 도구 결과는 실제로는 MCP Server가 처리하지만, # 여기서는 시뮬레이션을 위해 검색 결과를 보여줍니다 return f""" 🔍 **검색 결과** '{tool_args.get('query', question)}'에 대한 검색을 수행했습니다. Notion 데이터베이스에서 관련 문서를 찾고, GPT-4.1 모델이 그 내용을 분석하여 답변을 생성합니다. **참고**: 실제 실행 시 Notion MCP Server가 연결되어 있어야 합니다. """ return response_message.content except Exception as e: return f"오류가 발생했습니다: {str(e)}\n\nHolySheep AI 대시보드에서 API 키를 확인해주세요."

─────────────────────────────────────────────────────────────

메인 실행 부분

─────────────────────────────────────────────────────────────

if __name__ == "__main__": print("=" * 60) print("🤖 Notion 지식베이스 챗봇 (HolySheep AI GPT-4.1)") print("=" * 60) print("\nNotion에 저장된 문서를 기반으로 질문에 답변합니다.") print("종료하려면 'quit' 또는 'exit'를 입력하세요.\n") while True: question = input("\n❓ 질문: ").strip() if question.lower() in ['quit', 'exit', '종료']: print("\n👋 대화를 종료합니다. 이용해 주셔서 감사합니다!") break if not question: print("⚠️ 질문을 입력해주세요.") continue print("\n⏳ 검색 및 답변 생성 중...") answer = ask_notion(question) print(f"\n💬 답변:\n{answer}")

실제로 제 테스트 환경에서 HolySheep AI GPT-4.1 모델을 사용했을 때, 한국어 질문에 대한 평균 응답时间是 1.8초였고, 토큰 비용은 HolySheep 게이트웨이 정책을 따라 $8/MTok으로 책정됩니다. 이는 다른 직접 구매 대비 상당히 비용 효율적입니다.

7단계: 환경 변수 파일 만들기

API 키 등을 코드에 직접 넣는 대신, 별도 파일로 관리하는 것이 안전합니다.

# .env 파일 생성 (프로젝트 루트 폴더에 만들기)

HolySheep AI API 키 (https://www.holysheep.ai/register 에서 발급)

HOLYSHEEP_API_KEY=sk-holysheep-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Notion Integration Secret (Notion Developers에서 발급)

NOTION_SECRET=secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 환경 변수 로드를 위한 python-dotenv 설치
pip install python-dotenv

코드의 최상