# MCP 도구로 노출 설정하기

### 1. 워크플로우 상세 페이지 진입

* 에이전트 > 워크플로우 메뉴에서 MCP 도구로 노출할 워크플로우의 상세 페이지로 이동합니다.

<figure><img src="/files/UboOHQhOVmhkweXd1G4C" alt=""><figcaption></figcaption></figure>

***

### 2. MCP 도구 탭 진입

* 상세 페이지에서 **"MCP 도구"** 탭을 클릭합니다.
* 처음에는 토글이 꺼져 있고, 아래와 같은 화면이 표시됩니다.

<figure><img src="/files/tf30QtBKVBdvEVCo4yhY" alt=""><figcaption></figcaption></figure>

***

### 3. MCP 도구 노출 활성화

* **"MCP 도구로 노출"** 토글을 켭니다. 토글을 켜면 추가 설정 필드가 나타납니다.

<figure><img src="/files/ogOP1WrWREJM6B5tKHCB" alt=""><figcaption></figcaption></figure>

#### 설정 항목

<table><thead><tr><th width="162.33984375">필드</th><th width="459.5">설명</th><th width="121.0703125">필수</th></tr></thead><tbody><tr><td><strong>도구 이름</strong></td><td><p>다른 에이전트에서 이 도구를 호출할 때 사용하는 이름. </p><p>비워두면 워크플로우 이름이 사용됩니다.</p></td><td>선택</td></tr><tr><td><strong>도구 설명</strong></td><td><p>다른 에이전트가 이 도구를 선택할 때 참고하는 설명입니다. </p><p>도구의 기능을 명확하게 작성하세요.</p></td><td>선택</td></tr><tr><td><strong>입력 스키마 (JSON)</strong></td><td><p>도구가 받을 수 있는 입력 파라미터의 JSON Schema입니다. </p><p>기본값은 <code>question</code> 파라미터만 포함합니다.</p></td><td>선택</td></tr></tbody></table>

***

### 4. 설정 입력 및 저장

* 도구 이름, 설명, 입력 스키마를 입력한 후 **"저장"** 버튼을 클릭합니다
  * 도구 이름 미입력 시 기본값(기본 워크플로우)으로 입력됩니다.
  * 'MCP 도구' 탭의 설정 수정 후 저장 시 \*\*'워크플로우' 읽기/쓰기\*\*와 \*\*'MCP 서버' 읽기/쓰기\*\* 권한이 필요합니다.&#x20;

<figure><img src="/files/7lMZ6q3CLIepnNjpvo1m" alt=""><figcaption></figcaption></figure>

* 확인 다이얼로그에서 \*\*"확인"\*\*을 클릭하면 저장됩니다

  <figure><img src="/files/42MT8esBGW0ssXqdLCbI" alt=""><figcaption></figcaption></figure>

> **참고**: 저장만으로는 MCP 서버가 즉시 생성되지 않습니다. 워크플로우를 \*\*배포(Deploy)\*\*할 때 MCP 서버가 자동으로 생성됩니다.

***

### 5. 워크플로우 배포 시 동작

* MCP 도구 노출이 활성화된 상태에서 워크플로우를 배포하면:

&#x20;      **1) MCP 서버 자동 생성** — `server_type=WORKFLOW`인 MCP 서버가 자동으로 생성됩니다

&#x20;      **2) MCP 도구 등록** — 설정한 이름/설명/입력 스키마로 도구가 등록됩니다

&#x20;      **3) 배포 레코드** — MCP 서버 배포 상태가 Online으로 표시됩니다

* 워크플로우를 **중지**하면 MCP 서버 배포가 자동으로 비활성화(Offline)됩니다.

***

### 6. MCP 서버 목록에서 확인

* 도구 > MCP 서버 메뉴에서 자동 생성된 "워크플로우 기반" 타입 MCP 서버를 확인할 수 있습니다

<figure><img src="/files/k3toYulV4ylZsGN2rIk2" alt=""><figcaption></figcaption></figure>

* **타입** 컬럼에 "워크플로우 기반"로 표시됩니다
* "워크플로우 기반" 타입 MCP 서버는 직접 배포/중지할 수 없습니다 (워크플로우 배포/중지에 연동)

***

### 7. MCP 서버 상세에서 도구 확인

* MCP 서버 상세 페이지에서 자동 생성된 서버의 정보를 확인할 수 있습니다.

#### 기본 정보 탭

* 워크플로우 타입으로 생성된 MCP 서버의 기본 정보를 확인합니다

<figure><img src="/files/DPwm0ETkF0UDUuEm2beq" alt=""><figcaption></figcaption></figure>

