{
  "openapi": "3.1.0",
  "info": {
    "title": "One Server Management API",
    "version": "v1",
    "description": "One Server 관리 API. 모든 요청에 Authorization: Bearer <토큰> 헤더가 필요해요. 토큰은 콘솔의 계정 → API · MCP 토큰에서 만들어요. ?lang=en 또는 ?lang=ja로 오류 문장의 언어를 골라요."
  },
  "servers": [
    {
      "url": "https://end.blackall.ai/api/v1"
    }
  ],
  "tags": [
    {
      "name": "account",
      "description": "계정과 리전"
    },
    {
      "name": "projects",
      "description": "프로젝트"
    },
    {
      "name": "keys",
      "description": "키와 서명"
    },
    {
      "name": "database",
      "description": "데이터베이스"
    },
    {
      "name": "auth",
      "description": "인증과 사용자"
    },
    {
      "name": "storage",
      "description": "파일 저장소"
    },
    {
      "name": "deployments",
      "description": "배포와 저장소"
    },
    {
      "name": "functions",
      "description": "함수"
    },
    {
      "name": "domains",
      "description": "도메인과 엣지"
    },
    {
      "name": "network",
      "description": "네트워크"
    },
    {
      "name": "jobs",
      "description": "예약 작업"
    },
    {
      "name": "webhooks",
      "description": "데이터베이스 웹훅"
    },
    {
      "name": "backups",
      "description": "백업과 복원"
    },
    {
      "name": "logs",
      "description": "로그와 관측"
    },
    {
      "name": "team",
      "description": "팀과 알림"
    },
    {
      "name": "billing",
      "description": "요금과 사용량"
    },
    {
      "name": "other",
      "description": "기타"
    }
  ],
  "paths": {
    "/": {
      "get": {
        "operationId": "get_root",
        "summary": "API 버전",
        "description": "이 API의 이름과 버전을 돌려줘요. 토큰이 맞는지 확인할 때 써요.",
        "tags": [
          "account"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {},
                    "version": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          }
        },
        "x-oneend-scope": null
      }
    },
    "/me": {
      "get": {
        "operationId": "whoami",
        "summary": "내 계정",
        "description": "이 토큰이 누구의 것이고 어떤 권한을 가졌는지 알려줘요. operator는 운영자 도구를 쓸 수 있는지(active)와, 못 쓰면 이 계정의 이유(refused: not_listed, token_bound, no_second_factor)예요. 무엇부터 할지 모를 때 먼저 부르세요.",
        "tags": [
          "account"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "email": {},
                    "organisation": {},
                    "projects": {},
                    "scopes": {},
                    "zone": {},
                    "read_only": {},
                    "next": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "whoami"
      }
    },
    "/regions": {
      "get": {
        "operationId": "list_regions",
        "summary": "리전 목록",
        "description": "리전 목록이에요. can_create가 true인 곳만 지금 만들 수 있어요. 리전은 나중에 못 바꾸니 create_project 전에 확인하세요.",
        "tags": [
          "account"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "code": {},
                      "name": {},
                      "country": {},
                      "status": {},
                      "is_default": {},
                      "can_create": {}
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_regions"
      }
    },
    "/regions/requests": {
      "post": {
        "operationId": "request_region",
        "summary": "리전 요청",
        "description": "아직 열리지 않은 리전(can_create가 false인 곳)이 필요하다고 남겨요. 담당자가 직접 연락해요. 날짜를 약속하지는 않아요. 이미 열린 리전은 요청하지 말고 create_project로 바로 만드세요.",
        "tags": [
          "account"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "region": {},
                    "name": {},
                    "recorded": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "request_region",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "region": {
                    "type": "string",
                    "description": "list_regions가 can_create=false로 알려준 코드."
                  },
                  "note": {
                    "type": "string",
                    "description": "거기에 무엇을 두려는지, 왜 그 리전이어야 하는지. 선택 사항이지만 담당자가 연락할 때 이것부터 읽어요."
                  }
                },
                "required": [
                  "region"
                ]
              }
            }
          }
        }
      }
    },
    "/server-sizes": {
      "get": {
        "operationId": "list_server_sizes",
        "summary": "서버 크기와 가격",
        "description": "서버 크기(메모리)마다 구글 서버, CPU, 지역별 월 금액(monthly_minor)이에요. 통화를 비우면 조직의 결제 통화예요. KRW는 원(부가세 포함), USD는 센트(결제할 때 세금 추가)예요. included_in이 pro인 크기는 Pro 요금제에 포함돼요. region_status가 planned인 지역은 준비 중이라 고를 수 없어요. listed가 false면 아직 팔지 않는 것이라 sizes가 비어 있어요.",
        "tags": [
          "account"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "region",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "한 지역만 볼 때 그 코드(list_regions의 code). 비우면 모든 지역."
            }
          },
          {
            "name": "currency",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "KRW",
                "USD"
              ],
              "description": "KRW 또는 USD. 비우면 조직의 결제 통화."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_server_sizes"
      }
    },
    "/imports/sources": {
      "get": {
        "operationId": "import_sources",
        "summary": "가져올 곳",
        "description": "이 조직에 연결한 원본 계정(Supabase, Vercel, PostgreSQL)마다 프로젝트 목록과 지금까지의 가져오기를 봐요. 계정 연결은 토큰이 대화에 남지 않게 콘솔(connect_url)에서 해요.",
        "tags": [
          "account"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "org",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "조직의 id나 이름. 비우면 이 토큰이 닿는 첫 조직."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "organisation": {},
                    "connect_url": {},
                    "sources": {},
                    "imports": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "import_sources"
      }
    },
    "/imports": {
      "post": {
        "operationId": "start_import",
        "summary": "가져오기 시작",
        "description": "콘솔에서 만든 가져오기(import)나 import_sources의 connection·project로 가져오기를 시작해요(묶음마다 새 프로젝트, 원본은 그대로). Supabase는 address에 세션 풀러 연결 문자열이 필요해요(쓰고 지워요). 다시 시작하면 바뀐 것만 옮겨요. 소유자·관리자·개발자만 돼요.",
        "tags": [
          "account"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "org",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "조직의 id나 이름. 비우면 이 토큰이 닿는 첫 조직."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "start_import",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        }
      }
    },
    "/imports/{id}": {
      "get": {
        "operationId": "get_import",
        "summary": "가져오기 진행 상황",
        "description": "콘솔의 가져오기 진행 화면과 같아요. 옮길 곳마다 단계(스키마, 로그인 사용자, 데이터, 파일, 예약 작업…)의 상태와 수, 옮기지 않는 것과 이유, 확인할 것을 보여줘요.",
        "tags": [
          "account"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "가져오기 id."
            }
          },
          {
            "name": "org",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "조직의 id나 이름. 비우면 이 토큰이 닿는 첫 조직."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_import"
      }
    },
    "/projects": {
      "get": {
        "operationId": "get_projects",
        "summary": "프로젝트 목록",
        "description": "이 계정의 프로젝트와 각각의 API 주소를 돌려줘요. status는 ready(쓸 수 있음), provisioning(데이터베이스를 만드는 중, 몇 초), failed(retry_provisioning), paused예요.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "ref": {},
                      "name": {},
                      "organisation": {},
                      "organisation_id": {},
                      "region": {},
                      "api_url": {},
                      "paused": {},
                      "archive_at": {},
                      "archive_purge_at": {},
                      "created_at": {}
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_projects"
      },
      "post": {
        "operationId": "create_project",
        "summary": "프로젝트 만들기",
        "description": "데이터베이스·인증·파일 저장소가 딸린 프로젝트를 만들어요. 리전은 비우면 기본 리전이고 나중에 못 바꿔요. 조직이 여럿이면 org로 골라요(요금제의 프로젝트 수 안에서). status가 provisioning이면 wait(초)를 주거나 ready가 된 뒤 표·키를 쓰세요.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "wait",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 120,
              "description": "데이터베이스가 준비될(status: ready) 때까지 기다릴 초. 기본 0은 바로 답해요. 보통 몇 초면 돼요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "organisation": {},
                    "region": {},
                    "api_url": {},
                    "status": {},
                    "created_at": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          },
          "502": {
            "$ref": "#/components/responses/E502"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "create_project",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "사람이 읽는 이름."
                  },
                  "region": {
                    "type": "string",
                    "description": "어디에 둘지. list_regions가 쓸 수 있는 값을 알려줘요. 비우면 기본 리전."
                  },
                  "org": {
                    "type": "string",
                    "description": "만들 조직의 id나 이름(list_projects의 organisation_id·organisation). 비우면 프로젝트를 만들 수 있는 첫 조직."
                  },
                  "wait": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 120,
                    "description": "데이터베이스가 준비될(status: ready) 때까지 기다릴 초. 기본 0은 바로 답해요. 보통 몇 초면 돼요."
                  },
                  "tier": {
                    "type": "string",
                    "description": "이 프로젝트만의 서버 크기. list_server_sizes가 알려준 값(예: 4gb)이나 default(요금제의 기본 크기)를 주면 만든 직후 서버를 요청해요. 비우면 공용 서버에서 시작해요."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}": {
      "get": {
        "operationId": "get_projects_ref",
        "summary": "프로젝트 하나",
        "description": "list_projects가 돌려주는 항목 하나를 ref로 찾아 돌려줘요.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "ref": {},
                      "name": {},
                      "organisation": {},
                      "organisation_id": {},
                      "region": {},
                      "api_url": {},
                      "paused": {},
                      "archive_at": {},
                      "archive_purge_at": {},
                      "created_at": {}
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_projects"
      },
      "patch": {
        "operationId": "rename_project",
        "summary": "이름 바꾸기",
        "description": "프로젝트 이름이나 조직 이름, 또는 둘 다 바꿔요. ID(ref)와 주소는 바뀌지 않아요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "organisation": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "rename_project",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "새 프로젝트 이름."
                  },
                  "organisation": {
                    "type": "string",
                    "description": "새 조직 이름."
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_project",
        "summary": "프로젝트 삭제",
        "description": "프로젝트의 표·가입자·파일·함수·예약 작업·환경 변수·도메인을 영구히 지워요. 되돌릴 수 없어요. 사용자가 요청할 때만 쓰고 confirm에 프로젝트 이름을 넣으세요. 마지막 프로젝트는 못 지워요. 소유자·관리자만 돼요.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "deleted": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "delete_project",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "프로젝트 이름. list_projects의 name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/transfer": {
      "get": {
        "operationId": "list_transfer_targets",
        "summary": "옮길 수 있는 조직",
        "description": "이 프로젝트를 옮길 수 있는 다른 조직(내가 소유자나 관리자인 조직)의 id·이름·요금제예요. can_transfer는 내가 지금 조직의 소유자라서 옮길 수 있는지예요. transfer_project의 organisation에 id를 넣어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "organisation": {},
                    "organisation_id": {},
                    "targets": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_transfer_targets"
      },
      "post": {
        "operationId": "transfer_project",
        "summary": "프로젝트 옮기기",
        "description": "프로젝트를 다른 조직으로 옮겨요. 지금 조직의 소유자이면서 받는 조직의 소유자나 관리자여야 하고, 받는 조직의 요금제에 프로젝트 자리가 있어야 해요. 옮긴 뒤 사용량은 받는 조직에 청구되고 이번 달 청구는 옮긴 시점에서 나뉘어요. 원래 조직 구성원에게 따로 준 접근은 사라지고, 되돌리려면 받는 조직의 소유자가 다시 옮겨야 해요. 주소·키·데이터·배포는 그대로예요. 사용자가 분명히 요청했을 때만 쓰고 confirm에 프로젝트 이름을 그대로 넣으세요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "organisation": {},
                    "organisation_id": {},
                    "transferred": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "transfer_project",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "organisation": {
                    "type": "string",
                    "description": "받을 조직의 id. list_transfer_targets가 알려줘요. 이름이 하나뿐이면 이름도 돼요."
                  },
                  "confirm": {
                    "type": "string",
                    "description": "프로젝트 이름. list_projects의 name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "organisation",
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/pause": {
      "post": {
        "operationId": "pause_project",
        "summary": "프로젝트 일시정지",
        "description": "프로젝트를 멈춰요: 사이트·API·함수는 503, 실시간·예약 작업·새 배포도 멈춰요. 데이터는 남고 resume_project로 바로 돌아와요. 90일 넘게 멈추면 데이터베이스를 보관 저장소로 옮겨요. 소유자·관리자만 돼요.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "paused": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "pause_project"
      }
    },
    "/projects/{ref}/resume": {
      "post": {
        "operationId": "resume_project",
        "summary": "프로젝트 다시 시작",
        "description": "일시정지한 프로젝트를 다시 시작해요. 무료 요금제에서 3일 동안 쓰지 않아 멈춘 프로젝트도 이걸로(또는 새 배포로) 다시 켜요. 예약 작업은 놓친 실행을 몰아서 하지 않고 다음 일정부터 돌아요.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "paused": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "resume_project"
      }
    },
    "/projects/{ref}/server": {
      "get": {
        "operationId": "get_server",
        "summary": "전용 서버",
        "description": "프로젝트의 전용 서버를 봐요: 크기(tier), 위치, 상태, 주소, 한 달 금액, 대기 서버, 자동 전환, 되돌리기 기간, 다음 위치 옮기기 날짜, 진행 중인 작업(jobs). server가 null이면 공용 서버를 써요. offered가 false면 아직 열리지 않았어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "offered": {},
                    "server": {},
                    "standby": {},
                    "options": {},
                    "next_move_at": {},
                    "jobs": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_server"
      },
      "post": {
        "operationId": "request_server",
        "summary": "전용 서버 빌리기",
        "description": "이 프로젝트만 쓰는 서버를 빌려요. 크기와 위치별 월 금액은 list_server_sizes로 먼저 보여 주고 사용자가 고른 것만 넣으세요. 보통 10분 안에 준비되고 데이터베이스와 앱을 옮긴 뒤 주소를 바꿔요. Pro부터, 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "request_server",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tier": {
                    "type": "string",
                    "pattern": "^[0-9]+gb$",
                    "description": "서버 크기. list_server_sizes의 tier(예: 4gb)."
                  },
                  "region": {
                    "type": "string",
                    "pattern": "^[a-z]{2}-[a-z]+-[0-9]$",
                    "description": "위치. 없으면 프로젝트 위치. list_server_sizes의 region."
                  }
                },
                "required": [
                  "tier"
                ]
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "resize_server",
        "summary": "서버 크기 바꾸기",
        "description": "전용 서버의 크기를 바꿔요. when=now는 지금, tonight는 서버 위치 시간 새벽 3~5시. 대기 서버가 없으면 3~5분 응답하지 않고, 있으면 전환하는 몇 초만 멈춰요. 크기 바꾸기는 무료이고 월 금액은 새 크기 값이에요(list_server_sizes). 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "resize_server",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tier": {
                    "type": "string",
                    "pattern": "^[0-9]+gb$",
                    "description": "서버 크기. list_server_sizes의 tier(예: 4gb)."
                  },
                  "when": {
                    "type": "string",
                    "enum": [
                      "now",
                      "tonight"
                    ],
                    "description": "now(지금, 기본) 또는 tonight(새벽 3~5시)."
                  }
                },
                "required": [
                  "tier"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "release_server",
        "summary": "전용 서버 반납",
        "description": "전용 서버를 반납해요: 마지막 백업을 받고 데이터베이스와 앱을 공용 서버로 옮긴 뒤 서버(와 대기 서버)를 지워요. 옮기는 동안 쓰기가 멈춰요. 사용자가 요청할 때만 쓰고 confirm에 ref를 그대로 넣으세요. 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "release_server",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "프로젝트 ID(ref). ref와 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/server/standby": {
      "put": {
        "operationId": "set_standby",
        "summary": "대기 서버",
        "description": "같은 위치·같은 크기의 대기 서버를 켜거나 꺼요. 데이터베이스를 계속 복제하고, 월 금액은 그 크기 값과 같아요(list_server_sizes). auto_failover=true면 주 서버가 60초 응답하지 않을 때 대기 서버로 저절로 바꿔요(대기 서버가 있어야 해요). 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_standby",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "standby": {
                    "type": "boolean",
                    "description": "대기 서버를 둘지."
                  },
                  "auto_failover": {
                    "type": "boolean",
                    "description": "자동 전환. 기본 false."
                  }
                },
                "required": [
                  "standby"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/server/move": {
      "post": {
        "operationId": "move_server",
        "summary": "서버 위치 옮기기",
        "description": "전용 서버를 다른 위치로 옮겨요. 무료이고 한 달에 한 번이에요(next_move_at). 새 위치에 서버를 만들어 복제하고 주소를 바꾸는 순간 쓰기가 몇 초 멈춰요. 옛 서버는 7일 남겨요. 월 금액은 새 위치 값이에요(list_server_sizes). 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "move_server",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "region": {
                    "type": "string",
                    "pattern": "^[a-z]{2}-[a-z]+-[0-9]$",
                    "description": "위치. list_server_sizes의 region(예: kr-seoul-1)."
                  }
                },
                "required": [
                  "region"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/server/restore-days": {
      "put": {
        "operationId": "set_restore_days",
        "summary": "되돌리기 기간",
        "description": "특정 시각으로 되돌릴 수 있는 기간을 7일 또는 28일로 정해요. 28일은 전용 서버에서만 되고 월 추가 요금이 있어요(get_server의 options, get_billing). 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_restore_days",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "days": {
                    "type": "integer",
                    "enum": [
                      7,
                      28
                    ],
                    "description": "7 또는 28."
                  }
                },
                "required": [
                  "days"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/archive": {
      "get": {
        "operationId": "get_project_archive",
        "summary": "데이터베이스 보관 상태",
        "description": "데이터베이스를 못 쓰는 상태(결제 실패, 무료 요금제, 일시정지)가 90일 이어지면 보관 저장소로 옮겨요. 이 프로젝트의 state(none, scheduled, archiving, archived, restoring, purged), reason, archive_at, purge_at(옮긴 뒤 1년, 보관 파일과 파일을 지우는 때), restore_blocked_by를 돌려줘요.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_project_archive"
      }
    },
    "/projects/{ref}/archive/restore": {
      "post": {
        "operationId": "restore_project_archive",
        "summary": "보관한 데이터베이스 복원",
        "description": "보관한 데이터베이스를 다시 만들어요(보통 몇 분). 결제가 안 끝났거나 무료 요금제면 거절해요(restore_blocked_by). 보관 파일이 지워졌으면 빈 데이터베이스를 만들어요. 소유자·관리자만 돼요.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "restore": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "restore_project_archive"
      }
    },
    "/projects/{ref}/archive/download": {
      "post": {
        "operationId": "create_archive_download_url",
        "summary": "보관 파일 내려받기 주소",
        "description": "보관한 데이터베이스(pg_dump 형식, pg_restore로 복원)를 1시간 동안 내려받을 수 있는 서명 주소를 만들어요. 이유를 함께 적어야 하고, 개인정보 접속기록에 남아요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "url": {},
                    "expires_at": {},
                    "bytes": {},
                    "format": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "create_archive_download_url",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "minLength": 4,
                    "maxLength": 300,
                    "description": "내려받는 이유. 접속기록에 남아요."
                  }
                },
                "required": [
                  "reason"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/keys": {
      "get": {
        "operationId": "get_project_keys",
        "summary": "API 키 가져오기",
        "description": "프로젝트 주소와 두 키예요. 비밀 키는 접근 규칙을 무시하니 서버에서만 쓰세요(쓰기 권한 토큰 필요). 프론트엔드용이면 only: \"publishable\"로 부르세요: 주소와 공개 키만 오고 읽기 권한 토큰으로도 돼요.",
        "tags": [
          "keys"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "only",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "publishable"
              ],
              "description": "publishable이면 주소와 공개 키만 돌려줘요. 비우면 두 키 모두."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "api_url": {},
                    "publishable_key": {},
                    "secret_key": {},
                    "key_version": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "secrets.read (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "get_project_keys"
      }
    },
    "/projects/{ref}/advisors": {
      "get": {
        "operationId": "get_advisors",
        "summary": "보안·성능 점검",
        "description": "데이터베이스 구조의 보안·성능 문제를 찾아요: RLS가 꺼진 표, 누구나 쓰는 규칙, 규칙을 무시하는 뷰, search_path 없는 security definer 함수, 사용자 표를 내보내는 뷰, 인덱스 없는 외래 키, 기본 키 없는 표, 중복 인덱스, 행마다 uid()를 부르는 규칙. 고칠 SQL(remedy)도 줘요. 표나 규칙을 바꾼 뒤 부르세요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_advisors"
      }
    },
    "/projects/{ref}/api-keys": {
      "get": {
        "operationId": "list_api_keys",
        "summary": "이름 붙은 API 키 목록",
        "description": "용도별로 만든 bw_publishable_·bw_secret_ 키의 이름, 종류, 앞부분, 마지막 사용 시각, 폐기 여부예요. 비밀 키의 값은 돌려주지 않아요. 공개 키는 값도 줘요.",
        "tags": [
          "keys"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {},
                      "name": {},
                      "kind": {},
                      "prefix": {},
                      "publishable_key": {},
                      "created_at": {},
                      "created_by": {},
                      "last_used_at": {},
                      "revoked_at": {}
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_api_keys"
      },
      "post": {
        "operationId": "create_api_key",
        "summary": "API 키 만들기",
        "description": "이름 붙은 키를 하나 만들어요. publishable은 브라우저용(접근 규칙을 따름), secret은 서버용(접근 규칙을 무시)이에요. 비밀 키 값은 이 응답에만 있고 다시 볼 수 없어요. 소유자·관리자만 만들 수 있고, 프로젝트마다 20개까지예요.",
        "tags": [
          "keys"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "create_api_key",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "publishable",
                      "secret"
                    ],
                    "description": "publishable for browsers, secret for servers."
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60,
                    "description": "어디에 쓰는 키인지. 예: 결제 서버"
                  }
                },
                "required": [
                  "kind",
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/api-keys/{id}": {
      "delete": {
        "operationId": "revoke_api_key",
        "summary": "API 키 폐기",
        "description": "이름 붙은 키 하나를 폐기해요. 30초 안에 그 키로 오는 요청이 거부돼요. 다른 키는 그대로예요. 되돌릴 수 없어요.",
        "tags": [
          "keys"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_api_keys의 id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "revoke_api_key"
      }
    },
    "/projects/{ref}/s3-keys": {
      "get": {
        "operationId": "list_s3_keys",
        "summary": "S3 접근 키 목록",
        "description": "S3 엔드포인트(endpoint, region, force_path_style)와 TUS 이어 올리기 주소, 그리고 S3 접근 키의 이름·접근 키 ID·마지막 사용 시각·폐기 여부예요. 비밀 접근 키는 돌려주지 않아요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_s3_keys"
      },
      "post": {
        "operationId": "create_s3_key",
        "summary": "S3 접근 키 만들기",
        "description": "AWS SDK·aws CLI·rclone이 /storage/v1/s3에 쓸 접근 키를 만들어요. 접근 규칙을 무시하니 서버에만 두세요. 비밀 접근 키는 이 응답에서만 보여요. 소유자·관리자만, 프로젝트마다 20개까지예요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "create_s3_key",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60,
                    "description": "어디에 쓰는 키인지. 예: 백업 서버"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/s3-keys/{id}": {
      "delete": {
        "operationId": "revoke_s3_key",
        "summary": "S3 접근 키 폐기",
        "description": "S3 접근 키 하나를 폐기해요. 30초 안에 그 키로 서명한 요청이 거부돼요. 다른 키는 그대로예요. 되돌릴 수 없어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_s3_keys의 keys[].id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "revoke_s3_key"
      }
    },
    "/projects/{ref}/tables/{table}/csv": {
      "get": {
        "operationId": "export_table_csv",
        "summary": "표를 CSV로 내보내기",
        "description": "표를 CSV로 돌려줘요(첫 줄은 열 이름). 1MB를 넘으면 잘리고 truncated가 true예요: filters로 나눠 받으세요. 빈 칸은 NULL, \"\"는 빈 문자열이에요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "table",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "표 이름 (list_tables)."
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "이 열 순서로. 비우면 표의 기본 순서."
            }
          },
          {
            "name": "desc",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "true면 큰 것부터."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "table": {},
                    "rows": {},
                    "bytes": {},
                    "truncated": {},
                    "csv": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "export_table_csv"
      },
      "post": {
        "operationId": "import_table_csv",
        "summary": "CSV를 표로 가져오기",
        "description": "CSV를 표에 넣어요. 첫 줄의 열 이름대로 들어가요(columns로 바꿔요). 한 줄이라도 실패하면 아무것도 넣지 않고 줄 번호와 이유를 알려 줘요. 2MB, 10,000줄까지예요. 따옴표 없는 빈 칸은 NULL이나 기본값이에요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "table",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "표 이름 (list_tables)."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "table": {},
                    "inserted": {},
                    "columns": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "import_table_csv",
        "x-oneend-max-body-bytes": 4194304,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "csv": {
                    "type": "string",
                    "description": "CSV 내용. 첫 줄은 열 이름."
                  },
                  "columns": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "CSV의 열마다 넣을 표의 열 이름, 건너뛸 열은 \"\". 첫 줄과 길이가 같아야 해요. 비우면 같은 이름끼리."
                  }
                },
                "required": [
                  "csv"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/tables": {
      "get": {
        "operationId": "list_tables",
        "summary": "표 목록",
        "description": "프로젝트의 표와 각 표의 칸, 대략의 줄 수, 접근 규칙 상태를 돌려줘요. 규칙이 켜져 있고 규칙 수가 0이면 공개 키로는 아무것도 보이지 않아요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "name": {},
                      "approximate_rows": {},
                      "row_level_security": {},
                      "policies": {},
                      "columns": {}
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_tables"
      }
    },
    "/projects/{ref}/policies": {
      "get": {
        "operationId": "list_policies",
        "summary": "접근 규칙 목록",
        "description": "어떤 표의 어떤 동작이 누구에게 열려 있는지 돌려줘요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_policies"
      }
    },
    "/projects/{ref}/storage/policies": {
      "post": {
        "operationId": "post_projects_ref_storage_policies",
        "summary": "파일 접근 규칙 만들기",
        "description": "파일 표(`objects`)에 접근 규칙 하나를 더해요. `name`·`command`(select·insert·update·delete·all)·`roles`·`using`·`check`를 받아요. 프로젝트 로그인은 파일 표의 주인이 아니라 SQL로는 규칙을 만들 수 없어서 이 경로를 써요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/storage/copy-from-import": {
      "post": {
        "operationId": "copy_storage_from_import",
        "summary": "파일 가져오기",
        "description": "import_sources에 연결한 Supabase 계정으로 그 프로젝트의 버킷과 파일을 이 서버의 프로젝트(ref)에 복사해요. 여기 없는 버킷은 Supabase와 같은 공개 여부·크기 한도·형식으로 만들고, 파일은 upload_object와 같은 저장소에 같은 한도로 올려요. 여기 있는 파일과 크기가 같으면 건너뛰어서 다시 불러도 돼요. 한 번에 파일 200개(max_files)·45초까지 옮기고, 남으면 답의 next를 넘겨 다시 불러요(done이 true가 될 때까지). 답은 버킷마다 created, copied, skipped, failed, bytes와 실패한 파일 몇 개예요. Supabase 키는 대화에 나오지 않아요. 버킷의 접근 규칙은 옮기지 않아요. dry_run이면 아무것도 바꾸지 않고 수만 보여줘요. 소유자·관리자·개발자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "source_project": {},
                    "dry_run": {},
                    "done": {},
                    "next": {},
                    "buckets": {},
                    "failures": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "copy_storage_from_import",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "buckets": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "복사할 Supabase 버킷 이름. 비우면 모두."
                  },
                  "rename": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "버킷 이름 바꾸기 {\"Supabase 버킷\": \"여기 버킷\"}. 없으면 소문자로, 공백은 -로 바꿔요(My Files → my-files)."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "description": "true면 바꾸지 않고 만들 버킷과 옮길 파일 수만 보여줘요."
                  },
                  "max_files": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "이번에 옮길 파일 수의 상한(기본 200, 최대 1000)."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/usage": {
      "get": {
        "operationId": "usage",
        "summary": "사용량",
        "description": "표·줄·가입자·파일 수와 저장 용량, 이번 달 사용량, 그리고 분당 한도(limits.outbound_requests_per_minute: 함수·pg_net·HTTP 작업이 함께 쓰는 외부 요청 수, 자기 API 호출은 세지 않음)를 돌려줘요.",
        "tags": [
          "billing"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tables": {},
                    "approximate_rows": {},
                    "users": {},
                    "files": {},
                    "storage_bytes": {},
                    "database_bytes": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "usage"
      }
    },
    "/projects/{ref}/users": {
      "get": {
        "operationId": "list_users",
        "summary": "서비스 가입자 목록",
        "description": "이 프로젝트 서비스의 가입자예요(플랫폼 계정과 별개). 한 번에 200명까지 오고 total이 전체 인원이에요. has_more가 true면 offset을 올려 다시 부르세요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "description": "한 번에 받을 인원. 기본값 50, 최대 200."
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "건너뛸 인원. 기본값 0."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {},
                    "total": {},
                    "limit": {},
                    "offset": {},
                    "has_more": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_users"
      },
      "post": {
        "operationId": "add_user",
        "summary": "서비스 가입자 추가",
        "description": "이 프로젝트의 서비스에 가입자를 하나 만들어요. 비밀번호는 10자 이상이어야 해요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "added": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "add_user",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "The user's email address."
                  },
                  "password": {
                    "type": "string",
                    "description": "At least 10 characters."
                  }
                },
                "required": [
                  "email",
                  "password"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/buckets/{bucket}/empty": {
      "post": {
        "operationId": "empty_bucket",
        "summary": "버킷 비우기",
        "description": "버킷 안의 파일을 모두 지워요. 버킷은 남아요. 되돌릴 수 없으니 사용자가 분명히 요청했을 때만 쓰고, confirm에 버킷 이름을 그대로 넣어야 해요. removed가 지운 파일 수예요.",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "bucket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_buckets의 버킷 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "bucket": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "empty_bucket",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "버킷 이름. bucket과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/buckets/{bucket}/objects": {
      "get": {
        "operationId": "list_objects",
        "summary": "파일 목록",
        "description": "버킷 안의 한 폴더를 봐요: 하위 폴더와 파일의 이름, 크기, 형식. prefix로 폴더를 고르고(예: avatars/2024/), search로 이름을 찾아요.",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "bucket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_buckets의 버킷 이름."
            }
          },
          {
            "name": "prefix",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "볼 폴더. 비우면 맨 위."
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "이름에 이 말이 든 것만."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "description": "기본 100."
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "건너뛸 개수."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "bucket": {},
                    "prefix": {},
                    "total": {},
                    "objects": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_objects"
      },
      "post": {
        "operationId": "upload_object",
        "summary": "파일 올리기",
        "description": "파일 하나를 버킷에 올려요(2MB까지). 바이너리는 encoding: base64로 보내요. 같은 이름은 거절하고 upsert: true면 덮어써요. 버킷의 크기·형식 제한을 따라요. 더 크면 create_upload_url을 쓰세요.",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "bucket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_buckets의 버킷 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "bucket": {},
                    "name": {},
                    "size": {},
                    "mime": {},
                    "replaced": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "upload_object",
        "x-oneend-max-body-bytes": 4194304,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content": {
                    "type": "string",
                    "description": "파일 내용 (encoding이 base64면 base64)."
                  },
                  "name": {
                    "type": "string",
                    "description": "버킷 안의 경로. 예: docs/readme.txt"
                  },
                  "encoding": {
                    "type": "string",
                    "enum": [
                      "utf-8",
                      "base64"
                    ],
                    "description": "기본 utf-8."
                  },
                  "content_type": {
                    "type": "string",
                    "description": "예: image/png. 비우면 텍스트 또는 application/octet-stream."
                  },
                  "upsert": {
                    "type": "boolean",
                    "description": "true면 같은 이름의 파일을 바꿔요."
                  }
                },
                "required": [
                  "content",
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/buckets/{bucket}/object": {
      "get": {
        "operationId": "download_object",
        "summary": "파일 내려받기",
        "description": "파일 하나의 내용을 돌려줘요(2MB까지). 텍스트는 utf-8로, 바이너리는 base64로 줘요. 더 큰 파일은 create_signed_url로 주소를 만들어 받으세요.",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "bucket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_buckets의 버킷 이름."
            }
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "버킷 안의 경로."
            }
          },
          {
            "name": "encoding",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "utf-8",
                "base64"
              ],
              "description": "비우면 내용에 맞게 골라요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "bucket": {},
                    "name": {},
                    "size": {},
                    "mime": {},
                    "encoding": {},
                    "content": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "download_object"
      },
      "delete": {
        "operationId": "delete_object",
        "summary": "파일 삭제",
        "description": "버킷에서 파일 하나를 지워요. 되돌릴 수 없어요.",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "bucket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_buckets의 버킷 이름."
            }
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "버킷 안의 경로."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "bucket": {},
                    "name": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "delete_object"
      }
    },
    "/projects/{ref}/buckets/{bucket}/upload-urls": {
      "post": {
        "operationId": "create_upload_url",
        "summary": "파일 올리기 주소 만들기",
        "description": "2MB보다 큰 파일 하나를 올릴 주소를 만들어요(내용은 이 도구로 보내지 않아요). 받은 url에 파일 바이트를 그대로 PUT하고 content-type을 넣으세요(example의 curl). 주소는 2시간 동안 그 이름 하나에만 써요. max_bytes를 넘거나 allowed_mime_types에 없으면 거절돼요: 더 크면 blackwall://storage의 이어 올리기(TUS)를 쓰세요. 공개 버킷이면 public_url이 공개 주소예요.",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "bucket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_buckets의 버킷 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "bucket": {},
                    "name": {},
                    "method": {},
                    "url": {},
                    "expires_at": {},
                    "max_bytes": {},
                    "allowed_mime_types": {},
                    "public_url": {},
                    "example": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_upload_url",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "버킷 안의 경로. 예: videos/intro.mp4"
                  },
                  "upsert": {
                    "type": "boolean",
                    "description": "true면 같은 이름의 파일을 바꿔요. 기본은 거절해요."
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/buckets/{bucket}/signed-urls": {
      "post": {
        "operationId": "create_signed_url",
        "summary": "서명 주소 만들기",
        "description": "비공개 버킷의 파일 하나를 정해진 시간 동안 누구나 받을 수 있는 주소를 만들어요(기본 1시간, 최대 7일). 주소를 가진 사람은 로그인 없이 받으니 필요한 만큼만 쓰세요.",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "bucket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_buckets의 버킷 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "bucket": {},
                    "name": {},
                    "url": {},
                    "expires_at": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_signed_url",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "버킷 안의 경로."
                  },
                  "expires_in": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 604800,
                    "description": "열려 있는 초. 기본 3600."
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/buckets/{bucket}": {
      "patch": {
        "operationId": "update_bucket",
        "summary": "버킷 설정 바꾸기",
        "description": "버킷의 공개 여부, 파일 하나의 최대 크기, 받을 형식을 바꿔요. 준 것만 바뀌고 나머지는 그대로예요. 공개로 바꾸면 그 안의 파일을 누구나 받을 수 있게 되니 사용자가 분명히 요청했을 때만 쓰세요. 이미 있는 파일은 그대로 둬요.",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "bucket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_buckets의 버킷 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "bucket": {},
                    "public": {},
                    "file_size_limit": {},
                    "allowed_mime_types": {},
                    "files": {},
                    "bytes": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "update_bucket",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "public": {
                    "type": "boolean",
                    "description": "true면 공개, false면 비공개."
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_bucket",
        "summary": "버킷 삭제",
        "description": "빈 버킷을 지워요. 파일이 남아 있으면 거절하니 먼저 empty_bucket으로 비우세요. 되돌릴 수 없어요. 사용자가 분명히 요청했을 때만 쓰고, confirm에 버킷 이름을 그대로 넣어야 해요.",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "bucket",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_buckets의 버킷 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "bucket": {},
                    "deleted": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "delete_bucket",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "버킷 이름. bucket과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/buckets": {
      "get": {
        "operationId": "list_buckets",
        "summary": "버킷 목록",
        "description": "파일 저장소의 버킷과 각각의 파일 수·용량을 돌려줘요.",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_buckets"
      },
      "post": {
        "operationId": "create_bucket",
        "summary": "버킷 만들기",
        "description": "공개 버킷은 누구나 읽을 수 있고, 비공개 버킷은 올린 사람만 읽어요. file_size_limit와 allowed_mime_types로 파일 하나의 크기와 받을 형식을 처음부터 정할 수 있어요(나중에는 update_bucket).",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "bucket": {},
                    "public": {},
                    "file_size_limit": {},
                    "allowed_mime_types": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_bucket",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^[a-z0-9][a-z0-9._-]{1,62}$",
                    "description": "The bucket name: 2 to 63 characters of lowercase letters, digits, \". _ -\"."
                  },
                  "public": {
                    "type": "boolean",
                    "description": "기본값은 비공개예요."
                  }
                },
                "required": [
                  "id"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/deployments/sources/upload-urls": {
      "post": {
        "operationId": "create_source_upload_url",
        "summary": "배포할 압축 파일 올리기 주소 만들기",
        "description": "3MB 넘는 사이트를 저장소 없이 배포할 때, 압축 파일(.zip, .tar, .tar.gz) 하나를 올릴 주소를 만들어요. url에 그대로 PUT하면(토큰 없이, example의 curl) source가 오니 deploy_source를 부르세요. 주소는 1시간, max_bytes까지예요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "method": {},
                    "url": {},
                    "expires_at": {},
                    "max_bytes": {},
                    "formats": {},
                    "example": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_source_upload_url"
      }
    },
    "/projects/{ref}/deployments/sources": {
      "post": {
        "operationId": "post_projects_ref_deployments_sources",
        "summary": "배포할 파일 올리기",
        "description": "저장소 없이 배포할 파일을 압축 파일(`.zip`, `.tar`, `.tar.gz`) 하나로 본문에 그대로 보내요. 내용의 해시(digest)로 저장되고, 배포는 그다음 `POST /deployments`에 `{\"source\": \"<digest>\"}`로 만들어요. 한 번 올린 것을 프리뷰와 프로덕션에 같은 바이트로 배포할 수 있어요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-max-body-bytes": 52428800,
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "contentMediaType": "application/octet-stream"
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/deployments": {
      "post": {
        "operationId": "post_projects_ref_deployments",
        "summary": "배포 만들기",
        "description": "본문에 무엇이 있느냐에 따라 세 가지예요. `source`는 `POST /deployments/sources`로 올린 압축 파일의 digest, `files`(또는 `files_base64`)는 경로별 파일 내용, 둘 다 없으면 `app`·`branch`·`commit`으로 저장소의 커밋을 빌드해요. `target`이 `production`이면 프로덕션, 아니면 프리뷰예요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "deploy_source",
        "x-oneend-max-body-bytes": 4194304,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "source": {
                    "type": "string",
                    "pattern": "^[0-9a-f]{64}$",
                    "description": "올릴 때 받은 source (64자리 SHA-256)."
                  },
                  "files": {
                    "type": "string"
                  },
                  "files_base64": {
                    "type": "string"
                  },
                  "app": {
                    "type": "string",
                    "description": "배포할 앱 (list_apps의 name). 앱이 하나면 생략해요."
                  },
                  "branch": {
                    "type": "string",
                    "description": "프리뷰의 이름. 프리뷰 주소가 돼요. 기본 preview."
                  },
                  "commit": {
                    "type": "string"
                  },
                  "wait": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 120,
                    "description": "빌드가 끝날(ready·error) 때까지 기다릴 초. 기본 0은 바로 답해요. 시간 안에 안 끝나면 still_running: true와 retry_after_seconds가 와요. MCP 클라이언트는 보통 60초쯤에 호출을 포기하니 45 정도가 안전해요."
                  },
                  "block_on_advisors": {
                    "type": "boolean",
                    "description": "true면 get_advisors의 심각한 보안 문제(advisors.critical)가 하나라도 있을 때 프로덕션 배포를 하지 않고 거절해요. 기본 false: 배포하고 advisors에 개수와 상위 3개를 알려줘요. 프리뷰는 막지 않아요."
                  },
                  "prebuilt": {
                    "type": "boolean",
                    "description": "true면 빌드하지 않고 그대로 서비스해요."
                  },
                  "target": {
                    "type": "string",
                    "enum": [
                      "preview",
                      "production"
                    ],
                    "description": "기본 preview."
                  },
                  "message": {
                    "type": "string",
                    "description": "배포 목록에 남길 메모 (선택)."
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "list_deployments",
        "summary": "배포 목록",
        "description": "최근 배포를 최신순으로 봐요: 상태(queued, building, ready, error), 환경, 주소, 브랜치, 커밋, 실패 이유. 삭제한 배포는 빠져요(list_deleted_deployments). next_before가 있으면 before에 넣어 다음 쪽을 봐요. url은 그 배포만의 dpl- 주소, production_url·preview_url은 프로덕션·브랜치 주소예요. preview_protection은 프리뷰를 누가 여는지예요(members 기본, password, off). 프로덕션 주소는 늘 공개지만, 보호가 켜지면 dpl- 주소는 보호돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "기본 20."
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^dpl-[0-9a-f]{16}$",
              "description": "이 배포 다음부터(더 오래된 쪽). 앞 쪽 답의 next_before."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "preview_protection": {},
                    "deployments": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_deployments"
      }
    },
    "/projects/{ref}/deployments/{id}/redeploy": {
      "post": {
        "operationId": "redeploy",
        "summary": "다시 배포",
        "description": "배포와 같은 커밋을 같은 환경에 다시 빌드해요. 환경 변수를 나중에 넣었거나 패키지 저장소가 잠시 죽어 실패한 빌드에 써요. 프로덕션은 소유자·관리자만 돼요. 답에 새 주소와 보안 점검(advisors)이 와요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "dpl-로 시작하는 배포 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "status": {},
                    "environment": {},
                    "preview_protection": {},
                    "advisors": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "redeploy"
      }
    },
    "/projects/{ref}/deployments/{id}/promote": {
      "post": {
        "operationId": "promote_deployment",
        "summary": "프리뷰를 프로덕션으로",
        "description": "빌드가 끝난 프리뷰 배포를 프로덕션으로 올려요. 같은 커밋을 프로덕션 환경 변수로 다시 빌드하고, 끝나면 프로덕션 주소가 그 결과를 가리켜요. 프리뷰용 키가 프로덕션에 들어가지 않게 프리뷰 빌드를 그대로 쓰지 않아요. 빌드가 끝난 프로덕션 배포를 주면 다시 빌드하지 않고 프로덕션 주소가 바로 그 배포를 가리키고, 되돌리기로 생긴 프로덕션 보류(production_held)가 풀려요. 지금 배포를 주면 보류만 풀려요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "올릴 배포의 dpl- 이름. 보통 프리뷰, 보류를 풀 때는 프로덕션 배포."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "status": {},
                    "environment": {},
                    "preview_protection": {},
                    "advisors": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)",
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "promote_deployment"
      }
    },
    "/projects/{ref}/deployments/{id}/rollback": {
      "post": {
        "operationId": "rollback_deployment",
        "summary": "프로덕션 되돌리기",
        "description": "프로덕션 주소를 예전에 서비스했던 프로덕션 배포로 바로 돌려놓아요. 다시 빌드하지 않고, 몇 초 안에 바뀌어요. 커스텀 도메인도 함께 따라가요. 그 뒤 프로덕션은 보류돼요(production_held): 새 프로덕션 빌드는 만들어지지만 promote_deployment로 올리기 전까지 나가지 않아요. 소유자·관리자만 할 수 있어요. 답에 그 배포의 url과 production_url이 와요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "되돌아갈 프로덕션 배포의 dpl- 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "status": {},
                    "production_held": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "rollback_deployment"
      }
    },
    "/projects/{ref}/deploy-hooks": {
      "get": {
        "operationId": "list_deploy_hooks",
        "summary": "배포 훅 목록",
        "description": "배포 훅과 그 주소를 봐요. 주소로 POST하면 그 브랜치의 최신 커밋을 빌드하니 주소 자체가 비밀이에요. 읽기 권한 토큰에는 주소의 끝 네 자리만 보여줘요(secret_hidden). 쓰기 권한 토큰이면 전부 보여요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "hooks": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "secrets.read (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "list_deploy_hooks"
      },
      "post": {
        "operationId": "create_deploy_hook",
        "summary": "배포 훅 만들기",
        "description": "push 없이 다시 빌드하게 하는 주소를 만들어요. CMS에서 글을 발행하거나 예약 작업이 돌 때 부르게 해요. 프로덕션 브랜치의 훅은 소유자·관리자만 만들 수 있어요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_deploy_hook",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "app": {
                    "type": "string",
                    "description": "The name from list_apps."
                  },
                  "branch": {
                    "type": "string",
                    "description": "The branch whose latest commit is built."
                  },
                  "name": {
                    "type": "string",
                    "description": "A name to recognise the hook by."
                  }
                },
                "required": [
                  "app",
                  "branch"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/deploy-hooks/{id}": {
      "delete": {
        "operationId": "remove_deploy_hook",
        "summary": "배포 훅 삭제",
        "description": "배포 훅을 지워요. 그 주소를 부르던 곳에서는 더 배포가 일어나지 않아요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The id from list_deploy_hooks."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_deploy_hook"
      }
    },
    "/projects/{ref}/deployment-retention": {
      "get": {
        "operationId": "get_deployment_retention",
        "summary": "배포 보관 기간",
        "description": "배포를 종류별로 며칠 남기는지예요: days(적용 값), project_days(null은 요금제), plan_days. 늘 남기는 배포(always_kept)와 삭제 후 되돌릴 수 있는 날(restore_days)도 와요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "canceled": {},
                    "error": {},
                    "preview": {},
                    "production": {},
                    "always_kept": {},
                    "restore_days": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_deployment_retention"
      },
      "put": {
        "operationId": "set_deployment_retention",
        "summary": "배포 보관 기간 바꾸기",
        "description": "배포 종류별 보관 기간을 바꿔요. 기간이 지난 배포는 삭제되고 3일 동안 restore_deployment로 되돌릴 수 있어요. 최근 배포와 서비스 중인 배포는 기간과 상관없이 남아요. 프로젝트 관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_deployment_retention",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "canceled_days": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 3650,
                    "description": "취소·건너뛴 배포를 남기는 날 수(1~3650). null이면 요금제 기본값. 적지 않으면 그대로."
                  },
                  "error_days": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 3650,
                    "description": "실패한 배포를 남기는 날 수(1~3650). null이면 요금제 기본값. 적지 않으면 그대로."
                  },
                  "preview_days": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 3650,
                    "description": "프리뷰 배포를 남기는 날 수(1~3650). null이면 요금제 기본값. 적지 않으면 그대로."
                  },
                  "production_days": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 3650,
                    "description": "프로덕션 배포를 남기는 날 수(1~3650). null이면 요금제 기본값. 적지 않으면 그대로."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/deployments/deleted": {
      "get": {
        "operationId": "list_deleted_deployments",
        "summary": "최근 삭제한 배포",
        "description": "3일 안에 삭제된 배포(직접 삭제했거나 보관 기간이 지난 것)와 되돌릴 수 있는 마감(restorable_until)을 돌려줘요. 그동안 그 배포의 주소는 410으로 답해요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "deployments": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_deleted_deployments"
      }
    },
    "/projects/{ref}/deployments/{id}": {
      "delete": {
        "operationId": "delete_deployment",
        "summary": "배포 삭제",
        "description": "배포 하나를 삭제해요(서비스 중·빌드 중인 배포는 안 돼요). 3일 동안 restore_deployment로 되돌릴 수 있고, 그 뒤 파일과 빌드 로그를 지워요. 프로덕션은 프로젝트 관리자, 나머지는 개발자 이상이 해요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^dpl-[0-9a-f]{16}$",
              "description": "배포 id(dpl-…). list_deployments나 list_deleted_deployments로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "deleted": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "delete_deployment"
      },
      "get": {
        "operationId": "get_deployment",
        "summary": "배포 하나와 빌드 로그",
        "description": "배포 하나의 상태, 주소, 빌드 로그 끝부분을 봐요(실패 이유는 대개 로그 끝). 환경 변수 값은 가려져요. 주소 필드는 list_deployments와 같아요. wait(초)를 주면 빌드가 끝날 때까지 기다려요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "dpl-로 시작하는 배포 이름."
            }
          },
          {
            "name": "tail",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 5000,
              "description": "빌드 로그 마지막 몇 줄. 기본 200."
            }
          },
          {
            "name": "wait",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 120,
              "description": "빌드가 끝날(ready·error) 때까지 기다릴 초. 기본 0은 바로 답해요. 시간 안에 안 끝나면 still_running: true와 retry_after_seconds가 와요. MCP 클라이언트는 보통 60초쯤에 호출을 포기하니 45 정도가 안전해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "preview_protection": {},
                    "build_log": {},
                    "build_log_lines": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_deployment"
      }
    },
    "/projects/{ref}/deployments/{id}/restore": {
      "post": {
        "operationId": "restore_deployment",
        "summary": "배포 되돌리기",
        "description": "3일 안에 삭제된 배포를 되돌려요. 주소가 다시 응답하고 롤백·승격도 할 수 있어요. 프로덕션 배포는 프로젝트 관리자, 나머지는 개발자 이상이 할 수 있어요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^dpl-[0-9a-f]{16}$",
              "description": "배포 id(dpl-…). list_deployments나 list_deleted_deployments로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "restored": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "restore_deployment"
      }
    },
    "/projects/{ref}/domains": {
      "get": {
        "operationId": "list_domains",
        "summary": "도메인 보기",
        "description": "이 프로젝트에 연결한 도메인과 각각의 용도(site/api), 따르는 브랜치, 리디렉트 대상, 확인 상태(아직이면 넣어야 할 TXT 레코드), 인증서 상태를 봐요.",
        "tags": [
          "domains"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "domains": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_domains"
      },
      "post": {
        "operationId": "add_domain",
        "summary": "도메인 연결",
        "description": "도메인을 연결해요. 받은 verification_record(TXT)를 DNS에 넣으면 몇 분 안에 확인돼요. target=api면 프로젝트 API로, branch를 주면 그 프리뷰로 답해요. *.example.com도 돼요. pair_www=true면 www도 연결해요.",
        "tags": [
          "domains"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "domains": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "add_domain",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "hostname": {
                    "type": "string",
                    "description": "예: example.com, api.example.com, *.example.com"
                  },
                  "target": {
                    "type": "string",
                    "enum": [
                      "site",
                      "api"
                    ],
                    "description": "site for the deployed site, api for the project API."
                  },
                  "branch": {
                    "type": "string",
                    "description": "사이트만. 비우면 프로덕션."
                  },
                  "pair_www": {
                    "type": "boolean",
                    "description": "Also connect the www address and redirect one to the other."
                  },
                  "app": {
                    "type": "string",
                    "description": "앱 이름(list_apps의 name). 비우면 프로젝트의 사이트(project_site가 true인 앱)."
                  }
                },
                "required": [
                  "hostname"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/domains/{hostname}": {
      "delete": {
        "operationId": "remove_domain",
        "summary": "도메인 연결 해제",
        "description": "도메인 연결을 끊어요. 그 주소는 몇 초 안에 더 이상 답하지 않아요. 사용자가 분명히 요청했을 때만 쓰고, confirm에 도메인을 그대로 넣어야 해요.",
        "tags": [
          "domains"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "hostname",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The connected domain."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "domains": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_domain",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "도메인. hostname과 같아야 해요(대소문자는 상관없어요)."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/domains/{hostname}/redirect": {
      "put": {
        "operationId": "set_domain_redirect",
        "summary": "도메인 리디렉트",
        "description": "이 도메인을 같은 프로젝트의 다른 도메인으로 넘기거나, to를 비워 다시 사이트를 열게 해요. to에 경로를 붙이면(example.com/vision) 방문한 경로가 그 뒤에 붙고 질의 문자열은 그대로 따라가요: vision.example.com/x?y=1 → example.com/vision/x?y=1, 첫 화면은 example.com/vision. to의 도메인은 이 프로젝트에 연결한, 리디렉트가 아닌 도메인이어야 해요.",
        "tags": [
          "domains"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "hostname",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "넘길 도메인."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "domains": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_domain_redirect",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "도메인 또는 도메인/경로(예: example.com/vision). 비우면 리디렉트를 꺼요."
                  },
                  "status": {
                    "type": "integer",
                    "enum": [
                      308,
                      307,
                      301,
                      302
                    ],
                    "description": "응답 코드. 기본 308(영구, 메서드 유지). 빼면 지금 값을 그대로 둬요."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/edge": {
      "get": {
        "operationId": "get_edge",
        "summary": "방화벽·캐시 보기",
        "description": "이 프로젝트의 IP 차단·허용 목록, 주소 하나당 분당 요청 한도, 적용 범위, 마지막 캐시 비우기 시각을 봐요.",
        "tags": [
          "domains"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "deny": {},
                    "allow": {},
                    "rate_per_minute": {},
                    "scope": {},
                    "cache_purged_at": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_edge"
      },
      "put": {
        "operationId": "set_edge",
        "summary": "방화벽 바꾸기",
        "description": "IP 차단(deny)·허용(allow, 비우면 모두 허용) 목록과 분당 요청 한도(10~100000, null이면 플랫폼 기본값), 적용 범위(all/site/api)를 바꿔요. 준 항목만 바뀌어요. 소유자·관리자만.",
        "tags": [
          "domains"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "deny": {},
                    "allow": {},
                    "rate_per_minute": {},
                    "scope": {},
                    "cache_purged_at": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_edge",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "deny": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "IP 또는 CIDR"
                  },
                  "allow": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "IP addresses or CIDR ranges to allow. Empty allows everyone."
                  },
                  "rate_per_minute": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Requests per minute from one address, 10 to 100000. null for the platform default."
                  },
                  "scope": {
                    "type": "string",
                    "enum": [
                      "all",
                      "site",
                      "api"
                    ],
                    "description": "What the rules apply to: all, site or api."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/edge/purge": {
      "post": {
        "operationId": "purge_edge_cache",
        "summary": "캐시 비우기",
        "description": "서버 배포가 s-maxage로 공유를 허락해 엣지에 저장된 응답을 모두 버려요. 다음 요청부터 배포가 다시 답해요.",
        "tags": [
          "domains"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "deny": {},
                    "allow": {},
                    "rate_per_minute": {},
                    "scope": {},
                    "cache_purged_at": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "purge_edge_cache"
      }
    },
    "/projects/{ref}/branch-previews": {
      "get": {
        "operationId": "get_branch_previews",
        "summary": "브랜치 미리보기 보기",
        "description": "이 프로젝트가 속한 조직에서 프로덕션 브랜치가 아닌 브랜치에 푸시할 때 미리보기를 빌드하는지 봐요(branch_previews). false면 프로덕션 브랜치(보통 main)에 들어온 것만 빌드해요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "organization": {},
                    "branch_previews": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_branch_previews"
      },
      "put": {
        "operationId": "set_branch_previews",
        "summary": "브랜치 미리보기 바꾸기",
        "description": "조직 전체에서 브랜치 푸시마다 미리보기를 빌드할지 정해요. false면 프로덕션 브랜치(보통 main)에 들어온 것만 빌드하고, 건너뛴 푸시는 배포 기록에 건너뜀으로 남아요. redeploy, 직접 올린 배포, 배포 훅은 그대로 빌드해요. 이 조직의 모든 프로젝트에 적용돼요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "organization": {},
                    "branch_previews": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "team.manage (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_branch_previews",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true면 브랜치 푸시마다 미리보기를 빌드해요."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/preview-protection": {
      "get": {
        "operationId": "get_preview_protection",
        "summary": "프리뷰 보호 보기",
        "description": "프로덕션이 아닌 배포(브랜치 프리뷰, 배포마다의 주소)를 누가 열 수 있는지 봐요: off, members(조직 멤버만), password. 보호하는 주소(scope), 로그인 없이 들이는 IP(trusted_ips), 그냥 통과시키는 경로(options_paths), 우회 키(bypass_secrets, 값은 끝 네 글자만), 공유 링크(share_links)도 함께 돌려줘요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "mode": {},
                    "has_password": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_preview_protection"
      },
      "put": {
        "operationId": "set_preview_protection",
        "summary": "프리뷰 보호 바꾸기",
        "description": "프리뷰를 누가 여는지 바꿔요: members(로그인한 조직 멤버), password(처음 켤 때 8자 이상 password 필요), off(누구나). 프로덕션 주소와 연결한 도메인은 늘 공개예요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_preview_protection",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "off",
                      "members",
                      "password"
                    ],
                    "description": "off, members or password."
                  },
                  "password": {
                    "type": "string",
                    "description": "mode가 password일 때. 비우면 이미 있는 비밀번호를 그대로 써요."
                  }
                },
                "required": [
                  "mode"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/apps": {
      "get": {
        "operationId": "list_apps",
        "summary": "연결된 저장소와 빌드 설정",
        "description": "배포하는 저장소마다 프로덕션 브랜치, root_directory, framework(null이면 자동 감지), build_command·output_directory·install_command(null이면 프리셋 기본값)를 봐요. detected_framework는 최근 빌드가 쓴 것, frameworks는 고를 수 있는 프리셋이에요. 저장소는 첫 push 때 생겨요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "apps": {},
                    "frameworks": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_apps"
      }
    },
    "/projects/{ref}/apps/{name}": {
      "delete": {
        "operationId": "delete_app",
        "summary": "앱 삭제",
        "description": "프로젝트의 앱 하나를 지워요(모노레포에서 폴더를 없앤 앱). 주소는 바로 내려가고, 진행 중인 빌드는 취소되고, 배포는 복원 없이 지워져 파일이 몇 분 안에 사라져요. 저장소에 폴더가 남아 있어도 다시 빌드하지 않아요. 되돌릴 수 없어요. 프로젝트의 기본 사이트, 도메인이 연결된 앱, 디스크가 있는 앱은 거절하고 먼저 할 일을 알려줘요. 사용자가 분명히 요청했을 때만 쓰고, confirm에 앱 이름을 그대로 넣어야 해요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_apps의 name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "delete_app",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "앱 이름. name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "update_app",
        "summary": "빌드 설정 바꾸기",
        "description": "저장소 하나의 프로덕션 브랜치, 빌드할 폴더, 프리셋, 빌드·출력·설치 명령을 바꿔요. 모노레포면 root_directory에 앱 폴더(예: apps/web)를 넣어요. 뺀 값은 그대로, null은 자동 감지, 빈 문자열 명령은 그 단계를 건너뛰어요. blackwall.json 값이 있으면 그걸 써요. 다음 배포부터 적용되고, port만 1분 안에 서버를 다시 시작해 적용해요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_apps의 name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "update_app",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "production_branch": {
                    "type": "string",
                    "description": "The branch that deploys to production."
                  },
                  "root_directory": {
                    "type": "string",
                    "description": "저장소 안의 상대 경로. 저장소 전체는 \".\""
                  },
                  "run_as": {
                    "type": "string",
                    "enum": [
                      "platform",
                      "image"
                    ],
                    "description": "서버를 누구로 실행할지. platform(기본)은 일반 사용자(10001), image는 이미지에 적힌 사용자(root 포함)로 gVisor 격리 환경에서 실행해요. WordPress 공식 이미지처럼 root로 시작해야 하는 Dockerfile 앱에만 image를 쓰세요. 빌드 없이 1분 안에 서버가 다시 시작해요."
                  },
                  "port": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 65535,
                    "description": "서버가 컨테이너 안에서 듣는 포트. null이면 이미지의 EXPOSE, 없으면 3000. 바꾸면 1분 안에 서버가 다시 시작해요(다시 배포할 필요 없어요)."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/logs": {
      "get": {
        "operationId": "get_logs",
        "summary": "로그 보기",
        "description": "로그를 최신순으로 봐요: 사이트·API·인증·함수 요청(메서드, 경로, 상태, 시간)과 서버·함수 출력. 500이 나면 level: error로 먼저 보세요. 다음 쪽은 next_before를 before로 넘겨요.",
        "tags": [
          "logs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "site",
                "server",
                "api",
                "auth",
                "functions",
                "build"
              ],
              "description": "Where the lines come from: site, server, api, auth, functions, build."
            }
          },
          {
            "name": "level",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "warn",
                "error"
              ],
              "description": "warn은 경고와 오류, error는 오류만이에요."
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "이 시각보다 오래된 줄만. 이전 응답의 next_before."
            }
          },
          {
            "name": "deployment",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "description": "기본 100."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "lines": {},
                    "next_before": {},
                    "retention_days": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_logs"
      }
    },
    "/projects/{ref}/rows/{table}": {
      "get": {
        "operationId": "read_rows",
        "summary": "표 내용 보기",
        "description": "표의 앞부분을 그대로 읽어요. 확인용이며, 조건이 필요하면 run_sql을 쓰세요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "table",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "표 이름."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "description": "기본 50줄."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "columns": {},
                    "rows": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "read_rows"
      }
    },
    "/projects/{ref}/migrations": {
      "get": {
        "operationId": "list_migrations",
        "summary": "마이그레이션 기록",
        "description": "apply_migrations로 적용한 마이그레이션의 버전·이름·적용 시각을 오래된 순으로 돌려줘요. 기록은 프로젝트 스키마의 oneend_migrations 표에 있어요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "ledger": {},
                    "migrations": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_migrations"
      },
      "post": {
        "operationId": "apply_migrations",
        "summary": "마이그레이션 적용",
        "description": "적용하지 않은 마이그레이션을 버전 순으로 하나씩 트랜잭션으로 실행하고 기록해요(적용된 건 건너뛰어요). 실패하면 그것만 되돌리고 멈추며 앞의 것은 남아요. run_sql 대신 쓰면 같은 변경을 다른 프로젝트에도 적용할 수 있어요. supabase/migrations 파일도 그대로 돼요: Supabase 이름(public., auth.uid(), storage., to authenticated)은 이 프로젝트 이름으로 바꿔 실행하고 translated로 알려 줘요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "applied": {},
                    "recorded_only": {},
                    "already_applied": {},
                    "drifted": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "apply_migrations",
        "x-oneend-max-body-bytes": 8388608,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "migrations": {
                    "type": "array",
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": "string",
                          "pattern": "^[0-9]{1,32}$"
                        },
                        "name": {
                          "type": "string"
                        },
                        "sql": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "version",
                        "sql"
                      ],
                      "additionalProperties": false
                    },
                    "description": "The migrations, each with version, name and sql."
                  },
                  "include_all": {
                    "type": "boolean",
                    "description": "이미 적용된 마지막 버전보다 앞선 버전도 적용해요. 기본 false."
                  },
                  "record_only": {
                    "type": "boolean",
                    "description": "실행하지 않고 적용한 것으로 기록만 해요. 기본 false."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "description": "무엇이 적용될지만 알려줘요."
                  }
                },
                "required": [
                  "migrations"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/migrations/{version}": {
      "delete": {
        "operationId": "remove_migration_record",
        "summary": "마이그레이션 기록 지우기",
        "description": "마이그레이션 하나를 적용하지 않은 것으로 되돌려요. 기록만 지우고 그 마이그레이션이 만든 것은 그대로 둬요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,32}$",
              "description": "The version from list_migrations."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "version": {},
                    "removed": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_migration_record"
      }
    },
    "/projects/{ref}/schema": {
      "get": {
        "operationId": "dump_schema",
        "summary": "스키마를 SQL로",
        "description": "프로젝트의 스키마(타입, 시퀀스, 표와 제약, 외래 키, 인덱스, 함수, 뷰, 트리거, RLS와 규칙)를 다시 만들 수 있는 SQL로 돌려줘요. 행 데이터와 권한은 들어 있지 않아요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "sql": {},
                    "objects": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "dump_schema"
      }
    },
    "/projects/{ref}/types/typescript": {
      "get": {
        "operationId": "generate_typescript_types",
        "summary": "TypeScript 타입 만들기",
        "description": "프로젝트의 표·뷰·함수·열거형으로 supabase-js의 createClient<Database>()에 넣는 Database 타입을 만들어요. 스키마를 바꾼 뒤 다시 부르세요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "schema",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "기본 public. 프로젝트가 만든 스키마(list_schemas의 name)도 돼요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "schema": {},
                    "types": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "generate_typescript_types"
      }
    },
    "/projects/{ref}/sql/query": {
      "post": {
        "operationId": "query_sql",
        "summary": "SQL 조회 (읽기 전용)",
        "description": "조회 한 문장(SELECT 등)을 읽기 전용으로 실행해요(읽기 권한 토큰도 돼요). 바꾸는 문장은 run_sql을 쓰세요. Vault 비밀 값은 비어 있어요. 문법: https://www.postgresql.org/docs/16/sql-commands.html",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "query_sql",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sql": {
                    "type": "string",
                    "description": "실행할 조회 한 문장."
                  }
                },
                "required": [
                  "sql"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/sql": {
      "post": {
        "operationId": "run_sql",
        "summary": "SQL 실행 (변경)",
        "description": "데이터나 구조를 바꾸는 SQL(CREATE, INSERT, UPDATE, DELETE 등)을 실행해요. 조회만이면 query_sql을 쓰세요. 문법은 PostgreSQL 16(https://www.postgresql.org/docs/16/sql-commands.html)이에요. 새 표는 접근 규칙이 켜진 채라 규칙을 만들기 전엔 공개 키로 안 보여요. 규칙의 권한 이름은 <ref>_anon, <ref>_authenticated, <ref>_service_role이에요. Supabase SQL(public., auth.uid(), storage., to authenticated)은 이 프로젝트 이름으로 바꿔 실행하고 translated로 알려 줘요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "run_sql",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sql": {
                    "type": "string",
                    "description": "실행할 SQL 한 문장."
                  }
                },
                "required": [
                  "sql"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/users/{id}/links": {
      "post": {
        "operationId": "generate_link",
        "summary": "로그인 링크 만들기",
        "description": "메일로 가는 링크를 메일 없이 만들어요: invite(없으면 가입자 생성), magiclink, recovery, signup(password 필요). action_link를 열면 그 가입자로 로그인되니 비밀번호처럼 다뤄요: 사용자가 요청할 때만 만들고 그 사람에게만 전하세요. redirect_to는 add_redirect_url로 등록한 주소만 돼요. 소유자·관리자·개발자만 돼요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "가입자의 이메일."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "type": {},
                    "user_id": {},
                    "email": {},
                    "action_link": {},
                    "email_otp": {},
                    "redirect_to": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "secrets.read (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "generate_link",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "invite",
                      "magiclink",
                      "recovery",
                      "signup"
                    ],
                    "description": "invite, magiclink, recovery or signup."
                  },
                  "password": {
                    "type": "string",
                    "description": "signup일 때 새 가입자의 비밀번호 (10자 이상)."
                  },
                  "data": {
                    "type": "object",
                    "description": "invite·signup·magiclink로 새로 만들 때 넣을 사용자 메타데이터."
                  },
                  "redirect_to": {
                    "type": "string",
                    "description": "확인 뒤 돌아갈 주소. list_redirect_urls에 있는 것만."
                  }
                },
                "required": [
                  "type"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/users/{id}": {
      "patch": {
        "operationId": "update_user",
        "summary": "서비스 가입자 바꾸기",
        "description": "가입자 한 명의 이메일, 비밀번호, 이메일 확인, 정지, 메타데이터(합쳐짐)를 바꿔요. 비밀번호를 바꾸거나 정지하면 로그인이 모두 끊겨요. 비밀번호는 10자 이상, 유출된 것은 거절돼요. 사용자가 요청할 때만 쓰세요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_users의 id (UUID)."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "user": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "update_user",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "새 이메일."
                  },
                  "password": {
                    "type": "string",
                    "description": "새 비밀번호 (10자 이상)."
                  },
                  "email_confirm": {
                    "type": "boolean",
                    "description": "true면 이메일을 확인된 것으로 표시해요."
                  },
                  "ban_duration": {
                    "type": "string",
                    "description": "정지 기간. 예: 24h, 30m, 876000h(사실상 영구). none이면 정지를 풀어요."
                  },
                  "user_metadata": {
                    "type": "object",
                    "description": "사용자가 바꿀 수 있는 메타데이터에 합칠 값."
                  },
                  "app_metadata": {
                    "type": "object",
                    "description": "서버만 바꾸는 메타데이터에 합칠 값(역할, 요금제 등)."
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_user",
        "summary": "가입자 삭제",
        "description": "프로젝트의 가입자 한 명을 지워요. 되돌릴 수 없어요. id는 list_users가 돌려준 값이에요. 사용자가 분명히 요청했을 때만 쓰고, confirm에 그 가입자의 이메일(또는 id)을 그대로 넣어야 해요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_users의 id(UUID)."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_user",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "지울 가입자의 이메일 또는 id. list_users의 email이나 id와 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/users/import": {
      "post": {
        "operationId": "import_users",
        "summary": "서비스 가입자 한꺼번에 가져오기",
        "description": "다른 서비스(Supabase auth.users 내보내기 등)의 가입자를 한 번에 500명까지 가져와요. id와 bcrypt 비밀번호 해시를 그대로 지켜서 비밀번호를 다시 정하지 않아도 로그인돼요. 목록 전체를 먼저 검사해 틀린 줄 번호를 알려 주고 하나도 가져오지 않아요. 이미 있는 계정은 건너뛰어서 다시 불러도 안전해요. dry_run=true면 검사만 해요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "dry_run": {},
                    "found": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "import_users",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "users": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "email": {
                          "type": "string"
                        },
                        "id": {
                          "type": "string"
                        },
                        "encrypted_password": {
                          "type": "string"
                        },
                        "email_confirmed": {
                          "type": "boolean"
                        },
                        "user_metadata": {
                          "type": "object"
                        },
                        "app_metadata": {
                          "type": "object"
                        }
                      },
                      "required": [
                        "email"
                      ],
                      "additionalProperties": false
                    },
                    "description": "The accounts: { email, id?, encrypted_password?, email_confirmed?, user_metadata?, app_metadata? }."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "description": "Check the list and import nothing."
                  }
                },
                "required": [
                  "users"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/retry-provisioning": {
      "post": {
        "operationId": "retry_provisioning",
        "summary": "준비 실패한 프로젝트 다시 시도",
        "description": "데이터베이스를 만들지 못한 프로젝트를 다시 준비해요. 다른 도구가 \"만들지 못했어요\"로 거절할 때 쓰세요. 프로젝트를 새로 만들지 마세요. 요금만 두 배가 돼요.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "retried": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "retry_provisioning"
      }
    },
    "/projects/{ref}/functions": {
      "get": {
        "operationId": "list_functions",
        "summary": "함수 목록",
        "description": "배포한 함수와 각 호출 주소, 공개 여부를 봐요. egress는 외부 요청이 켜졌는지, outbound_requests_per_minute은 함수·pg_net·HTTP 작업이 함께 쓰는 분당 외부 요청 한도예요(자기 API 호출은 세지 않아요).",
        "tags": [
          "functions"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "functions": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_functions"
      }
    },
    "/projects/{ref}/functions/{name}": {
      "get": {
        "operationId": "get_function",
        "summary": "함수 코드 보기",
        "description": "배포된 함수의 코드와 버전을 봐요. 고치기 전에 먼저 읽으세요. deploy_function이 \"building\"으로 답했으면 build.status(building·deployed·failed)와 build.error를 확인해요.",
        "tags": [
          "functions"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The function name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "status": {},
                    "public": {},
                    "version": {},
                    "url": {},
                    "updated_at": {},
                    "bundled": {},
                    "bytes": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_function"
      },
      "put": {
        "operationId": "deploy_function",
        "summary": "함수 배포",
        "description": "함수 하나를 배포해요. 같은 이름이 있으면 통째로 바꾸고 다음 호출부터 새 코드가 돌아요. 코드는 TypeScript 파일 하나로, export default로 (request, { sql }) => 응답 을 내보내요. request에는 method, headers, claims(role: anon·authenticated·service_role, 키 없이 부른 공개 함수는 null), text(), json()이 있어요. sql(text, values)은 service_role 권한으로 한 문장을 실행해 행 배열을 돌려줘요. 응답은 객체(JSON), 문자열, { status, headers, body } 중 하나예요. npm 패키지는 dependencies({\"zod\":\"^3.23.8\"})나 package_json(문자열)으로 보내요. 배포할 때 설치해 ESM 파일 하나로 묶어요(5MB까지, 설치 스크립트 실행 안 함, 네이티브 모듈 불가). 40초 안에 안 끝나면 status \"building\"으로 답하고 이어서 배포해요: get_function으로 build.status가 deployed나 failed가 될 때까지 확인하세요. 여러 파일은 files({\"lib/util.ts\": \"...\"})로 보내고 상대 경로로 import해요. 폴더째 보내려면 source를 비우고 files에 index.ts까지 넣으세요. ../_shared/cors.ts 같은 옆 폴더 파일은 files에 \"../_shared/cors.ts\"로 넣어요. deno.json·import_map.json의 imports와 npm:·jsr:·URL import(npm:zod@3, https://esm.sh/…, https://deno.land/std@0.177.0/http/server.ts 등)도 돼요. 모두 배포할 때 받아 묶고(주소와 SHA-256은 get_function의 remote_imports, deno.lock이 있으면 맞아야 해요) 실행 중에는 받지 않아요. 호출 하나는 150초까지예요(set_function_limits로 바꿔요). 네트워크는 기본으로 꺼져 있어요(set_function_egress). 호출한 사람의 Authorization 헤더가 그대로 들어오니 createClient(url, anonKey, { global: { headers: { Authorization: req.headers.get('Authorization') } } })가 그 사람으로 동작해요. 번들된 함수를 고칠 때는 get_function의 package_json·files를 그대로 다시 보내세요. 빼면 파일 하나짜리가 돼요. 프로덕션 환경 변수가 process.env로 들어와요. 소유자·관리자만 배포할 수 있어요. 기본은 비공개라 이 프로젝트의 키(공개 키, 사용자 토큰, 비밀 키)가 있어야 해요(Supabase verify_jwt와 같아요). 로그인한 사용자만 받으려면 request.claims.role을 확인하세요. public이 true면 키 없이 누구나 부르니 결제사 웹훅 같은 경우에만 쓰세요. 호출: POST https://<ref>.<zone>/functions/v1/<name>, 헤더 Authorization: Bearer <공개 키, 사용자 토큰 또는 비밀 키>.",
        "tags": [
          "functions"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "영문 소문자로 시작, 소문자·숫자·하이픈. 호출 주소의 끝이 돼요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "status": {},
                    "version": {},
                    "public": {},
                    "url": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          },
          "429": {
            "$ref": "#/components/responses/E429"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "deploy_function",
        "x-oneend-max-body-bytes": 4194304,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "source": {
                    "type": "string",
                    "description": "함수 코드 전체 (8MB까지). files가 있으면 entry 파일로 저장돼요. files에 entry가 있으면 생략해요."
                  },
                  "public": {
                    "type": "boolean",
                    "description": "생략하면 기존 값을 유지하고, 새 함수는 비공개예요."
                  },
                  "package_json": {
                    "type": "string",
                    "description": "package.json 전체 (선택). 있으면 설치 후 하나의 파일로 번들해요."
                  },
                  "package_lock": {
                    "type": "string",
                    "description": "package-lock.json (선택). 있으면 npm ci로 정확히 그 버전을 설치해요."
                  },
                  "dependencies": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "쓸 npm 패키지와 버전. 예: {\"zod\": \"^3.23.8\"}. package_json의 dependencies에 합쳐져요."
                  },
                  "files": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "source 옆에 둘 다른 파일들, 상대 경로 → 내용 (최대 200개, 합쳐 8MB). 함수 폴더 옆 폴더는 \"../_shared/cors.ts\"처럼 써요."
                  },
                  "entry": {
                    "type": "string",
                    "description": "source를 저장할 파일 이름. 기본 index.ts."
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "set_function_limits",
        "summary": "함수 시간 한도",
        "description": "호출 하나(timeout_seconds)와 SQL 한 문장(sql_timeout_seconds)의 시간 한도를 초로 정해요. 기본 150초·8초, 최대는 get_function의 timeout_cap_seconds예요. null은 기본값, 빼면 그대로예요. 넘긴 호출은 504로 끊겨요.",
        "tags": [
          "functions"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The function name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          },
          "429": {
            "$ref": "#/components/responses/E429"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_function_limits",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "public": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_function",
        "summary": "함수 삭제",
        "description": "함수를 지워요. 그 주소는 404가 되고, 이 함수를 부르는 예약 작업은 실패해요. 되돌릴 수 없으니 사용자가 분명히 요청했을 때만 쓰고, confirm에 함수 이름을 그대로 넣어야 해요.",
        "tags": [
          "functions"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The function name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          },
          "429": {
            "$ref": "#/components/responses/E429"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_function",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "함수 이름. name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/database": {
      "get": {
        "operationId": "get_database_connection",
        "summary": "데이터베이스 연결 정보",
        "description": "이 프로젝트 PostgreSQL에 직접 연결할 주소를 봐요: direct(5432, 세션: 마이그레이션 도구·DB 클라이언트)와 pooler(6543, 트랜잭션: 서버리스). 비밀번호는 저장하지 않아 [YOUR-PASSWORD]로 나와요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "available": {},
                    "host": {},
                    "database": {},
                    "user": {},
                    "password_set": {},
                    "direct": {},
                    "pooler": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "secrets.read (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "get_database_connection"
      }
    },
    "/projects/{ref}/database/password": {
      "post": {
        "operationId": "reset_database_password",
        "summary": "데이터베이스 비밀번호 새로 만들기",
        "description": "직접 연결 비밀번호를 새로 만들어 한 번만 보여 줘요. 이전 비밀번호의 연결은 다음부터 거부되니 confirm에 프로젝트 이름(list_projects의 name)이 필요해요. 이 사용자는 RLS를 거치지 않으니 서버에만 두세요. keep_for_deploys: true면 암호화해 저장하고 서버·미들웨어·함수가 실행될 때 DATABASE_URL·POSTGRES_URL·DIRECT_URL로 받아요(빌드 제외). 배포한 코드가 모든 행을 읽게 되니 사용자가 원할 때만 켜요. 빼면 넘기던 것도 멈춰요. 사용자가 요청할 때만 쓰고, 소유자·관리자만 돼요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "reset_database_password",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "keep_for_deploys": {
                    "type": "boolean",
                    "description": "true: 운영 배포에 DATABASE_URL로 넘겨요(암호화해 저장). 없거나 false: 보관하지 않고, 넘기던 것도 멈춰요."
                  },
                  "confirm": {
                    "type": "string",
                    "description": "프로젝트 이름. list_projects의 name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/backups": {
      "get": {
        "operationId": "list_backups",
        "summary": "백업 목록",
        "description": "프로젝트 백업(매일 밤 프로젝트 리전 시각 03:00~05:00에 자동, 직접 만든 것, 복원 직전 것)과 복원 기록을 봐요. 보관 기간은 retention_days예요.",
        "tags": [
          "backups"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "retention_days": {},
                    "point_in_time": {},
                    "backups": {},
                    "restores": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_backups"
      },
      "post": {
        "operationId": "create_backup",
        "summary": "지금 백업",
        "description": "표·가입자·파일을 지금 백업해요. 큰 변경(마이그레이션, 대량 삭제) 전에 만드세요. 7일 보관돼요.",
        "tags": [
          "backups"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "status": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_backup"
      }
    },
    "/projects/{ref}/backups/{backup_id}/restore": {
      "post": {
        "operationId": "post_projects_ref_backups_backup_id_restore",
        "summary": "백업으로 복원",
        "description": "표·가입자·파일을 백업 시점으로 되돌려요. backup_id 대신 at(ISO 시각)을 주면 초 단위로 되돌려요(Pro 이상, list_backups의 point_in_time 안. 파일은 파일 버킷 서버에서만, 지난 14일 안에 지운 것까지). 그 뒤 변경은 모두 사라지니 사용자가 요청할 때만 쓰세요. 직전 상태를 백업하니 undo_backup_id로 되돌릴 수 있어요. 소유자·관리자만 돼요.",
        "tags": [
          "backups"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "backup_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The id from list_backups."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "restore_backup"
      }
    },
    "/projects/{ref}/backups/restore-to-time": {
      "post": {
        "operationId": "post_projects_ref_backups_restore_to_time",
        "summary": "백업으로 복원",
        "description": "표·가입자·파일을 백업 시점으로 되돌려요. backup_id 대신 at(ISO 시각)을 주면 초 단위로 되돌려요(Pro 이상, list_backups의 point_in_time 안. 파일은 파일 버킷 서버에서만, 지난 14일 안에 지운 것까지). 그 뒤 변경은 모두 사라지니 사용자가 요청할 때만 쓰세요. 직전 상태를 백업하니 undo_backup_id로 되돌릴 수 있어요. 소유자·관리자만 돼요.",
        "tags": [
          "backups"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "restore_backup",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "at": {
                    "type": "string",
                    "description": "예: 2026-10-01T14:59:00+09:00"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/webhooks": {
      "get": {
        "operationId": "list_db_webhooks",
        "summary": "데이터베이스 웹훅 목록",
        "description": "표의 변경을 알리는 웹훅과 최근 전달 결과를 봐요. attached가 false면 표가 지워져 멈춘 것이에요. 서명 키(signing_secret)는 만들 때(create_db_webhook) 한 번만 보여주고, 목록에는 signing_secret_set과 끝 네 글자(signing_secret_last4)만 실어요.",
        "tags": [
          "webhooks"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "webhooks": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_db_webhooks"
      },
      "post": {
        "operationId": "create_db_webhook",
        "summary": "데이터베이스 웹훅 만들기",
        "description": "표에 줄이 추가·수정·삭제되면 커밋 후 몇 초 안에 POST로 알려요. kind가 url이면 target은 공개 https 주소(사설 주소 불가, 리다이렉트 안 따라감), function이면 이 프로젝트의 함수 이름이에요. 본문: { type: \"INSERT\"|\"UPDATE\"|\"DELETE\", table, schema: \"public\", record, old_record, hook, delivery, occurred_at }. 서명 헤더: x-blackwall-signature: t=<초>,v1=<HMAC-SHA256(signing_secret, \"<t>.<본문>\") 16진수>. signing_secret은 이 응답에만 실려요. 다시 볼 수 없으니 받는 쪽에 바로 저장하세요. 실패(2xx 아님, 10초 초과)하면 10초·1분·5분·30분 뒤 다시 보내고 다섯 번째에 버려요.",
        "tags": [
          "webhooks"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "webhook": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          },
          "500": {
            "$ref": "#/components/responses/E500"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_db_webhook",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "A name to recognise the webhook by."
                  },
                  "table": {
                    "type": "string",
                    "description": "list_tables의 표 이름."
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "insert",
                        "update",
                        "delete"
                      ]
                    },
                    "description": "Which changes to send: insert, update, delete."
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "url",
                      "function"
                    ],
                    "description": "url to POST to an address, function to call a function in this project."
                  },
                  "target": {
                    "type": "string",
                    "description": "The https address, or the function name."
                  }
                },
                "required": [
                  "name",
                  "table",
                  "events",
                  "kind",
                  "target"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/webhooks/{webhook}": {
      "patch": {
        "operationId": "set_db_webhook_enabled",
        "summary": "데이터베이스 웹훅 켜기·끄기",
        "description": "웹훅을 끄거나 켜요. 꺼진 동안의 변경은 나중에도 보내지 않아요. webhook은 id나 이름이에요.",
        "tags": [
          "webhooks"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "webhook",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The webhook id or name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "enabled": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_db_webhook_enabled",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true to turn it on, false to turn it off."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_db_webhook",
        "summary": "데이터베이스 웹훅 삭제",
        "description": "웹훅과 그 전달 기록, 아직 보내지 못한 변경을 지워요.",
        "tags": [
          "webhooks"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "webhook",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The webhook id or name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_db_webhook"
      }
    },
    "/projects/{ref}/webhooks/{webhook}/deliveries": {
      "get": {
        "operationId": "list_db_webhook_deliveries",
        "summary": "데이터베이스 웹훅 전달 기록",
        "description": "웹훅의 최근 전달과 응답 상태, 실패 이유를 최신순으로 봐요. 7일간 보관해요.",
        "tags": [
          "webhooks"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "webhook",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The webhook id or name."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "How many deliveries to show."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "deliveries": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_db_webhook_deliveries"
      }
    },
    "/projects/{ref}/jobs": {
      "get": {
        "operationId": "list_jobs",
        "summary": "예약 작업 목록",
        "description": "예약 작업(cron)과 일정, 다음 실행 시각, 마지막 결과를 봐요. SQL의 cron.schedule로 만든 작업은 source가 sql이에요. limit은 요금제의 작업 수 한도예요. 시각은 모두 UTC예요.",
        "tags": [
          "jobs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "timezone": {},
                    "limit": {},
                    "used": {},
                    "jobs": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_jobs"
      }
    },
    "/projects/{ref}/jobs/{job}": {
      "put": {
        "operationId": "save_job",
        "summary": "예약 작업 만들기·바꾸기",
        "description": "정해진 일정마다 함수를 부르거나 SQL 한 문장을 실행해요. 같은 이름이면 그 작업을 바꿔요. schedule은 다섯 칸 cron(분 시 일 월 요일), UTC 기준이에요(한국 자정 = \"0 15 * * *\"). kind가 function이면 target은 함수 이름(본문 {}로 POST), sql이면 서비스 역할로 실행할 SQL이에요. 외부 URL은 못 불러요: 함수나 SQL의 net.http_post를 쓰세요. SQL은 timeout_seconds(기본 120초) 안에 끝나야 해요(statement_timeout을 늘리면 그만큼). 최대는 Free 300초, Pro·Enterprise 3600초예요. SQL의 cron.schedule로 만든 작업도 source=sql로 나와요. 프로젝트당 작업 수 한도는 list_jobs의 limit이에요.",
        "tags": [
          "jobs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "job",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The job name. Saving a name that exists changes that job."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "timezone": {},
                    "job": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "save_job",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "schedule": {
                    "type": "string",
                    "description": "예: \"*/5 * * * *\" (5분마다), \"0 15 * * *\" (한국 자정)."
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "function",
                      "sql"
                    ],
                    "description": "function to call a deployed function, sql to run SQL."
                  },
                  "target": {
                    "type": "string",
                    "description": "The function name, or the SQL to run."
                  },
                  "enabled": {
                    "type": "boolean",
                    "description": "Whether the job runs. On by default."
                  },
                  "timeout_seconds": {
                    "type": "number",
                    "description": "SQL 작업이 실행될 수 있는 최대 시간(초). 기본 120, 최대는 요금제마다(Free 300, Pro·Enterprise 3600)."
                  }
                },
                "required": [
                  "schedule",
                  "kind",
                  "target"
                ]
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "set_job_enabled",
        "summary": "예약 작업 켜기·끄기",
        "description": "예약 작업을 끄거나 다시 켜요. 다시 켜면 놓친 실행을 몰아서 하지 않고 다음 일정부터 돌아요. job은 id나 이름이에요.",
        "tags": [
          "jobs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "job",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The job id or name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "enabled": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_job_enabled",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true to turn it on, false to turn it off."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_job",
        "summary": "예약 작업 삭제",
        "description": "예약 작업 하나와 그 실행 기록을 지워요.",
        "tags": [
          "jobs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "job",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The job id or name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_job"
      }
    },
    "/projects/{ref}/schemas": {
      "get": {
        "operationId": "list_schemas",
        "summary": "프로젝트 스키마",
        "description": "프로젝트가 SQL로 만든 스키마(public 제외)와 데이터 API 노출 여부(exposed)를 봐요. 데이터베이스 안 이름은 app_<ref>_이름이지만 SQL과 클라이언트에선 만든 이름을 그대로 써요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "always_exposed": {},
                    "schemas": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_schemas"
      }
    },
    "/projects/{ref}/schemas/exposed": {
      "put": {
        "operationId": "set_exposed_schemas",
        "summary": "노출 스키마 정하기",
        "description": "데이터 API가 public 말고도 답할 스키마 목록을 통째로 정해요(빈 목록은 public만). Accept-Profile 헤더나 supabase-js의 .schema()로 써요. RLS와 권한은 public과 같아요. 30초 안에 적용돼요. 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "exposed": {},
                    "schemas": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_exposed_schemas",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "exposed": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "노출할 스키마 이름들(list_schemas의 name). public은 늘 노출돼요."
                  }
                },
                "required": [
                  "exposed"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/data-api": {
      "get": {
        "operationId": "get_data_api_settings",
        "summary": "데이터 API 설정 보기",
        "description": "데이터 API(/rest/v1)가 켜졌는지, 최대 행 수(max_rows, null은 제한 없음), 노출 스키마, search_path를 봐요. search_path_choices는 넣을 수 있는 스키마예요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "enabled": {},
                    "max_rows": {},
                    "exposed_schemas": {},
                    "search_path": {},
                    "search_path_choices": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_data_api_settings"
      },
      "patch": {
        "operationId": "set_data_api_settings",
        "summary": "데이터 API 설정 바꾸기",
        "description": "데이터 API(/rest/v1)를 켜고 끄고, 최대 행 수와 search_path를 정해요. 준 것만 바꿔요. search_path의 스키마는 요청 스키마 뒤에 붙어 이름 없이 찾을 수 있어요. 30초 안에 적용돼요. 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_data_api_settings",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "false면 /rest/v1이 모두 404로 답해요."
                  },
                  "max_rows": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 1000000,
                    "description": "한 번에 돌려주는 최대 행 수. null이면 제한 없음."
                  },
                  "search_path": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 20,
                    "description": "검색 경로에 넣을 스키마(get_data_api_settings의 search_path_choices의 name). 빈 목록이면 넣지 않아요."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/jobs/{job}/run": {
      "post": {
        "operationId": "run_job",
        "summary": "예약 작업 지금 실행",
        "description": "일정을 기다리지 않고 1분 안에 한 번 실행해요. 결과는 list_job_runs로 봐요.",
        "tags": [
          "jobs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "job",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The job id or name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "run_job"
      }
    },
    "/projects/{ref}/jobs/{job}/runs": {
      "get": {
        "operationId": "list_job_runs",
        "summary": "예약 작업 실행 기록",
        "description": "예약 작업의 최근 실행과 결과, 실패했다면 그 오류를 최신순으로 봐요.",
        "tags": [
          "jobs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "job",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The job id or name."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "description": "How many runs to show."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "runs": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_job_runs"
      }
    },
    "/projects/{ref}/env": {
      "get": {
        "operationId": "list_env_vars",
        "summary": "환경 변수 보기",
        "description": "배포한 앱이 빌드·실행 때 받는 환경 변수예요. 같은 이름이 production과 preview에 따로 있을 수 있어요. 민감한 값은 value_hint(뒤 네 자리)만 줘요. readable이 false면 빌드에서 빠지니 다시 저장하세요. automatic은 저장하지 않아도 들어가는 변수예요(SUPABASE_URL, NEXT_PUBLIC_SUPABASE_URL, SUPABASE_ANON_KEY, NEXT_PUBLIC_SUPABASE_ANON_KEY, NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY, SUPABASE_SERVICE_ROLE_KEY). available_in은 들어가는 곳으로, SUPABASE_SERVICE_ROLE_KEY는 실행(runtime)에만 들어가요. 같은 이름으로 저장한 값이 먼저이고 빌드에도 들어가요(overridden_in).",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "automatic": {},
                    "variables": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "secrets.read (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "list_env_vars"
      },
      "post": {
        "operationId": "set_env_vars",
        "summary": "환경 변수 저장",
        "description": "환경 변수를 저장해요. variables로 하나씩, 또는 dotenv에 .env 내용을 통째로 줘요. 같은 이름은 덮어쓰고, 하나라도 틀리면 아무것도 저장하지 않아요. 단, dotenv에서 플랫폼이 정하는 이름의 줄은 건너뛰고 skipped에 알려 줘요. PORT, HOST, HOSTNAME, HOME과 BLACKWALL_로 시작하는 이름은 못 써요. CI는 빌드에 기본 1이고, 직접 정하면(CI=false 등) 그 값을 써요. 다음 배포부터 적용돼요. sensitive를 빼면 비밀 같은 이름(API_KEY, STRIPE_SECRET, DATABASE_URL 등)은 민감한 값으로 저장돼 다시 못 읽어요(sensitive_keys). production 값은 소유자·관리자만 바꿔요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_env_vars",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "variables": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "value": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "key",
                        "value"
                      ],
                      "additionalProperties": false
                    },
                    "description": "A list of { key, value }."
                  },
                  "dotenv": {
                    "type": "string",
                    "description": ".env 파일 내용. 주석과 빈 줄은 건너뛰어요."
                  },
                  "targets": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "production",
                        "preview",
                        "development"
                      ]
                    },
                    "minItems": 1,
                    "description": "preview는 프로덕션 브랜치가 아닌 모든 브랜치의 배포예요."
                  },
                  "sensitive": {
                    "type": "boolean",
                    "description": "true면 저장한 뒤 값을 다시 읽을 수 없어요. 주지 않으면 이름에 SECRET, TOKEN, PASSWORD, PRIVATE, DSN, DATABASE_URL이 들어가거나 _KEY로 끝나거나 KEY_가 든 변수만 민감한 값으로 저장해요. false면 모두 다시 읽을 수 있어요."
                  },
                  "app": {
                    "type": "string",
                    "description": "이 앱에만 넣을 때 앱 이름(list_apps의 name). 같은 이름의 프로젝트 변수보다 먼저예요. 비우면 프로젝트의 모든 앱."
                  },
                  "branch": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "이 git 브랜치의 미리보기에만 넣을 때 브랜치 이름. targets는 preview 하나여야 해요. app과 함께 쓰면 그 앱의 그 브랜치에만 들어가요. 비우면 모든 미리보기."
                  }
                },
                "required": [
                  "targets"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/env/{target}/{key}": {
      "delete": {
        "operationId": "remove_env_var",
        "summary": "환경 변수 삭제",
        "description": "환경 변수 하나를 production이나 preview 중 한 곳에서 지워요. 민감한 값이었다면 되살릴 수 없어요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "target",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "production",
                "preview",
                "development"
              ],
              "description": "production or preview."
            }
          },
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The variable name."
            }
          },
          {
            "name": "app",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "앱에만 넣은 변수를 지울 때 앱 이름. 비우면 프로젝트의 변수."
            }
          },
          {
            "name": "branch",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200,
              "description": "한 git 브랜치의 미리보기에만 넣은 변수를 지울 때 브랜치 이름(list_env_vars의 branch)."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {},
                    "target": {},
                    "app": {},
                    "branch": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_env_var"
      }
    },
    "/projects/{ref}/auth/providers": {
      "get": {
        "operationId": "list_auth_providers",
        "summary": "소셜 로그인 설정 보기",
        "description": "로그인할 수 있는 제공자를 모두 봐요(설정 전이면 configured: false). 직접 등록한 custom:<이름>은 custom 항목(주소, scopes, 필드 매핑)과 함께 나와요. callback_url은 제공자 콘솔에 붙여 넣을 주소예요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "anonymous_sign_in": {},
                    "providers": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_auth_providers"
      }
    },
    "/projects/{ref}/auth/providers/{provider}": {
      "put": {
        "operationId": "set_auth_provider",
        "summary": "소셜 로그인 켜기",
        "description": "제공자 하나의 클라이언트 ID와 시크릿을 저장하고 켜요(시크릿은 암호화해 저장하고 뒤 네 자리만 보여요). 먼저 제공자 콘솔에 list_auth_providers의 callback_url을 등록하세요. ID만 고치려면 client_secret을 빈 문자열로 둬요. provider를 custom:<이름>으로 주면 목록에 없는 OAuth 2.0·OpenID Connect 제공자를 등록해요: issuer(OIDC) 또는 authorize_url·token_url(·userinfo_url)이 필요하고, scopes와 claims(id·email·email_verified·name·avatar·phone이 응답의 어느 필드인지, 점 경로)를 줄 수 있어요. 앱에서는 signInWithOAuth({ provider: \"custom:<이름>\" })로 부르고, 로그인 직후 세션에 provider_token이 한 번 와요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^(google|kakao|naver|apple|github|gitlab|microsoft|facebook|line|discord|x|bitbucket|figma|linkedin_oidc|notion|twitch|slack_oidc|spotify|zoom|azure|keycloak|workos|twitter|slack|custom:[a-z0-9][a-z0-9_-]{0,39})$",
              "description": "로그인 제공자. google(구글), kakao(카카오), naver(네이버), apple(애플), github(GitHub), gitlab(GitLab), microsoft(Microsoft), facebook(Facebook), line(LINE), discord(Discord), x(X), bitbucket(Bitbucket), figma(Figma), linkedin_oidc(LinkedIn), notion(Notion), twitch(Twitch), slack_oidc(Slack), spotify(Spotify), zoom(Zoom), azure(Microsoft Entra ID), keycloak(Keycloak), workos(WorkOS), twitter(Twitter (OAuth 1.0a)), slack(Slack (legacy)), 또는 직접 등록하는 제공자 custom:<이름>(영문 소문자·숫자·-·_, 40자까지)"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "provider": {},
                    "enabled": {},
                    "callback_url": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_auth_provider",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_id": {
                    "type": "string",
                    "description": "The client ID from the provider's console."
                  },
                  "client_secret": {
                    "type": "string",
                    "description": "빈 문자열이면 이미 저장된 시크릿을 그대로 둬요. 새 제공자에는 반드시 필요해요."
                  },
                  "enabled": {
                    "type": "boolean",
                    "description": "기본값은 켜짐이에요."
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "set_auth_provider_enabled",
        "summary": "소셜 로그인 껐다 켜기",
        "description": "저장된 자격증명은 두고 제공자만 껐다 켜요. 다시 켤 때 시크릿을 새로 넣지 않아도 돼요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^(google|kakao|naver|apple|github|gitlab|microsoft|facebook|line|discord|x|bitbucket|figma|linkedin_oidc|notion|twitch|slack_oidc|spotify|zoom|azure|keycloak|workos|twitter|slack|custom:[a-z0-9][a-z0-9_-]{0,39})$",
              "description": "로그인 제공자. google(구글), kakao(카카오), naver(네이버), apple(애플), github(GitHub), gitlab(GitLab), microsoft(Microsoft), facebook(Facebook), line(LINE), discord(Discord), x(X), bitbucket(Bitbucket), figma(Figma), linkedin_oidc(LinkedIn), notion(Notion), twitch(Twitch), slack_oidc(Slack), spotify(Spotify), zoom(Zoom), azure(Microsoft Entra ID), keycloak(Keycloak), workos(WorkOS), twitter(Twitter (OAuth 1.0a)), slack(Slack (legacy)), 또는 직접 등록하는 제공자 custom:<이름>(영문 소문자·숫자·-·_, 40자까지)"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "provider": {},
                    "enabled": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_auth_provider_enabled",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true to turn it on, false to turn it off."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_auth_provider",
        "summary": "소셜 로그인 지우기",
        "description": "제공자 설정을 자격증명째로 지워요(다시 쓰려면 시크릿을 새로 받아야 해요). 잠시 끄려면 set_auth_provider_enabled를 쓰세요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^(google|kakao|naver|apple|github|gitlab|microsoft|facebook|line|discord|x|bitbucket|figma|linkedin_oidc|notion|twitch|slack_oidc|spotify|zoom|azure|keycloak|workos|twitter|slack|custom:[a-z0-9][a-z0-9_-]{0,39})$",
              "description": "로그인 제공자. google(구글), kakao(카카오), naver(네이버), apple(애플), github(GitHub), gitlab(GitLab), microsoft(Microsoft), facebook(Facebook), line(LINE), discord(Discord), x(X), bitbucket(Bitbucket), figma(Figma), linkedin_oidc(LinkedIn), notion(Notion), twitch(Twitch), slack_oidc(Slack), spotify(Spotify), zoom(Zoom), azure(Microsoft Entra ID), keycloak(Keycloak), workos(WorkOS), twitter(Twitter (OAuth 1.0a)), slack(Slack (legacy)), 또는 직접 등록하는 제공자 custom:<이름>(영문 소문자·숫자·-·_, 40자까지)"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "provider": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_auth_provider"
      }
    },
    "/projects/{ref}/auth/redirect-urls": {
      "get": {
        "operationId": "list_redirect_urls",
        "summary": "로그인 후 돌아갈 주소 목록",
        "description": "로그인이 끝난 사람을 돌려보낼 수 있는 주소예요. 여기 없는 주소로는 돌려보내지 않아요. 로그인은 되는데 아무 데도 안 간다면 여기부터 보세요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "urls": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_redirect_urls"
      },
      "post": {
        "operationId": "add_redirect_url",
        "summary": "돌아갈 주소 추가",
        "description": "주소 하나를 허용 목록에 넣어요. 스킴·호스트·포트가 모두 같아야 하고 경로는 보지 않아서 https://app.example.com/callback을 넣으면 https://app.example.com이 저장돼요. 모바일 앱은 자기 스킴(co.example.app://callback)을 넣으면 co.example.app://callback이 저장돼요. 점이 들어간 앱 스킴만 받아요. 응답에 실제로 저장된 목록이 와요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "urls": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "add_redirect_url",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "The address, for example https://app.example.com."
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_redirect_url",
        "summary": "돌아갈 주소 제거",
        "description": "허용 목록에서 주소 하나를 빼요. list_redirect_urls가 돌려준 그대로 넣으세요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "urls": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_redirect_url",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "The address, as list_redirect_urls returned it."
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/auth/sms": {
      "get": {
        "operationId": "get_sms_settings",
        "summary": "문자 로그인 설정 보기",
        "description": "전화번호 인증번호 로그인에 쓰는 문자 계정을 봐요: 제공자, 발신 번호, 허용 국가, 인증번호 길이·유효 시간, 시간당 한도. 자격증명은 뒤 네 자리만 보여요. platform_available이면 플랫폼 계정(1건 ₩100, 국내만)도 돼요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "configured": {},
                    "provider": {},
                    "enabled": {},
                    "sender": {},
                    "allowed_countries": {},
                    "otp_length": {},
                    "otp_ttl_seconds": {},
                    "hourly_limit": {},
                    "template": {},
                    "key_hint": {},
                    "secret_hint": {},
                    "account_hint": {},
                    "credentials_readable": {},
                    "platform_available": {},
                    "providers": {},
                    "updated_at": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_sms_settings"
      },
      "put": {
        "operationId": "set_sms_settings",
        "summary": "문자 로그인 설정",
        "description": "문자 계정을 저장하고 켜요. 직접 계약한 제공자면 key·secret·account와 등록한 발신 번호가 필요해요(Solapi: API Key·API Secret, NHN Cloud: App Key·Secret Key, Aligo: API Key·User ID(account), Twilio·Twilio Verify: Account SID(account)·Auth Token(secret), MessageBird·Textlocal: key, Vonage: key·secret. MessageBird·Textlocal·Vonage는 11자 이하 발신자 ID, Twilio Verify는 VA로 시작하는 Verify Service SID도 돼요). 나머지 설정은 update_auth_config의 SMS_* 키로 바꿔요. 비운 자격증명은 그대로예요. allowed_countries는 기본 82(한국)만이고, 모르는 나라를 넣으면 해외 유료 번호 문자 사기에 노출돼요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_sms_settings",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "platform",
                      "solapi",
                      "nhn",
                      "aligo",
                      "twilio",
                      "messagebird",
                      "textlocal",
                      "vonage",
                      "twilio_verify"
                    ],
                    "description": "platform (the platform account, paid plans only), solapi, nhn, aligo, twilio, messagebird, textlocal, vonage or twilio_verify."
                  },
                  "key": {
                    "type": "string",
                    "description": "Solapi API Key, NHN Cloud App Key or Aligo API Key. Empty keeps the stored one."
                  },
                  "secret": {
                    "type": "string",
                    "description": "Solapi API Secret, NHN Cloud Secret Key or Twilio Auth Token. Empty keeps the stored one."
                  },
                  "account": {
                    "type": "string",
                    "description": "Aligo User ID or Twilio Account SID. Empty keeps the stored one."
                  },
                  "sender": {
                    "type": "string",
                    "description": "발신 번호. 예: 01012345678. Twilio는 +1… 번호나 MG로 시작하는 Messaging Service SID."
                  },
                  "allowed_countries": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "국가 번호 목록. 예: [\"82\"]."
                  },
                  "otp_length": {
                    "type": "integer",
                    "minimum": 6,
                    "maximum": 10,
                    "description": "Digits in a code, 6 to 10. Default 6."
                  },
                  "otp_ttl_seconds": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 3600,
                    "description": "How long a code is valid, 60 to 3600 seconds. Default 300."
                  },
                  "hourly_limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100000,
                    "description": "Most messages the whole project may send in an hour. Default 200."
                  },
                  "template": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "{{code}}나 {{ .Code }}가 들어간 문구. null이면 기본 문구."
                  },
                  "enabled": {
                    "type": "boolean",
                    "description": "On by default."
                  }
                },
                "required": [
                  "provider"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_sms_settings",
        "summary": "문자 로그인 지우기",
        "description": "문자 계정 설정을 자격증명째로 지워요. 이후 전화번호 로그인은 phone_provider_disabled로 거부돼요. 잠시 끄려면 set_sms_settings에 enabled: false를 주세요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_sms_settings"
      }
    },
    "/projects/{ref}/auth/smtp": {
      "get": {
        "operationId": "get_smtp_settings",
        "summary": "SMTP 설정 보기",
        "description": "인증 메일을 보내는 SMTP 서버와 보내는 사람을 봐요. 비밀번호는 password_hint(뒤 네 자리)만 와요. configured가 false거나 last_error가 있으면(그 서버가 거부) 플랫폼 주소로 보내요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "configured": {},
                    "enabled": {},
                    "sender_email": {},
                    "sender_name": {},
                    "host": {},
                    "port": {},
                    "username": {},
                    "password_hint": {},
                    "password_readable": {},
                    "minimum_interval_seconds": {},
                    "rate_limit_per_hour": {},
                    "last_sent_at": {},
                    "last_error": {},
                    "last_error_at": {},
                    "updated_at": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_smtp_settings"
      },
      "put": {
        "operationId": "set_smtp_settings",
        "summary": "SMTP 설정",
        "description": "인증 메일을 이 프로젝트의 SMTP 서버와 보내는 사람으로 보내요. 처음엔 sender_email, host, username, password가 필요하고, 그 뒤엔 바꿀 값만 줘요(password를 비우면 그대로). 공인 주소와 TLS(465 또는 STARTTLS)가 필요해요. 서버가 거부하면 플랫폼 주소로 대신 보내고 last_error에 남겨요. 저장 후 test_smtp_settings로 확인하세요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_smtp_settings",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sender_email": {
                    "type": "string",
                    "description": "보내는 메일 주소(Sender email). 예: no-reply@shop.example."
                  },
                  "sender_name": {
                    "type": "string",
                    "description": "보내는 사람 이름(Sender name). 예: 우리 가게."
                  },
                  "host": {
                    "type": "string",
                    "description": "SMTP 서버 주소(Host). 예: smtp.sendgrid.net."
                  },
                  "port": {
                    "type": "integer",
                    "enum": [
                      25,
                      465,
                      587,
                      2465,
                      2525
                    ],
                    "description": "포트(Port). 기본 587."
                  },
                  "username": {
                    "type": "string",
                    "description": "SMTP 사용자 이름(Username)."
                  },
                  "password": {
                    "type": "string",
                    "description": "SMTP 비밀번호(Password). 비우면 저장된 값을 써요."
                  },
                  "minimum_interval_seconds": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 3600,
                    "description": "같은 주소로 다시 보내기까지의 최소 간격(초). 기본 60."
                  },
                  "rate_limit_per_hour": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10000,
                    "description": "프로젝트 전체가 한 시간에 보낼 수 있는 메일 수. 기본 100. 넘으면 over_email_send_rate_limit(429)로 거부돼요."
                  },
                  "enabled": {
                    "type": "boolean",
                    "description": "false면 설정은 두고 플랫폼 발신 주소로 보내요."
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_smtp_settings",
        "summary": "SMTP 설정 지우기",
        "description": "SMTP 설정을 비밀번호째로 지워요. 이후 인증 메일은 플랫폼 발신 주소로 나가요. 잠시 멈추려면 set_smtp_settings에 enabled: false를 주세요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "removed": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_smtp_settings"
      }
    },
    "/projects/{ref}/auth/smtp/test": {
      "post": {
        "operationId": "test_smtp_settings",
        "summary": "SMTP 시험 메일 보내기",
        "description": "저장된 SMTP 서버로 시험 메일 한 통을 보내요. 플랫폼으로 대신 보내지 않아서, 실패하면 그 서버가 준 이유가 그대로 나와요. to를 빼면 호출한 사람의 주소로 보내요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "sent": {},
                    "to": {},
                    "sender_email": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "test_smtp_settings",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "받을 주소. 빼면 내 주소."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/auth/templates": {
      "get": {
        "operationId": "get_projects_ref_auth_templates",
        "summary": "이메일 템플릿 보기",
        "description": "인증 메일 여섯 종류(confirmation, invite, magic_link, recovery, email_change, reauthentication)의 제목과 HTML 본문이에요. custom이 false면 기본 문구(한국어·영어·일본어)를 써요. type을 주면 그 하나만 봐요. 변수는 Supabase와 같아요: {{ .ConfirmationURL }}, {{ .Token }}, {{ .TokenHash }}, {{ .SiteURL }}, {{ .Email }}, {{ .NewEmail }}, {{ .RedirectTo }}, {{ .Data.<key> }}.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "variables": {},
                    "templates": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_email_templates"
      }
    },
    "/projects/{ref}/auth/templates/{type}": {
      "get": {
        "operationId": "get_projects_ref_auth_templates_type",
        "summary": "이메일 템플릿 보기",
        "description": "인증 메일 여섯 종류(confirmation, invite, magic_link, recovery, email_change, reauthentication)의 제목과 HTML 본문이에요. custom이 false면 기본 문구(한국어·영어·일본어)를 써요. type을 주면 그 하나만 봐요. 변수는 Supabase와 같아요: {{ .ConfirmationURL }}, {{ .Token }}, {{ .TokenHash }}, {{ .SiteURL }}, {{ .Email }}, {{ .NewEmail }}, {{ .RedirectTo }}, {{ .Data.<key> }}.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "confirmation",
                "invite",
                "magic_link",
                "recovery",
                "email_change",
                "reauthentication",
                "password_changed",
                "email_changed",
                "mfa_enrolled",
                "mfa_removed",
                "identity_linked",
                "identity_unlinked"
              ],
              "description": "confirmation, invite, magic_link, recovery, email_change or reauthentication."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "variables": {},
                    "templates": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_email_templates"
      },
      "put": {
        "operationId": "set_email_template",
        "summary": "이메일 템플릿 저장",
        "description": "한 종류의 제목과 HTML 본문을 정해요(Supabase 템플릿 그대로 돼요). 제목은 한 줄, {{ if }} 같은 문법은 거부돼요. reauthentication은 아직 보내지 않아요. 저장 전에 preview_email_template로 확인하세요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "confirmation",
                "invite",
                "magic_link",
                "recovery",
                "email_change",
                "reauthentication",
                "password_changed",
                "email_changed",
                "mfa_enrolled",
                "mfa_removed",
                "identity_linked",
                "identity_unlinked"
              ],
              "description": "confirmation, invite, magic_link, recovery, email_change or reauthentication."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_email_template",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "subject": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "The subject line, up to 200 characters."
                  },
                  "body": {
                    "type": "string",
                    "maxLength": 50000,
                    "description": "본문 HTML. 예: <a href=\"{{ .ConfirmationURL }}\">가입 확인</a>"
                  }
                },
                "required": [
                  "subject",
                  "body"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_email_template",
        "summary": "이메일 템플릿 되돌리기",
        "description": "한 종류의 템플릿을 지우고 기본 문구(한국어·영어·일본어)로 돌아가요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "confirmation",
                "invite",
                "magic_link",
                "recovery",
                "email_change",
                "reauthentication",
                "password_changed",
                "email_changed",
                "mfa_enrolled",
                "mfa_removed",
                "identity_linked",
                "identity_unlinked"
              ],
              "description": "confirmation, invite, magic_link, recovery, email_change or reauthentication."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "type": {},
                    "removed": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_email_template"
      }
    },
    "/projects/{ref}/auth/templates/{type}/preview": {
      "post": {
        "operationId": "preview_email_template",
        "summary": "이메일 템플릿 미리보기",
        "description": "예시 값을 넣어 메일이 어떻게 보일지 돌려줘요(제목, HTML, 텍스트). subject와 body를 주면 저장하지 않고 그 내용을, 빼면 저장된 템플릿이나 기본 문구를 보여 줘요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "confirmation",
                "invite",
                "magic_link",
                "recovery",
                "email_change",
                "reauthentication",
                "password_changed",
                "email_changed",
                "mfa_enrolled",
                "mfa_removed",
                "identity_linked",
                "identity_unlinked"
              ],
              "description": "confirmation, invite, magic_link, recovery, email_change or reauthentication."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "type": {},
                    "custom": {},
                    "subject": {},
                    "html": {},
                    "text": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "preview_email_template",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "subject": {
                    "type": "string",
                    "description": "A subject to try without saving."
                  },
                  "body": {
                    "type": "string",
                    "description": "A body to try without saving."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/auth/sso": {
      "get": {
        "operationId": "list_sso_providers",
        "summary": "SAML SSO 보기",
        "description": "이 프로젝트에 등록된 SAML IdP와 이메일 도메인, 그리고 IdP에 넣어야 하는 두 주소(acs_url, entity_id)를 봐요. 앱에서는 supabase.auth.signInWithSSO({ domain })로 로그인해요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "acs_url": {},
                    "entity_id": {},
                    "metadata_url": {},
                    "new_providers_allowed": {},
                    "providers": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_sso_providers"
      }
    },
    "/projects/{ref}/{param0}/{param1}": {
      "post": {
        "operationId": "post_projects_ref_param0_param1",
        "summary": "SAML SSO 추가",
        "description": "IdP 메타데이터(https 주소나 XML)로 SAML IdP를 등록해요(HTTP-Redirect 로그인 주소와 서명 인증서 필요). domains의 이메일로 signInWithSSO를 부르면 이 IdP로 가요(도메인 하나에 IdP 하나). 새 IdP는 엔터프라이즈 요금제에서만 추가돼요(new_providers_allowed). 이미 등록한 IdP는 그대로 동작해요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "param0",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "param1",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {},
                    "entity_id": {},
                    "metadata_url": {},
                    "domains": {},
                    "attribute_mapping": {},
                    "created_at": {},
                    "updated_at": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "add_sso_provider",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "metadata_url": {
                    "type": "string",
                    "description": "https 주소. metadata_xml과 둘 중 하나."
                  },
                  "metadata_xml": {
                    "type": "string",
                    "description": "The IdP's metadata XML. Give this or metadata_url."
                  },
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "예: [\"example.com\"]"
                  },
                  "attribute_mapping": {
                    "type": "object",
                    "description": "GoTrue 형식: {\"keys\": {\"email\": {\"name\": \"mail\"}}}"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/{param0}/{param1}/{param2}": {
      "put": {
        "operationId": "put_projects_ref_param0_param1_param2",
        "summary": "SAML SSO 추가",
        "description": "IdP 메타데이터(https 주소나 XML)로 SAML IdP를 등록해요(HTTP-Redirect 로그인 주소와 서명 인증서 필요). domains의 이메일로 signInWithSSO를 부르면 이 IdP로 가요(도메인 하나에 IdP 하나). 새 IdP는 엔터프라이즈 요금제에서만 추가돼요(new_providers_allowed). 이미 등록한 IdP는 그대로 동작해요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "param0",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "param1",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "param2",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {},
                    "entity_id": {},
                    "metadata_url": {},
                    "domains": {},
                    "attribute_mapping": {},
                    "created_at": {},
                    "updated_at": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "add_sso_provider",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "metadata_url": {
                    "type": "string",
                    "description": "https 주소. metadata_xml과 둘 중 하나."
                  },
                  "metadata_xml": {
                    "type": "string",
                    "description": "The IdP's metadata XML. Give this or metadata_url."
                  },
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "예: [\"example.com\"]"
                  },
                  "attribute_mapping": {
                    "type": "object",
                    "description": "GoTrue 형식: {\"keys\": {\"email\": {\"name\": \"mail\"}}}"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/auth/sso/{id}": {
      "delete": {
        "operationId": "remove_sso_provider",
        "summary": "SAML SSO 지우기",
        "description": "IdP 하나를 지워요. 그 IdP로 가입한 사용자 계정은 남지만 더는 SSO로 로그인할 수 없어요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_sso_providers의 id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_sso_provider"
      }
    },
    "/projects/{ref}/config/auth": {
      "get": {
        "operationId": "get_auth_config",
        "summary": "로그인 설정 전체 보기",
        "description": "로그인 설정 전체를 Supabase auth config와 같은 소문자 키로 돌려줘요: 가입(disable_signup, mailer_autoconfirm 등), 이메일·비밀번호 규칙, 전화·문자(sms_*), SAML(saml_*), Web3, 소셜 제공자별 external_<제공자>_*. 비밀 값은 ••••abcd처럼 뒤 네 자리만 오고, 그대로 update_auth_config에 돌려주면 바뀌지 않아요. callback_url은 제공자 콘솔에 붙여 넣을 주소예요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_auth_config"
      },
      "patch": {
        "operationId": "update_auth_config",
        "summary": "로그인 설정 바꾸기",
        "description": "준 키만 바꿔요(대문자 GoTrue 이름도 돼요). 콘솔 로그인 화면과 같은 규칙으로 확인해요: 켠 제공자는 필요한 값이 다 있어야 하고(예: external_google_client_id), Apple 시크릿은 7일 넘게 남은 ES256 JWT, 문자 내용엔 {{ .Code }}가 있어야 해요. 하나라도 틀리면 아무것도 저장하지 않고 키마다 이유를 줘요. 카카오 동의 항목은 external_kakao_scopes(쉼표로), 네이버는 external_naver_scopes, Google·GitHub 추가 스코프는 external_<제공자>_additional_scopes예요. 비밀 값을 빈 문자열로 주면 지워요. 소유자·관리자·개발자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "update_auth_config",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/config/auth/custom-providers": {
      "get": {
        "operationId": "list_custom_providers",
        "summary": "사용자 정의 로그인 제공자 보기",
        "description": "프로젝트가 직접 정의한 OAuth·OIDC 제공자(custom:<ID>)와 요금제 한도(max_providers), 스위치(enabled)를 봐요. 앱에서는 signInWithOAuth({ provider: \"custom:<ID>\" })로 불러요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_custom_providers"
      },
      "post": {
        "operationId": "create_custom_provider",
        "summary": "사용자 정의 로그인 제공자 만들기",
        "description": "OAuth·OIDC 제공자(custom:<ID>)를 만들고 켜요(set_auth_provider와 같은 저장소). oidc는 issuer만 주면 {issuer}/.well-known/openid-configuration에서 주소와 jwks_uri를 읽고, id_token의 서명·issuer·대상·만료·nonce를 확인해요. oauth2는 issuer나 authorization_url·token_url이 필요하고, 빈 주소는 {issuer}/oauth/authorize, /oauth/token, /oauth/userinfo예요. claim_map은 id·email·email_verified·name·avatar·phone이 응답의 어느 필드인지(점 경로)예요. PKCE는 기본으로 켜져요. 요금제 한도를 넘으면 거부돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "create_custom_provider",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "pkce": {
                    "type": "boolean",
                    "description": "On by default; turn it off only if the provider refuses PKCE."
                  },
                  "pkce_enabled": {
                    "type": "string"
                  },
                  "identifier": {
                    "type": "string",
                    "description": "영문 소문자·숫자·하이픈. custom: 은 붙여도 되고 안 붙여도 돼요."
                  },
                  "name": {
                    "type": "string",
                    "description": "The display name, under 100 characters."
                  },
                  "label": {
                    "type": "string"
                  },
                  "provider_type": {
                    "type": "string",
                    "enum": [
                      "oidc",
                      "oauth2"
                    ],
                    "description": "oidc (endpoints discovered, id_token verified) or oauth2 (endpoints given, read through claim_map)."
                  },
                  "issuer": {
                    "type": "string",
                    "description": "The provider's base URL."
                  },
                  "discovery_url": {
                    "type": "string",
                    "description": "For oidc, when the discovery document is not at the standard path."
                  },
                  "authorization_url": {
                    "type": "string",
                    "description": "Required for oauth2 without an issuer; for oidc, empty is discovered."
                  },
                  "authorize_url": {
                    "type": "string"
                  },
                  "token_url": {
                    "type": "string",
                    "description": "Required for oauth2 without an issuer; for oidc, empty is discovered."
                  },
                  "userinfo_url": {
                    "type": "string",
                    "description": "Where the user is read; for oidc, empty is discovered."
                  },
                  "jwks_uri": {
                    "type": "string",
                    "description": "For oidc, to verify ID tokens; empty is discovered."
                  },
                  "client_id": {
                    "type": "string",
                    "description": "The client ID."
                  },
                  "client_secret": {
                    "type": "string",
                    "description": "The client secret."
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "For example [\"openid\", \"email\", \"profile\"]."
                  },
                  "email_optional": {
                    "type": "boolean",
                    "description": "Allow users without an email."
                  },
                  "claim_map": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      ]
                    },
                    "description": "Which field of the answer is id, email, email_verified, name, avatar and phone, as dotted paths. Left out: the OpenID standard names."
                  },
                  "claims": {
                    "type": "string"
                  },
                  "token_auth": {
                    "type": "string",
                    "enum": [
                      "body",
                      "basic"
                    ],
                    "description": "Send client_secret in the body (body, the default) or as HTTP Basic (basic)."
                  },
                  "enabled": {
                    "type": "boolean",
                    "description": "On by default."
                  }
                },
                "required": [
                  "identifier",
                  "name",
                  "provider_type",
                  "client_id",
                  "client_secret"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/config/auth/custom-providers/{identifier}": {
      "put": {
        "operationId": "update_custom_provider",
        "summary": "사용자 정의 로그인 제공자 수정",
        "description": "사용자 정의 제공자 하나를 고쳐요. ID는 바꿀 수 없어요. client_secret을 빈 문자열로 두면 저장된 시크릿을 그대로 써요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "identifier",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_custom_providers의 identifier"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "update_custom_provider",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "pkce": {
                    "type": "boolean",
                    "description": "On by default; turn it off only if the provider refuses PKCE."
                  },
                  "pkce_enabled": {
                    "type": "string"
                  },
                  "identifier": {
                    "type": "string",
                    "description": "list_custom_providers의 identifier"
                  },
                  "name": {
                    "type": "string",
                    "description": "The display name, under 100 characters."
                  },
                  "label": {
                    "type": "string"
                  },
                  "provider_type": {
                    "type": "string",
                    "enum": [
                      "oidc",
                      "oauth2"
                    ],
                    "description": "oidc (endpoints discovered, id_token verified) or oauth2 (endpoints given, read through claim_map)."
                  },
                  "issuer": {
                    "type": "string",
                    "description": "The provider's base URL."
                  },
                  "discovery_url": {
                    "type": "string",
                    "description": "For oidc, when the discovery document is not at the standard path."
                  },
                  "authorization_url": {
                    "type": "string",
                    "description": "Required for oauth2 without an issuer; for oidc, empty is discovered."
                  },
                  "authorize_url": {
                    "type": "string"
                  },
                  "token_url": {
                    "type": "string",
                    "description": "Required for oauth2 without an issuer; for oidc, empty is discovered."
                  },
                  "userinfo_url": {
                    "type": "string",
                    "description": "Where the user is read; for oidc, empty is discovered."
                  },
                  "jwks_uri": {
                    "type": "string",
                    "description": "For oidc, to verify ID tokens; empty is discovered."
                  },
                  "client_id": {
                    "type": "string",
                    "description": "The client ID."
                  },
                  "client_secret": {
                    "type": "string",
                    "description": "Empty keeps the stored secret."
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "For example [\"openid\", \"email\", \"profile\"]."
                  },
                  "email_optional": {
                    "type": "boolean",
                    "description": "Allow users without an email."
                  },
                  "claim_map": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      ]
                    },
                    "description": "Which field of the answer is id, email, email_verified, name, avatar and phone, as dotted paths. Left out: the OpenID standard names."
                  },
                  "claims": {
                    "type": "string"
                  },
                  "token_auth": {
                    "type": "string",
                    "enum": [
                      "body",
                      "basic"
                    ],
                    "description": "Send client_secret in the body (body, the default) or as HTTP Basic (basic)."
                  },
                  "enabled": {
                    "type": "boolean",
                    "description": "Turn it on or off as it is saved."
                  }
                },
                "required": [
                  "identifier",
                  "name",
                  "provider_type",
                  "client_id"
                ]
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "set_custom_provider_enabled",
        "summary": "사용자 정의 로그인 제공자 껐다 켜기",
        "description": "사용자 정의 제공자 하나를 끄거나 켜요. 끄면 지금 세션은 그대로지만 새 로그인은 다시 켤 때까지 실패해요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "identifier",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The identifier from list_custom_providers."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "set_custom_provider_enabled",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true to turn it on, false to turn it off."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_custom_provider",
        "summary": "사용자 정의 로그인 제공자 삭제",
        "description": "사용자 정의 제공자 하나를 지워요. 되돌릴 수 없고, 이 제공자로 로그인하던 사용자는 들어올 수 없어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "identifier",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The identifier from list_custom_providers."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "remove_custom_provider"
      }
    },
    "/projects/{ref}/config/auth/copy-from-import": {
      "post": {
        "operationId": "copy_auth_from_import",
        "summary": "로그인 설정 가져오기",
        "description": "import_sources에 연결한 Supabase 계정으로 그 프로젝트의 로그인 설정을 이 서버의 프로젝트(ref)에 복사해요: 켜 둔 소셜 제공자(Client ID·시크릿 등, update_auth_config와 같은 확인), 돌아갈 주소 목록(uri_allow_list, add_redirect_url과 같아요), 비어 있을 때만 site_url. 시크릿은 대화에 나오지 않아요. 답은 제공자마다 copied와 이유예요. 답의 callback_url을 각 제공자 콘솔에 등록하기 전에는 로그인이 실패해요. dry_run이면 아무것도 바꾸지 않고 보여만 줘요. 소유자·관리자·개발자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "source_project": {},
                    "dry_run": {},
                    "callback_url": {},
                    "providers": {},
                    "site_url": {},
                    "redirect_urls": {},
                    "console_url": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "copy_auth_from_import",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "providers": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "복사할 제공자(google, kakao, apple, x…). 비우면 Supabase에서 켜 둔 것 모두."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "description": "true면 바꾸지 않고 무엇을 복사할지만 보여줘요."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/config/auth/third-party-auth": {
      "get": {
        "operationId": "list_third_party_auth",
        "summary": "서드파티 인증 보기",
        "description": "Data API가 받는 다른 인증 서비스(Firebase, Clerk, WorkOS, Auth0, Amazon Cognito, OIDC issuer)의 토큰 목록이에요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_third_party_auth"
      },
      "post": {
        "operationId": "add_third_party_auth",
        "summary": "서드파티 인증 추가",
        "description": "다른 인증 서비스의 JWT로 로그인하게 해요. value는 type마다 달라요: firebase는 프로젝트 ID, clerk는 https://clerk.<도메인>이나 https://<이름>.clerk.accounts.dev, workos·oidc는 issuer URL, auth0은 테넌트 이름(<이름>.auth0.com의 앞부분), cognito는 사용자 풀 ID(region도 함께). Auth0·Cognito는 audiences도 넣으세요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "add_third_party_auth",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "firebase",
                      "clerk",
                      "workos",
                      "auth0",
                      "cognito",
                      "oidc"
                    ],
                    "description": "firebase, clerk, workos, auth0, cognito or oidc."
                  },
                  "value": {
                    "type": "string",
                    "description": "What the type takes, as above."
                  },
                  "region": {
                    "type": "string",
                    "description": "cognito의 AWS 리전. 예: ap-northeast-2"
                  },
                  "audiences": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Values a token’s aud must contain."
                  },
                  "jwks_url": {
                    "type": "string",
                    "description": "oidc에서 디스커버리 대신 쓸 JWKS 주소"
                  }
                },
                "required": [
                  "type",
                  "value"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/config/auth/third-party-auth/{id}": {
      "delete": {
        "operationId": "remove_third_party_auth",
        "summary": "서드파티 인증 삭제",
        "description": "서드파티 인증 하나를 지워요. 그 서비스로 로그인한 사용자의 요청은 30초 안에 401로 거부돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_third_party_auth의 id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "remove_third_party_auth"
      }
    },
    "/projects/{ref}/auth/anonymous": {
      "put": {
        "operationId": "set_anonymous_sign_in",
        "summary": "익명 로그인 켜기·끄기",
        "description": "이메일 없이 바로 세션을 받는 익명 로그인을 켜거나 꺼요. 지금 상태는 list_auth_providers의 anonymous_sign_in이에요.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "anonymous_sign_in": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_anonymous_sign_in",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true to turn it on, false to turn it off."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/git": {
      "get": {
        "operationId": "list_git_access",
        "summary": "Git 연결",
        "description": "배포하는 저장소(connected), 연결한 GitHub 계정(github_accounts), 비공개 저장소를 받을 방법(토큰 끝 네 글자, GitHub App 설치), GitHub 저장소마다 검사를 One Server에서 실행하는지(checks_on_server: available, enabled, state, permission_url, workflows_using)를 봐요. 비공개 저장소 빌드가 받기에서 실패하면 여기부터 보세요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "access": {},
                    "repositories": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_git_access"
      }
    },
    "/projects/{ref}/git/tokens/{provider}": {
      "put": {
        "operationId": "set_repo_token",
        "summary": "저장소 토큰 저장",
        "description": "비공개 저장소를 받을 접근 토큰을 저장해요(읽기 권한이면 충분해요). 암호화해 저장하고 다시 보여 주지 않아요. 자체 GitLab이면 gitlab_base를 넣으세요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "github",
                "gitlab",
                "bitbucket"
              ],
              "description": "github or gitlab."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "provider": {},
                    "saved": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_repo_token",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "type": "string",
                    "description": "The access token. Read access is enough."
                  },
                  "gitlab_base": {
                    "type": "string",
                    "description": "자체 GitLab 주소. gitlab.com이면 비워요."
                  }
                },
                "required": [
                  "token"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_repo_token",
        "summary": "저장소 토큰 삭제",
        "description": "저장한 토큰을 지워요. 연결한 GitHub App 설치는 그대로 둬요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "github",
                "gitlab",
                "bitbucket"
              ],
              "description": "github or gitlab."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "provider": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "remove_repo_token"
      }
    },
    "/projects/{ref}/git/repos": {
      "post": {
        "operationId": "add_repository",
        "summary": "저장소 추가",
        "description": "첫 push 전에 저장소를 이 프로젝트에 붙여요. 그러면 push가 이 프로젝트로 오고 create_deploy_hook도 쓸 수 있어요. repo는 owner/name(GitLab은 group/name)이에요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "access": {},
                    "repositories": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "add_repository",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "github",
                      "gitlab",
                      "bitbucket"
                    ],
                    "description": "github or gitlab."
                  },
                  "repo": {
                    "type": "string",
                    "description": "owner/name for GitHub, group/name for GitLab."
                  },
                  "branch": {
                    "type": "string",
                    "description": "프로덕션 브랜치. 비우면 main."
                  }
                },
                "required": [
                  "provider",
                  "repo"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/git/github-app": {
      "delete": {
        "operationId": "delete_projects_ref_git_github_app",
        "summary": "GitHub 계정 연결 해제",
        "description": "이 프로젝트와 GitHub 계정(App 설치)의 연결을 해제해요. installation을 주면 그 계정만, 비우면 모두예요. 저장한 토큰과 GitHub의 App 설치는 그대로예요. 다시 연결은 콘솔에서만 돼요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "unlinked": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "unlink_github_app"
      }
    },
    "/projects/{ref}/git/github-app/{installation}": {
      "delete": {
        "operationId": "delete_projects_ref_git_github_app_installation",
        "summary": "GitHub 계정 연결 해제",
        "description": "이 프로젝트와 GitHub 계정(App 설치)의 연결을 해제해요. installation을 주면 그 계정만, 비우면 모두예요. 저장한 토큰과 GitHub의 App 설치는 그대로예요. 다시 연결은 콘솔에서만 돼요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "installation",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "description": "list_git_access의 github_accounts[].installation_id. 비우면 모두."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "unlinked": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "unlink_github_app"
      }
    },
    "/projects/{ref}/git/importable": {
      "get": {
        "operationId": "list_importable_repositories",
        "summary": "가져올 저장소 찾기",
        "description": "GitHub App이 볼 수 있는 저장소를 최근 푸시 순으로 50개까지 봐요. query를 주면 전체에서 찾고, 방금 추가했다면 refresh: true. 계정이 여럿이면 installation으로 골라요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "query",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "저장소 이름의 일부. 비우면 최근에 푸시한 순서."
            }
          },
          {
            "name": "installation",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "description": "어느 GitHub 계정의 설치인지. 비우면 기본 계정."
            }
          },
          {
            "name": "refresh",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "GitHub에 다시 묻기(1분 캐시를 건너뜀)."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "github_account": {},
                    "installation_id": {},
                    "other_accounts": {},
                    "repositories": {},
                    "shown": {},
                    "matched": {},
                    "total": {},
                    "searched": {},
                    "add_repositories_url": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "list_importable_repositories"
      }
    },
    "/projects/{ref}/git/import": {
      "post": {
        "operationId": "import_repository",
        "summary": "저장소 가져오기",
        "description": "콘솔의 [연결하고 배포]와 같아요. 저장소를 연결하고 프로덕션 브랜치(비우면 기본 브랜치)의 최신 커밋으로 바로 배포해요. 빌드 설정과 환경 변수(dotenv)를 첫 빌드 전에 함께 저장해요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "app": {},
                    "repo": {},
                    "branch": {},
                    "github_account": {},
                    "deployment": {},
                    "status": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "import_repository",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "repo": {
                    "type": "string",
                    "description": "owner/name. list_importable_repositories의 repo."
                  },
                  "branch": {
                    "type": "string",
                    "description": "프로덕션 브랜치. 비우면 저장소의 기본 브랜치."
                  },
                  "root_directory": {
                    "type": "string",
                    "description": "모노레포의 앱 폴더(예: apps/web). 비우면 저장소 맨 위. 이미 연결한 저장소에서 다른 폴더를 주면 새 앱으로 추가해요."
                  },
                  "installation": {
                    "type": "integer",
                    "description": "어느 GitHub 계정의 설치로 받을지. 비우면 저장소 주인의 계정."
                  },
                  "dotenv": {
                    "type": "string",
                    "description": ".env 파일 내용. 프로덕션과 프리뷰 모두에 저장해요."
                  },
                  "sensitive": {
                    "type": "boolean",
                    "description": "dotenv의 값을 저장한 뒤 다시 보여주지 않아요."
                  },
                  "app": {
                    "type": "string",
                    "description": "앱 이름(콘솔의 \"앱 이름\"). 비우면 폴더 이름, 없으면 저장소 이름. 같은 이름의 앱이 있으면 그 앱의 설정을 바꿔요."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/git/checks/{repo}/{repo}": {
      "put": {
        "operationId": "set_checks_on_server",
        "summary": "검사를 One Server에서 실행",
        "description": "연결한 GitHub 저장소의 GitHub Actions 검사를 One Server의 머신에서 실행하도록 켜거나 꺼요. 콘솔의 Git 연결 → [검사를 One Server에서 실행]과 같아요. 켜면 저장소 변수 POOL_RUNNER를 저장하고, 작업이 runs-on: ${{ vars.POOL_RUNNER || 'ubuntu-latest' }}를 쓰면 One Server에서 돌아요. 끄면 변수를 지워 GitHub의 머신으로 돌아가요. state가 needs_permission이면 permission_url에서 GitHub App의 새 권한을 승인하면 저절로 켜져요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "repo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_git_access의 repositories[].repo (owner/name)."
            }
          },
          {
            "name": "repo",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_git_access의 repositories[].repo (owner/name)."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_checks_on_server",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true면 켜고 false면 꺼요."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/git/repos/{name}": {
      "delete": {
        "operationId": "disconnect_repository",
        "summary": "저장소 연결 해제",
        "description": "저장소 연결을 해제해 푸시해도 배포하지 않아요. 서비스 중인 배포, 배포 기록, 빌드 설정, 환경 변수는 그대로이고 import_repository로 다시 연결돼요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_git_access의 repositories[].name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "repo": {},
                    "connected": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "disconnect_repository"
      }
    },
    "/projects/{ref}/log-drains": {
      "get": {
        "operationId": "list_log_drains",
        "summary": "로그 내보내기 목록",
        "description": "로그를 보내는 곳(https 또는 datadog), 보내는 출처, 마지막 전송과 오류. 서명 키(signing_secret)는 만들 때(create_log_drain) 한 번만 보여주고, 목록에는 signing_secret_set과 소유자·관리자에게 끝 네 글자(signing_secret_last4)만 실어요.",
        "tags": [
          "logs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "sources": {},
                    "drains": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_log_drains"
      },
      "post": {
        "operationId": "create_log_drain",
        "summary": "로그 내보내기 추가",
        "description": "이 프로젝트의 로그를 외부로 보내요. 만든 뒤에 쌓이는 로그부터 보내요. kind=https는 서명한 JSON을 POST하고, kind=datadog는 secret에 API 키가 필요해요. https 드레인의 signing_secret은 이 응답에만 실리니 받는 쪽에 바로 저장하세요. 프로젝트마다 5개까지. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "logs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "create_log_drain",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "A name to recognise the drain by."
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "https",
                      "datadog"
                    ],
                    "description": "https or datadog."
                  },
                  "url": {
                    "type": "string",
                    "description": "공개된 https 주소."
                  },
                  "secret": {
                    "type": "string",
                    "description": "Datadog API 키, 또는 https로 보낼 때 Authorization 헤더에 넣을 값."
                  },
                  "sources": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "site",
                        "server",
                        "api",
                        "auth",
                        "functions",
                        "build"
                      ]
                    },
                    "description": "비우면 전부."
                  }
                },
                "required": [
                  "name",
                  "kind",
                  "url"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/log-drains/{id}": {
      "patch": {
        "operationId": "set_log_drain_enabled",
        "summary": "로그 내보내기 끄기·켜기",
        "description": "설정은 두고 보내기만 멈추거나 다시 시작해요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "logs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The id from list_log_drains."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "enabled": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_log_drain_enabled",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true to send, false to stop."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_log_drain",
        "summary": "로그 내보내기 삭제",
        "description": "로그 내보내기를 지워요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "logs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The id from list_log_drains."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "remove_log_drain"
      }
    },
    "/projects/{ref}/analytics": {
      "get": {
        "operationId": "get_analytics",
        "summary": "웹 분석",
        "description": "페이지뷰와 방문자를 날짜별로, 많이 본 페이지·유입 경로·국가·기기·브라우저·운영체제와 함께 돌려줘요. 개인을 알아볼 수 있는 값은 저장하지 않아서 합계만 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "enum": [
                1,
                7,
                30,
                90
              ],
              "description": "기간. 기본 7."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "settings": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_analytics"
      }
    },
    "/projects/{ref}/analytics/breakdown": {
      "get": {
        "operationId": "get_analytics_breakdown",
        "summary": "웹 분석 세부",
        "description": "캠페인(utm_source·utm_medium·utm_campaign), 라우트, 사용자 정의 이벤트와 걸러낸 봇의 수를 돌려줘요. event를 주면 그 이벤트의 속성별 값을 함께 돌려줘요. 합계만 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "enum": [
                1,
                7,
                30,
                90
              ],
              "description": "기간. 기본 7."
            }
          },
          {
            "name": "event",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 100,
              "description": "속성을 볼 이벤트 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "days": {},
                    "utm_source": {},
                    "utm_medium": {},
                    "utm_campaign": {},
                    "routes": {},
                    "events": {},
                    "bots_filtered": {},
                    "crawlers": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_analytics_breakdown"
      }
    },
    "/projects/{ref}/analytics/previews": {
      "put": {
        "operationId": "set_analytics_previews",
        "summary": "프리뷰 방문 세기",
        "description": "프리뷰 배포와 dpl- 주소의 방문을 웹 분석에 셀지 정해요. 끄면(기본) 프리뷰에는 스크립트를 넣지 않고 보내온 것도 버려요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "include_previews": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_analytics_previews",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "include_previews": {
                    "type": "boolean",
                    "description": "프리뷰도 세기."
                  }
                },
                "required": [
                  "include_previews"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/analytics/export": {
      "get": {
        "operationId": "export_analytics",
        "summary": "웹 분석 내보내기",
        "description": "기간의 합계를 날짜·항목·값별 CSV 문자열로 돌려줘요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "enum": [
                1,
                7,
                30,
                90
              ],
              "description": "기간. 기본 7."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "days": {},
                    "format": {},
                    "csv": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "export_analytics"
      }
    },
    "/projects/{ref}/analytics/reports": {
      "get": {
        "operationId": "list_analytics_reports",
        "summary": "맞춤 리포트 목록",
        "description": "저장한 웹 분석 리포트와 넣을 수 있는 차트 이름을 돌려줘요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "widgets": {},
                    "reports": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_analytics_reports"
      },
      "post": {
        "operationId": "post_projects_ref_analytics_reports",
        "summary": "맞춤 리포트 저장",
        "description": "리포트를 만들거나, id를 주면 그 리포트를 바꿔요. 개발자 이상만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "report": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "save_analytics_report",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80,
                    "description": "이름."
                  },
                  "days": {
                    "type": "integer",
                    "enum": [
                      1,
                      7,
                      30,
                      90
                    ],
                    "description": "기간. 기본 7."
                  },
                  "widgets": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "views",
                        "visitors",
                        "path",
                        "referrer",
                        "country",
                        "device",
                        "browser",
                        "os",
                        "utm_source",
                        "utm_medium",
                        "utm_campaign",
                        "route",
                        "event",
                        "bot",
                        "vitals"
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 16,
                    "description": "넣을 차트와 표."
                  }
                },
                "required": [
                  "name",
                  "widgets"
                ]
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patch_projects_ref_analytics_reports",
        "summary": "맞춤 리포트 저장",
        "description": "리포트를 만들거나, id를 주면 그 리포트를 바꿔요. 개발자 이상만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "report": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "save_analytics_report",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80,
                    "description": "이름."
                  },
                  "days": {
                    "type": "integer",
                    "enum": [
                      1,
                      7,
                      30,
                      90
                    ],
                    "description": "기간. 기본 7."
                  },
                  "widgets": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "views",
                        "visitors",
                        "path",
                        "referrer",
                        "country",
                        "device",
                        "browser",
                        "os",
                        "utm_source",
                        "utm_medium",
                        "utm_campaign",
                        "route",
                        "event",
                        "bot",
                        "vitals"
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 16,
                    "description": "넣을 차트와 표."
                  }
                },
                "required": [
                  "name",
                  "widgets"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/analytics/reports/{id}": {
      "get": {
        "operationId": "get_analytics_report",
        "summary": "맞춤 리포트 보기",
        "description": "저장한 리포트 하나를 그 기간의 합계, 세부, 속도와 함께 돌려줘요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_analytics_reports가 돌려준 id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "report": {},
                    "totals": {},
                    "breakdown": {},
                    "speed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_analytics_report"
      },
      "delete": {
        "operationId": "remove_analytics_report",
        "summary": "맞춤 리포트 삭제",
        "description": "리포트만 지워요. 분석 기록은 그대로예요. 개발자 이상만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_analytics_reports가 돌려준 id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "remove_analytics_report"
      }
    },
    "/projects/{ref}/speed-insights": {
      "get": {
        "operationId": "get_speed_insights",
        "summary": "속도 인사이트",
        "description": "실제 방문자의 브라우저가 잰 Core Web Vitals(LCP, INP, CLS, FCP, TTFB)의 75번째 백분위와 평가, 느린 페이지를 돌려줘요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "enum": [
                1,
                7,
                30,
                90
              ],
              "description": "기간. 기본 7."
            }
          },
          {
            "name": "device",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "desktop",
                "mobile"
              ],
              "description": "기기. 기본 all."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "settings": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_speed_insights"
      }
    },
    "/projects/{ref}/insights": {
      "put": {
        "operationId": "set_insights",
        "summary": "분석 켜기·끄기",
        "description": "웹 분석과 속도 인사이트를 켜고 꺼요. 켜면 HTML에 /_oneend/insights/script.js가 들어가고, @vercel/analytics·@vercel/speed-insights도 그대로 집계돼요. 쿠키와 IP는 저장하지 않아요. 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "settings": {},
                    "script": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_insights",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "analytics": {
                    "type": "boolean",
                    "description": "웹 분석."
                  },
                  "speed_insights": {
                    "type": "boolean",
                    "description": "속도 인사이트."
                  },
                  "vitals_sample_percent": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "description": "속도를 재는 방문 비율."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/remote-cache": {
      "get": {
        "operationId": "get_remote_cache",
        "summary": "원격 캐시",
        "description": "Turborepo 원격 캐시의 주소, 저장된 결과 수와 용량, 최근 30일 적중·업로드, 이번 달 저장 사용량(remote_cache_gb_hour)과 단가를 돌려줘요. 내려받은 데이터는 egress_gb로 세요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "api": {},
                    "artifacts": {},
                    "bytes": {},
                    "last_30_days": {},
                    "metered": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_remote_cache"
      }
    },
    "/projects/{ref}/remote-cache/artifacts": {
      "delete": {
        "operationId": "clear_remote_cache",
        "summary": "원격 캐시 비우기",
        "description": "저장된 결과를 모두 지워요. 다음 빌드부터 다시 채워지고, 지운 만큼 저장 용량 사용량이 줄어요. 개발자 이상만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "cleared": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "clear_remote_cache"
      }
    },
    "/projects/{ref}/flags": {
      "get": {
        "operationId": "list_flags",
        "summary": "기능 플래그 목록",
        "description": "기능 플래그와, 엣지 설정에 둔 플래그 모양의 값을 함께 돌려줘요. source는 어디에 있는지, shadows는 같은 키의 엣지 설정 값을 가리는지 알려 줘요. 키가 같으면 플래그를 따라요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "flags": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_flags"
      }
    },
    "/projects/{ref}/flags/evaluate": {
      "get": {
        "operationId": "evaluate_flag",
        "summary": "기능 플래그 값 보기",
        "description": "앱이 받을 값을 돌려줘요. 컨텍스트(예: {\"user\": {\"id\": \"u1\"}})와 환경을 주면 플래그 규칙을, 플래그가 없으면 엣지 설정 값을 따라요. source가 어느 쪽인지 알려 줘요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "key",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 256,
              "description": "플래그 키."
            }
          },
          {
            "name": "environment",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "환경. 기본 production."
            }
          },
          {
            "name": "context",
            "in": "query",
            "required": false,
            "schema": {
              "type": "object",
              "description": "평가할 컨텍스트(JSON 객체)."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "key": {},
                    "environment": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "evaluate_flag"
      }
    },
    "/projects/{ref}/flags/{key}/environments/{environment}": {
      "put": {
        "operationId": "set_flag_enabled",
        "summary": "기능 플래그 켜기·끄기",
        "description": "한 환경에서 플래그를 켜거나 꺼요. 프로덕션은 소유자·관리자, 그 밖의 환경은 개발자 이상이 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 64,
              "description": "플래그 키."
            }
          },
          {
            "name": "environment",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "환경."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "key": {},
                    "environment": {},
                    "enabled": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-mcp-tool": "set_flag_enabled",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "켜기."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/edge-config": {
      "get": {
        "operationId": "get_edge_config",
        "summary": "엣지 설정 읽기",
        "description": "프로젝트의 엣지 설정(배포 없이 바꾸는 값과 기능 플래그) 전체와 버전, 크기, 한도를 돌려줘요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "version": {},
                    "bytes": {},
                    "limits": {},
                    "items": {},
                    "read_url": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_edge_config"
      },
      "patch": {
        "operationId": "set_edge_config",
        "summary": "엣지 설정 바꾸기",
        "description": "키를 저장하거나 지워요. 몇 초 안에 모든 서버에 적용돼요. 플래그는 true/false, {\"enabled\": true, \"percent\": 20}, {\"enabled\": true, \"allow\": [\"user-1\"]} 모양이에요. 개발자 이상만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "version": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_edge_config",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "set": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "저장할 키와 값 (값은 JSON)."
                  },
                  "delete": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "지울 키."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/edge-config/tokens": {
      "get": {
        "operationId": "list_edge_config_tokens",
        "summary": "엣지 설정 읽기 토큰",
        "description": "다른 프로젝트가 이 프로젝트의 엣지 설정을 읽는 읽기 토큰과 연결된 프로젝트(변수 이름, 환경), 이 프로젝트에 연결된 다른 프로젝트의 엣지 설정을 돌려줘요. 토큰 값은 돌려주지 않아요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "tokens": {},
                    "connected_here": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_edge_config_tokens"
      },
      "post": {
        "operationId": "create_edge_config_token",
        "summary": "엣지 설정 읽기 토큰 만들기",
        "description": "읽기 토큰을 만들어요. connect를 주면 같은 조직의 프로젝트에 연결해, 다음 배포부터 연결 문자열(https://<ref>.<zone>/config/v1?token=…)을 변수로 받아요. 토큰은 이때만 보여요. 프로젝트 관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "name": {},
                    "token": {},
                    "connection_string": {},
                    "connected": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "create_edge_config_token",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "connect": {
                    "type": "object",
                    "properties": {
                      "ref": {
                        "type": "string",
                        "pattern": "^[a-z]{20}$"
                      },
                      "variable": {
                        "type": "string",
                        "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$"
                      },
                      "targets": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "enum": [
                            "production",
                            "preview",
                            "development"
                          ]
                        },
                        "minItems": 1,
                        "uniqueItems": true
                      }
                    },
                    "required": [
                      "ref"
                    ],
                    "additionalProperties": false,
                    "description": "바로 연결할 같은 조직의 프로젝트: ref, 변수 이름 variable(기본 GLOBAL_CONFIG), 환경 targets(기본 셋 다, 프로덕션은 그 프로젝트의 소유자·관리자만)."
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60,
                    "description": "토큰 이름."
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/edge-config/tokens/{id}": {
      "delete": {
        "operationId": "revoke_edge_config_token",
        "summary": "읽기 토큰 폐기",
        "description": "읽기 토큰을 폐기해요. 바로 읽지 못하고, 연결된 프로젝트의 다음 배포부터 변수가 빠져요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "읽기 토큰 id. list_edge_config_tokens로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "revoked": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "revoke_edge_config_token"
      }
    },
    "/projects/{ref}/edge-config/tokens/{id}/connections/{ref}": {
      "put": {
        "operationId": "connect_edge_config_token",
        "summary": "읽기 토큰을 프로젝트에 연결",
        "description": "읽기 토큰을 같은 조직의 다른 프로젝트 배포에 변수로 연결해요. 이미 연결돼 있으면 변수 이름과 환경을 바꿔요. 그 프로젝트의 개발자 이상(프로덕션은 소유자·관리자)이어야 해요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "읽기 토큰 id. list_edge_config_tokens로 확인해요."
            }
          },
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "connected": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "connect_edge_config_token",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "variable": {
                    "type": "string",
                    "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$",
                    "description": "배포에서 읽을 변수 이름. 기본 GLOBAL_CONFIG."
                  },
                  "targets": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "production",
                        "preview",
                        "development"
                      ]
                    },
                    "minItems": 1,
                    "uniqueItems": true,
                    "description": "변수가 들어갈 환경. 기본은 셋 다. 프로덕션은 그 프로젝트의 소유자·관리자만."
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "disconnect_edge_config_token",
        "summary": "읽기 토큰 연결 끊기",
        "description": "읽기 토큰을 한 프로젝트에서 떼요. 그 프로젝트의 다음 배포부터 변수가 빠져요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "읽기 토큰 id. list_edge_config_tokens로 확인해요."
            }
          },
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "연결할 같은 조직의 프로젝트."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "disconnected": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "disconnect_edge_config_token"
      }
    },
    "/projects/{ref}/edge-config/history": {
      "get": {
        "operationId": "get_edge_config_history",
        "summary": "엣지 설정 변경 기록",
        "description": "누가 언제 어떤 키를 무엇에서 무엇으로 바꿨는지, 최근 것부터 돌려줘요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "description": "몇 개. 기본 50."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "changes": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_edge_config_history"
      }
    },
    "/projects/{ref}/rolling-releases": {
      "get": {
        "operationId": "get_rolling_releases",
        "summary": "점진적 배포 상태",
        "description": "점진적 배포 설정과, 진행 중인 배포(새 배포가 받는 방문자 비율)와 최근 기록을 돌려줘요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "config": {},
                    "active": {},
                    "recent": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_rolling_releases"
      },
      "put": {
        "operationId": "set_rolling_releases",
        "summary": "점진적 배포 설정",
        "description": "새 프로덕션 배포를 단계별 비율(stages, 예: [10, 50])로 내보낼지 정해요. auto_advance가 false면 단계마다 승인해요. abort_error_rate(0.05 = 5%)를 넘으면 자동으로 되돌려요. 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "config": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_rolling_releases",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "켜기."
                  },
                  "stages": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 99
                    },
                    "description": "단계별 비율(%)."
                  },
                  "stage_minutes": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 1440,
                    "description": "단계 길이(분)."
                  },
                  "auto_advance": {
                    "type": "boolean",
                    "description": "시간이 지나면 자동 진행."
                  },
                  "abort_error_rate": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0.001,
                    "maximum": 1,
                    "description": "자동 중단 5xx 비율. null이면 끄기."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/rolling-releases/{action}": {
      "post": {
        "operationId": "advance_rolling_release",
        "summary": "점진적 배포 다음 단계로",
        "description": "진행 중인 배포를 다음 단계 비율로 올려요. 마지막 단계였다면 모두에게 배포해요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "action",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "release": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "advance_rolling_release",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/kv": {
      "get": {
        "operationId": "list_kv_keys",
        "summary": "KV 키 목록",
        "description": "KV 저장소의 키를 접두어로, 50개씩 돌려줘요. 사용량과 한도, REST 주소도 함께예요. 비밀을 볼 수 있는 역할만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "prefix",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "접두어."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "이전 응답의 cursor."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "usage": {},
                    "keys": {},
                    "cursor": {},
                    "rest_url": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "secrets.read (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "list_kv_keys"
      }
    },
    "/projects/{ref}/kv/{id}": {
      "get": {
        "operationId": "get_kv",
        "summary": "KV 값 읽기",
        "description": "키 하나의 값과 남은 초(ttl, -1은 만료 없음)를 돌려줘요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "key": {},
                    "value": {},
                    "ttl": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "secrets.read (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "get_kv"
      },
      "put": {
        "operationId": "set_kv",
        "summary": "KV 값 저장",
        "description": "키에 JSON 값을 저장해요. ttl은 만료까지 초예요. 개발자 이상만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "key": {},
                    "saved": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_kv",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "value": {
                    "description": "값 (JSON)."
                  },
                  "ttl": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "만료까지 초."
                  }
                },
                "required": [
                  "value"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_kv",
        "summary": "KV 키 삭제",
        "description": "키를 지워요. 개발자 이상만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "key": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "delete_kv"
      }
    },
    "/projects/{ref}/ai-gateway": {
      "get": {
        "operationId": "get_ai_gateway",
        "summary": "AI 게이트웨이",
        "description": "AI 게이트웨이 주소(OpenAI 호환), 설정, 공급자(키는 끝 네 자리만), 최근 30일 사용량을 돌려줘요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "base_url": {},
                    "settings": {},
                    "providers": {},
                    "usage_30d": {},
                    "top_users_30d": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_ai_gateway"
      },
      "put": {
        "operationId": "set_ai_gateway",
        "summary": "AI 게이트웨이 설정",
        "description": "AI 게이트웨이의 켜기, 로그인 사용자 허용, 캐시, 분당 한도, 플랫폼 공급자 대체(토큰 요금), 사용자별 하루 한도를 정해요. 사용자는 로그인한 id나 x-oneend-user 헤더예요. 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "settings": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_ai_gateway",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "켜기."
                  },
                  "allow_users": {
                    "type": "boolean",
                    "description": "로그인한 사용자 허용."
                  },
                  "cache_seconds": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 86400,
                    "description": "캐시 초."
                  },
                  "rate_per_minute": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "분당 요청 한도."
                  },
                  "platform_fallback": {
                    "type": "boolean",
                    "description": "플랫폼 공급자로 대체."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/ai-gateway/logs": {
      "get": {
        "operationId": "get_ai_gateway_logs",
        "summary": "AI 게이트웨이 호출 기록",
        "description": "최근 호출의 공급자, 모델, 상태, 토큰, 지연, 대체 여부를 돌려줘요. 대화 내용은 저장하지 않아요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "description": "몇 개. 기본 50."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "logs": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_ai_gateway_logs"
      }
    },
    "/projects/{ref}/ai-gateway/providers": {
      "post": {
        "operationId": "add_ai_provider",
        "summary": "AI 공급자 추가",
        "description": "공급자를 키와 함께 추가해요: OpenAI 호환, Anthropic(Messages API로 바꿔 줌), Google Gemini. 주소는 공개 https만 돼요. 키는 암호화해 저장하고 다시 보여 주지 않아요. 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "add_ai_provider",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9-]{0,39}$",
                    "description": "이름. 모델을 이름/모델로 부를 때 써요."
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "openai",
                      "anthropic",
                      "google",
                      "deepseek",
                      "openai-compatible"
                    ],
                    "description": "종류."
                  },
                  "base_url": {
                    "type": "string",
                    "description": "주소. openai, anthropic, google, deepseek는 비워도 돼요."
                  },
                  "key": {
                    "type": "string",
                    "description": "API 키."
                  },
                  "models": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "받는 모델. 비우면 모두."
                  },
                  "priority": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000,
                    "description": "우선순위. 낮은 것부터."
                  }
                },
                "required": [
                  "name",
                  "kind"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/ai-gateway/providers/{id}": {
      "patch": {
        "operationId": "set_ai_provider_enabled",
        "summary": "AI 공급자 끄기·켜기",
        "description": "설정과 키는 두고 공급자를 쓰지 않거나 다시 써요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "get_ai_gateway가 돌려준 id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "enabled": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_ai_provider_enabled",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "쓰기."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_ai_provider",
        "summary": "AI 공급자 삭제",
        "description": "공급자와 저장한 키를 지워요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "get_ai_gateway가 돌려준 id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "remove_ai_provider"
      }
    },
    "/projects/{ref}/ai-gateway/budgets": {
      "put": {
        "operationId": "set_ai_budgets",
        "summary": "AI 게이트웨이 예산",
        "description": "프로젝트의 AI 게이트웨이 예산을 달러로 정해요(하루·주·달, UTC). 다 쓰면 다음 기간까지 호출을 거절해요. 적지 않은 값은 그대로 둬요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "budgets": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_ai_budgets",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "daily_usd": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 1000000,
                    "description": "하루(UTC) 예산, 달러. null이면 없음."
                  },
                  "weekly_usd": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 1000000,
                    "description": "한 주(월요일부터, UTC) 예산, 달러. null이면 없음."
                  },
                  "monthly_usd": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 1000000,
                    "description": "한 달(UTC) 예산, 달러. null이면 없음."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/ai-gateway/keys": {
      "get": {
        "operationId": "list_ai_gateway_keys",
        "summary": "AI 게이트웨이 키 목록",
        "description": "게이트웨이 키의 이름, 앞부분, 예산, 이번 달 지출, 마지막 사용 시각을 돌려줘요. 키 자체는 돌려주지 않아요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "keys": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_ai_gateway_keys"
      },
      "post": {
        "operationId": "create_ai_gateway_key",
        "summary": "AI 게이트웨이 키 만들기",
        "description": "앱 하나, 또는 프로젝트가 AI를 되파는 고객 한 명에게 줄 게이트웨이 키(bwai_…)를 예산·꼬리표·분당 한도와 함께 만들어요. 키는 이 응답에서 한 번만 보여요. 꼬리표(external_ref)를 단 키는 프로젝트당 50개 제한에 들지 않아요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "name": {},
                    "key": {},
                    "base_url": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "create_ai_gateway_key",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60,
                    "description": "키 이름."
                  },
                  "daily_usd": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 1000000,
                    "description": "하루(UTC) 예산, 달러. null이면 없음."
                  },
                  "weekly_usd": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 1000000,
                    "description": "한 주(월요일부터, UTC) 예산, 달러. null이면 없음."
                  },
                  "monthly_usd": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 1000000,
                    "description": "한 달(UTC) 예산, 달러. null이면 없음."
                  },
                  "external_ref": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 200,
                    "description": "이 키가 프로젝트 장부에서 누구인지(예: 고객의 사용자 ID). 훅에 같이 보내요."
                  },
                  "labels": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 100
                    },
                    "description": "자유 라벨 20개까지. 예: {\"tier\": \"1\"}. 훅에 같이 보내요."
                  },
                  "rate_per_minute": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 100000,
                    "description": "분당 요청 수 한도. null이면 없음."
                  },
                  "tokens_per_minute": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 100000000,
                    "description": "분당 토큰(입력+출력) 한도. null이면 없음."
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/ai-gateway/keys/{id}/limits": {
      "put": {
        "operationId": "set_ai_gateway_key_limits",
        "summary": "AI 게이트웨이 키 한도",
        "description": "게이트웨이 키 하나의 분당 요청 수와 분당 토큰 수 한도를 바꿔요. 모든 서버가 같은 수를 세요. 적지 않은 값은 그대로 두고, null이면 한도를 없애요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_ai_gateway_keys가 돌려준 id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "limits": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_ai_gateway_key_limits",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rate_per_minute": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 100000,
                    "description": "분당 요청 수 한도. null이면 없음."
                  },
                  "tokens_per_minute": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 100000000,
                    "description": "분당 토큰(입력+출력) 한도. null이면 없음."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/ai-gateway/aliases": {
      "put": {
        "operationId": "set_ai_model_aliases",
        "summary": "AI 모델 별칭",
        "description": "부르는 사람이 쓰는 모델 이름(별칭)과 실제로 보낼 모델을 정해요. 별칭마다 맨 앞에 넣을 시스템 지침을 둘 수 있어요. 응답의 model은 별칭으로 나가요. 보낸 목록이 지금 목록을 통째로 바꿔요. aliases_only를 켜면 별칭 말고는 부를 수 없고 /models도 별칭만 보여요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "aliases_only": {},
                    "aliases": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_ai_model_aliases",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "aliases": {
                    "type": "array",
                    "maxItems": 50,
                    "items": {
                      "type": "object",
                      "properties": {
                        "alias": {
                          "type": "string",
                          "pattern": "^[a-z0-9][a-z0-9._-]{0,63}$"
                        },
                        "target": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 160
                        },
                        "system_prompt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "maxLength": 20000
                        }
                      },
                      "required": [
                        "alias",
                        "target"
                      ],
                      "additionalProperties": false
                    },
                    "description": "별칭 전체 목록. 빈 배열이면 모두 지워요."
                  },
                  "aliases_only": {
                    "type": "boolean",
                    "description": "별칭만 부를 수 있게 해요. 적지 않으면 그대로 둬요."
                  }
                },
                "required": [
                  "aliases"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/ai-gateway/hooks": {
      "put": {
        "operationId": "set_ai_gateway_hooks",
        "summary": "AI 게이트웨이 훅",
        "description": "게이트웨이 키로 부른 호출마다 물어보고 알려 줄 https 주소를 정해요. ai.before에 2xx가 아니거나 timeout_ms 안에 답이 없으면 호출을 거절해요(402는 잔액 부족으로 그대로 전해요). ai.after에는 사용량·비용·상태를 보내고, 받지 못하면 하루 동안 다시 보내요. 응답에 서명 비밀이 있어요. url을 null로 하면 꺼요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "url": {},
                    "timeout_ms": {},
                    "signing_secret": {},
                    "events": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_ai_gateway_hooks",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 500,
                    "description": "훅 주소(https). null이면 꺼요."
                  },
                  "timeout_ms": {
                    "type": "integer",
                    "minimum": 200,
                    "maximum": 10000,
                    "description": "ai.before가 답할 시간(밀리초). 기본 2000."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/ai-gateway/keys/{id}": {
      "patch": {
        "operationId": "set_ai_gateway_key_budgets",
        "summary": "AI 게이트웨이 키 예산",
        "description": "게이트웨이 키 하나의 예산을 바꿔요. 적지 않은 값은 그대로 둬요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_ai_gateway_keys가 돌려준 id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "budgets": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_ai_gateway_key_budgets",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "daily_usd": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 1000000,
                    "description": "하루(UTC) 예산, 달러. null이면 없음."
                  },
                  "weekly_usd": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 1000000,
                    "description": "한 주(월요일부터, UTC) 예산, 달러. null이면 없음."
                  },
                  "monthly_usd": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 1000000,
                    "description": "한 달(UTC) 예산, 달러. null이면 없음."
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "revoke_ai_gateway_key",
        "summary": "AI 게이트웨이 키 폐기",
        "description": "게이트웨이 키를 폐기해요. 30초 안에 모든 서버에서 거절돼요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_ai_gateway_keys가 돌려준 id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "revoked": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "revoke_ai_gateway_key"
      }
    },
    "/projects/{ref}/ai-gateway/spend": {
      "get": {
        "operationId": "get_ai_spend",
        "summary": "AI 게이트웨이 지출",
        "description": "오늘·이번 주·이번 달 지출과 예산, 하루별·모델별·키별 지출을 달러로 돌려줘요. 자기 키로 부른 공급자는 정가로 계산한 추정이에요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 400,
              "description": "며칠. 기본 30."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "spent_usd": {},
                    "budgets": {},
                    "days": {},
                    "models": {},
                    "keys": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_ai_spend"
      }
    },
    "/projects/{ref}/middleware": {
      "get": {
        "operationId": "get_middleware",
        "summary": "미들웨어 설정",
        "description": "사이트 미들웨어(middleware.ts)를 실행하는지와 시간 한도를 돌려줘요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "enabled": {},
                    "timeout_ms": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_middleware"
      },
      "put": {
        "operationId": "set_middleware",
        "summary": "미들웨어 설정 바꾸기",
        "description": "사이트 미들웨어를 끄거나 켜고, 시간 한도(100~5000ms)를 정해요. 끄면 다시 배포하지 않아도 미들웨어 없이 서빙해요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "enabled": {},
                    "timeout_ms": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_middleware",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "실행."
                  },
                  "timeout_ms": {
                    "type": "integer",
                    "minimum": 100,
                    "maximum": 5000,
                    "description": "시간 한도(ms)."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/function-egress": {
      "put": {
        "operationId": "set_function_egress",
        "summary": "함수의 외부 요청",
        "description": "함수 안에서 fetch()로 공개 HTTPS 주소를 부를 수 있게 하거나 막아요. 지금 상태는 list_functions의 egress예요. 30초 안에 적용돼요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "functions"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "egress": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_function_egress",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true to allow outbound requests, false to block them."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/function-secrets": {
      "get": {
        "operationId": "list_function_secrets",
        "summary": "함수 시크릿 목록",
        "description": "함수만 보는 시크릿의 이름과 바꾼 때예요. 값은 어떤 도구로도 다시 읽을 수 없어요. readable이 false면 값이 열리지 않아 함수에 들어가지 않으니 다시 저장하세요. 소유자·관리자만 볼 수 있어요.",
        "tags": [
          "functions"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "secrets": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "list_function_secrets"
      },
      "post": {
        "operationId": "set_function_secrets",
        "summary": "함수 시크릿 저장",
        "description": "함수만 읽는 시크릿을 저장해요(웹훅 서명 키 등). 빌드에는 안 들어가고 같은 이름의 환경 변수보다 먼저 쓰여요. 다음 호출부터 process.env로 읽어요. 하나라도 틀리면 아무것도 저장하지 않고, 저장한 값은 다시 못 봐요. SUPABASE_·BLACKWALL로 시작하는 이름과 NODE_ENV·HOME·PATH·NODE_OPTIONS·TZ는 못 써요. 프로젝트에 100개, 값 하나 32KB까지예요. 소유자·관리자만 돼요.",
        "tags": [
          "functions"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "saved": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_function_secrets",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "secrets": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "이름과 값. 예: {\"STRIPE_WEBHOOK_SECRET\": \"whsec_…\"}. 값은 다시 보여 주지 않아요."
                  },
                  "dotenv": {
                    "type": "string",
                    "description": ".env 파일 내용을 통째로. 주석과 빈 줄은 건너뛰어요."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/function-secrets/copy": {
      "post": {
        "operationId": "copy_function_secrets",
        "summary": "함수 시크릿 복사",
        "description": "내 다른 프로젝트(from)에 있는 함수 시크릿을 이 프로젝트(ref)로 이름만 대서 복사해요. 값은 서버 안에서만 옮겨지고 답에는 이름만 와요. 같은 키를 다시 붙여 넣지 않아도 돼요. 이 프로젝트에 이미 있는 이름은 건너뛰고(skipped) overwrite: true면 바꿔요. from에 없는 이름은 missing으로 알려 주고 나머지는 복사해요. 한 번에 50개까지예요. 두 프로젝트 모두에서 소유자·관리자여야 해요(조직이 달라도 돼요).",
        "tags": [
          "functions"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "from": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "copy_function_secrets",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "from": {
                    "type": "string",
                    "description": "복사해 올 프로젝트의 ref. list_projects로 확인해요."
                  },
                  "names": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "maxItems": 50,
                    "description": "복사할 시크릿 이름. from 프로젝트의 list_function_secrets에 있는 name. 예: [\"ANTHROPIC_API_KEY\"]"
                  },
                  "overwrite": {
                    "type": "boolean",
                    "description": "이 프로젝트에 같은 이름이 있으면 바꿀지. 기본은 false(건너뜀)."
                  }
                },
                "required": [
                  "from",
                  "names"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/function-secrets/{name}": {
      "delete": {
        "operationId": "delete_function_secret",
        "summary": "함수 시크릿 삭제",
        "description": "함수 시크릿 하나를 지워요. 값은 되살릴 수 없고, 함수는 다음 호출부터 이 값 없이 실행돼요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "functions"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_function_secrets의 name"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "deleted": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "delete_function_secret"
      }
    },
    "/projects/{ref}/volumes": {
      "get": {
        "operationId": "list_volumes",
        "summary": "볼륨 목록",
        "description": "앱의 볼륨(서버를 다시 시작하거나 새로 배포해도 남는 디스크)과 백업, 요금제가 허용하는 합계(max_gb)와 지금 쓰는 양(used_gb), 앱마다 서버가 듣는 포트(apps[].listens_on)를 돌려줘요. 볼륨은 프로덕션 서버에만 붙어요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "max_gb": {},
                    "used_gb": {},
                    "volumes": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_volumes"
      },
      "post": {
        "operationId": "create_volume",
        "summary": "볼륨 만들기",
        "description": "앱의 프로덕션 서버 mount_path에 볼륨을 붙여요(WordPress는 /var/www/html). 크기가 상한이고 /etc·/usr 같은 시스템 경로는 안 돼요. 1분 안에 서버가 다시 시작해요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "volume": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "create_volume",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "app": {
                    "type": "string",
                    "description": "list_apps의 name."
                  },
                  "mount_path": {
                    "type": "string",
                    "description": "컨테이너 안의 절대 경로. 예: /var/www/html"
                  },
                  "size_gb": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 500,
                    "description": "크기(GB). 1부터 500까지, 기본 1."
                  }
                },
                "required": [
                  "app",
                  "mount_path"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/volumes/{id}": {
      "patch": {
        "operationId": "resize_volume",
        "summary": "볼륨 늘리기",
        "description": "볼륨을 더 크게 해요. 서버를 멈추지 않고 늘리고, 줄일 수는 없어요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_volumes의 볼륨 id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "volume": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "resize_volume",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "size_gb": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 500,
                    "description": "크기(GB). 1부터 500까지."
                  }
                },
                "required": [
                  "size_gb"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_volume",
        "summary": "볼륨 지우기",
        "description": "볼륨과 그 파일, 백업을 모두 지우고 프로덕션 서버를 볼륨 없이 다시 시작해요. 되돌릴 수 없으니 사용자가 요청할 때만 쓰고 confirm에 mount_path를 넣으세요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_volumes의 볼륨 id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "volume": {},
                    "deleted": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "delete_volume",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "볼륨 경로. list_volumes의 mount_path와 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/volumes/{id}/backups": {
      "post": {
        "operationId": "create_volume_backup",
        "summary": "볼륨 백업",
        "description": "볼륨의 파일을 지금 묶어 30일 동안 보관해요. 몇 분 안에 끝나고, list_volumes의 backups에 나타나요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_volumes의 볼륨 id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "volume_id": {},
                    "backup": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "create_volume_backup"
      }
    },
    "/projects/{ref}/volumes/{id}/restore": {
      "post": {
        "operationId": "restore_volume_backup",
        "summary": "볼륨 복원",
        "description": "볼륨의 지금 파일을 백업의 파일로 바꿔요. 백업 뒤에 바뀐 파일은 사라지지만, 바꾸기 전에 지금 파일을 7일 동안 백업해 두니 그 백업으로 되돌릴 수 있어요. 사용자가 요청했을 때만 쓰고, 소유자·관리자만 할 수 있어요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "list_volumes의 볼륨 id."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "volume": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "restore_volume_backup",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "backup_id": {
                    "type": "string",
                    "description": "list_volumes의 backups[].id. status가 ready인 것."
                  }
                },
                "required": [
                  "backup_id"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/server-memory": {
      "get": {
        "operationId": "get_server_memory",
        "summary": "서버 메모리",
        "description": "서버 배포의 메모리(MB)·CPU 수, 요금제 최대값, 1GB·시간 요금과 한 달 금액이에요. 프로덕션과 브랜치 서버는 늘 켜져 있어(최소 1대) 그 금액이 서버 하나의 한 달 요금이에요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "server_memory_mb": {},
                    "cpus": {},
                    "max_server_memory_mb": {},
                    "sizes": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_server_memory"
      },
      "put": {
        "operationId": "set_server_memory",
        "summary": "서버 메모리 바꾸기",
        "description": "서버 배포(Node 서버, 작업자)의 메모리를 512·1024·2048·4096MB 중에서 골라요(1024MB 넘으면 CPU 2개). 쓴 만큼 runtime_gb_hour로 사용량을 재요. 1분 안에 새 크기로 다시 시작해요. 소유자·관리자만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_server_memory",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "memory_mb": {
                    "type": "integer",
                    "enum": [
                      512,
                      1024,
                      2048,
                      4096
                    ],
                    "description": "Memory in MB: 512, 1024, 2048 or 4096."
                  }
                },
                "required": [
                  "memory_mb"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/gpu": {
      "get": {
        "operationId": "list_gpu",
        "summary": "GPU 작업과 서버",
        "description": "GPU 작업(최근 50개), 서버, 저장소, 장비별 시간 요금과 저장소 1GB·월 요금, 고를 수 있는 지역·데이터센터, 조직의 동시 GPU 한도와 지금 쓰는 수예요. 무료 요금제는 GPU를 못 써요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "prices": {},
                    "max_gpus": {},
                    "in_use": {},
                    "jobs": {},
                    "servers": {},
                    "volumes": {},
                    "volume_price": {},
                    "max_volume_gb": {},
                    "volume_gb": {},
                    "regions": {},
                    "datacenters": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_gpu"
      }
    },
    "/projects/{ref}/gpu/jobs": {
      "post": {
        "operationId": "create_gpu_job",
        "summary": "GPU 작업 만들기",
        "description": "GPU를 빌려 공개 이미지에서 명령을 끝까지 실행해요. 끝나거나 max_minutes가 지나면 반납하고, 쓴 초만큼(이미지 받는 시간 포함) 청구해요. 결과는 바깥에 올려야 남아요. 이미지에 curl, wget, python3 중 하나가 필요해요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_gpu_job",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "gpu": {
                    "type": "string",
                    "enum": [
                      "rtx4090",
                      "l40s",
                      "a100",
                      "h100"
                    ],
                    "description": "rtx4090, l40s, a100 or h100"
                  },
                  "image": {
                    "type": "string",
                    "description": "공개 이미지, 예: pytorch/pytorch:2.4.0-cuda12.1-cudnn9-runtime"
                  },
                  "command": {
                    "type": "string",
                    "description": "sh로 실행할 명령"
                  },
                  "name": {
                    "type": "string",
                    "description": "A name"
                  },
                  "env": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "환경 변수. 암호화해 저장해요."
                  },
                  "max_minutes": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10080,
                    "description": "기본 60분"
                  },
                  "region": {
                    "type": "string",
                    "enum": [
                      "auto",
                      "asia",
                      "us",
                      "eu"
                    ],
                    "description": "빌릴 지역. 기본 auto(빈 장비가 있는 곳 어디든). asia는 일본·인도예요. 저장소를 고르면 그 저장소의 데이터센터에서 빌려요."
                  },
                  "volume": {
                    "type": "string",
                    "description": "/workspace에 붙일 GPU 저장소 이름(create_gpu_volume으로 만든 것)"
                  }
                },
                "required": [
                  "gpu",
                  "image",
                  "command"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/gpu/jobs/{id}": {
      "get": {
        "operationId": "get_gpu_job",
        "summary": "GPU 작업 보기",
        "description": "GPU 작업 하나의 상태, 쓴 시간과 금액, 종료 코드, 출력의 마지막 부분(최대 64KB)을 돌려줘요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The job id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {},
                    "name": {},
                    "gpu": {},
                    "image": {},
                    "command": {},
                    "max_minutes": {},
                    "status": {},
                    "created_at": {},
                    "started_at": {},
                    "ended_at": {},
                    "seconds": {},
                    "cost_minor": {},
                    "exit_code": {},
                    "error": {},
                    "region": {},
                    "volume": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_gpu_job"
      }
    },
    "/projects/{ref}/gpu/jobs/{id}/cancel": {
      "post": {
        "operationId": "cancel_gpu_job",
        "summary": "GPU 작업 멈추기",
        "description": "GPU 작업을 멈춰요. 아직 시작 전이면 시작하지 않고, 실행 중이면 GPU를 돌려줘요. 돌려줄 때까지 쓴 시간은 청구돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The job id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {},
                    "name": {},
                    "gpu": {},
                    "image": {},
                    "command": {},
                    "max_minutes": {},
                    "status": {},
                    "created_at": {},
                    "started_at": {},
                    "ended_at": {},
                    "seconds": {},
                    "cost_minor": {},
                    "exit_code": {},
                    "error": {},
                    "region": {},
                    "volume": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "cancel_gpu_job"
      }
    },
    "/projects/{ref}/gpu/servers": {
      "post": {
        "operationId": "create_gpu_server",
        "summary": "GPU 서버 만들기",
        "description": "공개 이미지로 모델을 띄울 GPU 서버를 만들어요. https://<ref>.<zone>/gpu/v1/servers/<name>/ 에 secret 키로 부르면 꺼져 있을 땐 켜고(그동안 503) 요청을 넘겨요. idle_minutes 동안 요청이 없으면 꺼요(0은 계속 켬). 켜기 시작부터 꺼질 때까지(이미지 받기 포함) 초 단위로 청구해요. 서버는 x-oneend-gpu-token 헤더 값을 ONEEND_GPU_TOKEN으로 받아요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_gpu_server",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "영문 소문자, 숫자, 하이픈"
                  },
                  "gpu": {
                    "type": "string",
                    "enum": [
                      "rtx4090",
                      "l40s",
                      "a100",
                      "h100"
                    ],
                    "description": "rtx4090, l40s, a100 or h100"
                  },
                  "image": {
                    "type": "string",
                    "description": "공개 이미지, 예: vllm/vllm-openai:latest"
                  },
                  "command": {
                    "type": "string",
                    "description": "비우면 이미지의 기본 명령"
                  },
                  "env": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Environment variables, kept sealed"
                  },
                  "port": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 65535,
                    "description": "기본 8000"
                  },
                  "idle_minutes": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1440,
                    "description": "기본 15분, 0은 계속 켜 둠"
                  },
                  "region": {
                    "type": "string",
                    "enum": [
                      "auto",
                      "asia",
                      "us",
                      "eu"
                    ],
                    "description": "빌릴 지역. 기본 auto(빈 장비가 있는 곳 어디든). asia는 일본·인도예요. 저장소를 고르면 그 저장소의 데이터센터에서 빌려요."
                  },
                  "volume": {
                    "type": "string",
                    "description": "/workspace에 붙일 GPU 저장소 이름(create_gpu_volume으로 만든 것)"
                  }
                },
                "required": [
                  "name",
                  "gpu",
                  "image"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/gpu/servers/{name}/stop": {
      "post": {
        "operationId": "stop_gpu_server",
        "summary": "GPU 서버 멈추기",
        "description": "GPU 서버를 지금 멈춰요. 꺼질 때까지 쓴 시간은 청구돼요. 다음 요청 때 다시 켜져요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The server name"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "stop_gpu_server"
      }
    },
    "/projects/{ref}/gpu/servers/{name}": {
      "delete": {
        "operationId": "delete_gpu_server",
        "summary": "GPU 서버 지우기",
        "description": "GPU 서버를 지워요. 켜져 있으면 먼저 멈춘 뒤 지워요. 되돌릴 수 없으니 confirm에 GPU 서버 이름을 그대로 넣어야 해요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The server name"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "deleted": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "delete_gpu_server",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "GPU 서버 이름. name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/gpu/volumes": {
      "post": {
        "operationId": "create_gpu_volume",
        "summary": "GPU 저장소 만들기",
        "description": "모델·데이터를 남길 GPU 저장소를 한 데이터센터에 만들어요(작업·서버의 /workspace에 붙어요). 쓰지 않아도 1GB·월 요금이 청구되고, 이걸 쓰면 그 데이터센터에서만 GPU를 빌려요. 유료 요금제만 돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_gpu_volume",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "영문 소문자, 숫자, 하이픈"
                  },
                  "size_gb": {
                    "type": "integer",
                    "minimum": 10,
                    "maximum": 4000,
                    "description": "기본 50GB"
                  },
                  "datacenter": {
                    "type": "string",
                    "description": "데이터센터, 예: AP-JP-1(일본). 고를 수 있는 목록은 list_gpu에 있어요."
                  }
                },
                "required": [
                  "name",
                  "datacenter"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/gpu/volumes/{name}": {
      "delete": {
        "operationId": "delete_gpu_volume",
        "summary": "GPU 저장소 지우기",
        "description": "GPU 저장소와 그 안의 파일을 모두 지워요. 쓰는 작업이나 서버가 있으면 지우지 않아요. 되돌릴 수 없어요. 지울 때까지의 저장 요금은 청구돼요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The storage name"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "deleted": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "delete_gpu_volume"
      }
    },
    "/projects/{ref}/mysql": {
      "get": {
        "operationId": "list_mysql_databases",
        "summary": "MySQL 데이터베이스 목록",
        "description": "MySQL 데이터베이스(MariaDB 11.4)마다 받는 앱(app, null은 프로젝트 전체), 상태, 크기와 요금제 최대 개수(max)예요. available이 false면 이 서버에 아직 MySQL이 없어요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "available": {},
                    "max": {},
                    "apps": {},
                    "databases": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_mysql_databases"
      },
      "post": {
        "operationId": "create_mysql_database",
        "summary": "MySQL 데이터베이스 만들기",
        "description": "WordPress 같은 MySQL 앱용 데이터베이스와 전용 로그인을 만들어요(보통 1분). app을 주면 그 앱만, 없으면 프로젝트의 앱 모두가 받아요. 서버는 시작할 때 MYSQL_URL·MYSQL_HOST·MYSQL_PORT·MYSQL_USER·MYSQL_PASSWORD·MYSQL_DATABASE와 WORDPRESS_DB_HOST·WORDPRESS_DB_USER·WORDPRESS_DB_PASSWORD·WORDPRESS_DB_NAME을 받아요(빌드 제외). 매일 밤 백업돼요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_mysql_database",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9_]{0,31}$",
                    "description": "영문 소문자로 시작하고 영문 소문자, 숫자, 밑줄(_)로 32자까지. 예: wordpress"
                  },
                  "app": {
                    "type": "string",
                    "description": "이 데이터베이스를 받을 앱 이름. 비우면 프로젝트 전체용"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/mysql/{name}": {
      "patch": {
        "operationId": "bind_mysql_database",
        "summary": "MySQL 데이터베이스를 앱에 연결",
        "description": "MySQL 데이터베이스를 받을 앱을 바꿔요. app이 null이면 프로젝트 전체용이 돼요. 앱 하나에는 데이터베이스 하나만 연결돼요. 실행 중인 서버는 다시 시작하거나 다시 배포하면 바뀐 값을 받아요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The MySQL database name"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "bind_mysql_database",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "app": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "앱 이름, 또는 프로젝트 전체용이면 null"
                  }
                },
                "required": [
                  "app"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_mysql_database",
        "summary": "MySQL 데이터베이스 지우기",
        "description": "MySQL 데이터베이스와 로그인, 백업을 모두 지워요. 되돌릴 수 없으니 사용자가 요청할 때만 쓰고 confirm에 데이터베이스 이름을 넣으세요. 받던 앱은 다음 시작부터 MYSQL_*를 받지 않아요. 소유자·관리자만 돼요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The MySQL database name"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "deleted": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "delete_mysql_database",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "MySQL 데이터베이스 이름. name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/mysql/{name}/connection": {
      "get": {
        "operationId": "get_mysql_connection",
        "summary": "MySQL 연결 정보",
        "description": "MySQL 데이터베이스의 주소, 포트, 데이터베이스 이름, 로그인, 비밀번호와 앱이 받는 변수(variables)를 돌려줘요. 주소는 이 서버 안의 앱에서만 닿아요. 비밀번호는 쓰기 권한 토큰에만 보여요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The MySQL database name"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "host": {},
                    "port": {},
                    "database": {},
                    "user": {},
                    "password": {},
                    "url": {},
                    "variables": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "secrets.read (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "get_mysql_connection"
      }
    },
    "/projects/{ref}/mysql/{name}/backups": {
      "get": {
        "operationId": "list_mysql_backups",
        "summary": "MySQL 백업 목록",
        "description": "MySQL 데이터베이스의 백업(매일 밤 자동, 직접 만든 것, 복원 직전 것)과 복원 기록을 돌려줘요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The MySQL database name"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "backups": {},
                    "restores": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_mysql_backups"
      },
      "post": {
        "operationId": "create_mysql_backup",
        "summary": "MySQL 지금 백업",
        "description": "MySQL 데이터베이스를 지금 백업해요. 플러그인 업데이트나 대량 변경 전에 만드세요. 7일 보관돼요. 매일 밤 백업은 따로 자동으로 돼요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The MySQL database name"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "id": {},
                    "status": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_mysql_backup"
      }
    },
    "/projects/{ref}/mysql/{name}/restore": {
      "post": {
        "operationId": "restore_mysql_backup",
        "summary": "MySQL 백업으로 복원",
        "description": "MySQL 데이터베이스를 백업 시점으로 되돌려요. 그 뒤 변경은 사라지니 사용자가 요청할 때만 쓰고 confirm에 데이터베이스 이름을 넣으세요. 직전 상태를 백업하니 undo_backup_id로 되돌릴 수 있어요. 소유자·관리자만 돼요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The MySQL database name"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "restore_id": {},
                    "status": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "restore_mysql_backup",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "backup_id": {
                    "type": "string",
                    "description": "list_mysql_backups의 백업 id"
                  },
                  "confirm": {
                    "type": "string",
                    "description": "MySQL 데이터베이스 이름. name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "backup_id",
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/concurrent-builds": {
      "get": {
        "operationId": "get_concurrent_builds",
        "summary": "동시 빌드",
        "description": "이 프로젝트의 빌드가 한꺼번에 몇 개까지 도는지예요. null이면 빌더가 허락하는 만큼 돌아요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "concurrent_builds": {},
                    "max": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_concurrent_builds"
      },
      "put": {
        "operationId": "set_concurrent_builds",
        "summary": "동시 빌드 바꾸기",
        "description": "이 프로젝트의 빌드가 한꺼번에 몇 개까지 돌지 1~20으로 정하거나, null로 한도를 없애요. 넘는 빌드는 대기열에서 기다리고, 기다리는 동안은 청구되지 않아요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "deployments"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "concurrent_builds": {},
                    "max": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_concurrent_builds",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "concurrent_builds": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 20,
                    "description": "A whole number from 1 to 20, or null for no limit."
                  }
                },
                "required": [
                  "concurrent_builds"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/network": {
      "get": {
        "operationId": "get_projects_ref_network",
        "summary": "네트워크 주소",
        "description": "요청을 받는 주소(inbound, 커스텀 도메인 A 레코드)와, 고정 아웃바운드 IP를 켰다면 나가는 고정 주소(outbound.addresses)예요. 켜지 않았으면 나가는 주소는 공유라 돌려주지 않으니 허용 목록에 넣지 마세요.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "region": {},
                    "inbound": {},
                    "outbound": {},
                    "static_outbound_ip": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_network"
      }
    },
    "/projects/{ref}/network/ips": {
      "get": {
        "operationId": "get_projects_ref_network_ips",
        "summary": "네트워크 주소",
        "description": "요청을 받는 주소(inbound, 커스텀 도메인 A 레코드)와, 고정 아웃바운드 IP를 켰다면 나가는 고정 주소(outbound.addresses)예요. 켜지 않았으면 나가는 주소는 공유라 돌려주지 않으니 허용 목록에 넣지 마세요.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "region": {},
                    "inbound": {},
                    "outbound": {},
                    "static_outbound_ip": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_network"
      }
    },
    "/projects/{ref}/network/static-outbound-ip": {
      "post": {
        "operationId": "post_projects_ref_network_static_outbound_ip",
        "summary": "고정 아웃바운드 IP",
        "description": "유료 부가 서비스인 고정 아웃바운드 IP를 켜거나 꺼요. 켜면 서버 배포, 함수 fetch(), 데이터베이스 웹훅이 고정 주소로 나가고 월 요금을 쓴 날만큼 청구해요. Pro 이상, 소유자·관리자·결제 담당자만 돼요. 요금이 드니 사용자가 요청할 때만 쓰세요. 가격·상태는 get_network에 있어요. outcome이 provisioning이면 주소를 만들고 있고(보통 1시간 안) 그 전엔 요금이 없어요.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "active": {},
                    "status": {},
                    "outcome": {},
                    "addresses": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "billing.manage (소유자·관리자·결제 담당)"
        ],
        "x-oneend-mcp-tool": "set_static_outbound_ip"
      },
      "delete": {
        "operationId": "delete_projects_ref_network_static_outbound_ip",
        "summary": "고정 아웃바운드 IP",
        "description": "유료 부가 서비스인 고정 아웃바운드 IP를 켜거나 꺼요. 켜면 서버 배포, 함수 fetch(), 데이터베이스 웹훅이 고정 주소로 나가고 월 요금을 쓴 날만큼 청구해요. Pro 이상, 소유자·관리자·결제 담당자만 돼요. 요금이 드니 사용자가 요청할 때만 쓰세요. 가격·상태는 get_network에 있어요. outcome이 provisioning이면 주소를 만들고 있고(보통 1시간 안) 그 전엔 요금이 없어요.",
        "tags": [
          "network"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "active": {},
                    "status": {},
                    "outcome": {},
                    "addresses": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "billing.manage (소유자·관리자·결제 담당)"
        ],
        "x-oneend-mcp-tool": "set_static_outbound_ip"
      }
    },
    "/projects/{ref}/team": {
      "get": {
        "operationId": "list_team",
        "summary": "팀 구성원",
        "description": "이 프로젝트를 가진 조직의 구성원과 역할, 2단계 인증 여부, 아직 수락하지 않은 초대.",
        "tags": [
          "team"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "mfa_required": {},
                    "members": {},
                    "invitations": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_team"
      }
    },
    "/projects/{ref}/team/invitations": {
      "post": {
        "operationId": "invite_member",
        "summary": "구성원 초대",
        "description": "이메일로 초대 링크를 보내요. 받은 사람이 링크를 열어야 참여해요. 이미 구성원인 주소는 역할만 바뀌어요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "team"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "email": {},
                    "role": {},
                    "outcome": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "team.manage (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "invite_member",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "The email address to invite."
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "developer",
                      "billing",
                      "viewer"
                    ],
                    "description": "비우면 developer."
                  }
                },
                "required": [
                  "email"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/team/invitations/{id}": {
      "delete": {
        "operationId": "cancel_invitation",
        "summary": "초대 취소",
        "description": "보낸 초대를 취소해요. 그 링크는 바로 열리지 않게 돼요. id는 list_team의 invitations에 있어요.",
        "tags": [
          "team"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The invitation id from list_team."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "cancelled": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "team.manage (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "cancel_invitation"
      }
    },
    "/projects/{ref}/team/members/{email}": {
      "patch": {
        "operationId": "set_member_role",
        "summary": "구성원 역할 바꾸기",
        "description": "이미 구성원인 사람의 역할을 바꿔요. 소유자의 역할은 바꿀 수 없어요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "team"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "email",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The member's email address."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "email": {},
                    "role": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "team.manage (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_member_role",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "developer",
                      "billing",
                      "viewer"
                    ],
                    "description": "The new role."
                  }
                },
                "required": [
                  "role"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_member",
        "summary": "구성원 내보내기",
        "description": "조직에서 내보내요. 소유자는 내보낼 수 없어요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "team"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "email",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The member's email address."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "email": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "team.manage (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "remove_member"
      }
    },
    "/projects/{ref}/team/mfa": {
      "put": {
        "operationId": "set_mfa_required",
        "summary": "2단계 인증 요구",
        "description": "조직의 모든 구성원에게 2단계 인증을 요구하거나 그만둬요. 켜려면 이 토큰의 주인이 먼저 2단계 인증을 켜야 해요. 켜지 않은 구성원은 켤 때까지 이 조직을 열 수 없고 응답의 without_mfa에 나와요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "team"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "mfa_required": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "team.manage (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_mfa_required",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "required": {
                    "type": "boolean",
                    "description": "true to require it, false to stop requiring it."
                  }
                },
                "required": [
                  "required"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/channels": {
      "get": {
        "operationId": "list_channels",
        "summary": "알림 채널 목록",
        "description": "배포·도메인·사용량·결제 소식을 받는 채널(Slack·카카오워크·웹훅)과 마지막 전송 결과예요(조직 단위). 웹훅 채널의 서명 키(signing_secret)는 만들 때(create_channel) 한 번만 보여주고, 목록에는 signing_secret_set과 끝 네 글자(signing_secret_last4)만 실어요.",
        "tags": [
          "team"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "notices": {},
                    "channels": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_channels"
      },
      "post": {
        "operationId": "create_channel",
        "summary": "알림 채널 추가",
        "description": "Slack·카카오워크(웹훅 주소)·서명 웹훅·메일(emails에 1~10개)로 알림을 보내요. 메일은 확인 링크를 연 주소에만 보내요. notices를 비우면 모든 종류를 받아요. 웹훅 채널의 signing_secret은 이 응답에만 실리니 받는 쪽에 바로 저장하세요. 만든 뒤 test_channel로 확인하세요. 소유자·관리자만 돼요.",
        "tags": [
          "team"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "team.manage (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "create_channel",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "slack",
                      "kakaowork",
                      "webhook",
                      "email"
                    ],
                    "description": "slack, kakaowork, webhook or email."
                  },
                  "name": {
                    "type": "string",
                    "description": "A name to recognise the channel by."
                  },
                  "url": {
                    "type": "string",
                    "description": "Slack·카카오워크·웹훅의 주소. 메일 채널에는 쓰지 않아요."
                  },
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 10,
                    "description": "메일 채널의 받는 주소. 예: [\"ops@example.com\"]."
                  },
                  "notices": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "deployments",
                        "domains",
                        "usage",
                        "billing"
                      ]
                    },
                    "description": "Which kinds to receive: deployments, domains, usage, billing. Empty means all."
                  }
                },
                "required": [
                  "kind",
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/channels/{id}/test": {
      "post": {
        "operationId": "test_channel",
        "summary": "알림 채널 시험",
        "description": "그 채널 하나에만 시험 메시지를 보내요. 메일 채널이면 확인된 주소에만 보내고, 확인을 기다리는 주소에는 확인 메일을 다시 보내요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "team"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The id from list_channels."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "sent": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "team.manage (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "test_channel"
      }
    },
    "/projects/{ref}/channels/{id}": {
      "patch": {
        "operationId": "set_channel_enabled",
        "summary": "알림 채널 끄기·켜기",
        "description": "설정은 두고 알림만 멈추거나 다시 받아요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "team"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The id from list_channels."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "enabled": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "team.manage (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_channel_enabled",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true to send, false to stop."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_channel",
        "summary": "알림 채널 삭제",
        "description": "알림 채널을 지워요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "team"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The id from list_channels."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "id": {},
                    "removed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "team.manage (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "remove_channel"
      }
    },
    "/projects/{ref}/extensions": {
      "get": {
        "operationId": "list_extensions",
        "summary": "DB 확장 목록",
        "description": "켤 수 있는 PostgreSQL 확장(vector, postgis, citext 등)과 available·enabled·버전이에요. extensions 스키마에 설치되고 SQL에서 vector(1536)처럼 바로 써요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "extensions": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_extensions"
      }
    },
    "/projects/{ref}/extensions/{name}": {
      "put": {
        "operationId": "enable_extension",
        "summary": "DB 확장 켜기",
        "description": "확장 하나를 켜요(create extension ... with schema extensions). 임베딩 검색은 vector, 지도·거리 계산은 postgis. 목록 밖의 확장은 거절돼요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "확장 이름: vector, postgis, citext, hstore, uuid-ossp, pgcrypto, ltree, fuzzystrmatch, btree_gin, btree_gist, intarray, tablefunc"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "extension": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "enable_extension"
      },
      "delete": {
        "operationId": "disable_extension",
        "summary": "DB 확장 끄기",
        "description": "확장을 꺼요. 쓰는 열·인덱스·함수가 남아 있으면 거절돼요. 다른 프로젝트가 쓰면 설치는 남고 이 프로젝트 기록만 지워요(note). pg_trgm·unaccent는 못 꺼요. confirm에 확장 이름이 필요해요. 소유자·관리자만 돼요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The extension name, as in list_extensions."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "extension": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "disable_extension",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "확장 이름. name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/branches": {
      "get": {
        "operationId": "list_branches",
        "summary": "DB 브랜치 목록",
        "description": "데이터베이스 브랜치 목록이에요: 이름, 브랜치의 ref(다른 도구에 그대로 써요), git 브랜치, 상태(creating·ready·merging·resetting·failed·deleting), 크기, 만료 시각. 자동 브랜치 설정도 와요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "automatic": {},
                    "lifetime_days": {},
                    "has_seed": {},
                    "branches": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_branches"
      },
      "post": {
        "operationId": "create_branch",
        "summary": "DB 브랜치 만들기",
        "description": "마이그레이션(apply_migrations 기록)을 다시 실행하고 시드를 넣어 미리보기 데이터베이스를 만들어요. 데이터는 with_data일 때만 복사해요. 브랜치는 ref가 따로 있어 모든 도구에 그 ref를 써요. git_branch를 주면 그 프리뷰 배포가 이걸 써요. Pro부터 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "branch": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_branch",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "브랜치 이름(영문 소문자·숫자·-, 30자까지). 없으면 git_branch에서 만들어요."
                  },
                  "git_branch": {
                    "type": "string",
                    "description": "연결할 git 브랜치. 그 브랜치의 미리보기 배포에 이 데이터베이스의 주소·키·연결 문자열이 들어가요."
                  },
                  "with_seed": {
                    "type": "boolean",
                    "description": "false면 시드를 넣지 않아요."
                  },
                  "with_data": {
                    "type": "boolean",
                    "description": "true면 프로젝트의 행까지 복사해요(마이그레이션 다시 실행과 시드 대신). 파일과 그 행은 복사하지 않아요. 데이터가 512MB를 넘으면 거절해요. 진행 상황은 list_branches의 copy에 나와요."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/branching": {
      "put": {
        "operationId": "set_branching",
        "summary": "자동 DB 브랜치 설정",
        "description": "미리보기로 배포되는 git 브랜치마다 DB 브랜치를 자동으로 만들지, 모든 브랜치에 넣을 시드 SQL, 쓰지 않는 브랜치를 남겨 둘 날짜(1~90일, 배포할 때마다 연장). 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "automatic": {},
                    "lifetime_days": {},
                    "has_seed": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_branching",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "automatic": {
                    "type": "boolean",
                    "description": "true면 미리보기 브랜치마다 자동으로 만들어요."
                  },
                  "seed_sql": {
                    "type": "string",
                    "description": "새 브랜치마다 마이그레이션 뒤에 실행할 SQL(1MB까지). 빈 문자열이면 지워요."
                  },
                  "lifetime_days": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 90,
                    "description": "마지막 배포 뒤 브랜치를 남겨 둘 날짜."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/branches/{name}/merge": {
      "post": {
        "operationId": "merge_branch",
        "summary": "DB 브랜치 병합",
        "description": "브랜치에만 있는 마이그레이션을 버전 순으로 운영 프로젝트에 적용해요. 하나씩 트랜잭션으로 실행하고 실패하면 그것만 되돌리고 멈춰요. 데이터는 안 옮겨요. 브랜치 스키마는 apply_migrations로 바꿔야 병합돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "브랜치 이름(list_branches의 name)."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "422": {
            "$ref": "#/components/responses/E422"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "merge_branch"
      }
    },
    "/projects/{ref}/branches/{name}/reset": {
      "post": {
        "operationId": "reset_branch",
        "summary": "DB 브랜치 초기화",
        "description": "브랜치의 데이터베이스를 지우고 프로젝트의 마이그레이션과 시드로 다시 만들어요. 브랜치의 데이터와 사용자는 모두 사라지고 백업은 남지 않아요. confirm에 브랜치 이름을 그대로 넣어야 해요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "브랜치 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "branch": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "reset_branch",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "브랜치 이름. name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/branches/{name}": {
      "delete": {
        "operationId": "delete_branch",
        "summary": "DB 브랜치 삭제",
        "description": "브랜치와 그 데이터베이스·키를 지워요. 되돌릴 수 없으니 confirm에 브랜치 이름을 그대로 넣어야 해요. git 브랜치를 지우거나 풀 리퀘스트를 닫으면 자동으로 지워져요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "브랜치 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "branch": {},
                    "deleted": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "delete_branch",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "브랜치 이름. name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/queues": {
      "get": {
        "operationId": "list_queues",
        "summary": "대기열 목록",
        "description": "대기열마다 메시지 수, 지금 읽을 수 있는 수, 보관된 수, 가장 오래된 메시지 나이예요. enabled는 pgmq 설치 여부, exposed는 데이터 API(pgmq_public)로 부를 수 있는지예요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_queues"
      },
      "post": {
        "operationId": "create_queue",
        "summary": "대기열 만들기",
        "description": "대기열을 만들어요(pgmq.create, 처음이면 pgmq도 설치). 메시지는 pgmq.q_<이름> 표에 있고, SQL에서 pgmq.send(이름, 메시지)로 넣고 pgmq.read(이름, 초, 개수)로 읽어요. 전용 데이터베이스에서만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "create_queue",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "대기열 이름(영문 소문자·숫자·_, 47자까지)."
                  },
                  "unlogged": {
                    "type": "boolean",
                    "description": "true면 WAL을 쓰지 않는 빠른 표로 만들어요(서버가 비정상 종료되면 메시지를 잃어요)."
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/queues/metrics": {
      "get": {
        "operationId": "get_queue_metrics",
        "summary": "큐 지표",
        "description": "5분마다 잰 기록으로 큐마다 지금 대기 수·읽을 수 있는 메시지·가장 오래 기다린 시간·보관 수와, 전체의 시간별 대기·보낸·처리된 수를 돌려줘요. 기본 24시간, 최대 168시간.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 168,
              "description": "기간(시간). 기본 24."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "hours": {},
                    "queues": {},
                    "points": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_queue_metrics"
      }
    },
    "/projects/{ref}/queues/api": {
      "put": {
        "operationId": "set_queues_api",
        "summary": "대기열을 데이터 API로 열기",
        "description": "true면 pgmq_public 스키마를 만들어 supabase.schema(\"pgmq_public\").rpc(\"send\", …)로 부르게 해요. 부른 사람 권한으로 실행되니 대기열 표에 권한과 접근 규칙을 주세요. 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_queues_api",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "exposed": {
                    "type": "boolean",
                    "description": "true면 열고 false면 닫아요."
                  }
                },
                "required": [
                  "exposed"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/queues/{name}": {
      "delete": {
        "operationId": "delete_queue",
        "summary": "대기열 삭제",
        "description": "대기열과 그 메시지, 보관함을 지워요(pgmq.drop_queue). 되돌릴 수 없으니 confirm에 대기열 이름을 그대로 넣어야 해요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "대기열 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "queue": {},
                    "dropped": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "delete_queue",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "대기열 이름. name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/queues/{name}/purge": {
      "post": {
        "operationId": "purge_queue",
        "summary": "대기열 비우기",
        "description": "대기열의 메시지를 모두 지워요(pgmq.purge_queue). 보관함은 그대로 둬요. 되돌릴 수 없으니 confirm에 대기열 이름을 그대로 넣어야 해요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "대기열 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "queue": {},
                    "purged": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "purge_queue",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "대기열 이름. name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/queues/{name}/messages": {
      "post": {
        "operationId": "send_queue_message",
        "summary": "대기열에 메시지 넣기",
        "description": "메시지(JSON) 하나를 대기열에 넣어요(pgmq.send). delay초 동안은 읽히지 않아요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "대기열 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "queue": {},
                    "msg_id": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "send_queue_message",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "message": {
                    "description": "넣을 메시지. JSON 값이면 무엇이든 돼요."
                  },
                  "delay": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "이 초만큼 지난 뒤에 읽을 수 있게 해요."
                  }
                },
                "required": [
                  "message"
                ]
              }
            }
          }
        }
      },
      "get": {
        "operationId": "peek_queue",
        "summary": "대기열 메시지 보기",
        "description": "대기열의 앞쪽 메시지를 가져가지 않고 봐요. 읽음 횟수도 가시성 시간도 바꾸지 않아서 작업자가 받을 메시지를 가로채지 않아요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "대기열 이름."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "볼 메시지 수(기본 20)."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "queue": {},
                    "messages": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "peek_queue"
      }
    },
    "/projects/{ref}/vault": {
      "get": {
        "operationId": "list_vault_secrets",
        "summary": "Vault 비밀 목록",
        "description": "Vault에 저장한 비밀의 이름과 설명. 값은 돌려주지 않아요. 프로젝트의 코드는 비밀 키로 select decrypted_secret from vault.decrypted_secrets where name = …로 읽어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "enabled": {},
                    "secrets": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "secrets.read (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "list_vault_secrets"
      },
      "post": {
        "operationId": "create_vault_secret",
        "summary": "Vault 비밀 저장",
        "description": "비밀 하나를 암호화해 프로젝트 데이터베이스의 vault.secrets에 저장해요(vault.create_secret). 키는 플랫폼이 갖고 있어 덤프·백업에는 암호문만 남아요. 처음이면 Vault를 켜요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "secret": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "create_vault_secret",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "비밀 이름(영문자나 _로 시작, 128자까지)."
                  },
                  "value": {
                    "type": "string",
                    "description": "저장할 값(64KB까지). 다시 보여 주지 않아요."
                  },
                  "description": {
                    "type": "string",
                    "description": "설명(500자까지)."
                  }
                },
                "required": [
                  "name",
                  "value"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/vault/{name}": {
      "patch": {
        "operationId": "update_vault_secret",
        "summary": "Vault 비밀 바꾸기",
        "description": "비밀의 값이나 설명을 바꿔요(vault.update_secret). 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "비밀 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "secret": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "update_vault_secret",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "value": {
                    "type": "string",
                    "description": "새 값."
                  },
                  "description": {
                    "type": "string",
                    "description": "새 설명."
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete_vault_secret",
        "summary": "Vault 비밀 삭제",
        "description": "비밀 하나를 지워요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "비밀 이름."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "name": {},
                    "deleted": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "delete_vault_secret"
      }
    },
    "/projects/{ref}/database/move": {
      "get": {
        "operationId": "get_database_move",
        "summary": "전용 데이터베이스로 옮기기 상태",
        "description": "전용 데이터베이스에 있는지(dedicated), 요금제 포함 여부(plan_allows), 옮기는 상태(stopped, last_error)를 봐요. size_bytes가 auto_move_max_bytes보다 크면 move_to_dedicated_database로 요청하세요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_database_move"
      },
      "post": {
        "operationId": "move_to_dedicated_database",
        "summary": "전용 데이터베이스로 옮기기",
        "description": "프로젝트를 전용 데이터베이스로 옮기도록 요청해요(콘솔 \"지금 옮기기\"). 옮기는 동안 쓰기는 멈추고 읽기는 돼요. 직전 상태를 백업하고, 실패하면 그대로예요. Pro부터, 소유자·관리자만 돼요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "402": {
            "$ref": "#/components/responses/E402"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "move_to_dedicated_database"
      }
    },
    "/projects/{ref}/database/dedicated-disk": {
      "get": {
        "operationId": "get_dedicated_disk",
        "summary": "전용 디스크",
        "description": "전용 디스크와 Postgres를 봐요: size_gb, 쓴 공간, 한 달 비용, 30일 기록, 하고 있는 요청, 줄이기 제안(shrink). 공용 디스크면 옮기는 기준(threshold_gb)과 지금 크기를 보여 줘요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_dedicated_disk"
      },
      "post": {
        "operationId": "request_dedicated_disk",
        "summary": "전용 디스크로 옮기기",
        "description": "데이터베이스를 전용 디스크(max(1.2 × 데이터베이스, 20GB))로 옮기도록 요청해요. GB당 월 ₩1,200(75¢)이고, 옮기는 동안 쓰기는 실패해요. Enterprise는 언제든, 다른 유료 요금제는 기준을 넘으면 돼요. 소유자·관리자만 돼요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "402": {
            "$ref": "#/components/responses/E402"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "request_dedicated_disk"
      }
    },
    "/projects/{ref}/database/dedicated-disk/shrink": {
      "post": {
        "operationId": "shrink_dedicated_disk",
        "summary": "디스크 줄이기",
        "description": "전용 디스크를 줄여요: 작은 디스크(1.2 × 데이터베이스, 최소 20GB)로 옮기고 원래 것을 지워요. 7일 동안 25% 아래로 쓴 디스크만 돼요(shrink.suggested). 옮기는 동안 쓰기는 실패하고 읽기는 돼요. 소유자·관리자만 돼요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "402": {
            "$ref": "#/components/responses/E402"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "shrink_dedicated_disk"
      }
    },
    "/projects/{ref}/network-restrictions": {
      "get": {
        "operationId": "get_network_restrictions",
        "summary": "DB 접속 제한 보기",
        "description": "데이터베이스 직접 연결(5432·6543)에 접속할 수 있는 주소와 TLS 강제 여부. restricted가 false면 모든 주소가 접속할 수 있어요. your_address_allowed는 이 요청을 보낸 주소가 허용되는지예요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_network_restrictions"
      },
      "put": {
        "operationId": "update_network_restrictions",
        "summary": "DB 접속 제한 바꾸기",
        "description": "직접 연결을 허용할 주소(CIDR, 100개까지)와 TLS 강제를 바꿔요. allow_all이면 모두 허용해요. 지금 요청한 주소가 목록에 없으면 confirm이 필요해요(콘솔·API는 영향 없어요). 소유자·관리자만 돼요.",
        "tags": [
          "other"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "update_network_restrictions",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "allowed_cidrs": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "허용할 주소나 CIDR(예: 203.0.113.0/24). 빈 배열이면 제한을 풀어요."
                  },
                  "allow_all": {
                    "type": "boolean",
                    "description": "true면 제한을 풀고 모든 주소를 허용해요."
                  },
                  "enforce_ssl": {
                    "type": "boolean",
                    "description": "true면 TLS(sslmode=require) 연결만 받아요. 기본값은 true예요."
                  },
                  "confirm": {
                    "type": "boolean",
                    "description": "이 요청을 보낸 주소가 목록에 없어도 저장해요."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/realtime": {
      "get": {
        "operationId": "list_realtime_tables",
        "summary": "실시간 켠 표",
        "description": "변경을 실시간으로 알리는 표 목록. 여기 없는 표를 구독하면 아무것도 오지 않아요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "tables": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "list_realtime_tables"
      }
    },
    "/projects/{ref}/realtime/{table}": {
      "put": {
        "operationId": "set_realtime",
        "summary": "표의 실시간 켜기·끄기",
        "description": "표 하나의 변경 알림을 켜거나 꺼요. 알림도 접근 규칙을 통과한 줄만 가요.",
        "tags": [
          "database"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "table",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The table name."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "tables": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "data.write (소유자·관리자·개발자)"
        ],
        "x-oneend-mcp-tool": "set_realtime",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true to turn it on, false to turn it off."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/metrics": {
      "get": {
        "operationId": "get_metrics",
        "summary": "지표",
        "description": "요청 수·실패 수·지연(p50/p95/p99)을 표면별·시간대별로, 그리고 데이터베이스 크기·연결·캐시 적중률을 돌려줘요.",
        "tags": [
          "logs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "range",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1h",
                "24h",
                "7d"
              ],
              "description": "비우면 24h."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "range": {},
                    "requests": {},
                    "failures": {},
                    "latency_ms": {},
                    "by_surface": {},
                    "points": {},
                    "database": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_metrics"
      }
    },
    "/projects/{ref}/billing/plan": {
      "get": {
        "operationId": "get_plan",
        "summary": "요금제",
        "description": "조직의 요금제, 예약된 변경, 고를 수 있는 요금제와 월 요금, 켜 둔 부가 서비스(addons)예요. 무료면 free에 한도와 Pro 전용 기능이 있어요. 요금제 변경은 콘솔에서만 돼요. 소유자·관리자·결제 담당만 돼요.",
        "tags": [
          "billing"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "currency": {},
                    "plan": {},
                    "scheduled": {},
                    "options": {},
                    "billed_by": {},
                    "addons": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "billing.manage (소유자·관리자·결제 담당)"
        ],
        "x-oneend-mcp-tool": "get_plan"
      }
    },
    "/projects/{ref}/billing/spend": {
      "get": {
        "operationId": "get_spend_controls",
        "summary": "지출 한도",
        "description": "지출 상한(spend cap: 켜면 포함량을 넘는 사용을 막고 초과 요금을 받지 않음), 월 초과 요금 한도와 알림 웹훅, 이번 달 사용량을 봐요. 소유자·관리자·결제 담당만 볼 수 있어요.",
        "tags": [
          "billing"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "spend_cap": {},
                    "spend_cap_applies": {},
                    "spend_limit_minor": {},
                    "spend_limit_floor_minor": {},
                    "webhook_url": {},
                    "progress": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "billing.manage (소유자·관리자·결제 담당)"
        ],
        "x-oneend-mcp-tool": "get_spend_controls"
      }
    },
    "/projects/{ref}/billing/spend-cap": {
      "put": {
        "operationId": "set_spend_cap",
        "summary": "지출 상한 켜기·끄기",
        "description": "유료 요금제의 지출 상한을 켜고 꺼요. 켜면 포함량에서 멈춰 초과 요금이 없어요. 끄면 넘는 만큼 청구되니 끌 때 confirm에 프로젝트 이름(list_projects의 name)이 필요해요. 소유자·관리자·결제 담당만 돼요.",
        "tags": [
          "billing"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "spend_cap": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "billing.manage (소유자·관리자·결제 담당)"
        ],
        "x-oneend-mcp-tool": "set_spend_cap",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean",
                    "description": "true면 켜요."
                  },
                  "confirm": {
                    "type": "string",
                    "description": "끌 때(enabled: false)만: 프로젝트 이름. list_projects의 name과 정확히 같아야 해요."
                  }
                },
                "required": [
                  "enabled"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/billing/spend-limit": {
      "put": {
        "operationId": "set_spend_limit",
        "summary": "월 지출 한도",
        "description": "지출 상한이 꺼졌을 때 한 달 초과 요금 한도(원 단위)와 알림 웹훅을 정해요. spend_limit_minor가 null이면 무제한, webhook_url을 빼면 그대로예요. 알림은 create_channel이 더 좋아요. 소유자·관리자·결제 담당만 돼요.",
        "tags": [
          "billing"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "spend_cap": {},
                    "spend_cap_applies": {},
                    "spend_limit_minor": {},
                    "spend_limit_floor_minor": {},
                    "webhook_url": {},
                    "progress": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "billing.manage (소유자·관리자·결제 담당)"
        ],
        "x-oneend-mcp-tool": "set_spend_limit",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "spend_limit_minor": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 0,
                    "description": "한도. null이면 없음."
                  },
                  "webhook_url": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "알림을 받을 https 주소. 빈 문자열이면 지워요."
                  }
                },
                "required": [
                  "spend_limit_minor"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/billing": {
      "get": {
        "operationId": "get_billing",
        "summary": "청구서와 사용량",
        "description": "한 달 청구서(항목별 사용량·포함량·금액)와 날짜별 사용량이에요. period를 비우면 이번 달(UTC). 금액은 currency의 가장 작은 단위예요(KRW는 원, USD는 센트). amount_minor·total_minor는 청구액, list_amount_minor·list_total_minor는 정가(Pro 기준)예요. included는 이번 달 실제로 쓴 요금제의 포함량(바꾼 날까지 날짜로 나눔), list_included는 Pro 포함량이에요. billing_exempt면 청구액이 0이에요. 카드·결제 내역은 콘솔에만 있어요. 소유자·관리자·결제 담당만 돼요.",
        "tags": [
          "billing"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "period",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "YYYY-MM"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "period": {},
                    "plan": {},
                    "period_start": {},
                    "period_end": {},
                    "currency": {},
                    "list_total_minor": {},
                    "billing_exempt": {},
                    "lines": {},
                    "usage": {},
                    "months": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "billing.manage (소유자·관리자·결제 담당)"
        ],
        "x-oneend-mcp-tool": "get_billing"
      }
    },
    "/projects/{ref}/audit": {
      "get": {
        "operationId": "get_audit_log",
        "summary": "감사 기록",
        "description": "tab=activity는 누가 무엇을 바꿨는지, tab=access는 누가 개인정보에 접근했는지예요. 최신순 200개씩, has_more면 offset을 늘려요. from·to는 YYYY-MM-DD(한국 날짜). 소유자·관리자만 돼요.",
        "tags": [
          "logs"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "tab",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "activity",
                "access"
              ],
              "description": "activity for changes, access for access to personal data."
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "The first date, YYYY-MM-DD."
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "The last date, YYYY-MM-DD."
            }
          },
          {
            "name": "actor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "이메일 일부."
            }
          },
          {
            "name": "action",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "이 말로 시작하는 동작. 예: member."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "description": "How many entries to get, up to 200."
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "How many entries to skip."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "tab": {},
                    "total": {},
                    "has_more": {},
                    "records": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-permissions": [
          "audit.read (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "get_audit_log"
      }
    },
    "/projects/{ref}/signing": {
      "get": {
        "operationId": "get_jwt_signing",
        "summary": "토큰 서명 방식",
        "description": "로그인 토큰을 HS256과 ES256 중 무엇으로 서명하는지와, 지금 받아 주는 예전 키(유예 중인 키)를 보여줘요.",
        "tags": [
          "keys"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "alg": {},
                    "keys": {},
                    "grace_hours": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "read",
        "x-oneend-mcp-tool": "get_jwt_signing"
      },
      "put": {
        "operationId": "set_jwt_signing",
        "summary": "토큰 서명 방식 바꾸기",
        "description": "ES256으로 바꾸면 새 로그인부터 비대칭 키로 서명하고, 다른 서버가 공개 키(JWKS)로 토큰을 확인할 수 있어요. 이미 받은 토큰은 만료될 때까지 그대로 통해요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "keys"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "alg": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "set_jwt_signing",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "alg": {
                    "type": "string",
                    "enum": [
                      "HS256",
                      "ES256"
                    ],
                    "description": "HS256 or ES256."
                  }
                },
                "required": [
                  "alg"
                ]
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/signing/rotate": {
      "post": {
        "operationId": "rotate_signing_key",
        "summary": "키 교체",
        "description": "공개 키·비밀 키를 서명하는 키를 새로 만들어요. 예전 키는 grace_hours(0, 1, 24, 168) 동안 더 받아요. 0(기본)이면 지금 앱이 30초 안에 모두 멈추니 confirm에 프로젝트 이름이 필요해요. 사용자가 요청할 때만, 소유자·관리자만 돼요.",
        "tags": [
          "keys"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "key_version": {},
                    "grace_hours": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "rotate_signing_key",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "grace_hours": {
                    "type": "integer",
                    "enum": [
                      0,
                      1,
                      24,
                      168
                    ],
                    "description": "How many hours the old key is still accepted: 0, 1, 24 or 168."
                  },
                  "confirm": {
                    "type": "string",
                    "description": "grace_hours가 0(또는 비움)일 때만: 프로젝트 이름. list_projects의 name과 정확히 같아야 해요."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/projects/{ref}/signing/keys/{kid}": {
      "delete": {
        "operationId": "retire_signing_key",
        "summary": "예전 키 폐기",
        "description": "유예 중인 예전 키를 지금 끝내요. kid는 get_jwt_signing의 keys에서 state가 rotating인 것이에요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "keys"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "kid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The kid from get_jwt_signing."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ref": {},
                    "kid": {},
                    "retired": {},
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "retire_signing_key"
      }
    },
    "/projects/{ref}/domains/{hostname}/certificate": {
      "put": {
        "operationId": "upload_certificate",
        "summary": "인증서 올리기",
        "description": "연결한 도메인에 직접 가진 TLS 인증서를 써요. certificate는 PEM 체인(서버 인증서가 먼저), key는 PEM 개인 키. 도메인 이름이 인증서에 들어 있어야 해요. 1분 안에 적용돼요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "domains"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "hostname",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The connected domain."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          },
          "413": {
            "$ref": "#/components/responses/E413"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "upload_certificate",
        "x-oneend-max-body-bytes": 262144,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "certificate": {
                    "type": "string",
                    "description": "The PEM certificate chain, the server certificate first."
                  },
                  "key": {
                    "type": "string",
                    "description": "The PEM private key."
                  }
                },
                "required": [
                  "certificate",
                  "key"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove_certificate",
        "summary": "올린 인증서 삭제",
        "description": "올린 인증서를 지우고 자동 발급 인증서로 돌아가요. 소유자·관리자만 할 수 있어요.",
        "tags": [
          "domains"
        ],
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "ref",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z]{20}$",
              "description": "프로젝트 ID(ref). list_projects로 확인해요."
            }
          },
          {
            "name": "hostname",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The connected domain."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "성공. 본문은 결과 JSON이에요.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "note": {}
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/E400"
          },
          "401": {
            "$ref": "#/components/responses/E401"
          },
          "403": {
            "$ref": "#/components/responses/E403"
          },
          "404": {
            "$ref": "#/components/responses/E404"
          },
          "409": {
            "$ref": "#/components/responses/E409"
          }
        },
        "x-oneend-scope": "write",
        "x-oneend-permissions": [
          "project.admin (소유자·관리자)"
        ],
        "x-oneend-mcp-tool": "remove_certificate"
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "bwk_… personal access token, or an OAuth access token (ADR 0016)."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "message"
            ],
            "properties": {
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "responses": {
      "E400": {
        "description": "요청이 올바르지 않거나 작업이 거절됐어요. error.message에 이유가 있어요.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "E401": {
        "description": "토큰이 없거나, 올바르지 않거나, 만료됐어요.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "E402": {
        "description": "402",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "E403": {
        "description": "토큰의 범위(read/write)나 조직 안의 역할이 모자라거나, 조직이 2단계 인증을 요구해요.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "E404": {
        "description": "프로젝트나 대상이 없거나, 이 토큰으로는 보이지 않아요.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "E409": {
        "description": "지금은 할 수 없어요. 예를 들어 프로젝트 데이터베이스를 아직 만드는 중이에요.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "E413": {
        "description": "본문이 이 경로의 한도보다 커요.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "E422": {
        "description": "422",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "E429": {
        "description": "429",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "E500": {
        "description": "서버가 결과를 다시 읽지 못했어요. 잠시 뒤 다시 시도하세요.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "E502": {
        "description": "502",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
