계약 원칙
- 버전 경로
/api/v1과 저장소의 OpenAPI 문서를 기준 계약으로 사용 - UI와 API·MCP에 동일한 Keycloak/개인 키 인증과 RBAC 적용
- 객체 범위 RBAC는 Hub·통합 사용자·서버 REST에서 SQL pagination 전 적용하며, 현재 MCP·통합 검색·통계는 전역 권한만 허용
- 개인 API 키 permission은 사용자 전역·객체 범위와 교집합으로 판정
- 대시보드·세션·LLM 사용량처럼 수집 시각이 중요한 응답은
sampled_at,data_freshness또는stale을 제공 - 오류 응답에 비밀값·외부 token·프롬프트 본문 미포함
- REST 목록은
page와page_size기반이며 Hub filter에는 정수hub_id사용 - 현재 버전 MCP는 읽기 전용 도구 네 개만 제공
이 문서는 사용 개념과 대표 리소스를 설명합니다. 구체적인 field·endpoint·status code는 이미지의 /app/openapi/openapi.yaml과 HTTP GET /api/v1/openapi.yaml 명세를 최종 기준으로 삼으세요.
인증과 개인 키
브라우저는 HttpOnly jupiq_session JWT cookie를, 자동화는 Authorization: Bearer <JWT|jqk_API_KEY>를 사용합니다. 로컬 로그인은 POST /api/v1/auth/login, Keycloak 시작은 GET /api/v1/auth/oidc/login과 callback 흐름을 사용합니다. 개인 키에는 resource/action scope와 만료를 적용합니다.
curl --fail-with-body \
-H "Authorization: Bearer ${JUPIQ_API_KEY}" \
-H "Accept: application/json" \
https://jupiq.internal/api/v1/version키 평문은 생성 직후 한 번만 표시됩니다. 로그와 shell history에 키가 남지 않도록 파일 descriptor 또는 조직 secret manager를 사용하고 정기 회전하세요.
대표 REST 리소스
| 리소스 | 대표 목적 |
|---|---|
/api/v1/hubs | Hub 등록·상태·연결 테스트·동기화 |
/api/v1/users | 통합 사용자 목록과 360도 상세 |
/api/v1/servers | 서버 조회와 조건부 승인 기반 시작·중지·재시작 |
/api/v1/usage | 기간·granularity·group별 집계 |
/api/v1/gpus | 선택형 GPU 관측 |
/api/v1/policies | 정책 CRUD 카탈로그(자동 집행 없음) |
/api/v1/profiles, /images, /projects | 운영 카탈로그 CRUD |
/api/v1/incidents, /notifications, /costs | Incident·알림·비용 카탈로그 CRUD |
/api/v1/audit | 권한 범위 내 변경 감사 |
/api/v1/version | 서비스 version·commit·build time |
목록 요청 예시
GET /api/v1/servers?hub_id=2&status=running&page=1&page_size=50
Accept: application/json
Authorization: Bearer ••••오류 모델 예시
{
"error": {
"code": "not_found",
"message": "요청한 대상을 찾을 수 없습니다",
"request_id": "req_01..."
}
}신선도 응답
대시보드 응답은 화면 생성 시각과 최근 수집 시각, stale 여부를 데이터 본문에 제공합니다.
{
"data": {
"sampled_at": "2026-09-02T06:20:02Z",
"data_freshness": "2026-09-02T06:12:00Z",
"stale": true,
"summary": {"active_users": 31, "running_servers": 39}
}
}active_users는 브라우저 로그인 연결 수가 아니라 최신 JupyterHub snapshot에서 실행 서버가 있는 사용자 수입니다. Hub 목록은 status, last_seen_at, last_error를 제공합니다. 클라이언트는 stale 자료를 현재 수집값처럼 표시하지 않고 기준 시각을 함께 보여줘야 합니다.
AI API는 스트리밍 기본
POST /api/v1/ai/chat은 OpenAI-compatible Provider에 항상 stream: true로 요청하고 SSE 응답을 그대로 중계합니다. 관리자는 Provider·model·최대 token을 설정하며 요청의 max_tokens는 관리자 한도와 262,144를 모두 넘을 수 없습니다.
data: {"choices":[{"delta":{"content":"요청하신 내용을 "}}]}
data: {"choices":[{"delta":{"content":"한국어로 정리했습니다."}}]}
data: [DONE]클라이언트 연결 종료는 upstream 요청 context에 전달됩니다. 현재 버전 AI endpoint는 분석 응답을 스트리밍할 뿐 변경 작업이나 Preview endpoint를 실행하지 않습니다.
현재 버전 MCP 도구
MCP Streamable HTTP/JSON-RPC endpoint는 POST /mcp이며 POST /api/v1/mcp도 같은 기능을 제공합니다. REST와 동일한 cookie/Bearer 인증을 사용하고 initialize, ping, tools/list, tools/call을 지원합니다. JSON 응답이 기본이며 Accept: text/event-stream 요청에는 한 개의 SSE data 이벤트로 응답합니다.
| 도구 | 내용 | 필요 권한 |
|---|---|---|
jupiq.dashboard | 사용자·서버·자원 요약 | dashboard:read |
jupiq.list_hubs | 등록된 Hub 상태 목록 | hubs:read |
jupiq.list_servers | Hub ID·상태·검색어로 서버 조회, 최대 200건 | servers:read |
jupiq.usage | 기간·granularity·group 기준 사용량 집계 | usage:read |
도구 결과는 JSON text와 structuredContent로 반환됩니다. jupiq.list_servers에는 후속 페이지 cursor가 없으므로 200건을 넘는 전체 조회는 REST 목록 API를 사용하세요.
현재 버전 안전 경계
- MCP에는 Resource capability와 write tool이 없습니다.
- MCP를 통한 서버 중지·정책 적용·승인·Preview·idempotency 계약은 제공하지 않습니다.
- 서버 제어와 관리 변경은 권한이 있는 REST/UI 흐름과 활성화된 승인 정책을 사용합니다.
- 각 MCP 도구는
mcp:use와 도구별 전역 read 권한을 모두 확인합니다. 객체 범위 역할만으로는 MCP 결과를 열지 않습니다.
AI Agent와 MCP client에 Super Admin 장기 키를 주지 마세요. 업무별 최소 read scope와 짧은 만료를 사용하세요.