* 도구는 워크플로우 배포 시 자동 생성되며, 설정 변경 후 재배포하면 갱신됩니다

***

### 8. 배포 후 MCP 탭 확인

* 워크플로우 배포 후 MCP 도구 탭에서 연결된 MCP Server ID가 표시됩니다.&#x20;

<figure><img src="/files/ucR6a1bHfnqEGMXkHwFx" alt=""><figcaption></figcaption></figure>

***

### 9. 다른 워크플로우에서 호출 (마스터/서브에이전트 패턴)

* MCP 도구로 노출된 워크플로우는 다른 워크플로우에서 호출할 수 있습니다. 이를 통해 **마스터 에이전트 → 서브에이전트 MCP** 멀티에이전트 구조를 구성할 수 있습니다.

#### 아키텍처 개요

```
사용자 요청
  ↓
마스터 에이전트 (워크플로우 A, Python 단계)
  ↓ admin-api MCP tools/list  → 사용 가능한 도구 확인
  ↓ admin-api MCP tools/call  → 서브에이전트 호출
  ↓
서브에이전트 MCP (WORKFLOW 타입, 배포 시 자동 생성)
  ↓ 내부적으로 /run/v2 호출로 변환
  ↓
서브에이전트 (워크플로우 B, Python 단계)
  ↓ 비즈니스 로직 처리
  ↓
응답 반환 → 마스터 에이전트 종합 → 최종 응답
```

***

#### 9-1. 서브에이전트 구현 (Python 단계)

* 워크플로우에 **Python 단계 추가** 버튼으로 서브에이전트를 구현합니다.
* 아래는 잔액 조회 서브에이전트 예시입니다:

```
async def run(data):
    """잔액조회 서브에이전트: 모의 데이터 기반 잔액 응답"""
    question = data.get("question", "")

    accounts = {
        "입출금": {"number": "110-***-1234", "balance": 1234500},
        "적금": {"number": "230-***-5678", "balance": 5000000},
        "CMA": {"number": "350-***-9012", "balance": 2300000},
    }

    total = sum(a["balance"] for a in accounts.values())

    lines = []
    for name, info in accounts.items():
        lines.append("  - {} ({}): {:,}원".format(name, info["number"], info["balance"]))

    response = "잔액 조회 결과입니다.\n\n" + "\n".join(lines)
    response += "\n\n총 잔액: {:,}원".format(total)

    return {
        "question": question,
        "text": response,
        "json": {
            "accounts": [
                {"name": k, "account": v["number"], "balance": v["balance"]}
                for k, v in accounts.items()
            ],
            "total_balance": total
        }
    }
```

> **참고**: `run(data)` 함수를 정의하면 워크플로우 엔진이 자동으로 실행합니다. `data`에는 `question` 등 요청 데이터가 전달됩니다.

**서브에이전트 워크플로우 상세 — 배포 및 테스트 버튼 활성화**

<figure><img src="/files/Mob3Nr1BWkQz5tbzCSgO" alt=""><figcaption></figcaption></figure>

**서브에이전트 테스트 — 입력 JSON 작성**

<figure><img src="/files/A88G09hIOkRsMEF5mJ34" alt=""><figcaption></figcaption></figure>

**서브에이전트 테스트 결과 — 잔액 조회 응답**

<figure><img src="/files/qXECrOdCtwnjX7xsggZx" alt=""><figcaption></figcaption></figure>

***

#### 9-2. MCP 도구 노출 설정 및 배포

* 서브에이전트 워크플로우를 생성하고 Python 단계를 추가한 후:

&#x20;     1\) 워크플로우 상세 > **MCP 도구** 탭에서 토글을 켜고 설정을 입력합니다

&#x20;     2\) 워크플로우를 **배포(Deploy)** 합니다

&#x20;     3\) WORKFLOW 타입 MCP 서버가 자동으로 생성됩니다

**서브에이전트 MCP 도구 설정 화면**

<figure><img src="/files/3W3II2QYiUb8e3yWPaUY" alt=""><figcaption></figcaption></figure>

**배포 후 MCP 서버 목록에 자동 생성된 WORKFLOW 타입 서버**

<figure><img src="/files/qwaczFhS11nMBnduFtWW" alt=""><figcaption></figcaption></figure>

**MCP 서버 상세 > 기본 정보**

<figure><img src="/files/OWOGc9Gcedi2wDEc5hbQ" alt=""><figcaption></figcaption></figure>

**MCP 서버 상세 > 중요 정보 탭에서 등록된 도구 확인**

