자연어 기반 스마트홈 AIoT 제어 시스템의 AI/MCP Server입니다.
AI_MCP_Server는 Backend로부터 사용자 자연어 명령을 전달받아, 사용자의 의도를 분석하고 실행 가능한 commands JSON을 생성합니다.
현재는 실제 LLM API를 연결하기 전 단계이며, 규칙 기반 Mock Parser로 전체 파이프라인을 검증하고 있습니다.
AI_MCP_Server의 주요 역할은 다음과 같습니다.
- 사용자 자연어 명령 해석
- Backend API를 통한 MCP Tool 목록 조회
- Backend API를 통한 현재 기기 상태 조회
- Backend API를 통한 Routine 목록 및 상세 조회
- 자연어 명령을 commands JSON으로 변환
- 모호한 명령에 대한 재질문 판단
- pending_command와 사용자 추가 답변을 결합하여 최종 명령 생성
- 필요한 경우 Backend의 command execute API 호출
AI_MCP_Server는 DB에 직접 접근하지 않습니다.
AI_MCP_Server
→ Backend API 호출
→ Backend가 DB 조회
→ Tool / Resource / Routine 정보 반환
즉, DB 접속 정보는 Backend만 가지고 있습니다.
AI_MCP_Server는 Backend가 제공하는 API를 통해서만 다음 정보를 조회합니다.
GET /api/v1/mcp/tools
GET /api/v1/mcp/resources/device-states
GET /api/v1/routines
GET /api/v1/routines/{routine_name}
Backend /api/v1/commands/parse
→ AI_MCP_Server /parse
→ Backend API로 Tool 목록 조회
→ Backend API로 현재 Device State 조회
→ 필요 시 Routine 조회
→ 사용자 자연어 명령 분석
→ commands 또는 clarification_needed 반환
즉시 실행 흐름은 다음과 같습니다.
AI_MCP_Server /parse-and-execute
→ /parse 내부 로직 수행
→ clarification_needed=false인 경우
→ Backend /api/v1/commands/execute 호출
→ DB 상태 업데이트 결과 반환
재질문 흐름은 다음과 같습니다.
사용자: 집이 너무 덥네
→ /parse
→ clarification_needed=true
→ pending_command 반환
사용자: 24도로 해줘
→ /clarify
→ pending_command + user_answer 결합
→ 최종 commands 반환
AI_MCP_Server : http://127.0.0.1:8001
Backend : http://127.0.0.1:8000
Swagger 문서:
http://127.0.0.1:8001/docs
| 구분 | 기술 |
|---|---|
| Framework | FastAPI |
| Language | Python |
| Backend 연동 | HTTP API |
| Parser | Mock Parser |
| 향후 LLM 후보 | OpenAI GPT API 또는 Claude API |
AI_MCP_Server 루트 경로에 .env 파일을 생성합니다.
BACKEND_BASE_URL=http://127.0.0.1:8000
AI_SERVER_PORT=8001실제 LLM API 연결 시 아래 값 중 하나를 추가할 수 있습니다.
OPENAI_API_KEY=your_openai_api_key또는
ANTHROPIC_API_KEY=your_anthropic_api_key현재 단계에서는 실제 LLM API를 아직 사용하지 않습니다.
python -m venv venv
.\venv\Scripts\activatepip install -r requirements.txtuvicorn app.main:app --reload --host 127.0.0.1 --port 8001Backend API 연동 상태를 확인하기 위한 API입니다.
| 기능 | Method | URL |
|---|---|---|
| Tool 목록 확인 | GET | /debug/tools |
| Device State 확인 | GET | /debug/device-states |
| Routine 목록 확인 | GET | /debug/routines |
| Routine 상세 확인 | GET | /debug/routines/{routine_name} |
정상 확인 기준:
tools_count = 16
device_states_count = 3
routines_count = 3
POST /parse
사용자 자연어 명령을 분석하여 commands JSON을 반환합니다.
{
"session_id": "sess-tv001",
"raw_text": "나는솔로 틀어줘"
}{
"session_id": "sess-tv001",
"intent": "device_control",
"commands": [
{
"step_order": 1,
"device_name": "living_room_tv",
"device_type": "tv",
"tool_name": "tv.set_power",
"parameters": {
"power": "on"
}
},
{
"step_order": 2,
"device_name": "living_room_tv",
"device_type": "tv",
"tool_name": "tv.play_content",
"parameters": {
"content_title": "나는솔로"
}
}
],
"clarification_needed": false,
"clarification_turn": 0,
"clarification_question": null,
"pending_command": null,
"response_text": "TV를 켜고 나는솔로를 재생할게요."
}POST /parse-and-execute
자연어 명령을 분석한 뒤, 명령이 명확하면 Backend의 /api/v1/commands/execute를 호출하여 즉시 실행합니다.
흐름:
raw_text
→ /parse
→ commands 생성
→ Backend /api/v1/commands/execute
→ DB 상태 업데이트
POST /clarify
재질문 이후 사용자의 추가 응답을 받아 pending_command와 결합하고 최종 commands를 생성합니다.
{
"session_id": "sess-ac004",
"user_answer": "24도로 해줘",
"pending_command": {
"device_name": "living_room_aircon",
"device_type": "air_conditioner",
"inferred_intent": "cooling",
"context_trigger": "hot",
"candidate_tools": [
"air_conditioner.set_power",
"air_conditioner.set_mode",
"air_conditioner.set_temperature"
],
"known_parameters": {
"power": "on",
"mode": "cool"
},
"missing_parameters": [
"temperature"
]
}
}{
"session_id": "sess-ac004",
"intent": "device_control",
"commands": [
{
"step_order": 1,
"device_name": "living_room_aircon",
"device_type": "air_conditioner",
"tool_name": "air_conditioner.set_power",
"parameters": {
"power": "on"
}
},
{
"step_order": 2,
"device_name": "living_room_aircon",
"device_type": "air_conditioner",
"tool_name": "air_conditioner.set_mode",
"parameters": {
"mode": "cool"
}
},
{
"step_order": 3,
"device_name": "living_room_aircon",
"device_type": "air_conditioner",
"tool_name": "air_conditioner.set_temperature",
"parameters": {
"temperature": 24
}
}
],
"clarification_needed": false,
"clarification_turn": 1,
"clarification_question": null,
"pending_command": null,
"response_text": "거실 에어컨을 24도 냉방으로 켤게요."
}POST /clarify-and-execute
재질문 응답을 처리한 뒤, 최종 commands가 완성되면 Backend의 /api/v1/commands/execute를 호출하여 즉시 실행합니다.
현재 실제 LLM API는 연결하지 않았고, 규칙 기반 Mock Parser로 아래 케이스를 처리합니다.
| 사용자 입력 | 처리 결과 |
|---|---|
| 나는솔로 틀어줘 | tv.set_power + tv.play_content |
| 유튜브에서 뉴진스 틀어줘 | tv.set_power + tv.play_content(app_name=youtube) |
| 에어컨 24도로 켜줘 | air_conditioner.set_power + air_conditioner.set_temperature |
| 집이 너무 덥네 | clarification_needed=true |
| 영화 모드로 해줘 | routine_control + movie routine steps |
현재 Mock Parser가 담당하는 부분은 추후 실제 LLM 호출 로직으로 교체합니다.
교체 대상:
/parse
/clarify
LLM에 제공할 정보:
1. 사용자 raw_text
2. MCP Tool 목록
3. 현재 device_states
4. routines 목록
5. 필요한 경우 routine detail
6. system prompt
7. 출력 JSON schema
LLM 출력 형식은 현재 Mock Parser의 반환 형식을 유지해야 합니다.
{
"session_id": "...",
"intent": "device_control",
"commands": [],
"clarification_needed": false,
"clarification_turn": 0,
"clarification_question": null,
"pending_command": null,
"response_text": "..."
}이 형식을 유지해야 Backend와 Frontend 구조를 변경하지 않고 실제 AI로 교체할 수 있습니다.
- AI_MCP_Server는 DB에 직접 접근하지 않습니다.
- Backend API를 통해서만 Tool, Resource, Routine 정보를 조회합니다.
- AI_MCP_Server는 임의의 tool_name을 생성하면 안 됩니다.
- 반드시 Backend가 제공한 MCP Tool 목록 안에서만 명령을 생성해야 합니다.
- 필수 파라미터가 부족하면 즉시 실행하지 않고 재질문해야 합니다.
- 최종 실행은 Backend가 담당합니다.