@davenai/mcp 도구 **daven_guidelines**를 호출하세요 (topic=edu_app, 학생 제출 시 topic=submission). 모호하면 추측하지 말고 그 출력을 따르세요.
원문: llms.txt · Proxy: openapi.yaml · 제출: lms-openapi.yaml · activity-submission.schema.json
이미 있는 앱을 교실에 올릴 때는 기존 앱을 Daven에 얹기의 불변 조건을 지키세요. 학습 화면을 Hub나 Vibe로 바꾸지 마세요.
MUST
- HTTPS(또는 local) 웹앱을 호스팅한다. Hub 시작은 새 탭으로 연다.
- TypeScript 앱은
@davenai/sdk/edu를 우선 사용한다. SDK가 launch의session,proxy를 읽고 주소에서 제거한다. - Daven 호출은 SDK 또는
{proxy}base만 사용한다. - raw fetch fallback은 매 요청에
Authorization: Bearer {session}그리고X-Edu-Session: {session}을 넣는다. - 응답 envelope를 파싱한다:
status === "success" | "error". - 프론트에 API 키 / MCP 시크릿을 넣지 않는다.
- SDK 기본 신뢰 proxy만 사용한다. custom proxy가 필요하면 앱의 정적 설정으로만
additionalTrustedProxyUrls에 추가하고 launch query 값을 그대로 allowlist하지 않는다. shouldRelaunchEducationApp(error)가true이면 저장한 작업은 유지하고 Hub에서 활동을 다시 열도록 안내한다.
MUST NOT
- 브라우저에서
daven.ai/app.daven.ai를 직접 호출하지 않는다. - 추가 OAuth 팝업을 Edu 기본 플로우에 필수로 두지 않는다.
- 학생 원문을 AI 결과로 자동 덮어쓰지 않는다.
Defaults
Session v2 (deterministic)
새 세션은 서명된 HS256 JWT이며version: 2, purpose, actorId를 포함하고 sub === actorId입니다.
actor.id는 인증된 Hub 프로필이고 studentId는 작업 대상 학생입니다. 앱은 JWT를 직접 신뢰하지 말고 GET /api/session/context를 사용합니다. context의 학생·교사 actorId를 앱 사용자 매핑 키로 사용합니다. 이름이나 학생 코드로 매칭하지 마세요. teacher_manage만 GET /api/session/roster를 사용할 수 있으며, 응답에는 이메일·학생 코드·잔액·payer가 없습니다. 앱 전용 교사 작업 공간을 제공할 때 Master 승인 카탈로그의 supportsTeacherManage를 켜면 Hub가 이 목적의 실행 버튼을 표시합니다. 서버는 전환을 위해 서명된 v1 JWT를 정규화하지만 서명 없는 base64 세션은 거부합니다.
Submission v2 (deterministic)
- 최종 제출 POST는
student_activityEdu 세션만 사용할 수 있습니다. externalArtifactId는 선택이며[A-Za-z0-9._:-]문자 1–128자입니다.- 생략하면
__default__가 되어 기존 앱처럼 기본 행 하나를 갱신합니다. - Identity는
(activityId, studentId, appSlug, externalArtifactId)입니다. ID별로 여러 artifact와 재제출을 지원합니다. - 제출 URL은 공개 영구 HTTPS만 허용합니다. localhost, IP literal, 내부 hostname, credential 포함 URL은 금지합니다.
- 제출 목록 GET은 Edu 세션 API가 아닙니다. 일반 Hub 교사 bearer와 해당 교실 소유권이 필요하며 익명 조회는 금지합니다.
Endpoints (complete)
구현 시 이 표만 있으면 됩니다. 앞의 proxy 경로는 launch의{proxy}를 base로 사용합니다. 학생 제출은 SDK가 {proxy}에서 계산한 Edu API base를 사용합니다. body 필드 상세는 OpenAPI와 제출 schema를 따릅니다.
Canonical SDK client
session, proxy, expectedAppSlug로 @davenai/sdk/server를 사용합니다. expectedAppSlug가 session context와 다르면 SDK는 요청을 중단합니다. SDK를 사용할 수 없는 런타임만 llms.txt의 raw fetch fallback을 구현합니다.
Acceptance (binary)
에이전트는 아래가 전부 true일 때만 “연동 완료”라고 보고합니다.-
daven.billing.getAccount()성공 - 세션 헤더 제거 시 → 401
- SDK AI 호출은 사용자 동작마다 operation ID를 생성하고 같은 요청 재시도에만 재사용
- 최종 제출은
student_activity에서만 실행하고 artifact별externalArtifactId를 재사용 - session 만료/401에서 저장 작업을 유지한 재실행 UI 표시
- DevTools Network에 Edu proxy host만 존재
- 새 탭(최상위 페이지)에서 핵심 플로우 완료 가능
- 학생 Start로 텍스트·이미지가 각 1번 나온 뒤에만 카탈로그 Approve. 함정은 hosted-app
Reference paths
- App:
dv_mcp/apps/sihwa_project - Proxy:
dv-edu/apps/api/src/mcp-proxy/mcp-proxy.controller.ts
