Smishing Stop Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Smishing Stop Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
카카오 PlayMCP 등록용 원격 MCP 서버입니다. 의심스러운 문자/메시지를 받아 스미싱·메신저피싱·보이스피싱 유도 여부를 판정하고, 근거와 상황별 대응을 한국어로 돌려줍니다. (카카오 AGENTIC PLAYER 10 출품작)
보안 도구의 본질상 오판이 치명적이므로, 이 서버는 정확성과 보수성을 최우선으로 설계했습니다. 절대 "100% 안전"이라고 단정하지 않으며, 불확실하면 최소 "의심" 또는 "판단보류"로 내립니다.
스미싱 문구는 끝없이 변형됩니다. 그래서 문구를 일일이 나열하지 않고 두 개의 층으로 나눠 판단합니다.
입력 메시지
│
▼
┌──────────────────────────────────────────────────────────────┐
│ 1층 — 확정 신호 (닫힌 데이터 조회, 결정론적) │
│ · URL 추출 → 단축URL 펼치기 → KISA 피싱 차단목록 / Google │
│ Safe Browsing / KISA WHOIS 도메인 나이 조회 │
│ · 발신번호: 국제발신(+), 070, 변작 의심 │
│ ★ KISA/Safe Browsing 매칭 = '악성 확정' → verdict '위험' 고정 │
└──────────────────────────────────────────────────────────────┘
│ (확정 신호는 아래 2층이 절대 덮어쓰지 못함)
▼
┌──────────────────────────────────────────────────────────────┐
│ 2층 — 사회공학 추론 (점수에만 기여) │
│ · 휴리스틱(키 불필요): 긴급성·결제/환급·기관 사칭·링크 유도· │
│ APK 설치·인증번호/계좌 요구·지인 사칭의 '본질'을 카테고리로 판별 │
│ · LLM(선택): 새로운 표현·우회 문구·맥락 사칭을 보완(0~1 위험도) │
└──────────────────────────────────────────────────────────────┘
│
▼
점수 합산(0~100) → 3단계 판정(위험 / 의심 / 판단보류)
+ 근거 · 탐지 URL · 상황별 대응 · 위젯 카드 · 면책불변 규칙: 2층 추론은 점수에만 기여하며, 1층의 확정 악성 신호를 절대 덮어쓰지 못합니다. 1층에서 악성 URL이 확정되면 텍스트가 정상으로 보여도 "위험"으로 고정됩니다.
모든 외부 API 키는 선택입니다. 키가 없으면 해당 데이터 소스만 비활성화되고, 사용 가능한 신호만으로 판정하되 data_sources에 상태를 투명하게 표기합니다. 즉 키 0개로도 서버가 정상 작동합니다(2층 휴리스틱 + 발신번호/단축URL 분석).
check_smishing| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
message_text | string | ✅ | 분석할 의심 메시지 원문 |
sender | string | 발신번호 또는 발신자명 (예: +1 213-..., 070-..., 국민은행) | |
clicked | boolean | 링크 클릭 여부 (알 때만) | |
installed | boolean | 앱/APK/파일 설치 여부 (알 때만). true면 즉시 대처 가이드로 전환 |
| 필드 | 타입 | 설명 | ||
|---|---|---|---|---|
risk_level | `"위험" \ | "의심" \ | "판단보류"` | 3단계 판정 |
score | number (0~100) | 위험 점수 | ||
reasons | string[] | 판정 근거(점수 기여 순) | ||
detected_urls | {url, expanded_url?, verdict, source, detail?}[] | URL별 평판. verdict: 악성확정/의심/확인불가/특이사항없음 | ||
action_guide | string[] | 상황별 대응 | ||
follow_up_questions | string[] | 호스트가 조건부로 되물을 질문(비면 되묻지 않음) | ||
card | object | 카카오툴즈 위젯 카드용 구조(배지/근거/대응 버튼) | ||
data_sources | object | 각 소스의 사용/비활성 상태(투명성) | ||
disclaimer | string | 면책 및 신고 안내 |
message_text만으로 호출합니다. 미리 캐묻지 않습니다.follow_up_questions가 비어 있지 않을 때만 사용자에게 되묻습니다. 이 배열은 판정이 위험/의심이고 clicked/installed가 미상이라 출력이 바뀔 수 있을 때만 채워집니다. 비어 있으면 되묻지 않습니다.installed=true로 다시 호출되면 action_guide가 즉시 대처 모드(모바일 백신 검사, APK 삭제, 통신사 소액결제 차단, 118 신고, 금전 피해 시 112)로 전환됩니다.요구사항: Node.js ≥ 18 (개발 환경은 Node 22/25에서 검증).
# 1) 의존성 설치
npm install
# 2) 환경변수(선택) — 키 없이도 동작합니다
cp .env.example .env
# 필요하면 .env 에 KISA_WHOIS_SERVICE_KEY / GOOGLE_SAFE_BROWSING_API_KEY /
# ANTHROPIC_API_KEY / KISA_PHISHING_CSV_PATH 를 채웁니다.
# 3) 빌드 + 실행
npm run build
npm start # 기본 http://localhost:3000 , MCP 엔드포인트 POST /mcp
# 개발 모드(핫리로드)
npm run dev
# 오프라인 자체 검증(네트워크 없이 판정 로직 점검)
npm run selftest# 헬스체크
curl http://localhost:3000/healthz
# MCP 도구 호출 (Streamable HTTP는 Accept 헤더 두 개를 요구)
curl -s -X POST http://localhost:3000/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"check_smishing","arguments":{"message_text":"[CJ대한통운] 주소불일치로 배송보류. 앱 설치 후 확인 http://bit.ly/abcd","sender":"+1 213-555-0199"}}}'| 변수 | 기본값 | 설명 |
|---|---|---|
PORT | 3000 | 서버 포트 |
INBOUND_API_KEY | (없음) | 설정 시 인바운드 X-API-Key(또는 Bearer) 검사. PlayMCP 커스텀 헤더 인증 대응 |
CORS_ORIGIN | * | CORS 허용 오리진(* 또는 콤마구분) |
OFFLINE_MODE | false | true면 모든 외부 호출 차단(테스트용) |
FETCH_TIMEOUT_MS | 4000 | 외부 호출 타임아웃 |
MAX_REDIRECT_HOPS | 5 | 단축 URL 펼치기 최대 hop |
KISA_PHISHING_CSV_PATH | ./data/kisa_phishing_urls.csv | KISA 피싱 URL CSV 로컬 경로 |
EXTRA_BLOCKLIST_DOMAINS | (없음) | 보강/테스트용 악성 도메인(콤마구분) |
KISA_WHOIS_SERVICE_KEY | (없음) | 공공데이터포털 KISA WHOIS serviceKey |
GOOGLE_SAFE_BROWSING_API_KEY | (없음) | Google Safe Browsing v4 키 |
ANTHROPIC_API_KEY | (없음) | 2층 LLM 추론용(선택) |
LLM_MODEL | claude-haiku-4-5-20251001 | 2층 LLM 모델(경량 권장) |
ANTHROPIC_BASE_URL | https://api.anthropic.com | Anthropic API 베이스 URL |
각 API의 스펙은 공식 문서로 검증했습니다. 검증 결과와 출처는 아래에 명시합니다.
serviceKey나 실시간 조회 엔드포인트가 존재하지 않습니다. (출처: <https://www.data.go.kr/data/15109780/fileData.do>, 최신본 <https://www.data.go.kr/data/15143094/fileData.do>)KISA_PHISHING_CSV_PATH(기본 ./data/kisa_phishing_urls.csv)에 둡니다./healthz의 blocklist.size로 확인).node scripts/update-kisa-db.mjs (수동 다운로드 안내. KISA_CSV_DOWNLOAD_URL 환경변수로 직링크 자동화 가능)EXTRA_BLOCKLIST_DOMAINS로 보강 가능합니다.GET http://apis.data.go.kr/B551505/whois/domain_name?serviceKey=...&query=<도메인>&answer=json, 응답에 regDate(등록일)·endDate(만료일) 포함. ⚠️ `.kr`/`.한국` 국가도메인만 조회 가능(국제 TLD 불가). (출처: <https://www.data.go.kr/data/15094277/openapi.do>, <https://whois.kr/kor/openkey/keyCre.do>).env의 KISA_WHOIS_SERVICE_KEY에 입력.POST https://safebrowsing.googleapis.com/v4/threatMatches:find?key=API_KEY. 요청 threatInfo.threatEntries[{url}], 응답 matches[](비면 미탐). threatType 중 SOCIAL_ENGINEERING이 피싱 신호. 무료. (출처: <https://developers.google.com/safe-browsing/v4/lookup-api>) 참고: v4는 deprecated(동작 유지) — 향후 v5 hashes:search 또는 Web Risk로 이전 필요..env의 GOOGLE_SAFE_BROWSING_API_KEY에 입력.Location 헤더를 hop마다 직접 검증하며 최대 N회 따라갑니다. SSRF 방어: 각 hop의 호스트가 사설/내부/클라우드 메타데이터 대역(10/8,127/8,169.254/16,172.16-31,192.168/16, IPv6 ULA 등)이면 차단, http/https만 허용, 타임아웃·hop 상한 적용, 최종 페이지 본문/JS는 실행하지 않습니다..env의 ANTHROPIC_API_KEY. 분류 작업이므로 경량 모델(claude-haiku-4-5-...) 권장.sampling/createMessage)은 광범위하게 지원되지 않으므로 의존하지 않습니다.출처: PlayMCP 공식 공모전 가이드(Notion). Agentic Player 10 예선은 반드시 카카오가 제공하는 `PlayMCP in KC`(MCP 서버 배포 서비스, 무상)로 배포해야 합니다. 이 서버의 Dockerfile이 그대로 사용됩니다(저장소 루트에 Dockerfile 존재).
⚠️ PlayMCP in KC 발급은 예선 기간(2026-06-15 ~ 07-14)에만 가능합니다. 심사 시간을 고려해 미리 발급하세요. 계정당 최대 2대.
Dockerfile 포함 — 이미 있음).main.Dockerfile.Starting → 수십 초~수 분 후 `Active`.로컬에서 docker build 후 이미지를 등록하는 방식도 지원합니다(PlayMCP in KC의 "컨테이너 이미지로 MCP 서버 등록하기" 가이드 참고).
원리상 공개 HTTPS Streamable HTTP URL이면 동작하므로, 개발/테스트 단계에서는 Railway/Render/Fly.io나 임의 Docker 호스트로도 띄울 수 있습니다. 단, 공모전 예선 제출은 PlayMCP in KC Endpoint를 써야 합니다. 컨테이너에는 /healthz HEALTHCHECK가 포함돼 있습니다.
npm run selftest, MCP Inspector 권장 — 아래 8장).INBOUND_API_KEY 설정 시 X-API-Key 검사)를 사용합니다.https://playmcp.kakao.com/mcp/12345...).일정: 예선 접수 2026-06-15 ~ 07-14, 본선 카카오톡 공개투표 2026-08-31~09-28, 시상 2026-10-23. 평가 창의성·편의성·기술 안정성.
공식 개발가이드(2026-06-12 기준)의 필수 요건과 본 서버의 충족 상태입니다. (가이드: <https://kko.to/PlayMCPdevguide>)
| 요건 | 상태 |
|---|---|
| MCP 지원버전 2025-03-26 ~ 2025-11-25 | ✅ SDK 1.29가 범위 내 협상(테스트 시 2025-06-18) |
| Streamable HTTP만 지원 | ✅ StreamableHTTPServerTransport |
| Remote, 공개 URL | ✅ PlayMCP in KC Endpoint |
| Stateless 권장 | ✅ sessionIdGenerator: undefined |
| 인증: OAuth 또는 커스텀 헤더 | ✅ 커스텀 헤더(X-API-Key, 선택) |
| 서버/툴 이름에 "kakao" 미포함 | ✅ smishing-stop-mcp / check_smishing |
툴 이름: 1~128자, [A-Za-z0-9_-] | ✅ check_smishing |
| 툴 개수 ≤ 20 (권장 3~10) | ⚠️ 현재 1개(집중형). 필요 시 보조 툴 추가 가능 |
| 필수 property: name·description·inputSchema·annotations | ✅ annotations 5개 힌트 모두 지정 |
| annotations: title·readOnlyHint·destructiveHint·openWorldHint·idempotentHint | ✅ true/false/true/true |
| description ≤ 1,024자 + 서비스명 영/국문 병기 | ✅ 991자, Smishing-Stop(피싱멈춰) 포함 |
| result 크기 최소화 / error·비위젯은 마크다운 텍스트 | ✅ 간결한 text 폴백 + 구조화 content |
| 툴 응답 p99 ≤ 3,000ms 필수 | ✅ 전체 데드라인 OVERALL_DEADLINE_MS(기본 2800ms)로 강제 |
| 툴 평균 응답 ≤ 100ms | ⚠️ 외부 키 미설정 시 로컬(KISA CSV+휴리스틱)으로 <10ms. 외부 API 사용 시 지연↑ — 아래 참고 |
| 광고 유도 금지 | ✅ 해당 없음 |
| MCP Inspector 사전 점검 | ☐ 제출 전 직접 수행 권장: npx @modelcontextprotocol/inspector |
평균 100ms vs 정확도 트레이드오프: 외부 평판 API(Safe Browsing/WHOIS) 및 단축 URL 펼치기는 네트워크 지연이 있습니다. 엄격한 평균 100ms가 필요하면 외부 키를 비우거나 OFFLINE_MODE=true로 두어 로컬 결정론 모드(KISA CSV + 휴리스틱, <10ms)로 운용하세요. 정확도를 우선하면 키를 채워 전체 2층을 가동하되, p99는 데드라인으로 3초 이내가 보장됩니다.
risk_level/reasons/action_guide로 렌더되도록 설계하고 card 구조화 필드(배지/버튼)를 함께 제공합니다. 결선 진출 시 카카오 제공 규격에 맞춰 buildCard()를 조정하세요.KISA_CSV_DOWNLOAD_URL 자동화 옵션.src/
├── index.ts 진입점: Express + Streamable HTTP(stateless), 인증/CORS/헬스체크
├── server.ts McpServer 구성 + check_smishing 등록
├── config.ts 환경변수 + 점수 가중치(WEIGHTS) 중앙 집중
├── types.ts 공용 타입(출력 스키마와 1:1)
├── util.ts 타임아웃 fetch, 호스트/IP 파싱, SSRF 차단
├── tool/
│ ├── schema.ts 입력/출력 zod shape + 도구 설명(호스트 행동 규칙)
│ └── checkSmishing.ts 핸들러: structuredContent + 텍스트 폴백, 예외 안전
├── pipeline/
│ ├── index.ts 6단계 오케스트레이션
│ ├── parse.ts URL/발신번호/키워드 추출(NFC 정규화, 한글 안전)
│ ├── scoring.ts 점수 합산 + 3단계 판정 + 보수성 규칙
│ └── actionGuide.ts 상황별 대응 + 되묻기 + 카드 빌더
├── layer1/ 확정 신호(결정론적)
│ ├── urlReputation.ts URL별 KISA+SafeBrowsing+WHOIS 종합
│ ├── unshorten.ts 단축 URL 펼치기 + SSRF 방어
│ ├── kisa.ts 피싱 CSV 로더 + 호스트 매칭
│ ├── safeBrowsing.ts Google Safe Browsing v4 클라이언트
│ ├── whois.ts KISA WHOIS 도메인 나이
│ └── sender.ts 발신번호 분석
└── layer2/ 사회공학 추론(점수 기여)
├── heuristics.ts 카테고리 기반 결정론적 판별
└── llm.ts 선택적 Anthropic 추론(graceful)express.json() + LLM 호출은 모두 UTF-8로 처리합니다.본 도구의 결과는 참고용이며 최종 판단과 책임은 본인에게 있습니다. 스미싱 의심 신고 118(불법스팸대응센터), 금전 피해 발생 시 112(경찰), 개인정보 노출 시 KISA 보호나라(privacy.kisa.or.kr) 명의도용 차단 서비스를 이용하세요.
라이선스: MIT
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.