Skip to content
블로그 사이트용 MCP 서비스 구축 방법

Nextra와 LLMs를 이용한 MCP 기반 블로그 포스트 생성기 구축하기

Updated on

MCP 서비스를 어떻게 구축하나요? 이 튜토리얼에서는 OpenAI 또는 Claude와 채팅만으로 글을 작성하고 게시할 수 있는 MCP 서비스를 만들어 봅니다.

이 튜토리얼에서는 대형 언어 모델(LLM)과 채팅하며 콘텐츠 생성을 요청할 수 있는 기술적 솔루션을 만들어보겠습니다. 생성된 콘텐츠는 MDX 형식으로 작성되며, 자동으로 GitHub 저장소의 블로그에 새 게시물로 커밋됩니다. 본문에서는 Model Context Protocol (MCP) 통합을 위한 두 가지 구현 방식을 탐구합니다:

  1. 서버리스 방식: GitHub Actions 이용 — GitHub Actions 워크플로우를 활용하여 LLM 호출과 게시물 커밋 과정을 전체 자동화
  2. 호스팅 방식: Next.js API 이용jojocys/nextra-agent-blog와 같은 블로그 플랫폼에 간단한 MCP 서버역할의 Next.js API 엔드포인트를 구축하여, 실시간으로 LLM 요청 후 GitHub에 게시

MCP는 AI 어시스턴트와 외부 도구 및 데이터 연결을 위한 개방 표준입니다. AI 모델이 클라우드 서비스, 데이터베이스, GitHub, Slack 등과 인터랙션할 수 있도록 하는 범용 인터페이스를 제공하며, 각 도구와의 커스텀 통합 없이도 AI가 다양한 외부 시스템에서 작업을 수행할 수 있게 합니다 (Model Context Protocol (MCP) 설명 (opens in a new tab)). 즉, MCP는 AI 에이전트가 “도구”를 활용하여 내부 지식을 확장하거나 행동하는 능력을 지원합니다. 예를 들어, 이메일 발송, 코드 배포, 또는 블로그 게시와 같은 작업을 MCP를 통해 수행할 수 있습니다 (Cloudflare에서 원격 MCP 서버 구축 및 배포하기 (opens in a new tab)). 본 예제에서는 새로운 MDX 파일을 생성하고 이를 Git 저장소(블로그)에 커밋하는 것이 바로 이 “도구” 역할이 됩니다.

이 가이드를 따라하면, 단일 사용자로서 AI 에이전트가 요청하는 블로그 글이 자동으로 사이트에 나타나는 시스템을 갖추게 됩니다. MCP 클라이언트↔︎LLM, LLM↔︎GitHub 연결 구조를 이해하고, 인증 없이 단일 사용자 환경을 전제로 설명합니다.

솔루션 개요

먼저 전체 아키텍처와 워크플로를 개략적으로 정리해봅니다:

  • 블로그 플랫폼: Next.js와 Nextra 'blog theme'(jojocys/nextra-agent-blog 활용)을 기반으로 콘텐츠를 호스팅합니다. 블로그 포스트는 repository 내 pages/posts 폴더의 MDX 파일로 저장되며, Nextra는 해당 MDX 파일들을 읽어 블로그 목록에 보여줍니다. 제목, 날짜 등은 frontmatter로 포함.

  • LLM (AI 어시스턴트): OpenAI의 GPT, Anthropic의 Claude 등과 같은 AI 모델을 사용하여 블로그 내용 생성. 사용자는 채팅 또는 API 호출로 특정 주제 또는 요청을 보내면, AI는 MDX 포맷의 글을 생성하여 반환.

  • MCP 클라이언트 & 서버: MCP는 AI가 외부 도구를 호출하는 구조체입니다.

    • 서버리스 접근(GitHub Actions): 워크플로우가 MCP 클라이언트 역할을 하여 LLM 호출과 포스트 커밋을 담당.
    • 호스팅 API 접근(Next.js API): Next.js 자체 API 엔드포인트를 MCP 클라이언트/서버로 활용하여, 요청을 받아 LLM 호출 → 게시글 생성 → GitHub에 커밋의 전체 과정을 처리하는 역할.
  • GitHub 연동: 두 방식 모두 GitHub API를 통해 새로운 포스트를 repo에 추가합니다. Git operations 또는 HTTP API를 사용하며, 이를 위해 예제도 준비했습니다. (Cloudflare MCP 서버에 GitHub 연동 포함 (opens in a new tab)). 본 예제에서는 직접 구현하는 방법을 보여줍니다.

