# MCP 연결하기

> 에이전트가 이용권이 있는 제품의 도구를 부르게 합니다. 클라이언트에 주소만 넣고 Gujo 계정으로 로그인해 연결합니다.

## 주소와 인증

| 서버 | 주소 | 인증 |
|---|---|---|
| 고객 MCP | `https://api.gujo.ai/api/mcp` | 로그인(OAuth). CI·스크립트는 계정 API 키(`mcp.read` 능력) |
| 디자인 MCP | `https://design.gujo.ai/mcp` | 디자인 에이전트 토큰(`read` 역할) |

두 서버 모두 JSON-RPC 2.0 을 HTTP POST 로 받습니다. 주소는 언제나 `api.gujo.ai`·`design.gujo.ai` 입니다. `gujo.ai/api/...` 로 부르면 MCP 헤더가 전달되지 않고, 로그인으로 받은 토큰도 `api.gujo.ai` 주소에서만 통합니다.

이 문서는 고객 MCP 를 다룹니다. 디자인 MCP 는 [Design Gallery](../design.md)에 있습니다.

## 로그인으로 연결

클라이언트에 서버 주소만 넣습니다. 키를 만들거나 환경 변수에 넣을 필요가 없습니다.

1. 아래에서 클라이언트를 골라 설치 버튼을 누르거나 명령·설정을 넣습니다.
2. 클라이언트가 서버를 처음 부르면 브라우저가 열리고 account.gujo.ai 로그인 화면이 나옵니다. 이미 로그인해 있으면 바로 동의 화면이 나옵니다.
3. 동의 화면에서 앱 이름, 앱의 주소, 연결할 서버, 줄 권한을 확인하고 승인합니다.
4. 클라이언트가 토큰을 받아 보관하고, 그 뒤로는 만료되면 스스로 갱신합니다.

클라이언트는 서버가 알려 주는 표준 메타데이터(`/.well-known/oauth-protected-resource/api/mcp`)로 로그인할 곳을 스스로 찾습니다. 앱 등록도 클라이언트가 알아서 합니다.

### 권한

동의 화면의 권한은 [계정 API 키의 능력](../auth.md)과 이름이 같고, 판정도 키와 똑같이 합니다.

- 기본 권한은 `mcp.read`(MCP 연결)와 `products.read`(라이브러리·상품 읽기)이고, 동의하면 늘 들어갑니다.
- 앱이 `orders.read`·`subscriptions.read`·`device.install` 같은 권한을 더 청하면, 그 권한은 체크하지 않은 채로 나옵니다. 직접 체크한 권한만 들어갑니다.
- 도구 목록에는 준 권한으로 부를 수 있는 도구만 나옵니다. 권한이 모자란 도구를 부르면 서버가 403 과 함께 모자란 권한을 알려 주고, 앱은 그 권한으로 다시 동의를 청할 수 있습니다.
- 운영자 능력은 청할 수 없습니다.

### 토큰 수명과 연결 끊기