<figure><img src="/files/juMMb2ItNV86eTNDxRCJ" alt=""><figcaption></figcaption></figure>

***

#### 9-3. 마스터 에이전트 구현 (Python 단계)

* 마스터 에이전트도 별도 워크플로우에 **Python 단계**로 구현합니다. admin-api의 MCP REST API를 호출하여 서브에이전트와 통신합니다.
* 통합 API(`GET /mcp/server/workflow/tools`)를 사용하면 **배포 중인 모든 WORKFLOW MCP 도구를 한 번의 호출**로 조회할 수 있습니다. 중지된 워크플로우의 도구는 자동으로 제외됩니다.
* `ALLOWED_TOOLS`로 사용할 도구를 지정하면 원하는 서브에이전트만 선택적으로 호출할 수 있습니다. 빈 리스트(`[]`)이면 모든 도구를 사용합니다.

```
import json
import httpx

ADMIN_API_URL = "http://llmops-admin-api-service:8080"

# 사용할 도구만 지정 (빈 리스트면 모든 도구 사용)
ALLOWED_TOOLS = ["balance-inquiry-agent"]


async def get_auth_headers(client):
    """인증 토큰 획득"""
    resp = await client.post(
        "{}/api/admin/auth/login".format(ADMIN_API_URL),
        json={"user_id": "administrator", "password": "<password>"}
    )
    token = resp.json()["data"]["access_token"]
    return {"Authorization": "Bearer {}".format(token)}


async def run(data):
    """마스터 에이전트: 통합 API로 서브에이전트 MCP 도구를 조회하고 호출"""
    question = data.get("question", "")

    async with httpx.AsyncClient(timeout=30.0) as client:
        headers = await get_auth_headers(client)

        # 통합 API: 배포 중인 모든 WORKFLOW MCP 도구를 한번에 조회
        resp = await client.get(
            "{}/api/admin/mcp/server/workflow/tools".format(ADMIN_API_URL),
            headers=headers
        )
        all_tools = resp.json().get("data", [])

        # ALLOWED_TOOLS가 지정되어 있으면 필터링
        tools = [t for t in all_tools if t["name"] in ALLOWED_TOOLS] if ALLOWED_TOOLS else all_tools

        # 각 도구 호출 (mcp_server_id가 응답에 포함되어 있음)
        results = {}
        for tool in tools:
            call_resp = await client.post(
                "{}/api/admin/mcp/server/test/{}/tools/call".format(
                    ADMIN_API_URL, tool["mcp_server_id"]
                ),
                headers=headers,
                json={"tool_name": tool["name"], "input_schema": {"question": question}},
                timeout=60.0
            )
            call_data = call_resp.json()
            if call_data.get("code") == 0 and call_data.get("data"):
                results[tool["name"]] = call_data["data"][0]

    # 결과 종합
    lines = ["[마스터 에이전트]", ""]
    lines.append("사용자 질문: {}".format(question))
    lines.append("탐색된 MCP 도구 ({}개): {}".format(
        len(tools),
        ", ".join("{} ({})".format(t["name"], t["mcp_server_name"]) for t in tools)
    ))
    lines.append("")

    for tool_name, raw in results.items():
        lines.append("--- {} ---".format(tool_name))
        try:
            parsed = json.loads(raw) if isinstance(raw, str) else raw
            lines.append(json.dumps(parsed, indent=2, ensure_ascii=False))
        except Exception:
            lines.append(str(raw))
        lines.append("")

    return {"question": question, "text": "\n".join(lines)}
```

#### 통합 API 응답 형식

* `GET /mcp/server/workflow/tools`는 배포 중인 모든 WORKFLOW 타입 MCP 서버의 도구를 한번에 반환합니다:

```
{
  "code": 0,
  "data": [
    {
      "name": "balance-inquiry-agent",
      "description": "은행 잔액 조회 에이전트",
      "input_schema": { "type": "object", "properties": { ... } },
      "mcp_server_id": 3,
      "mcp_server_name": "wf-balance-inquiry-agent"
    },
    {
      "name": "transfer-agent",
      "description": "이체 처리 에이전트",
      "input_schema": { ... },
      "mcp_server_id": 5,
      "mcp_server_name": "wf-transfer-agent"
    }
  ]
}
```

| 필드                | 설명                                 |
| ----------------- | ---------------------------------- |
| `name`            | 도구 이름 (tools/call 시 사용)            |
| `description`     | 도구 설명                              |
| `input_schema`    | 입력 파라미터 JSON Schema                |
| `mcp_server_id`   | 도구가 속한 MCP 서버 ID (tools/call 시 사용) |
| `mcp_server_name` | MCP 서버 이름                          |