먼저, 서버리스 GitHub Actions 방식을 살펴보겠습니다.


방식 1: 서버리스 블로그 포스트 생성 & 게시 — GitHub Actions 활용

이 방법은 GitHub Actions 워크플로우를 이용하여, 요청 시 자동으로 블로그 포스트를 생성하고 게시하는 방식입니다. 서버 운영 없이, GitHub의 러너를 통해 작업이 수행됩니다. 전체 작업은 다음과 같습니다:

  1. 트리거: 사용자(본인)가 워크플로우를 수동 또는 이벤트 트리거(예: 디스패치 이벤트)로 시작하며, 포스트 주제 또는 요청을 입력.
  2. LLM 호출: 워크플로우가 OpenAI 또는 Claude API를 호출하여, MDX 형식의 콘텐츠를 요청.
  3. 파일 생성: AI 응답을 받아 MDX 내용으로 .mdx 파일을 만들어 posts/ 폴더에 저장.
  4. 커밋 및 푸시: 새 파일을 커밋 & 푸시하여 블로그 게시.

아래는 .github/workflows/llm-agent.yml 예제입니다:

name: LLM 블로그 포스트 생성기
 
on:
  workflow_dispatch:
    inputs:
      prompt:
        description: "블로그 포스트 주제 또는 요청"
        required: true
        type: string
 
permissions:
  contents: write
 
jobs:
  generate_post:
    runs-on: ubuntu-latest
    steps:
      - name: 저장소 체크아웃
        uses: actions/checkout@v3
      
      - name: jq 설치 (JSON 파싱용)
        run: sudo apt-get -y install jq
 
      - name: OpenAI로 블로그 콘텐츠 생성
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          echo "요청 주제: ${{ github.event.inputs.prompt }}"
          REQUEST_DATA=$(jq -n --arg prompt "${{ github.event.inputs.prompt }}" '{
              "model": "gpt-3.5-turbo",
              "messages": [
                {"role": "system", "content": "당신은 기술 블로그 글 작성 도우미입니다. YAML frontmatter (제목, 날짜, 설명)와 내용을 포함하는 MDX 포맷의 블로그 글을 작성하세요."},
                {"role": "user", "content": $prompt}
              ]
            }')
          RESPONSE=$(curl -sS -H "Content-Type: application/json" \
                          -H "Authorization: Bearer $OPENAI_API_KEY" \
                          -d "$REQUEST_DATA" \
                          https://api.openai.com/v1/chat/completions)
          POST_CONTENT=$(echo "$RESPONSE" | jq -r '.choices[0].message.content')
          TIMESTAMP=$(date +"%Y-%m-%d-%H%M")
          FILENAME="posts/llm-post-$TIMESTAMP.mdx"
          echo "$POST_CONTENT" > $FILENAME
 
      - name: 변경사항 커밋 및 푸시
        run: |
          git config user.name "github-actions"
          git config user.email "github-actions@users.noreply.github.com"
          git add posts/*.mdx
          git commit -m "AI 생성 블로그 포스트 추가"
          git push

이 워크플로우는 수동 실행이 가능하며, 제공한 주제로 LLM이 콘텐츠를 만들고 파일로 저장 후 push합니다. 사이트 배포 환경이 트리거될 경우, 새 글이 블로그에 바로 반영됩니다.

요약:
이 방식은 별도 서버 없이, GitHub 인프라만으로 쉽게 자동화된 포스팅이 가능하며, 비용 효율적입니다. 다만, 게시물 검토 단계가 없다면, 완전 자동 게시가 되기 때문에 콘텐츠 검증이 필요할 수 있습니다.


방식 2: Next.js API를 활용한 실시간 MCP 서버

이 방법은 블로그 애플리케이션 자체에 MCP 서버 역할을 하는 API 엔드포인트를 구현하는 방식입니다. 사용자 인터페이스에서 요청 시, 서버가 LLM에 요청하고 Content를 받아 GitHub에 커밋하는 과정을 수행합니다.

구성 개념

  • 환경설정: .env.local 등에 OpenAI API 키, GitHub Personal Access Token, 소유자명, 저장소명 등 기재
OPENAI_API_KEY=xxx
GITHUB_PAT=xxx
GITHUB_REPO_OWNER=yourusername
GITHUB_REPO_NAME=nextra-agent-blog
  • API 엔드포인트: pages/api/generate-post.js 또는 app/api/generate-post/route.js에 구현
  • 작동 흐름: 클라이언트에서 요청 → 서버에서 LLM 호출 및 MDX 콘텐츠 생성 → GitHub에 커밋파일 생성 → 응답

예제: pages/api/generate-post.js

import { Octokit } from "@octokit/rest";
import { Configuration, OpenAIApi } from "openai";
 
export default async function handler(req, res) {
  const { prompt } = req.body;
  if (!prompt) return res.status(400).json({ error: "No prompt" });
  try {
    const openaiConfig = new Configuration({ apiKey: process.env.OPENAI_API_KEY });
    const openai = new OpenAIApi(openaiConfig);
    const completion = await openai.createChatCompletion({
      model: "gpt-3.5-turbo",
      messages: [
        { role: "system", content: "MDX 블로그 포스트 작성자입니다. 제목, 날짜, 설명, 블로그 유형 포함." },
        { role: "user", content: prompt }
      ],
    });
    const mdxText = completion.data.choices[0].message.content;
 
    // 제목 parse
    const titleMatch = mdxText.match(/^title:\s*\"?(.+)\"?/m);
    const title = titleMatch ? titleMatch[1] : "untitled";
    const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
    const filename = `posts/${slug || "untitled"}-${Date.now()}.mdx`;
 
    // 필요시 frontmatter 수정
    let finalContent = mdxText;
    if (!/^date:\s*/m.test(finalContent)) {
      finalContent = finalContent.replace(/^(title:.*)$/m, `$1\ndate: ${new Date().toISOString()}`);
    }
    if (!/^type:\s*/m.test(finalContent)) {
      finalContent = finalContent.replace(/^(title:.*)$/m, `$1\ntype: posts`);
    }
 
    // GitHub에 커밋
    const octokit = new Octokit({ auth: process.env.GITHUB_PAT });
    await octokit.rest.repos.createOrUpdateFileContents({
      owner: process.env.GITHUB_REPO_OWNER,
      repo: process.env.GITHUB_REPO_NAME,
      path: filename,
      message: `자동 생성: "${title}" 포스트`,
      content: Buffer.from(finalContent, "utf-8").toString("base64"),
      committer: { name: "MCP Bot", email: "mcp-bot@example.com" },
      author: { name: "MCP Bot", email: "mcp-bot@example.com" }
    });
    res.status(200).json({ message: "포스트 생성 완료", filename });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: err.message });
  }
}

