ssuMCP
ssuAI
ssuAI 프로젝트는 두 개의 분리된 제품을 함께 만듭니다.
숭실대 MCP 서버 — 학식·기숙사·시설·도서관·u-SAINT/LMS 등 숭실대학교의 캠퍼스 정보를 MCP 표준 도구로 노출하는 공개 서버. Claude Desktop · Cursor · 그 외 어떤 MCP 클라이언트도 동일하게 붙어서 사용할 수 있습니다.
ssuAI 웹/앱 — 위 MCP 서버를 소비하는 자체 클라이언트. 학생이 보기 편한 카드형 대시보드 위에 자연어 챗봇과 AI 에이전트 기능을 얹어, 자연어 한 마디로 학교 생활을 처리할 수 있게 합니다.
🏆 Flagship — ssuAI 의 도서관 좌석 자동 예약 에이전트. 챗봇이 실시간 도서관 좌석 데이터를 가지고 사용자와 대화하다가, "이 자리 예약해줘" 한 마디에 에이전트가 학교 도서관 사이트에서 실제 예약을 수행합니다.
📖 처음 오신 분은 비전 문서 를 먼저 읽어 주세요 — 무엇을 만들고 있고 어디까지 와 있는지 5분이면 파악됩니다.
🌐 라이브 데모
항목 | URL |
웹 챗봇 (자연어로 학식·시설 질문) | |
웹 대시보드 (오늘·주간 학식, 기숙사 식단, 시설 검색) | |
REST API | |
MCP 엔드포인트 (Claude Desktop / Cursor 에서 사용) | |
API 문서 (Swagger UI) |
바로 체험: https://ssuai.vercel.app/chat 에서 "오늘 학식 뭐야?", "학생식당 점심 메뉴 알려줘", "학교 안에 편의점 어디 있어?" 같은 질문을 입력하세요. Gemini 가 MCP 서버에 도구 호출을 보내서 실제 데이터로 답합니다.
🔌 MCP 클라이언트에서 연결하기
숭실대 MCP 서버는 Streamable HTTP 전송 (MCP spec 2025-03-26) 을 사용합니다. 아래 설정을 그대로 복사해서 사용하세요.
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json
(Windows: %APPDATA%\Claude\claude_desktop_config.json) 에 추가:
{
"mcpServers": {
"ssuai": {
"url": "https://ssumcp.duckdns.org/mcp"
}
}
}Claude Desktop 재시작 후 채팅창에서 🔧 아이콘을 누르면 도구 목록이 보입니다.
Cursor
.cursor/mcp.json (또는 Cursor 설정 → MCP Servers) 에 추가:
{
"mcpServers": {
"ssuai": {
"url": "https://ssumcp.duckdns.org/mcp"
}
}
}공개 도구 (인증 불필요)
바로 사용 가능한 도구:
도구 | 설명 |
| 오늘 학식 메뉴 |
| 날짜별 학식 |
| 기숙사 주간 식단 |
| 교내 시설 검색 |
| 도서관 층별 좌석 현황 |
| 도서관 도서 검색 |
| 학교 공지사항 최신 목록 |
| 공지사항 키워드 검색 |
| 공지 카테고리 목록 |
| 공지 상세 본문 |
| 진행중(마감 전) 공지 |
| 학과/부서 공지 |
개인 도구 (인증 필요)
u-SAINT / LMS / 도서관 개인 정보 도구는 로그인이 필요합니다.
인증 흐름:
start_auth도구를 호출해 로그인 URL을 받습니다start_auth(provider="SAINT") → loginUrl: https://... mcpSessionId: abc123loginUrl을 브라우저에서 열어 숭실대 계정으로 로그인합니다이후 모든 개인 도구 호출에
mcp_session_id를 함께 전달합니다get_my_schedule(mcp_session_id="abc123")
개인 도구 목록:
도구 | provider | 설명 |
| SAINT | 시간표 |
| SAINT | 성적 |
| SAINT | 채플 출석 현황 |
| SAINT | 졸업 요건 충족 여부 |
| SAINT | 장학금 수혜 내역 |
| LMS | 과제·퀴즈 목록 |
| LIBRARY | 도서관 대출 현황 |
세션 유지: 세션은 서버 메모리에 보관되며 서버 재시작 시 초기화됩니다. 세션이 만료되면
get_auth_status로 확인 후start_auth로 재로그인하세요.
🎯 무엇을 만드는가
숭실대 학생이 하루를 보내려면 학식 페이지·u-SAINT·LMS·도서관 사이트· 학교 공식 페이지를 모두 들락거려야 합니다. 각 사이트는 모바일 UI 가 불편하고, 자연어 검색이 없으며, 매번 따로 로그인해야 합니다.
ssuAI 는 이 모든 데이터를 MCP 표준 도구로 묶고, 그 위에 자체 클라이언트(웹·앱·챗봇·에이전트) 를 올려 학생이 "오늘 학식 뭐고 내 다음 수업 시간은?" 같은 질문을 한 번에 처리할 수 있게 합니다.
4-layer 시스템
┌─────────────────────────────────────────────────────────────┐
│ Layer 4: AI 에이전트 (Phase 4 - 계획) │
│ 도서관 자리 자동 예약 등 실제 액션 실행 │
├─────────────────────────────────────────────────────────────┤
│ Layer 3: 챗봇 (Phase 1 ✓ 라이브) │
│ 자연어로 MCP 도구 호출, LLM 답변 생성 │
├─────────────────────────────────────────────────────────────┤
│ Layer 2: 자체 웹/앱 클라이언트 (web ✓ / app 🔜) │
│ Next.js 웹 대시보드 라이브, Expo 모바일 앱 예정 │
├─────────────────────────────────────────────────────────────┤
│ Layer 1: 공개 MCP 서버 (공개 도구 ✓ / 개인 도구 ✓ Phase 3) │
│ 공개: 학식·기숙사·시설·도서관 (라이브) │
│ 개인: 시간표·성적·과제·대출 현황 (Phase 3 라이브) │
└─────────────────────────────────────────────────────────────┘각 layer 의 구체적 도구 목록·정책·로드맵은 docs/vision.md
참고.
🏆 핵심 차별점 — 도서관 좌석 자동 예약 에이전트
ssuAI 의 정체성을 가장 잘 보여주는 사례. 단순 정보 챗봇이 아니라, 실제로 학교 시스템의 상태를 바꿀 수 있는 end-to-end AI 에이전트 임을 증명하는 flagship 기능입니다.
숭실대 도서관 사이트는 층별로 예약 가능한 좌석 정보를 제공하고, 좌석을 클릭하면 예약이 수행되는 구조입니다. ssuAI 도서관 에이전트는 이 인터랙션을 자연어 한 마디로 자동화합니다.
[사용자] "지금 도서관 4층에 자리 있어?"
[챗봇] get_library_seat_status(floor=4) MCP 도구 호출
→ 도서관 사이트에서 실시간 좌석 상태 스크랩
→ "4층 36석 중 12석 잔여. 창가는 412, 415, 418번이야."
[사용자] "412번으로 4시간 예약해줘"
[에이전트]
1. confirmation: "412번 좌석을 ~20:00 까지 예약할게요. 진행?"
2. yes 받음
3. reserve_library_seat(seat_id=412, duration=4h) 액션 도구 실행
→ 사용자 도서관 credential 로 인증
→ 도서관 사이트의 좌석 클릭 액션을 자동 수행 (POST)
4. 결과: "412번 예약 완료. 20:00 까지 이용 가능합니다."
(실패 시 race condition 처리, 후속 좌석 추천까지)핵심 포인트:
사용자는 도서관 사이트에 직접 로그인하거나 클릭할 필요 없음
모든 액션 도구는 사용자 명시 confirmation 후에만 실행
모든 요청·결과는 audit log 로 기록
학생 credential 은 AES-GCM 으로 암호화 보관 (Phase 3 인프라 활용)
race condition (다른 학생이 직전 선점) graceful 처리
현재 상태: Phase 4 (계획). Layer 4 의 모든 인프라 (액션 도구 정책, agent loop, audit, 분산 lock) 가 이 기능을 만들기 위한 준비. 설계 세부는 Phase 4 시작 시 별도 ADR.
전체 4-layer 시스템에서 이 flagship 이 차지하는 위치와 다른 후속
액션 도구 (예약 취소, 시간 연장, LMS 과제 알림 등) 는
docs/vision.md §3.4 참고.
📊 현재 진행 상황
Phase | 내용 | 상태 |
Phase 1 | 공개 데이터 MVP — 학식·기숙사·시설 MCP 도구 + 웹 + 챗봇 | ✅ 라이브 운영 중 |
Phase 2 | 도서관 도구 (책 검색, 좌석 상태) + 모바일 UI | ✅ 도서관 도구 라이브 (Task 12 좌석 mock + Task 15 도서 real Pyxis JSON) / 모바일 CSS 다듬기 잔여 |
Phase 3 | u-SAINT / LMS 인증 + 개인 MCP 도구 (시간표·성적·과제·대출 현황) | ✅ 라이브 운영 중 |
Phase 4 🏆 | 도서관 좌석 자동 예약 AI 에이전트 (프로젝트 flagship) | 📋 계획 |
Phase 1–2 에서 완료된 것 (라이브):
✅ Spring Boot 단일 프로세스 — REST + MCP 서버 동시 운영
✅ MCP 도구 6개:
get_today_meal,get_meal_by_date,get_dorm_weekly_meal,search_campus_facilities,get_library_seat_status,search_library_book✅
WeeklyMealCache— 학식은 주 1회 갱신이라 시작 시 + 매주 월요일 06:00 KST 에 일괄 적재하고 in-memory 캐시로 응답✅ MCP self-dogfood — 챗봇이 같은 JVM 의 MCP 서버를 Streamable HTTP 로 호출
✅ 9개 LLM 프로바이더 fallback (Gemini → Groq → OpenRouter → ...)
✅ Oracle Cloud Free Tier ARM64 k3s 라이브 배포
Phase 3 완료 (라이브):
✅ MCP 인증 세션 흐름 —
start_auth/get_auth_status/logout_provider/logout_all✅ 개인 도구 7개:
get_my_schedule,get_my_grades,get_my_chapel_info,check_graduation_requirements,get_my_scholarships,get_my_assignments,get_my_library_loans✅ u-SAINT SSO 로그인 (SmartID 리다이렉트)
✅ LMS SSO 로그인
✅ 도서관 자격증명 로그인 (AES-CBC 암호화)
🏗 아키텍처
┌─────────────────────────────────────────────────────────────┐
│ Clients │
│ 웹 챗봇/대시보드 (Next.js) │ Claude Desktop · Cursor │
└──────────────────┬────────────┴───────────────┬─────────────┘
│ HTTPS │ MCP / HTTP
▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ ssuAI Spring Boot 백엔드 (단일 JVM, Java 21) │
│ │
│ REST Controllers ──┐ ┌── MCP Tools │
│ ▼ ▼ │
│ ┌─── Service layer ───┐ │
│ │ + WeeklyMealCache │ │
│ └──────────┬──────────┘ │
│ ▼ │
│ Connectors (mock / real) │
│ └── Jsoup HTTP scrape ──┐ │
│ ▼ │
└──────────────────────────────────────┬──────────────────────┘
▼
soongguri.com · 레지던스홀 · 시설 페이지핵심 설계 원칙:
단일 Spring Boot 프로세스 — REST 와 MCP 두 surface 가 같은 Service layer 를 공유. 챗봇은 같은 프로세스의 MCP 서버를 Streamable HTTP 로 직접 호출하는 self-dogfood 구조.
Connector 경계 — 학교 사이트 HTML 모양은 connector 안에서만 알고, 위로는 내부 DTO 만 흐름.
mock↔real을@ConditionalOnProperty로 스위치. CI / local dev 는 외부 사이트 hit 안 함.WeeklyMealCache — 갱신 주기 (주 1회) 와 호출 주기 (분당 N) 의 격차가 크면 caching 이 자연스러운 답. cache miss 시 connector fallback 으로 회복력 유지.
시스템 다이어그램·패키지 layout·response envelope·error 매핑은
docs/architecture.md 에 있습니다.
🤖 Layer 1 — 공개 MCP 서버
ssuAI 의 main deliverable. Spring AI spring-ai-starter-mcp-server-webmvc
로 같은 Spring Boot 프로세스 안에서 SSE transport 로 동작합니다.
현재 노출 도구
공개 도구 (인증 불필요)
Tool | 설명 | 인자 |
| 오늘 학식 메뉴 (전체 or 특정 식당) |
|
| 지정한 날짜의 학식 메뉴 |
|
| 레지던스홀 이번 주 식단 | 없음 |
| 카페, 편의점, 복사실 등 시설 검색 |
|
| 중앙도서관 층별 좌석 현황 (읽기 전용) |
|
| 중앙도서관 도서 검색 (Pyxis JSON, 익명 GET) |
|
| 학교 공지사항 최신 목록 |
|
| 공지사항 키워드 검색 |
|
| 공지 카테고리 목록 반환 | 없음 |
| 공지 URL 로 본문 전체 조회 |
|
| 진행중(마감 전) 공지 |
|
| 학과/부서 공지 |
|
인증 관리 도구
Tool | 설명 | 인자 |
| MCP 인증 세션 상태 확인 |
|
| SAINT / LMS / LIBRARY 로그인 URL 발급 |
|
| 특정 provider 연결 해제 |
|
| MCP 인증 세션 전체 해제 |
|
개인 도구 (인증 필요)
Tool | 설명 | 인자 |
| u-SAINT 시간표 조회 |
|
| u-SAINT 성적 조회 |
|
| 채플 출석 현황 |
|
| 졸업 요건 충족 여부 |
|
| 장학금 수혜 내역 |
|
| LMS 과제·퀴즈 조회 |
|
| 도서관 대출 현황 조회 |
|
restaurant 는 한국어 별칭 지원 — 학생식당 / 숭실도담식당 /
스낵코너 / 푸드코트 / THE KITCHEN / FACULTY LOUNGE.
get_library_seat_status, search_library_book 은 Phase 2 의 도구이며
읽기 전용입니다. 좌석 예약 (reserve_library_seat) 은 Phase 4 flagship
에서 별도 도구로 추가됩니다. 자세한 설계는
docs/adr/0012-library-seat-read-only-tool.md.
예정된 도구
공개:
get_library_book_status(단일 책 상세 — 현재는search_library_book응답에 상태 포함)Phase 4 flagship:
reserve_library_seat
자세한 로드맵: docs/vision.md.
Claude Desktop / Cursor 연결
빠른 설정은 위의 MCP 클라이언트에서 연결하기 섹션을 사용하세요.
로컬 개발 서버로 연결하려면 URL 만 http://localhost:8080/mcp 로 변경합니다.
추가 troubleshooting 은 docs/mcp-tools.md에 정리합니다.
🌐 Layer 2 — 웹 대시보드 + Layer 3 — 챗봇
REST API
Method | Path | 응답 |
GET |
| 오늘 학식 (모든 식당) |
GET |
| 주간 학식 |
GET |
| 레지던스홀 주간 식단 |
GET |
| 캠퍼스 시설 검색 |
GET |
| 도서관 층별 좌석 현황 ( |
GET |
| 중앙도서관 도서 검색 |
POST |
| 챗봇 호출 ( |
응답은 모두 ApiResponse<T> envelope — data / error / traceId.
웹 대시보드 (Next.js)
App Router + TypeScript strict + Tailwind + shadcn/ui
TanStack Query v5 로 server state 관리, 카드별 loading / error / empty state 분리
백엔드 URL 은
NEXT_PUBLIC_SSUAI_API_BASEenv 로만 주입
챗봇 — Self-dogfood 데이터 플로우
사용자 "학생식당 오늘 점심 메뉴 알려줘"
└▶ POST /api/chat
└▶ LlmChatService → Gemini "이 질문 + 도구 4개"
└▶ Gemini: tool_call get_today_meal(restaurant="학생식당")
└▶ McpSyncClient → http://localhost:8080/mcp (같은 JVM)
└▶ MealMcpTools → MealService
└▶ WeeklyMealCache.find(today, STUDENT) ← 캐시 히트
←▶ MealResponse (학생식당만)
←▶ Gemini "오늘 학생식당 점심은 ..."
←▶ ChatResponseADR 참고: 0010 — chatbot MCP self-dogfood, 0011 — MCP tool dynamic discovery.
챗봇 안전 가드
Output token cap (
SSUAI_LLM_MAX_TOKENS)Turn 당 도구 호출 횟수 cap (
SSUAI_LLM_MAX_TOOL_CALLS)Secret 입력 감지 (비밀번호·학번·세션·토큰) — 저장·반복 안 함
학사·LMS·u-SAINT 같은 개인정보 질문 → MCP 인증 세션 기반 개인 도구로 처리
🚀 기술 스택
Backend — Java 21, Spring Boot 4.x, Spring AI 1.1.x (MCP server + MCP client + webmvc), Jsoup, Gradle, springdoc-openapi
Frontend — Next.js 16 (App Router), TypeScript strict, Tailwind CSS, shadcn/ui, TanStack Query v5, pnpm
Infra — Oracle Cloud Free Tier ARM Ampere A1, k3s 단일 노드, Traefik ingress, cert-manager + Let's Encrypt, GitHub Container Registry. Frontend 는 Vercel.
자동화 — GitHub Actions CI (backend test + frontend test + ARM64 image build + gitleaks scan), Dependabot, lefthook pre-commit hook.
스택 선택 이유: ADR 0006, ADR 0007, ADR 0009.
💻 로컬 개발
필요 도구
JDK 21 (Temurin 권장)
Node 20+, pnpm 9+
Git
백엔드 (mock 모드 — 외부 사이트 hit 없음)
# Windows
cd backend && .\gradlew.bat bootRun
# macOS / Linux
cd backend && ./gradlew bootRun:8080 에서 동작합니다.
curl http://localhost:8080/api/meals/todayOpenAPI: http://localhost:8080/v3/api-docs, Swagger UI: http://localhost:8080/swagger-ui.html.
백엔드 (real 데이터 + LLM 챗봇 모드)
cp backend/.env.example backend/.env
# backend/.env 에 SSUAI_GEMINI_API_KEY=... 입력# Windows
Push-Location backend
Get-Content .env | Where-Object { $_ -and $_ -notmatch '^\s*#' } |
ForEach-Object {
$name, $value = $_ -split '=', 2
[Environment]::SetEnvironmentVariable($name, $value, 'Process')
}
$env:SSUAI_CONNECTOR_CHAT = "llm"
$env:SSUAI_CONNECTOR_MEAL = "real"
$env:SSUAI_CONNECTOR_DORM_MEAL = "real"
.\gradlew.bat bootRun# macOS / Linux
cd backend
set -a; . ./.env; set +a
SSUAI_CONNECTOR_CHAT=llm \
SSUAI_CONNECTOR_MEAL=real \
SSUAI_CONNECTOR_DORM_MEAL=real \
./gradlew bootRun챗봇 테스트:
curl -X POST http://localhost:8080/api/chat \
-H "Content-Type: application/json" \
-d '{"message":"오늘 학식 뭐야?"}'프론트엔드
cp frontend/.env.example frontend/.env.local
pnpm --dir frontend install
pnpm --dir frontend devMCP 서버 단독 확인
npx @modelcontextprotocol/inspector
# Transport: Streamable HTTP, URL: http://localhost:8080/mcp → Connect → List Tools자세한 절차: docs/mcp-tools.md.
📚 문서 맵
각 문서가 무엇을 다루는지 한 줄씩 — 처음 보시는 분은 위에서 아래로 읽으면 됩니다.
문서 | 무엇이 들어 있나 |
🎯 ssuAI 의 4-layer 최종 목표 + phase 별 로드맵 (가장 먼저 읽어 보세요) | |
제품 정의 — 무엇을 만들고 무엇을 안 만드는가 | |
시스템 설계 — 패키지·response envelope·connector pattern·caching | |
secret · credential · logging · CORS 정책 | |
MCP 서버 사용법, Claude Desktop / Cursor 등록법 | |
모든 load-bearing 결정 (ADR 0001–0013) | |
단기 구현 단위 task spec | |
누적 개발 로그 (chronological) | |
상세 회고 / postmortem | |
최상위 트러블슈팅 로그 (한국어, portfolio 회고용) | |
배포 파이프라인 진단 / 운영 노트 | |
AI 협업 워크플로우 — claude1 / claude2 / codex 셋이 토큰 사정에 따라 돌아가며 active. 두 파일은 동일 내용 mirror (Claude Code 는 CLAUDE.md, Codex CLI 는 AGENTS.md 자동 로드). |
⚠️ 알려진 한계
단일 노드 운영. 라이브 데모는 Oracle Free Tier 단일 VM 위 k3s. Portfolio 시연 용도이고 고부하 트래픽은 가정하지 않습니다.
인증 세션은 서버 메모리 저장. u-SAINT / LMS / 도서관 로그인 세션이 서버 재시작 시 초기화됩니다. 재시작 후
start_auth로 재로그인 필요.모바일 UI 미세조정 미완. 웹 대시보드가 동작은 하지만 데스크탑 우선으로 설계.
학교 사이트 변경에 취약. Connector 가 학교 페이지 HTML 을 파싱하므로 학교 markup 이 바뀌면 동작이 깨질 수 있음. Connector boundary 가 격리되어 있어 connector swap 만으로 복구 가능한 구조.
🛠 프로젝트 컨벤션
Conventional Commits —
feat:,fix:,chore:,docs:,test:,refactor:prefix한 PR = 한 개념 — 변경 사항이 명확하게 review 되도록
ADR — load-bearing 결정은 모두
docs/adr/에Dependabot + gitleaks — 의존성·secret 자동 감시
AI 협업 워크플로우 — Claude Code 가 설계·구현·리뷰를 담당. 운영 규약:
CLAUDE.md
📜 라이선스
MIT — LICENSE 참고.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/hoeongj/ssuAI'
If you have feedback or need assistance with the MCP directory API, please join our Discord server