Jeju Humanities Tour MCP Server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Jeju Humanities Tour MCP Server추천해줘, 서귀포에서 역사 테마로 3시간 이내 코스"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
제주 인문학 투어 추천 MCP 서버 (학습용)
자연어 질문 → Claude Code가 MCP 툴 발견·호출 → SQLite에서 여러 테이블을 JOIN해 조합 → 정리된 결과 반환, 이 왕복(round-trip)을 손에 익히기 위한 연습 프로젝트.
프로젝트 구조
server.py: MCP 서버 + 툴 정의 (FastMCP, stdio)seed.py: SQLite 스키마 생성 + 시드 데이터 삽입tour.db:seed.py실행으로 생성되는 SQLite 파일 (git에 커밋하지 않음).mcp.json: VS Code의 Claude Code가 이 서버에 연결하는 설정pyproject.toml/uv.lock: uv 의존성 관리
Related MCP server: mcp-tour
1. 실행 준비 (최초 1회)
# 의존성 설치 (uv가 .venv를 알아서 만들고 관리)
uv sync
# DB 생성 + 시드 데이터 삽입 (다시 실행하면 tour.db를 지우고 새로 만듦)
uv run seed.py서버 단독 실행 확인 (선택, 정상이면 아무 출력 없이 대기 상태가 됨 — Ctrl+C로 종료):
uv run server.py2. VS Code(Claude Code)에 연결하기
이 폴더에 있는 .mcp.json이 프로젝트 범위 MCP 서버 설정이다.
VS Code로 이 프로젝트 폴더(
jeju-tour-mcp)를 연다.Claude Code가
.mcp.json을 감지하면 "이 프로젝트의 MCP 서버를 신뢰하고 연결할지" 승인을 요청한다 → 승인.대화창에서
/mcp명령으로 서버 연결 상태와 등록된 툴 목록을 확인할 수 있다.jeju-tour서버가 연결됨(connected) 상태여야 한다.만약 자동으로 뜨지 않으면, Claude Code 설정에서 프로젝트 MCP 서버를 수동으로 승인/새로고침 할 수 있다 (
/mcp안에서 재연결 시도 가능).
.mcp.json은uv run --directory <프로젝트경로> server.py로 서버를 띄우도록 되어 있어서, VS Code의 현재 작업 디렉터리와 무관하게 항상 같은 프로젝트의.venv/tour.db를 사용한다.
3. 단계별 진행 상황 & 테스트 질문
1단계 — list_regions() ✅
인자 없이 지역 목록만 반환. 연결·툴 발견이 되는지 확인하는 용도.
테스트 질문 예시:
"제주에서 투어 가능한 지역이 어디 어디 있어?"
"지역 목록 좀 알려줘."
체크포인트: Claude가
list_regions툴을 스스로 호출해서["서귀포", "성산", "안덕", "애월", "제주시"]형태의 응답을 가져오면 성공. (도구 호출 없이 모델이 그냥 아는 척 답하면 실패 —/mcp에서 연결 상태부터 다시 확인.)
2단계 — get_spot(name) ✅
스팟 이름(정확한 이름 또는 일부)으로 상세 정보 1건을 조회. 자연어에서 인자(스팟 이름)를 뽑아내는 걸 확인하는 용도.
정확히 일치하는 이름이 없으면 부분 일치(
LIKE %name%)를 시도하고, 일치가 1건이면 그걸 반환, 여러 건이면 에러 메시지로 후보 목록을 알려주고, 없으면 "찾을 수 없다"는 에러를 낸다.테스트 질문 예시:
"성산일출봉 몇 시에 열어?"
"이중섭거리는 실내야 실외야?"
"일출봉 정보 알려줘" (부분 일치 테스트)
"제주 알려줘" (의도적으로 모호한 이름 → 여러 후보 안내 확인)
체크포인트: Claude가
get_spot을 호출해서open_t/close_t,is_indoor등 구조화된 필드를 근거로 답하면 성공. 모호한 이름을 던졌을 때 후보 목록을 보여주며 되묻는지도 확인.
3단계 — recommend_course(region, theme, max_hours) ✅ (핵심 JOIN)
courses ⋈ course_spots ⋈ spots를 조인해 지역·테마·소요시간 조건에 맞는 코스 1개를 찾고,course_spots.seq순서로 정렬된 스팟 목록을 구성해서 반환한다. 조건에 맞는total_hours중max_hours를 넘지 않는 가장 긴(=꽉 채운) 코스를 고른다.반환 형태:
{ title, region, theme, total_hours, stops: [{ seq, name, walk_min, why }, ...] }. 원본 row가 아니라 서버에서 이미 조합·정렬된 구조만 LLM에 전달한다.조건에 맞는 코스가 없으면, 현재 DB에 있는 (지역/테마/소요시간) 조합 목록을 담은 에러 메시지를 반환해 대안을 제시할 수 있게 한다.
테스트 질문 예시:
"성산에서 신화 테마로 4시간 이내 코스 추천해줘"
"애월에서 성찰 테마로 3시간 반짜리 코스 있어?"
"서귀포 문학 코스 5시간 안에 뭐가 있어?"
"제주시에서 문학 테마 코스 추천해줘" (일부러 없는 조합 → 대안 안내 확인)
체크포인트: Claude가
stops를 seq 순서 그대로 나열하며 각 스팟의why(코스에 포함된 이유)까지 자연스럽게 설명하면 성공. 조건 불일치 질문에서는 에러 메시지 속 대안 조합을 근거로 되묻거나 대안을 제안하는지 확인.
4단계 — get_weather(region) (예정, mock)
각 단계 구현이 끝나면 이 섹션에 실제 내용과 테스트 질문을 채워 넣는다.
DB 스키마 메모
spots(id, name, region, theme, is_indoor, walk_min, open_t, close_t)
courses(id, title, region, theme, total_hours)
course_spots(course_id, spot_id, seq, why) -- 코스↔스팟 다대다 조인 테이블course_spots.why는 원래 스펙에는 없었지만, recommend_course가 각
스팟이 "왜 이 코스에 포함되었는지"를 반환해야 해서 코스-스팟 조합에
귀속되는 정보로 추가했다 (스팟 자체 속성이 아니라 코스 문맥에 따라
달라지는 값이라 spots 테이블이 아니라 조인 테이블에 둠).
Available Tools
3 toolsget_spotA
특정 관광 스팟(장소) 한 곳의 상세 정보를 조회할 때 사용. 사용자가 스팟 이름을 콕 집어 "OO는 어떤 곳이야?", "OO 정보 알려줘", "OO 몇 시에 열어?"처럼 장소 하나에 대해 물어볼 때 호출한다. name에는 사용자가 말한 스팟 이름(정확한 이름 또는 그 일부)을 그대로 넣는다.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided. The description implies a read-only query operation but does not disclose behavior for missing spots, error handling, or other side effects. Minimal disclosure beyond purpose.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is four sentences in Korean, front-loaded with purpose, and every sentence adds value. No redundancy or wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simplicity (1 param, no output schema), the description covers purpose, usage, and parameter. However, it lacks details on return value format or error behavior, leaving some gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so description compensates by specifying the name parameter should be the exact or partial name from user utterance. This adds useful guidance beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves detailed info about a specific tourist spot and provides example queries. However, it does not explicitly distinguish it from sibling tools beyond implying singularity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use (user asks about a specific spot by name) with examples, but does not mention when not to use or mention alternatives like list_regions or recommend_course.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_regionsA
제주도에서 투어가 가능한 지역 목록을 조회할 때 사용. 사용자가 "어떤 지역이 있어?", "지역 목록 알려줘"처럼 지역 자체를 물어볼 때 호출한다. 인자는 없다.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It states 'no arguments' and implies a list retrieval, but does not describe any potential side effects, return format, or other behavioral traits. Adequate for a simple read-only operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences, front-loaded with purpose, no redundancy or unnecessary information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (no parameters, simple list), the description is complete. An output schema exists, so return values are documented elsewhere.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema coverage is 100%. The description confirms 'no arguments', which is consistent. Baseline for 0 parameters is 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to list regions available for tours in Jeju Island, with example user queries. It distinguishes from sibling tools like get_spot (specific spots) and recommend_course (course recommendations).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear when-to-use guidance with example phrases, but does not explicitly mention when not to use or mention alternative tools for other queries.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recommend_courseA
특정 지역·테마·소요 시간 제약으로 인문학 투어 코스를 추천할 때 사용. 사용자가 "OO에서 XX 테마로 N시간 이내 코스 추천해줘"처럼 지역과 테마, 시간 제약을 함께 이야기하며 여러 스팟을 묶은 '코스'를 원할 때 호출한다. (스팟 하나만 물어보면 get_spot을 대신 사용할 것.) courses·course_spots·spots를 조인해서 조건에 맞는 코스 1개를 방문 순서(seq)대로 정리해 반환한다.
| Name | Required | Description | Default |
|---|---|---|---|
| theme | Yes | ||
| region | Yes | ||
| max_hours | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description mentions joining tables and returning one course ordered by sequence, but lacks details on selection logic (e.g., how the best course is chosen), permissions, side effects, or error handling. Since no annotations are provided, the description carries the full burden but only partially fulfills it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (4 sentences) and front-loaded: first sentence states purpose, second provides usage example, third distinguishes from sibling, fourth explains internal logic. No redundant information, though could be slightly more compact.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a recommendation tool with no annotations and no output schema, the description explains input and output (one course with spots in order) but omits details like output format, behavior when no matches, or how the single recommendation is selected. It is adequate but not thorough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description only reiterates the parameter names (region, theme, max_hours) without adding format, constraints, or examples. Given the low coverage, the description should compensate but does not add meaningful semantics beyond the parameter names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool recommends humanities tour courses based on region, theme, and time constraints. It distinguishes itself from the sibling tool 'get_spot' by specifying that this tool is for multi-spot courses, not single spots.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly provides when to use (user asks for a course with region, theme, and time constraints) and when not to use (single spot inquiry should use get_spot). This clear differentiation helps the agent select the correct tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool serves a distinct purpose: listing regions, getting spot details, and recommending courses. No overlap exists, so an agent can clearly select the correct tool.
All tools follow a consistent verb_noun snake_case pattern: list_regions, get_spot, recommend_course. No deviations or mixed conventions.
Three tools is well-scoped for a humanities tour server: regions, spots, and courses. Each tool earns its place without redundancy or excessive minimality.
Core operations are covered, but missing a tool to list spots within a region or list all courses. Agents may struggle to discover spots without a listing tool, creating a minor gap.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Official Seoul tourism data in 7 languages, in cooperation with the Seoul Tourism Organization.
Korean lodging: 84,490 stays from 4 government permit ledgers + KTO TourAPI, honest gaps
Korean premium short-term rental search: natural language or structured filters (SHV engine).
Ground your AI in verified Korean venue data: search & book across Seoul, Gyeonggi, Busan, Jeju.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to access South Korean tourism information via the official Korea Tourism Organization API, providing comprehensive search for attractions, events, food, and accommodations with multilingual support.89MIT
- AlicenseAqualityDmaintenanceProvides location-based place recommendations in South Korea using the Kakao Map API, optimized for Korean language queries. Supports recommending various places like restaurants, shops, public facilities, and tourist attractions based on user queries.116MIT
- FlicenseNot gradedqualityCmaintenanceEnables querying K League official data (rankings, matches, players) via SQL using natural language, with a pre-built SQLite database.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/openhee/MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server