본문 바로가기
WIKI 기술 지식 베이스

Connecting to an external MCP server

원문 보기 위키 갱신

출처: 문서

본문

외부 MCP 서버에 연결하기

3.0에 도입됨 {: .label .label-purple }

OpenSearch는 에이전트를 사용하는 에이전틱 워크플로를 지원해요. OpenSearch가 복잡한 쿼리를 실행하기 위한 내장 도구를 제공하는 반면, Model Context Protocol (MCP)는 외부 도구 및 데이터 소스와의 통합을 가능하게 해요. MCP는 AI 모델이 외부 데이터 소스와 도구에 연결하는 표준화된 방법을 제공하는 개방형 프로토콜 표준으로, 원격 MCP 서버 도구를 위한 "범용 어댑터" 역할을 해요.

OpenSearch는 Server-Sent Events (SSE) 프로토콜 또는 Streamable HTTP 프로토콜을 사용하는 MCP 서버를 지원해요. 표준 입력/출력(stdio) 프로토콜은 지원하지 않아요. {: .note}

다음 예제는 에이전틱 워크플로에서 MCP 도구를 사용하는 방법을 보여 줘요.

사전 준비

MCP 도구를 사용하기 전에 다음 사전 준비 작업을 완료해야 해요.

MCP 활성화 및 신뢰할 수 있는 커넥터 엔드포인트 구성

  • plugins.ml_commons.mcp_connector_enabled 설정을 구성해서 MCP 프로토콜을 활성화해요.
  • plugins.ml_commons.trusted_connector_endpoints_regex 설정에서 신뢰할 수 있는 커넥터 엔드포인트를 구성해요. 보안을 위해 이 설정은 regex 패턴을 사용해 어떤 MCP 서버 URL이 허용되는지 정의해요.

두 설정을 모두 구성하려면 다음 요청을 보내세요:

PUT /_cluster/settings/
{
  "persistent": {
    "plugins.ml_commons.trusted_connector_endpoints_regex": [
      "<mcp server url>"
    ],
    "plugins.ml_commons.mcp_connector_enabled": "true"
  }
}

{% include copy-curl.html %}

MCP 서버 준비

OpenSearch 클러스터에서 접근할 수 있는, 실행 중인 MCP 서버가 있는지 확인하세요.

1단계: MCP 커넥터 생성

MCP 커넥터는 MCP 서버의 연결 정보와 자격 증명을 저장해요. SSE 또는 Streamable HTTP 중 하나를 사용해서 연결할 수 있어요.

SSE를 사용해서 MCP 커넥터를 생성하려면 다음 요청을 보내세요:

POST /_plugins/_ml/connectors/_create
{
  "name":        "My MCP Connector",
  "description": "Connects to the external MCP server for weather tools",
  "version":     1,
  "protocol":    "mcp_sse",
  "url":         "https://my-mcp-server.domain.com",
  "credential": {
    "mcp_server_key": "THE_MCP_SERVER_API_KEY"
  },
  "parameters":{
    "sse_endpoint": "/sse" 
  },
  "headers": {
    "Authorization": "Bearer ${credential.mcp_server_key}"
  }
}

{% include copy-curl.html %}

Streamable HTTP를 사용해서 MCP 커넥터를 생성하려면 protocol을 mcp_streamable_http로 설정해요. 필요에 따라 parameters.endpoint를 설정해서 기본 엔드포인트(/_plugins/_ml/mcp)를 재정의할 수 있어요. SSE 전용 엔드포인트는 필요하지 않아요:

POST /_plugins/_ml/connectors/_create
{
  "name":        "My MCP Connector (Streamable HTTP)",
  "description": "Connects to the external MCP server using Streamable HTTP",
  "version":     1,
  "protocol":    "mcp_streamable_http",
  "url":         "https://my-mcp-server.domain.com",
  "credential": {
    "mcp_server_key": "THE_MCP_SERVER_API_KEY"
  },
  "parameters": {
    "endpoint": "/_plugins/_ml/mcp"
  },
  "headers": {
    "Authorization": "Bearer ${credential.mcp_server_key}"
  }
}

