AI 봇 – 직접 MCP 서버 가져오기

:bookmark: 이 가이드는 외부 Model Context Protocol (MCP) 서버를 Discourse AI 에이전트에 연결하는 방법을 설명합니다. 이를 통해 MCP 호환 도구 제공자 중 어떤 것이든 AI 봇 내에서 직접 사용할 수 있습니다.

:person_raising_hand: 필요한 사용자 권한: 관리자 (Administrator)


"Bring Your Own MCP"란?

Model Context Protocol는 AI 에이전트가 표준 HTTP/JSON-RPC 인터페이스를 통해 외부 도구 서버와 통신할 수 있게 하는 개방형 표준입니다(원래 Anthropic에서 제안). MCP 서버는 LLM이 작업을 수행하기 위해 호출할 수 있는 “도구” 목록을 노출합니다. 여기서 도구는 타입이 지정된 입력을 가진 함수입니다.

Discourse AI는 이제 MCP 클라이언트 역할을 수행합니다. 관리자 패널에서 HTTPS MCP 서버를 등록하면, Discourse는 사용 가능한 도구를 발견하고 해당 도구들은 사용자가 선택한 AI 에이전트 내에서 1급 시민(first-class citizens)이 됩니다. JavaScript를 작성할 필요가 없으며, 도구는 원격 서버에 의해 정의됩니다.

이는 Discourse 내에서 실행되는 JavaScript를 작성해야 하는 커스텀 스크립트 도구와 다릅니다. MCP의 경우 이미 실행 중인 외부 서버를 가져오게 됩니다.


요약

  • MCP 서버 등록 (URL + 선택적 인증)
  • Discourse가 서버의 도구를 자동으로 발견하고 캐시합니다
  • 서버를 하나 이상의 AI 에이전트에 할당합니다
  • 각 에이전트가 사용할 수 있는 도구를 선택적으로 제한합니다
  • 도구는 런타임에 LLM에 의해 호출되며, Discourse를 거쳐 외부 서버로 라우팅됩니다

MCP 서버 등록

다음 경로로 이동합니다:

Admin → Plugins → Discourse AI → ToolsMCP servers 탭 → New MCP server

다음 필드를 입력합니다:

필드 설명
Name 사람이 읽을 수 있는 라벨 (에이전트 에디터 및 로그에 표시됨)
Description 이 서버의 용도 (관리자 참고용)
URL MCP 서버의 HTTPS 엔드포인트 — 공개된 HTTPS URL이어야 하며, 사설 IP는 허용되지 않습니다
Authentication 다음 중 하나: No authentication, Header credential, 또는 OAuth
Timeout (seconds) 요청당 Discourse가 대기하는 시간 — 기본값 30초, 최대 300초
Enabled 서버를 삭제하지 않고 일시적으로 비활성화하기 위한 토글

:warning: URL은 HTTPS를 사용해야 합니다. localhost 및 RFC-1918 사설 주소는 차단됩니다 (SSRF 보호가 서버 측에서 적용됨).


인증 옵션

인증 없음 (No Authentication)

서버는 공개적으로 접근 가능합니다. 자격 증명은 전송되지 않습니다.

헤더 자격 증명 (Header Credential)

비밀 값이 모든 요청에 HTTP 헤더로 주입됩니다.

  1. 먼저 Admin → AI → Credentials에서 Credential을 생성합니다
  2. MCP 서버 폼에서 이를 Credential로 선택합니다
  3. Auth header 이름을 설정합니다 (기본값: Authorization)
  4. 선택적 Auth scheme 접두사를 설정합니다 (기본값: Bearer)

MCP 서버로 전송되는 요청 헤더는 다음과 같습니다:

Authorization: Bearer <your-secret-value>

서버가 요구하는 인증 스타일에 맞춰 헤더 이름과 스키마를 모두 변경할 수 있습니다 (예: 스키마를 비워두면 X-Api-Key: <value>).

OAuth

Discourse는 MCP 클라이언트로서 완전한 OAuth 2.0 + PKCE 플로우를 구현합니다. 이는 도구를 OAuth 뒤에 보호하는 MCP 서버를 지원합니다.

설정 단계:

  1. AuthenticationOAuth로 설정합니다
  2. Client registration을 선택합니다:
    • Client metadata document (기본값) — Discourse는 https://your-site.com/discourse-ai/mcp/oauth/client-metadata에 자체 OAuth 클라이언트 메타데이터를 게시합니다. MCP 서버가 RFC 7591 Dynamic Client Registration을 지원하면 Discourse가 자동으로 등록합니다
    • Manual client credentials — 사전에 등록한 OAuth client ID를 입력하고 OAuth client secret 자격 증명을 선택합니다
  3. 선택적으로 OAuth scopes를 설정합니다 (공백으로 구분)
  4. 서버를 저장합니다
  5. Connect를 클릭합니다 — Discourse가 제공자의 인증 페이지로 리다이렉트합니다
  6. 인증 후 관리자로 돌아오며 상태는 Connected로 표시됩니다