> **참고**: 중지된 워크플로우의 도구는 목록에 포함되지 않으므로, 마스터 에이전트가 중지된 서브에이전트를 호출하려다 실패하는 상황이 발생하지 않습니다.

**마스터 에이전트 워크플로우 배포 후:**

* 서브에이전트와 마스터 에이전트가 모두 Online 상태인 워크플로우 목록:

[![워크플로우 목록](https://github.com/genonai/GenOS/raw/feat/issue%239562/docs/mcp/guide-images/workflow-mcp/W10_workflow_list_master_sub.png)](https://github.com/genonai/GenOS/blob/feat/issue%239562/docs/mcp/guide-images/workflow-mcp/W10_workflow_list_master_sub.png)

***

#### 9-4. 동작 검증

* 마스터 에이전트 워크플로우 상세 페이지에서 **테스트** 버튼을 클릭하여 동작을 검증합니다.

**마스터 에이전트 상세 — 테스트 버튼 활성화**

<figure><img src="/files/91nuMCaAhDx0nhifupaP" alt=""><figcaption></figcaption></figure>

**테스트 드로어 — 입력 JSON 작성**

<figure><img src="/files/fT9Sx1lFo6y0UCAwU4xo" alt=""><figcaption></figcaption></figure>

**테스트 결과 — 마스터→서브에이전트 MCP 호출 성공**

<figure><img src="/files/txB6J25iryA6KnpTOWaB" alt=""><figcaption></figcaption></figure>

마스터 에이전트가 서브에이전트 MCP(`balance-inquiry-agent`)를 호출하여 잔액 정보를 받아오고, 결과를 종합하여 응답한 것을 확인할 수 있습니다.

MCP API로 직접 서브에이전트를 테스트할 수도 있습니다:

```
# 도구 목록 조회
GET /mcp/server/test/{mcp_server_id}/tools

# 도구 호출
POST /mcp/server/test/{mcp_server_id}/tools/call
{
  "tool_name": "balance-inquiry-agent",
  "input_schema": {
    "question": "잔액을 조회해주세요"
  }
}
```

> **참고**: 워크플로우 pod가 정상 실행 중이어야 도구 호출이 가능합니다. 도구 목록 조회는 DB 기반이므로 pod 상태와 무관하게 가능합니다.

***

### 10. 가용성 검증

* WORKFLOW 타입 MCP 도구는 호출 전에 자동으로 가용성을 확인합니다.

| 상태                 | tools/list | tools/call | 설명         |
| ------------------ | ---------- | ---------- | ---------- |
| 워크플로우 배포 + 정상      | 도구 목록 반환   | 정상 호출      | -          |
| 워크플로우 배포 + 헬스체크 실패 | 도구 목록 반환   | 에러 반환      | pod 일시적 오류 |
| 워크플로우 미배포          | 빈 목록       | 에러 반환      | 배포 필요      |

***

### 11. FAQ

**Q: MCP 도구 설정을 저장했는데 MCP 서버가 생성되지 않습니다.** A: 설정 저장만으로는 MCP 서버가 생성되지 않습니다. 워크플로우를 배포(Deploy)해야 MCP 서버가 자동으로 생성됩니다.

**Q: 워크플로우를 중지하면 MCP 도구도 사라지나요?** A: 도구 정보는 유지되지만, 배포 상태가 Offline으로 변경되어 호출할 수 없습니다. 재배포하면 다시 Online이 됩니다.

**Q: 입력 스키마를 변경하면 즉시 반영되나요?** A: 설정 저장 후 워크플로우를 재배포하면 변경된 스키마가 반영됩니다.

**Q: WORKFLOW 타입 MCP 서버를 직접 삭제할 수 있나요?** A: 워크플로우 상세에서 MCP 도구 노출을 비활성화(토글 OFF)하면 됩니다.

**Q: Python 단계에서 `run` 함수가 없다는 에러가 발생합니다.** A: 워크플로우 Python 단계의 코드에는 반드시 `run(data)` 함수가 정의되어 있어야 합니다. `async def run(data)` 또는 `def run(data)` 모두 지원됩니다.

**Q: 마스터 에이전트에서 서브에이전트 MCP 호출 시 타임아웃이 발생합니다.** A: `httpx.AsyncClient`의 `timeout`을 충분히 설정하세요 (서브에이전트가 LLM을 호출하는 경우 60초 이상 권장). 또한 서브에이전트 워크플로우 pod가 정상 Running 상태인지 확인하세요.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://genos-docs.gitbook.io/default/v1.8.5/basic-tutorials/guides/workflow/mcp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