{% include copy-curl.html %}

다음 표는 커넥터 파라미터를 설명해요. 표준 커넥터 파라미터에 대한 자세한 내용은 요청 본문 필드를 참고하세요.

파라미터 데이터 타입 필수 여부 설명
protocol String 예 SSE에는 mcp_sse를, Streamable HTTP에는 mcp_streamable_http를 지정해요.
url String 예 기본 포트를 사용하지 않는 경우 프로토콜, 호스트명, 포트를 포함한 MCP 서버의 전체 base URL이에요(예: https://my-mcp-server.com:8443).
credential Object 예 API 키나 토큰 같은 민감한 인증 정보를 담고 있어요. 이 객체에 저장된 값은 ${credential.*} 문법을 사용해서 headers 섹션에서 안전하게 참조할 수 있어요.
parameters Object 아니요 MCP 커넥터의 구성 파라미터를 담고 있어요.
parameters.sse_endpoint String 아니요 SSE에만 적용돼요. MCP 서버의 SSE 엔드포인트 경로예요. 기본값은 /sse예요.
parameters.endpoint String 아니요 Streamable HTTP에만 적용돼요. MCP 서버의 엔드포인트 경로예요. 기본값은 /mcp예요.
headers Object 아니요 MCP 서버에 보내는 요청에 포함할 HTTP 헤더예요. 인증 헤더의 경우 ${credential.*} 문법을 사용해서 credential 객체의 값을 참조하세요(예: "Authorization": "Bearer ${credential.mcp_server_key}").

응답에는 커넥터 ID가 포함되어 있어요:

{
  "connector_id": "NZ2W2ZUBZ_3SyqdOvh2n",
}

2단계: 모델 등록

커넥터를 사용해서 외부에서 호스팅되는 대규모 언어 모델(LLM)을 등록하세요. 지원되는 모델 목록은 OpenSearch에서 제공하는 커넥터 블루프린트를 참고하세요.

예를 들어 OpenAI 채팅 모델을 등록하려면 다음 요청을 보내세요:

POST /_plugins/_ml/models/_register
{
  "name": "My OpenAI model: gpt-4o-mini",
  "function_name": "remote",
  "description": "Test model registration (this example uses OpenAI, but you can register any model)",
  "connector": {
    "name": "My OpenAI Connector: gpt-4o-mini",
    "description": "Connector for the OpenAI chat model",
    "version": 1,
    "protocol": "http",
    "parameters": {
      "model": "gpt-4o"
    },
    "credential": {
      "openAI_key": "<YOUR_API_KEY>"
    },
    "actions": [
      {
        "action_type": "predict",
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "headers": {
          "Authorization": "Bearer ${credential.openAI_key}"
        },
        "request_body": "{ \"model\": \"${parameters.model}\", \"messages\": [{\"role\":\"developer\",\"content\":\"${parameters.system_instruction}\"},${parameters._chat_history:-}{\"role\":\"user\",\"content\":\"${parameters.prompt}\"}${parameters._interactions:-}], \"tools\": [${parameters._tools:-}],\"parallel_tool_calls\":${parameters.parallel_tool_calls},\"tool_choice\": \"${parameters.tool_choice}\" }"
      }
    ]
  }
}

{% include copy-curl.html %}

응답에는 모델 ID가 포함되어 있어요:

{
  "task_id": "K_iQfpYBjoQOEoSHN3wU",
  "status": "CREATED",
  "model_id": "LPiQfpYBjoQOEoSHN3zH"
}

작업 상태를 확인하려면 task ID를 Get ML Task API에 전달하세요. 등록이 완료되면 task의 state가 COMPLETED로 바뀌어요.

3단계: MCP 도구에 접근하기 위한 에이전트 등록

다음 표는 MCP 도구를 지원하는 에이전트 타입을 보여 줘요.

에이전트 타입 MCP 통합 방식
conversational LLM이 런타임에 MCP 도구를 선택해요.
plan_execute_and_reflect LLM이 런타임에 MCP 도구를 선택해요.
flow MCP 도구가 고정된 파이프라인 순서로 실행돼요.
conversational_flow 대화 메모리와 함께 MCP 도구가 고정된 파이프라인 순서로 실행돼요.

지원되는 모든 에이전트 타입에 대해 parameters.mcp_connectors에 하나 이상의 MCP 커넥터를 포함하세요. tools 배열을 구성하는 방법은 에이전트 타입에 따라 달라져요.

각 커넥터는 parameters.mcp_connectors 배열에서 다음 파라미터를 반드시 지정해야 해요.

파라미터 데이터 타입 필수 여부 설명
mcp_connector_id String 예 MCP 커넥터의 커넥터 ID예요.
tool_filters Array 아니요 에이전트가 MCP 서버의 어떤 도구를 사용할 수 있게 할지 지정하는 Java 스타일 정규식 배열이에요. 배열의 정규식 중 하나 이상과 일치하면 해당 도구가 포함돼요. 생략하거나 빈 배열로 설정하면 커넥터가 노출하는 모든 도구를 사용할 수 있어요. 도구 이름을 정확하게 일치시키려면 ^ 또는 $ 앵커나 리터럴 문자열을 사용하세요. 예를 들어 ^get_forecast는 "get_forecast"로 시작하는 모든 도구와 일치하고, search_indices는 "search_indices"와만 일치해요.
tool_descriptions Array 아니요 LLM에 보내는 도구 설명을 재정의하는 객체 배열이에요. 각 객체는 도구 이름(키)을 대체 설명(문자열 값)에 매핑해요. tool_filters 평가를 통과한 도구만 재정의할 수 있어요. 도구가 커넥터에 존재하지 않거나, tool_filters에 의해 제외되었거나, 값이 비어 있거나 null이거나 문자열이 아닌 경우 해당 항목은 무시돼요. 같은 도구 이름이 여러 객체에 나타나면 마지막 값이 적용돼요.

conversational 및 plan_execute_and_reflect 에이전트의 경우, 구성된 커넥터에서 MCP 도구를 발견해서 LLM에 제공해요. LLM이 실행 중에 어떤 MCP 도구를 호출할지 결정해요. tools 배열에 MCP 도구를 명시적으로 나열할 필요는 없지만, MCP 도구와 함께 OpenSearch 내장 도구를 포함할 수는 있어요.

다음 예제는 1단계에서 생성한 커넥터 ID를 사용해서 conversational 에이전트를 등록해요. MCP 서버에는 두 개의 도구(get_alerts와 get_forecasts)가 있지만, 지정된 regex 패턴 ^get_alerts$와 일치하는 get_alerts 도구만 에이전트 구성에 포함돼요:

POST /_plugins/_ml/agents/_register
{
  "name":        "Weather & Search Bot",
  "type":        "conversational",
  "description": "Uses MCP to fetch forecasts and OpenSearch indices",
  "llm": {
    "model_id": "<MODEL_ID_FROM_STEP_2>",
    "parameters": {
      "max_iteration": 5,
      "system_instruction": "You are a helpful assistant.",
      "prompt": "${parameters.question}"
    }
  },
  "memory": {
    "type": "conversation_index"
  },
  "parameters": {
    "_llm_interface": "openai/v1/chat/completions",
    "mcp_connectors": [
      {
        "mcp_connector_id": "<MCP_CONNECTOR_ID_FROM_STEP_1>",
        "tool_filters": [
          "^get_alerts$"
        ]
      }
    ]
  },
  "tools": [
    { "type": "ListIndexTool" },
    { "type": "SearchIndexTool" }
  ],
  "app_type": "os_chat"
}

{% include copy-curl.html %}

응답에는 에이전트 ID가 포함되어 있어요:

{
  "agent_id": "LfiXfpYBjoQOEoSH93w7"
}

MCP 도구 설명 재정의

3.8에 도입됨 {: .label .label-purple }

각 MCP 도구에는 LLM이 언제 호출할지 판단하는 데 도움이 되는 설명이 포함되어 있어요. MCP 서버를 수정하지 않고 도구의 설명을 바꾸려면 tool_descriptions 파라미터를 사용하세요. 서버가 제공한 설명이 너무 일반적이거나, 내부 명명 규칙을 사용하거나, 에이전트의 도메인 용어와 맞지 않을 때 유용해요.

tool_descriptions의 각 항목은 하나의 키-값 쌍을 가진 JSON 객체여야 해요. 즉, MCP 도구 이름과 재정의 설명 문자열이에요. 배열에 여러 객체를 추가해서 여러 재정의를 지정할 수 있어요.

다음 예제는 get_alerts 도구만 노출하는(tool_filters 사용) 에이전트를 등록하고, 그 설명을 에이전트 전용 안내로 바꿔요:

POST /_plugins/_ml/agents/_register
{
  "name": "Weather & Search Bot",
  "type": "conversational",
  "description": "Uses MCP to fetch forecasts and OpenSearch indices",
  "llm": {
    "model_id": "<MODEL_ID_FROM_STEP_2>",
    "parameters": {
      "max_iteration": 5
    }
  },
  "memory": {
    "type": "conversation_index"
  },
  "parameters": {
    "_llm_interface": "openai/v1/chat/completions",
    "mcp_connectors": [
      {
        "mcp_connector_id": "<MCP_CONNECTOR_ID_FROM_STEP_1>",
        "tool_filters": [
          "^get_alerts$"
        ],
        "tool_descriptions": [
          {
            "get_alerts": "Fetch active weather alerts for a US state. Use when the user asks about warnings or advisories."
          }
        ]
      }
    ]
  },
  "tools": [
    { "type": "ListIndexTool" }
  ],
  "app_type": "os_chat"
}

{% include copy-curl.html %}

tool_filters를 적용하지 않고 여러 도구의 설명을 재정의하려면 tool_filters 파라미터를 생략하거나 빈 배열로 설정해서 커넥터의 모든 도구를 계속 사용할 수 있게 하세요:

"mcp_connectors": [
  {
    "mcp_connector_id": "<MCP_CONNECTOR_ID_FROM_STEP_1>",
    "tool_descriptions": [
      { "get_alerts": "Fetch active weather alerts for a US state." },
      { "get_forecast": "Fetch a multi-day weather forecast for a city." }
    ]
  }
]

커넥터가 노출하지 않는 도구 이름이나 tool_filters가 제외하는 도구에 대한 재정의는 효과가 없어요. 유효한 재정의가 없는 도구에는 에이전트가 계속 MCP 서버의 원래 설명을 사용해요.

Flow 에이전트와 conversational flow 에이전트

3.8에 도입됨 {: .label .label-purple }

flow 및 conversational_flow 에이전트의 경우, MCP 도구는 tools 배열에 정의된 고정된 순서로 실행돼요. 각 MCP 도구를 명시적으로 선언해야 하고, 도구의 type을 커넥터 프로토콜에 맞춰야 해요.

커넥터 프로토콜 MCP 도구 type
mcp_streamable_http McpStreamableHttpTool
mcp_sse McpSseTool

tools 배열의 각 MCP 도구 항목은 다음 필드를 지원해요.

필드 데이터 타입 필수 여부 설명
name String 예 MCP 서버의 도구 이름이에요. 구성된 커넥터가 노출하는 도구와 일치해야 해요. 출력 체이닝에 사용돼요(예: ${parameters.get_simple_price.output}).
type String 예 커넥터 프로토콜에 맞는 McpStreamableHttpTool 또는 McpSseTool이에요.
description String 아니요 도구에 대한 설명이에요. 생략하면 사용 가능한 경우 OpenSearch가 MCP 서버의 설명을 사용해요.
parameters.input String 예 도구 입력 페이로드예요. 보통 MCP 서버 도구에 전달되는 JSON 문자열이에요.

같은 파이프라인에서 MCP 도구를 MLModelTool 같은 OpenSearch 도구와 함께 사용할 수 있어요. 한 단계의 출력은 ${parameters.<tool_name>.output}를 사용해서 다음 단계로 전달할 수 있어요.

MCP 도구가 tools에 나열되어 있지만 구성된 커넥터에서 사용할 수 없는 경우, 도구를 사용할 수 없다는 오류와 함께 에이전트 실행이 실패해요. 여러 MCP 커넥터가 같은 이름의 도구를 노출하는 경우, OpenSearch는 mcp_connectors 배열에서 일치하는 첫 번째 커넥터의 도구를 사용해요.

flow 또는 conversational flow 에이전트를 등록하기 전에, List Connector MCP Tools API를 사용해서 MCP 커넥터에서 도구 이름, 타입, 설명, 입력 스키마를 확인하세요. 에이전트에서 MCP 도구를 구성할 때 응답의 name과 type 값을 사용하고, 각 도구의 input_schema로 parameters.input JSON 문자열을 만드세요.

다음 예제는 search_documents와 get_weather를 순서대로 호출한 다음 MLModelTool로 결과를 요약하는 flow 에이전트를 등록해요:

POST /_plugins/_ml/agents/_register
{
  "name": "Research and weather flow agent",
  "type": "flow",
  "description": "Flow agent using MCP tools in a fixed order",
  "parameters": {
    "mcp_connectors": [
      {
        "mcp_connector_id": "<MCP_CONNECTOR_ID_FROM_STEP_1>"
      }
    ]
  },
  "tools": [
    {
      "name": "search_documents",
      "type": "McpStreamableHttpTool",
      "description": "Search a document repository for relevant content.",
      "parameters": {
        "input": "{\"query\":\"OpenSearch agentic search\",\"limit\":5}"
      }
    },
    {
      "name": "get_weather",
      "type": "McpStreamableHttpTool",
      "description": "Retrieve current weather conditions for a specified location.",
      "parameters": {
        "input": "{\"location\":\"Seattle\",\"units\":\"celsius\"}"
      }
    },
    {
      "name": "summarize_results",
      "type": "MLModelTool",
      "description": "Summarize MCP tool outputs",
      "parameters": {
        "model_id": "<MODEL_ID_FROM_STEP_2>",
        "prompt": "You are a research assistant.\n\nDocument search results:\n${parameters.search_documents.output}\n\nWeather:\n${parameters.get_weather.output}\n\nProvide a brief summary of the findings."
      }
    }
  ]
}

{% include copy-curl.html %}

대화 메모리와 함께 같은 MCP 파이프라인을 사용하려면 type을 conversational_flow로 설정하고 parameters 및 tools와 같은 수준에 memory 블록을 추가하세요:

POST /_plugins/_ml/agents/_register
{
  "name": "Research and weather conversational flow agent",
  "type": "conversational_flow",
  "description": "Conversational flow agent using MCP tools in a fixed order",
  "memory": {
    "type": "conversation_index"
  },
  "parameters": {
    "mcp_connectors": [
      {
        "mcp_connector_id": "<MCP_CONNECTOR_ID_FROM_STEP_1>"
      }
    ]
  },
  "tools": [
    {
      "name": "search_documents",
      "type": "McpStreamableHttpTool",
      "description": "Search a document repository for relevant content.",
      "parameters": {
        "input": "{\"query\":\"OpenSearch agentic search\",\"limit\":5}"
      }
    },
    {
      "name": "get_weather",
      "type": "McpStreamableHttpTool",
      "description": "Retrieve current weather conditions for a specified location.",
      "parameters": {
        "input": "{\"location\":\"Seattle\",\"units\":\"celsius\"}"
      }
    },
    {
      "name": "summarize_results",
      "type": "MLModelTool",
      "description": "Summarize MCP tool outputs",
      "parameters": {
        "model_id": "<MODEL_ID_FROM_STEP_2>",
        "prompt": "You are a research assistant.\n\nDocument search results:\n${parameters.search_documents.output}\n\nWeather:\n${parameters.get_weather.output}\n\nProvide a brief summary of the findings."
      }
    }
  ]
}

{% include copy-curl.html %}

4단계: 에이전트 실행

Execute Agent API를 호출하고 사용자 질문을 제공해서 등록된 에이전트를 실행해요:

POST /_plugins/_ml/agents/{Agent_ID}/_execute
{
  "parameters": {
    "question": "Any weather alerts in Washington",
    "verbose": true
  }
}

{% include copy-curl.html %}

에이전트는 tools 배열에 지정된 OpenSearch 도구와 MCP 서버에서 선택된 도구(도구 필터 기준)를 모두 사용해서 답변을 반환해요:

{
    "inference_results": [
        {
            "output": [
                {
                    "name": "memory_id",
                    "result": "MfiZfpYBjoQOEoSH13wj"
                },
                {
                    "name": "parent_interaction_id",
                    "result": "MviZfpYBjoQOEoSH13xC"
                },
                {
                    "name": "response",
                    "result": "{\"id\":\"chatcmpl-BRRcdxVjkrKG7HjkVWZVwueJSEjgd\",\"object\":\"chat.completion\",\"created\":1.745880735E9,\"model\":\"gpt-4o-2024-08-06\",\"choices\":[{\"index\":0.0,\"message\":{\"role\":\"assistant\",\"tool_calls\":[{\"id\":\"call_yWg0wk4mfE2v8ARebupfbJ87\",\"type\":\"function\",\"function\":{\"name\":\"get_alerts\",\"arguments\":\"{\\\"state\\\":\\\"WA\\\"}\"}}],\"annotations\":[]},\"finish_reason\":\"tool_calls\"}],\"usage\":{\"prompt_tokens\":201.0,\"completion_tokens\":16.0,\"total_tokens\":217.0,\"prompt_tokens_details\":{\"cached_tokens\":0.0,\"audio_tokens\":0.0},\"completion_tokens_details\":{\"reasoning_tokens\":0.0,\"audio_tokens\":0.0,\"accepted_prediction_tokens\":0.0,\"rejected_prediction_tokens\":0.0}},\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f5bdcc3276\"}"
                },
                {
                    "name": "response",
                    "result": "[{\"text\":\"\\nEvent: Wind Advisory\\nArea: Kittitas Valley\\nSeverity: Moderate\\nDescription: * WHAT...Northwest winds 25 to 35 mph with gusts up to 45 mph\\nexpected.\\n\\n* WHERE...Kittitas Valley.\\n\\n* WHEN...From 2 PM to 8 PM PDT Tuesday.\\n\\n* IMPACTS...Gusty winds will blow around unsecured objects. Tree\\nlimbs could be blown down and a few power outages may result.\\nInstructions: Winds this strong can make driving difficult, especially for high\\nprofile vehicles. Use extra caution.\\n\"}]"
                },
                {
                    "name": "response",
                    "result": "There is a Wind Advisory for the Kittitas Valley in Washington. Here are the details:\n\n- **Event:** Wind Advisory\n- **Area:** Kittitas Valley\n- **Severity:** Moderate\n- **Description:** Northwest winds 25 to 35 mph with gusts up to 45 mph expected.\n- **When:** From 2 PM to 8 PM PDT Tuesday.\n- **Impacts:** Gusty winds may blow around unsecured objects, potentially causing tree limbs to fall, and resulting in a few power outages.\n\n**Instructions:** These strong winds can make driving difficult, especially for high-profile vehicles. Use extra caution if you are traveling in the area."
                }
            ]
        }
    ]
}

추가 리소스

  • MCP 프로토콜에 대한 자세한 내용은 MCP 프로토콜 문서를 참고하세요.
  • Java에서 MCP를 사용하는 방법에 대한 내용은 MCP Java SDK를 참고하세요.

더 알아보기 (Learn more)