고급 OAuth 옵션 (“Show advanced options” 토글):

옵션 목적
OAuth authorization params 인증 요청에 병합되는 JSON 객체 (예: {"access_type":"offline"})
OAuth token params 토큰 교환 요청에 병합되는 JSON 객체
Require refresh token 제공자가 리프레시 토큰을 반환하지 않으면 연결 실패

Discourse는 만료 전에 액세스 토큰을 자동으로 갱신하고, 리프레시 토큰이 사용 가능한 경우 401 발생 시 재시도합니다.


연결 테스트

서버를 에이전트에 할당하기 전에 에디터 폼의 Test connection 버튼을 사용하십시오. 이는 즉시 MCP 세션을 초기화하고 tools/list를 호출하여 다음을 반환합니다:

  • 협상된 MCP 프로토콜 버전
  • 발견된 도구 수
  • 모든 도구의 이름

테스트가 실패하면 서버의 오류 메시지(또는 타임아웃 표시자)가 인라인으로 표시됩니다.


Discourse의 도구 발견 방식

Discourse는 MCP 스펙 2025-03-26를 따릅니다. 연결 시퀀스는 다음과 같습니다:

Discourse → POST /  { method: "initialize", params: { protocolVersion, capabilities, clientInfo } }
Server    → { result: { protocolVersion, capabilities } } + Mcp-Session-Id 헤더
Discourse → POST /  { method: "notifications/initialized" }   (세션 핸드셰이크 완료)
Discourse → POST /  { method: "tools/list", session_id: … }
Server    → { result: { tools: [ { name, description, inputSchema } … ] } }

도구 정의는 서버별로 1시간 동안 캐시됩니다. 캐시가 만료되면 백그라운드 작업이 투명하게 이를 새로고침합니다. 캐시 키는 사이트/서버별로 설정되므로 멀티 사이트 설치 환경에서는 격리됩니다.

Test connection을 클릭하여 수동으로 새로고침을 트리거할 수도 있습니다 — 이는 항상 실시간 데이터를 가져옵니다.

서버의 건강 상태(healthy / error)는 모든 캐시 새로고침 시 업데이트됩니다.


AI 에이전트에 MCP 서버 할당

서버가 등록되면 에이전트에 할당합니다:

  1. Admin → Plugins → Discourse AI → Agents로 이동하여 에이전트를 편집하거나 생성합니다
  2. MCP servers 섹션(일반적인 Tools 섹션 아래)으로 스크롤합니다
  3. 목록에는 활성화된 모든 MCP 서버와 도구 수 및 예상 토큰 비용이 표시됩니다
  4. 서버를 켜면 — 이제 해당 에이전트에서 사용할 수 있게 됩니다

팁: 기본적으로 서버의 모든 도구가 에이전트에 제공됩니다. 로케일 문자열이 잘 설명하고 있습니다: “선택된 MCP 서버는 기본적으로 모든 도구를 노출합니다. 토큰 사용량을 줄이고 도구 선택에 집중하려면 에이전트별로 범위를 좁히십시오.”


에이전트별 특정 도구 선택

사용 가능한 도구가 수십 개에 달하면 모든 메시지의 토큰 비용이 증가합니다(각 도구 정의는 시스템 프롬프트에서 모델에 전송됨). 이를 간결하게 유지하기 위해:

  1. 에이전트 에디터에서 할당된 MCP 서버 옆의 Choose tools를 클릭합니다
  2. 모달이 서버가 현재 노출하는 모든 도구와 그 설명 및 매개변수 목록을 표시합니다
  3. 이 에이전트가 필요한 도구만 선택합니다
  4. Save를 클릭합니다 — 이제 에이전트는 선택된 부분 집합만 볼 수 있습니다

ai_agent_mcp_servers 조인 테이블은 selected_tool_names를 JSONB 배열로 저장합니다. 빈 배열은 "모든 도구 활성화"를 의미합니다.


도구 명명 및 충돌 해결

MCP 도구 이름은 단일 에이전트의 도구 목록(에이전트의 내장 및 커스텀 스크립트 도구 포함) 내에서 고유해야 합니다. Discourse는 충돌을 자동으로 처리합니다:

  • 두 개의 다른 MCP 서버가 같은 이름의 도구를 노출하는 경우, Discourse는 네임스페이스를 지정합니다: servername__toolname
  • 내장 Discourse 도구와 MCP 도구가 이름을 공유하는 경우, MCP 도구도 네임스페이스가 지정됩니다
  • 네임스페이스 지정 후에도 충돌이 있으면 숫자 접미사가 추가됩니다 (_2, _3, …)

따라서 LLM 호출에 사용되는 function_name은 MCP 서버의 원본 tool_name과 다를 수 있습니다. 이는 투명하게 처리됩니다 — MCP 도구 클래스는 항상 원본 tool_name_value를 별도로 저장하고 서버 호출 시 이를 사용합니다.