사용 방법

  • API 요청 (/api/generate-post)에 대해 POST 요청, 내용을 JSON으로 전달 ({"prompt": "어떻게 MCP를 활용한 블로그 구축할까?"})
  • 서버는 LLM 호출 → 콘텐츠 생성 → GitHub 커밋 수행
  • 결과 URL 또는 메시지로 피드백 받을 수 있음

이 방법은 인터랙티브한 UI를 만들거나, 특정한 요청에 대해 즉시 게시 가능하도록 할 때 적합하며, MCP의 클라이언트-서버 역할을 모두 수행할 수 있습니다.


결론

이 튜토리얼에서는 AI와 블로그 콘텐츠 작업을 연결하는 두 가지 방식을 소개했습니다:

  • 서버리스: GitHub Actions — 비용 효율적, 자동화 가능, 별도 서버 불필요
  • 직접 호스팅: Next.js API — 실시간 요청 처리, 사용자 인터페이스 연동 용이

이 두 방법 모두, MCP 표준을 활용하여 AI가 외부 시스템에 액션을 취하도록 하는 아이디어의 실현 사례입니다. 앞으로 더 확장하여, 다양한 도구와 연동하거나, 다중 사용자 환경을 만들 수도 있습니다.

이와 같은 MCP 기반 연동을 통해, AI의 기능을 외부 도구와 손쉽게 통합하여, 자동화 및 지능적 업무 수행을 한 단계 높일 수 있습니다.

참고 자료:

  1. Anthropic, Introducing the Model Context Protocol (MCP)
  2. Cloudflare, MCP를 활용한 확장 시스템 구축 사례
  3. MCP 오픈소스 서버 모음, 특히 GitHub 연동 서버 예제

이제 여러분의 블로그와 외부 도구들을 MCP 표준으로 확장하여, AI와 함께하는 스마트 워크플로우를 만들어 보세요!

📚