- 접근 토큰은 1시간 동안 쓸 수 있고, 클라이언트가 갱신 토큰으로 새로 받습니다. 갱신할 때마다 두 토큰이 모두 바뀝니다.
- 갱신 토큰은 30일 동안 쓰지 않으면 만료됩니다. 연결은 동의한 날부터 90일 뒤 끝나고, 그때 한 번 더 로그인합니다.
- 로그인으로 연결한 앱은 [계정 보안 설정](https://account.gujo.ai/settings/security)의 **연결된 앱** 에 보입니다. 앱 이름, 권한, 마지막 사용 시각을 보고 **연결 끊기** 를 누르면 그 앱의 토큰이 모두 폐기됩니다.
- 한 계정에 살아 있는 연결은 20개까지입니다. 다 찼으면 쓰지 않는 연결을 끊습니다.
- 로그인으로 받은 토큰은 MCP 에서만 씁니다. 같은 토큰으로 다른 계정 API(`/api/products` 등)를 부르면 401 입니다.

## 키로 붙이기 (CI·스크립트용)

브라우저로 로그인할 수 없는 곳(CI, 서버의 스크립트, 헤드리스 에이전트)에서는 계정 API 키를 씁니다. 아래 클라이언트별 안내의 **키로 붙이기** 를 펼치면 설정이 있습니다.

설정 어디에도 키 값이 들어가지 않습니다. 설정은 환경 변수(`GUJO_API_KEY`, `GUJO_DESIGN_TOKEN`)나 클라이언트의 비밀번호 입력 칸을 가리킬 뿐입니다. 키는 [계정 API 키](../auth.md) 문서대로 `mcp.read` 능력을 골라 만들고, 만들 때 한 번 보이는 값을 셸 환경 변수에 넣습니다.

```bash
export GUJO_API_KEY="여기에 키"
```

## 클라이언트별 연결

### 고객 MCP

주소는 `https://api.gujo.ai/api/mcp` 입니다. 클라이언트에 주소만 넣으면, 처음 쓸 때 브라우저에서 Gujo 계정으로 로그인하고 권한에 동의해 토큰을 받습니다.

#### Cursor

[Cursor 에 설치](cursor://anysphere.cursor-deeplink/mcp/install?name=gujo&config=eyJ1cmwiOiJodHRwczovL2FwaS5ndWpvLmFpL2FwaS9tY3AifQ%3D%3D)

설치 버튼을 누르면 Cursor 가 서버를 추가하고, 처음 연결할 때 브라우저를 열어 로그인과 동의를 받습니다. 버튼을 쓰지 않을 때는 아래 내용을 설정 파일에 넣습니다.

파일: `~/.cursor/mcp.json`

```json
{
    "mcpServers": {
        "gujo": {
            "url": "https://api.gujo.ai/api/mcp"
        }
    }
}
```

**키로 붙이기 (CI·스크립트용)**

Cursor 는 키를 환경 변수 `GUJO_API_KEY` 에서 읽으므로, 그 변수가 있는 셸에서 Cursor 를 실행합니다. 아래 내용을 설정 파일에 넣습니다.

파일: `~/.cursor/mcp.json`

```json
{
    "mcpServers": {
        "gujo": {
            "url": "https://api.gujo.ai/api/mcp",
            "headers": {
                "Authorization": "Bearer ${env:GUJO_API_KEY}"
            }
        }
    }
}
```

#### VS Code

[VS Code 에 설치](vscode:mcp/install?%7B%22name%22%3A%22gujo%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fapi.gujo.ai%2Fapi%2Fmcp%22%7D)

설치 버튼을 누르면 VS Code 가 서버를 추가하고, 서버를 처음 시작할 때 브라우저에서 로그인과 동의를 받습니다. 설정을 저장소에 함께 두려면 아래 내용을 설정 파일에 넣습니다.

파일: `.vscode/mcp.json`

```json
{
    "servers": {
        "gujo": {
            "type": "http",
            "url": "https://api.gujo.ai/api/mcp"
        }
    }
}
```

**키로 붙이기 (CI·스크립트용)**

VS Code 는 서버를 처음 쓸 때 키를 비밀번호 입력 칸으로 묻고 따로 보관합니다. 아래 내용을 설정 파일에 넣습니다.

파일: `.vscode/mcp.json`

```json
{
    "inputs": [
        {
            "type": "promptString",
            "id": "gujo-token",
            "password": true,
            "description": "Gujo account API key (mcp.read)"
        }
    ],
    "servers": {
        "gujo": {
            "type": "http",
            "url": "https://api.gujo.ai/api/mcp",
            "headers": {
                "Authorization": "Bearer ${input:gujo-token}"
            }
        }
    }
}
```

#### Claude Code

아래 명령으로 서버를 추가한 뒤, Claude Code 에서 `/mcp` 를 열고 `gujo` 을 골라 로그인합니다. 브라우저에서 동의하면 Claude Code 가 토큰을 보관하고 스스로 갱신합니다. 프로젝트에 함께 두려면 명령 대신 `.mcp.json` 에 넣습니다.

```bash
claude mcp add --transport http gujo https://api.gujo.ai/api/mcp
```

파일: `.mcp.json`

```json
{
    "mcpServers": {
        "gujo": {
            "type": "http",
            "url": "https://api.gujo.ai/api/mcp"
        }
    }
}
```

**키로 붙이기 (CI·스크립트용)**

Claude Code 는 `.mcp.json` 의 `${GUJO_API_KEY}` 를 시작할 때 환경 변수에서 펼칩니다. `claude mcp add --header` 는 환경 변수를 펼치지 않아 키 원문이 설정에 남으므로, 서버는 이 파일로 추가합니다.

파일: `.mcp.json`

```json
{
    "mcpServers": {
        "gujo": {
            "type": "http",
            "url": "https://api.gujo.ai/api/mcp",
            "headers": {
                "Authorization": "Bearer ${GUJO_API_KEY}"
            }
        }
    }
}
```

#### Codex

아래 명령으로 서버를 추가하고 `codex mcp login gujo` 으로 브라우저에서 로그인합니다. 동의하면 Codex 가 토큰을 보관하고 스스로 갱신합니다.

```bash
codex mcp add gujo --url https://api.gujo.ai/api/mcp
codex mcp login gujo
```

**키로 붙이기 (CI·스크립트용)**

Codex 는 `bearer_token_env_var` 에 적은 환경 변수 `GUJO_API_KEY` 에서 키를 읽어 `Authorization: Bearer` 헤더로 보냅니다.

파일: `~/.codex/config.toml`

```toml
[mcp_servers.gujo]
url = "https://api.gujo.ai/api/mcp"
bearer_token_env_var = "GUJO_API_KEY"
```

#### Claude.ai

Claude.ai 나 Claude Desktop 의 설정 > 커넥터 > 커스텀 커넥터 추가에서 아래 주소만 넣고 연결합니다. 브라우저에서 Gujo 로그인과 동의를 마치면 커넥터가 토큰을 받습니다. 키는 넣지 않습니다.

```text
https://api.gujo.ai/api/mcp
```

**키로 붙이기 (CI·스크립트용)**

설정 > 커넥터 > 커스텀 커넥터 추가에서 아래 주소를 넣고, 요청 헤더 `Authorization` 에 `Bearer` 와 키를 넣습니다. 이렇게 하면 키가 Anthropic 에 저장됩니다. 이 커넥터에만 쓸 키를 따로 만들고, 더 쓰지 않으면 바로 폐기합니다.

```text
URL: https://api.gujo.ai/api/mcp
Authorization: Bearer <GUJO_API_KEY>
```

#### Windsurf

Windsurf(Devin Desktop)는 주소만 있는 설정으로 서버를 추가하고, 처음 연결할 때 브라우저에서 로그인과 동의를 받습니다. 아래 내용을 설정 파일에 넣습니다.

파일: `~/.codeium/windsurf/mcp_config.json`

```json
{
    "mcpServers": {
        "gujo": {
            "serverUrl": "https://api.gujo.ai/api/mcp"
        }
    }
}
```

**키로 붙이기 (CI·스크립트용)**

Windsurf(Devin Desktop)는 키를 환경 변수 `GUJO_API_KEY` 에서 읽습니다. 아래 내용을 설정 파일에 넣습니다.

파일: `~/.codeium/windsurf/mcp_config.json`

```json
{
    "mcpServers": {
        "gujo": {
            "serverUrl": "https://api.gujo.ai/api/mcp",
            "headers": {
                "Authorization": "Bearer ${env:GUJO_API_KEY}"
            }
        }
    }
}
```

### 디자인 MCP

주소는 `https://design.gujo.ai/mcp` 이고, 키는 환경 변수 `GUJO_DESIGN_TOKEN` 에 둡니다.

#### Cursor

[Cursor 에 설치](cursor://anysphere.cursor-deeplink/mcp/install?name=gujo-design&config=eyJ1cmwiOiJodHRwczovL2Rlc2lnbi5ndWpvLmFpL21jcCIsImhlYWRlcnMiOnsiQXV0aG9yaXphdGlvbiI6IkJlYXJlciAke2VudjpHVUpPX0RFU0lHTl9UT0tFTn0ifX0%3D)

Cursor 는 키를 환경 변수 `GUJO_DESIGN_TOKEN` 에서 읽으므로, 그 변수가 있는 셸에서 Cursor 를 실행합니다. 아래 내용을 설정 파일에 넣습니다.

파일: `~/.cursor/mcp.json`

```json
{
    "mcpServers": {
        "gujo-design": {
            "url": "https://design.gujo.ai/mcp",
            "headers": {
                "Authorization": "Bearer ${env:GUJO_DESIGN_TOKEN}"
            }
        }
    }
}
```

#### VS Code

[VS Code 에 설치](vscode:mcp/install?%7B%22name%22%3A%22gujo-design%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fdesign.gujo.ai%2Fmcp%22%2C%22headers%22%3A%7B%22Authorization%22%3A%22Bearer%20%24%7Binput%3Agujo-design-token%7D%22%7D%2C%22inputs%22%3A%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22gujo-design-token%22%2C%22password%22%3Atrue%2C%22description%22%3A%22Gujo%20design%20agent%20token%22%7D%5D%7D)

VS Code 는 서버를 처음 쓸 때 키를 비밀번호 입력 칸으로 묻고 따로 보관합니다. 아래 내용을 설정 파일에 넣습니다.

파일: `.vscode/mcp.json`

```json
{
    "inputs": [
        {
            "type": "promptString",
            "id": "gujo-design-token",
            "password": true,
            "description": "Gujo design agent token"
        }
    ],
    "servers": {
        "gujo-design": {
            "type": "http",
            "url": "https://design.gujo.ai/mcp",
            "headers": {
                "Authorization": "Bearer ${input:gujo-design-token}"
            }
        }
    }
}
```

#### Claude Code

Claude Code 는 `.mcp.json` 의 `${GUJO_DESIGN_TOKEN}` 를 시작할 때 환경 변수에서 펼칩니다. `claude mcp add --header` 는 환경 변수를 펼치지 않아 키 원문이 설정에 남으므로, 서버는 이 파일로 추가합니다.

파일: `.mcp.json`

```json
{
    "mcpServers": {
        "gujo-design": {
            "type": "http",
            "url": "https://design.gujo.ai/mcp",
            "headers": {
                "Authorization": "Bearer ${GUJO_DESIGN_TOKEN}"
            }
        }
    }
}
```

#### Codex

Codex 는 `bearer_token_env_var` 에 적은 환경 변수 `GUJO_DESIGN_TOKEN` 에서 키를 읽어 `Authorization: Bearer` 헤더로 보냅니다.

파일: `~/.codex/config.toml`

```toml
[mcp_servers.gujo-design]
url = "https://design.gujo.ai/mcp"
bearer_token_env_var = "GUJO_DESIGN_TOKEN"
```

#### Windsurf

Windsurf(Devin Desktop)는 키를 환경 변수 `GUJO_DESIGN_TOKEN` 에서 읽습니다. 아래 내용을 설정 파일에 넣습니다.

파일: `~/.codeium/windsurf/mcp_config.json`

```json
{
    "mcpServers": {
        "gujo-design": {
            "serverUrl": "https://design.gujo.ai/mcp",
            "headers": {
                "Authorization": "Bearer ${env:GUJO_DESIGN_TOKEN}"
            }
        }
    }
}
```

## 연결 확인

1. 에이전트에게 도구 목록을 물으면 준 권한(키면 키의 능력)으로 부를 수 있는 도구가 나옵니다.
2. 로그인 창이 뜨지 않으면 주소가 `https://api.gujo.ai/api/mcp` 인지 확인합니다. Claude Code 는 `/mcp`, Codex 는 `codex mcp login gujo` 로 로그인을 다시 시작합니다.
3. 키로 붙였을 때 401 이면 키를, 403 `missing_api_key_ability` 면 키의 `mcp.read` 능력을 확인합니다.
4. 키로 붙였는데 도구가 비어 있으면 클라이언트가 환경 변수를 읽지 못한 것일 수 있습니다. 그 변수가 있는 셸에서 클라이언트를 다시 실행합니다.

## 도구 묶음

도구를 한꺼번에 다 보이면 에이전트가 도구를 고르기 어려워지므로, 도구는 묶음(toolset)으로 나뉘어 있습니다. 처음 `tools/list` 에는 메타 도구 세 개와 `library` 묶음의 도구만 나옵니다.

| 메타 도구 | 입력 | 하는 일 |
|---|---|---|
| `search_tools` | `query?`, `toolset?` | 이 키로 부를 수 있는 도구를 찾습니다. 결과 항목은 `{name, toolset, method, path, read_only, description}` 입니다 |
| `enable_toolset` | `toolset` | 묶음을 켜서 그 세션의 도구 목록에 더합니다. 결과에 그 묶음 도구의 입력 스키마가 함께 옵니다 |
| `disable_toolset` | `toolset` | 묶음을 끕니다 |

묶음을 켜고 끄면 서버가 `notifications/tools/list_changed` 를 보냅니다. 클라이언트가 `Accept: text/event-stream` 을 보냈으면 같은 응답을 SSE 로 보내 그 알림 다음에 결과를 싣습니다. 모르는 묶음 이름은 `unknown_toolset` 도구 오류입니다.

| 묶음 | 도구 |
|---|---|
| `library`(처음부터 켜짐) | `library`, `products_content_assets_list` |
| `products` | `products_list`, `products_show`, `products_detail`, `products_releases`, `products_updates` |
| `install` | `products_install` |
| `license` | `license_check`, `products_license`, `entitlements_pass_check` |
| `setup` | `products_setup_progress_show`, `products_setup_progress_update` |
| `device` | `bundles_list`, `device_entitlements`, `device_installs_create`, `device_usage_create` |
| `orders` | `invoices_list`, `orders_list`, `orders_show`, `payment_methods_list` |
| `subscriptions` | `subscriptions_list` |
| `client_config` | `client_config` |

도구 하나는 계정 API 의 문 하나입니다. 도구 이름, 필요한 능력, 입력 칸은 [API 참조](../api-reference.md)의 `tool` 칸과 같습니다. 구매한 상품의 상세와 매뉴얼은 `products_detail` 로 읽습니다.

- 도구 목록에는 키에 그 문의 능력이 있는 도구만 나옵니다. 예를 들어 `orders.read` 가 없는 키에는 `orders` 묶음 도구가 보이지 않습니다.
- 이용권과 상품 범위 키 조건은 인자를 받아야 판정되므로, 부를 때 403 `product_entitlement_required` 같은 도구 오류로 돌아옵니다.
- 쓰기 도구 세 개(`products_setup_progress_update`, `device_installs_create`, `device_usage_create`)는 승인 없이 바로 실행됩니다.
- 키를 스스로 폐기하는 문과 새 키 원문을 돌려주는 문, 파일을 올리는 문, JSON 이 아닌 응답(번들 파일 같은)은 도구로 싣지 않습니다.

## 세션

1. `initialize` 응답 머리글의 `Mcp-Session-Id` 를 받습니다. 프로토콜 버전은 `2025-11-25` 입니다.
2. 그 뒤 요청에는 같은 `Mcp-Session-Id` 를 싣습니다. 켠 묶음은 세션마다 기억됩니다.
3. 세션은 쓸 때마다 12시간씩 늘어납니다. 모르는 세션이나 다른 키의 세션이면 HTTP 404 와 JSON-RPC `-32600` 이 오고, 그때는 `initialize` 부터 다시 합니다.

세션 머리글 없이 부르는 요청은 `library` 묶음만 켠 것으로 봅니다. 배치 요청은 받지 않고(400), 지원하는 메서드는 `initialize`·`ping`·`tools/list`·`tools/call` 과 알림(202 빈 본문)입니다.

## 결과와 오류

- 성공: `structuredContent = {status, body}`. `status` 와 `body` 는 그 문을 REST 로 불렀을 때의 HTTP 상태와 JSON 본문입니다.
- 실패: `isError: true`, `structuredContent = {error, message, status?, body?, field?}`. `error` 는 그 문의 오류 코드(`product_entitlement_required` 등)이거나, 입력 칸과 맞지 않는 인자면 `invalid_input`(`field` 에 그 칸)입니다.
- 보이지 않는 도구 이름을 부르면 JSON-RPC 오류 `-32602 Unknown tool` 입니다. 예전에 쓰던 `mcp_tool_{id}` 꼴의 이름도 이제는 이 오류입니다.
- 모르는 메서드는 `-32601` 입니다.

## 문제 해결

| 증상 | 원인과 해결 |
|---|---|
| 매 요청마다 세션이 끊기거나 켠 묶음이 사라짐 | `gujo.ai/api/mcp` 로 부르고 있습니다. 그 길은 `Mcp-Session-Id` 머리글을 넘기지 않습니다. 주소를 `https://api.gujo.ai/api/mcp` 로 바꿉니다 |
| 401 `missing_api_key` | 클라이언트가 `Authorization` 머리글을 보내지 않습니다. 로그인으로 연결했으면 아직 로그인하지 않은 것이니 클라이언트에서 로그인을 시작합니다(Claude Code `/mcp`, Codex `codex mcp login gujo`). 키로 붙였으면 환경 변수가 클라이언트를 띄운 셸에 있는지 확인합니다 |
| 401 `invalid_api_key` | 토큰이나 키가 만료·폐기됐습니다. 로그인으로 연결했으면 클라이언트에서 다시 로그인하고, 키로 붙였으면 새 키를 만듭니다 |
| 403 `missing_api_key_ability` | 그 일에 필요한 권한이 없습니다. 로그인으로 연결했으면 앱이 다시 청하는 동의에서 그 권한을 체크합니다. 키로 붙였으면 키에 `mcp.read` 가 있는지 봅니다. 기기 로그인 키(gujoctl)에는 이 능력이 없으므로 개발자 설정에서 키를 따로 만듭니다 |
| 404 와 `-32600` | 세션이 만료됐거나 다른 키로 만든 세션입니다. 다시 `initialize` 합니다 |
| `-32602 Unknown tool` | 그 도구가 이 키에 보이지 않습니다. `search_tools` 로 이름을 확인하고, 필요한 능력을 키에 더합니다 |
| 도구 결과가 403 `product_entitlement_required` | 그 상품의 이용권이 없습니다. `library` 로 쓸 수 있는 상품 id 를 먼저 확인합니다 |