런타임 도구 호출 작동 방식

LLM이 MCP 도구를 사용하기로 결정하면:

  1. 세션 재사용: Discourse는 현재 봇 컨텍스트(context.mcp_state)에서 이 서버에 대한 캐시된 MCP 세션 ID를 조회합니다. 세션은 봇 응답 체인별로 생성되며 동일한 서버에 대한 도구 호출 간에 재사용됩니다.
  2. 필요 시 초기화: 세션이 없으면 새로운 initialize + notifications/initialized 핸드셰이크가 실행됩니다.
  3. 호출: { method: "tools/call", params: { name: tool_name, arguments: params } }와 함께 POST /
  4. 세션 만료: 서버가 404(만료된 세션)를 반환하면, Discourse는 자동으로 재초기화하고 한 번 재시도합니다.
  5. 응답 정규화: text 유형의 MCP 콘텐츠 항목은 연결됩니다. 텍스트가 아닌 항목은 JSON 직렬화됩니다. structuredContent는 예쁘게 포맷된 JSON입니다.
  6. 오류 결과: 서버가 isError: true를 반환하면, 봇은 결과 대신 오류 메시지를 수신합니다.

서버 응답은 일반 JSON 또는 SSE 스트림일 수 있으며 — Discourse는 둘 다 처리합니다.


토큰 비용 표시

에이전트 에디터에서 각 할당된 MCP 서버는 예상 토큰 수를 표시합니다. 이는 각 도구의 전체 JSON 시그니처(이름 + 설명 + 입력 스키마)에 적용된 OpenAI cl100k_base 토크나이저를 사용하여 계산됩니다. 이는 근사치이며, 실제 비용은 LLM의 토크나이저에 따라 달라집니다.

특정 에이전트에 어떤 서버와 도구를 할당할지 정보에 입각한 결정을 내릴 수 있도록 토큰 비용 세부 사항이 표시됩니다.


문제 해결

증상 확인 사항
Test connection이 타임아웃으로 실패 **Timeout (seconds)**를 증가시킵니다. 기본값은 30초입니다. 서버 초기화가 느리면 60~120초를 시도해 보세요.
테스트는 성공하지만 에이전트에 도구가 표시되지 않음 서버가 Enabled 상태인지, 그리고 에이전트의 MCP servers 섹션에서 해당 서버가 켜져 있는지 확인합니다.
OAuth 상태가 "Needs attention"으로 표시 마지막 OAuth 오류가 에디터 폼에 표시됩니다. 일반적인 원인: 리프레시 토큰 만료 (Reconnect 클릭), 서버가 예상하지 못한 스코프를 반환, 또는 클라이언트 메타데이터 URL이 서버에서 접근 불가능.
도구 이름이 myserver__sometool처럼 보임 정상 — 다른 도구(내장 또는 다른 서버에서)가 같은 이름을 가졌습니다. LLM은 이 네임스페이스 지정된 이름을 자동으로 보고 사용합니다.
일정 기간 후 Health가 "error"로 표시 백그라운드 새로고침 작업이 서버에 도달하지 못했습니다. 사이트의 /logs를 확인하고 MCP 서버가 Discourse 호스트에서 도달 가능한지 검증합니다.
대화 도중 도구가 작동 중단 세션 만료. Discourse는 도구 호출당 자동으로 한 번 재시도하지만, 서버가 지속적으로 재시작되고 있다면 세션 TTL을 짧게 하거나 서버 측 로그를 조사해 보세요.

더 깊은 디버깅을 위해 ai_bot_debugging_allowed_groups를 통해 AI 트랜스크립트 접근을 활성화하고 전체 대화 로그를 검사하십시오.


기술 참고 사항

MCP 프로토콜 세부 사항

속성
프로토콜 버전 2025-03-26
전송 HTTP POST (JSON-RPC 2.0)
SSE 지원 예 (tools/call 응답 스트리밍을 위해)
세션 관리 Mcp-Session-Id HTTP 헤더
최대 응답 바디 5 MB
클라이언트 User-Agent Discourse AI MCP Client / <version>

JSON 스키마 지원

Discourse는 LLM에 전달하기 전에 도구 inputSchema 정의에서 다음 JSON 스키마 구성 요소를 해석합니다:

  • $ref — 루트 스키마의 $defs / definitions에 대해 해석됨
  • allOf — 병합됨 (properties 및 required 배열은 유니온 병합됨)
  • anyOf / oneOf — 첫 번째 비-null 변형이 사용됨

관련 소스 파일


관련 주제

:bulb: Discourse-as-MCP-server 기능(discourse/discourse-mcp)은 이 기능의 보완재입니다: 외부 AI 클라이언트(Claude Code, Cursor 등)가 Discourse 사이트를 읽고 쓸 수 있게 합니다. 이 가이드는 그 반대입니다 — Discourse AI 에이전트가 외부 MCP 서버를 호출할 수 있게 합니다.

3개의 좋아요