본문으로 건너뛰기

MCP 연동

검색·조회 기능을 MCP(Model Context Protocol) 툴로 노출해, Claude Desktop 같은 MCP 클라이언트나 LibreChat 같은 챗 서비스가 rag-api의 KB를 직접 조회하게 한다.

mcp:
enabled: true
transport: streamable-http # stdio | sse | streamable-http

전송 방식

transport에 따라 MCP 서버가 실행되는 위치 자체가 달라진다.

transport실행 위치
streamable-http / sserag-api serve(메인 FastAPI 앱)에 /mcp 경로로 자동 마운트된다. 별도 프로세스가 필요 없다
stdiorag-api serve에는 마운트되지 않는다. rag-api serve-mcp --transport stdio로 별도 프로세스를 띄워야 하며, MCP 클라이언트가 이 커맨드를 subprocess로 직접 실행하는 방식이 일반적이다

HTTP 서버에 내장 (streamable-http / sse)

mcp.enabled: true이고 transportstreamable-http 또는 sserag-api serve가 기동될 때 MCP 서버가 같은 프로세스·같은 포트에 /mcp 경로로 자동 마운트된다.

rag-api serve --port 8000

Streamable HTTP는 세션 기반이다 — initialize 호출로 세션을 먼저 열고, 응답 헤더의 mcp-session-id를 이후 모든 요청에 그대로 실어 보내야 한다.

# 1단계 — 세션 초기화
SESSION=$(curl -sD - -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "test", "version": "1.0"}
}
}' | grep -i mcp-session-id | awk '{print $2}' | tr -d '\r')

# 2단계 — 툴 목록 조회
curl -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "mcp-session-id: $SESSION" \
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}'

응답 본문은 SSE로 프레이밍되어 온다(event: message 줄 다음에 data: {...} 줄). 결과를 그대로 jq에 넘기면 event: message 줄에서 파싱 에러가 나므로, data: 줄만 뽑아 접두어를 제거한 뒤 전달해야 한다.

curl -s -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "mcp-session-id: $SESSION" \
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}' \
| sed -n 's/^data: //p' | jq

Claude Desktop처럼 HTTP 전송을 직접 지원하는 클라이언트는 command 대신 서버 URL만 설정하면 된다 — 세션 초기화는 클라이언트가 알아서 처리한다.

{
"mcpServers": {
"rag-api": {
"type": "http",
"url": "http://localhost:8000/mcp"
}
}
}

이 경우 mcp.host/mcp.port 설정은 쓰이지 않는다 — 서버 자체의 host/port(rag-api serve --host/--port, 기본 0.0.0.0:8000)를 그대로 쓴다. mcp.host/mcp.port는 아래처럼 serve-mcp를 독립 HTTP 프로세스로 띄울 때만 적용된다.

독립 프로세스로 실행 (stdio)

로컬 MCP 클라이언트(Claude Desktop 등)는 보통 서버를 subprocess로 직접 실행하고 표준 입출력으로 통신한다. --transport/--port 플래그는 settings.yamlmcp 섹션 값을 그때만 덮어쓴다.

rag-api serve-mcp --transport stdio
{
"mcpServers": {
"rag-api": {
"command": "rag-api",
"args": ["serve-mcp", "--transport", "stdio"]
}
}
}

stdio 모드는 표준입출력을 프로토콜이 그대로 점유하므로 포트 개념이 없다 — mcp.host/ mcp.port는 이 모드에서 의미가 없다. mcp.enabled: falseserve-mcp는 전송 방식과 무관하게 즉시 종료된다.

제공 Tool

list_knowledge_basessearch 순서로 호출하는 것이 기본 사용 흐름이다 — 서버가 MCP instructions로 클라이언트에 이 순서를 안내한다. 세 tool 모두 OpenTelemetry 스팬으로 자동 추적된다.

질의어로 KB를 검색해 관련 청크를 반환한다.

파라미터필수 여부설명
query필수검색어
kb_ids선택검색 대상 KB 목록. 생략하면 접근 가능한 전체 KB를 대상으로 한다
top_k선택반환할 최대 결과 수. 기본값은 retrieval.top_k
mode선택hybrid(키워드+의미 검색, 특정 용어에 유리) 또는 similarity(의미 검색 전용, 개념적 질의에 유리). 기본값은 retrieval.mode
min_score선택최소 유사도 점수(0.0~1.0). similarity 모드에서만 적용되며, 기본값은 retrieval.similarity.min_score

응답은 청크별 text/score/rerank_score/kb_id/source/page_num/page_label/ chunk_idx와 전체 latency_ms를 담은 결과 목록이다.

list_knowledge_bases

파라미터 없이 호출하며, 접근 가능한 모든 KB의 id/name/description/tags를 반환한다. search에 넘길 kb_ids를 알아내기 위한 첫 호출로 쓰인다.

get_document_status

문서 하나의 인덱싱 상태를 조회한다.

파라미터필수 여부설명
kb_id필수문서가 속한 KB
doc_id필수문서 ID

status는 문서가 없거나 kb_id가 일치하지 않으면 not_found를 반환하고, 그 외에는 문서의 실제 상태값을 그대로 반환한다 — 상태값의 의미와 전이 규칙은 문서 상태 흐름 참고. 함께 updated_at/ file_size/content_version도 반환한다.


Enterprise 배포에서는 REST·검색과 동일한 OIDC 인증 + KB 단위 역할(RBAC)이 MCP 호출 경로에도 그대로 적용된다 — search는 호출자가 접근 가능한 KB로 자동 필터링되고, list_knowledge_bases/get_document_status도 같은 권한 판단을 거친다. rag-api 단독 배포에는 이 인증 계층이 없다 — MCP 엔드포인트에 도달할 수 있는 클라이언트는 모든 KB의 모든 tool을 제한 없이 호출할 수 있다는 뜻이므로, 네트워크 경계에서 접근을 통제해야 한다. 자세한 흐름은 접근 제어 참고.