본문으로 건너뛰기

API와 MCP 차이, 날씨 데이터 하나로 직접 확인하기: curl 한 줄에서 AI가 쓰는 도구까지 5단계

· 약 10분
Datapopcorn CEO / AI automation educator
이 글과 연결된 글 보기
18편 · 46개 연결
100%
문자로 온 네이버페이 포인트 기프티콘, AI 브라우저 에이전트에게 등록시켜 봤습니다유료 문자 API 대신 내 안드로이드폰으로 무료 SMS 게이트웨이 만들기: Aside·무선 ADB·TextBee 실전 연동기API와 MCP 차이, 날씨 데이터 하나로 직접 확인하기: curl 한 줄에서 AI가 쓰는 도구까지 5단계Aside 커스텀 프로바이더 설정 가이드: 무료 스텔스 모델부터 Solar Pro 4까지 6단계로 연결하기온습도계를 키링으로 만들고 싶어서, 아스트라에게 3D 모델링을 맡겼습니다ChatGPT 데스크톱 앱으로 실시간 통역하는 법Claude Academy 열렸습니다: Claude Code·MCP를 무료로 배우는 방법Claude Code에서 n8n 워크플로우 만들기, MCP로 연결하는 법Aside로 30분 안에 당근비즈니스에 내 물건 등록하기: 따라 하는 프롬프트와 화면 11장데이터팝콘 AX 상담 페이지 오픈: 신청 방법부터 성공 온보딩 사례까지LLM에게 글을 쓰게 하지 않고 판단을 시킨다 — TypeSafe Jev 입문출장이라도 준비할 건 준비합니다 — 베를린 출장 중 AI로 챙긴 것들AI에게 오키나와 여행 계획을 통째로 맡겨봤습니다마이리얼트립 상품 검색, Claude에게 맡기기 — MCP 연결 한 줄이면 됩니다API 키 발급하고 마이리얼트립 마이링크 만들기n8n 첫 공식 컨퍼런스 'In The Loop 2026' 앱 뜯어보기: Fliplet 로우코드와 Node Runner 게이미피케이션 설계 분석공공데이터 수집에서 막히는 6가지와 해결법: 공공데이터포털·KOSIS·PDF 통계표 (Colab 노트북 포함)이번 주 팝콘 줍줍 — GPT-6 대화형 UI, Claude Haiku 5.5, 말로 만드는 게임 (10월 2주)

드래그로 이동 · 휠/두 손가락으로 확대 · 방향키로 글 선택 · 0으로 맞춤. 실선: 본문 링크, 점선: 시리즈·주제의 대표 연결.

표시된 글 18편 목록
전체 글 연결 탐색

API는 사람이 정확한 주소와 값을 알고 직접 부르는 창구이고, MCP는 그 창구에 AI가 읽을 수 있는 설명서를 붙여 AI가 스스로 골라 부르게 하는 규격입니다. 이 글에서는 같은 날씨 데이터를 한 번은 API로, 한 번은 MCP 서버로 불러 보면서 그 차이를 직접 확인합니다. 글에 나온 명령과 코드는 모두 2026년 10월 7일에 실제로 실행해 결과까지 확인했습니다.

이 글은 이런 분께 필요합니다​

  • "API 쓰면 되는데 MCP는 왜 쓰나요?"라는 질문에 아직 자신 있게 답하지 못하는 분
  • AI 에이전트를 만들려는데, 이미 쓰던 API를 그대로 부를지 MCP 서버로 감쌀지 고민되는 분
  • MCP 서버를 설치만 해봤고, 안에서 무슨 일이 일어나는지 직접 본 적은 없는 분

준비물은 네 가지입니다.

준비물확인 방법
Mac 또는 Linux 터미널터미널 앱을 열면 됩니다
curl대부분 기본으로 들어 있습니다. curl --version으로 확인합니다
uv (파이썬 실행 도구)uv --version이 안 되면 아래 명령으로 설치합니다
Codex CLI (Step 4에서만)ChatGPT 계정으로 로그인해 씁니다. 설치는 Step 4에서 안내합니다
curl -LsSf https://astral.sh/uv/install.sh | sh

uv 설치 명령은 uv 공식 설치 문서에 있는 그대로입니다. 설치 후 터미널을 한 번 닫았다 열어야 uv 명령이 잡힙니다.

이 글에서 쓰는 날씨 데이터는 Open-Meteo의 공개 API입니다. 회원가입도 API 키도 필요 없어서 복사해서 바로 따라 할 수 있습니다.

Step 1. 날씨 API를 curl로 직접 호출합니다​

먼저 "API를 쓴다"는 게 정확히 무엇인지 확인합니다. 터미널에 아래 한 줄을 붙여넣습니다. 서울(위도 37.5665, 경도 126.978)의 현재 기온과 풍속을 묻는 요청입니다.

curl "https://api.open-meteo.com/v1/forecast?latitude=37.5665&longitude=126.978&current=temperature_2m,wind_speed_10m&timezone=Asia%2FSeoul"

이런 JSON이 돌아오면 성공입니다. 숫자는 실행하는 시각에 따라 다릅니다.

{"timezone":"Asia/Seoul", ... ,"current":{"time":"2026-10-07T09:00","interval":900,"temperature_2m":14.7,"wind_speed_10m":1.3}}

여기서 눈여겨볼 점은 모든 걸 내가 정했다는 것입니다.

  • 어느 주소(/v1/forecast)로 보낼지
  • 서울의 위도·경도가 몇인지
  • 어떤 값(temperature_2m, wind_speed_10m)을 달라고 할지
  • 언제 이 요청을 보낼지

API는 "이 형식으로 요청하면 이 데이터를 준다"는 약속입니다. 그 약속을 읽고, 값을 채우고, 부를 시점을 정하는 일은 전부 사람(또는 사람이 짠 코드)의 몫입니다.

Step 2. 같은 기능을 MCP 서버로 감쌉니다​

이제 같은 날씨 API를 AI가 쓸 수 있는 도구(Tool) 로 바꿔 봅니다. 빈 폴더를 하나 만들고 그 안에 weather_server.py 파일을 만들어 아래 코드를 그대로 붙여넣습니다.

mkdir weather-mcp && cd weather-mcp
weather_server.py
import json
import urllib.parse
import urllib.request

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("korea-weather")

CITIES = {
"서울": (37.5665, 126.9780),
"부산": (35.1796, 129.0756),
"제주": (33.4996, 126.5312),
}


@mcp.tool()
def get_current_weather(city: str) -> str:
"""도시의 현재 기온(°C)과 풍속(km/h)을 조회합니다. city는 서울, 부산, 제주 중 하나입니다."""
if city not in CITIES:
return f"지원하지 않는 도시입니다: {city}. 서울, 부산, 제주 중 하나를 넣어 주세요."
lat, lon = CITIES[city]
query = urllib.parse.urlencode({
"latitude": lat,
"longitude": lon,
"current": "temperature_2m,wind_speed_10m",
"timezone": "Asia/Seoul",
})
url = f"https://api.open-meteo.com/v1/forecast?{query}"
with urllib.request.urlopen(url, timeout=10) as res:
now = json.load(res)["current"]
return f"{city} {now['time']} 기준 기온 {now['temperature_2m']}°C, 풍속 {now['wind_speed_10m']}km/h"


if __name__ == "__main__":
mcp.run()

코드를 잘 보면 안쪽은 Step 1과 똑같은 API 호출입니다. MCP는 API를 없애거나 대체하지 않습니다. 달라진 건 바깥에 붙은 두 가지입니다.

  1. @mcp.tool(): 이 함수를 AI가 부를 수 있는 도구로 등록합니다.
  2. 함수 바로 아래 큰따옴표 세 개로 쓴 설명 문장: AI가 "이 도구는 언제, 어떤 값을 넣어 쓰는가"를 판단할 때 읽는 설명서가 됩니다.

위도·경도도 사람이 외울 필요가 없어졌습니다. AI는 city에 "부산"만 넣으면 됩니다.

Step 3. AI가 보는 '도구 설명서'를 직접 열어봅니다​

MCP 서버는 AI 앱(클라이언트)과 JSON-RPC라는 형식의 메시지를 주고받습니다. 한 줄에 메시지 하나씩, 정해진 모양의 JSON을 보내고 받는 방식입니다. AI 앱이 MCP 서버에 처음 연결하면 하는 일을 우리가 손으로 똑같이 해보겠습니다.

같은 폴더에 ask.jsonl 파일을 만들고 아래 네 줄을 붙여넣습니다.

ask.jsonl
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"me","version":"1.0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_current_weather","arguments":{"city":"부산"}}}

각 줄의 뜻은 이렇습니다.

줄하는 일
initialize"연결할게요"라고 인사하고 서로 지원하는 기능을 맞춥니다
notifications/initialized준비가 끝났다고 알립니다
tools/list"쓸 수 있는 도구 목록과 설명서를 주세요"
tools/call"get_current_weather에 부산을 넣어 실행해 주세요"

이제 이 메시지를 서버에 흘려 넣습니다.

(cat ask.jsonl; sleep 3) | uv run --with "mcp<2" weather_server.py 2>/dev/null

처음 실행하면 uv가 MCP 파이썬 패키지를 내려받느라 몇 초 걸립니다. 응답 세 줄 중 두 번째 줄이 바로 AI가 보는 도구 설명서입니다. 보기 좋게 줄을 나누면 이렇습니다.

{
"tools": [{
"name": "get_current_weather",
"description": "도시의 현재 기온(°C)과 풍속(km/h)을 조회합니다. city는 서울, 부산, 제주 중 하나입니다.",
"inputSchema": {
"properties": {"city": {"title": "City", "type": "string"}},
"required": ["city"],
"type": "object"
}
}]
}

Step 2에서 쓴 함수 이름과 설명 문장이 그대로 name과 description이 됐고, city: str은 "city라는 글자 값이 반드시 필요하다"는 inputSchema가 됐습니다. 마지막 줄에는 실제 실행 결과가 들어 있습니다.

{"content":[{"type":"text","text":"부산 2026-10-07T09:00 기준 기온 17.5°C, 풍속 6.2km/h"}],"isError":false}

여기까지 오면 차이가 보입니다. Step 1에서는 내가 주소와 위도·경도를 알고 불렀습니다. Step 3에서는 서버가 먼저 "나는 이런 도구가 있고 이런 값이 필요해"라고 스스로 설명합니다. AI 앱은 이 설명서를 읽고, 사용자가 "부산 날씨 어때?"라고 물으면 get_current_weather에 "부산"을 넣어야겠다고 스스로 판단합니다.

Step 4. AI 앱에 연결하고, AI가 도구를 고르는지 확인합니다​

이제 이 서버를 실제 AI 앱에 붙입니다. MCP는 공통 규격이라 MCP를 지원하는 앱이면 같은 서버를 그대로 연결할 수 있습니다. 여기서는 ChatGPT 계정으로 쓰는 터미널 앱 Codex CLI로 확인합니다. Codex CLI가 없다면 Codex CLI 공식 페이지의 설치 명령으로 설치하고, codex를 한 번 실행해 ChatGPT 계정으로 로그인합니다.

① 서버를 등록합니다. weather-mcp 폴더 안에서 아래 명령을 실행합니다. /절대/경로/ 부분은 pwd로 확인한 이 폴더의 실제 경로로 바꿉니다.

codex mcp add korea-weather -- uv run --with "mcp<2" /절대/경로/weather-mcp/weather_server.py

Added global MCP server 'korea-weather'.가 나오면 등록된 것입니다. codex mcp list를 실행하면 korea-weather가 enabled로 보입니다.

② 이 서버의 도구는 묻지 않고 쓰도록 허용합니다. Codex는 MCP 도구를 부르기 전에 승인을 받습니다. 날씨 조회는 읽기만 하는 도구라서, 설정 파일 ~/.codex/config.toml을 열어 방금 생긴 [mcp_servers.korea-weather] 칸 맨 아래에 한 줄을 추가합니다.

~/.codex/config.toml
[mcp_servers.korea-weather]
command = "uv"
args = ["run", "--with", "mcp<2", "/절대/경로/weather-mcp/weather_server.py"]
default_tools_approval_mode = "approve"

default_tools_approval_mode는 Codex MCP 공식 문서에 나오는 설정입니다. 파일을 고치거나 메시지를 보내는 도구에는 이 줄을 넣지 않는 편이 안전합니다.

③ 질문만 던집니다. 도구 이름도, 위도·경도도 말하지 않습니다. 웹 검색은 끄고 실행합니다(이유는 바로 아래에서 설명합니다).

codex exec --skip-git-repo-check -c web_search='"disabled"' "부산이랑 제주 중 지금 어디가 더 따뜻해?"

2026년 10월 7일 오전에 실제로 실행한 결과입니다.

codex
지금 날씨는 실시간성이 커서 바로 확인해볼게요. 부산과 제주 현재 기온을 같은 기준으로 비교하겠습니다.
mcp: korea-weather/get_current_weather started
mcp: korea-weather/get_current_weather (completed)
mcp: korea-weather/get_current_weather started
mcp: korea-weather/get_current_weather (completed)
codex
지금은 **제주가 더 따뜻해요.**

- 부산: **19.4°C**
- 제주: **20.5°C**

get_current_weather를 두 번 불렀습니다. 한 번은 부산, 한 번은 제주를 넣어서입니다. 질문 어디에도 "get_current_weather를 두 번 불러라"라는 말은 없습니다. AI가 Step 3에서 본 설명서 한 줄("city는 서울, 부산, 제주 중 하나입니다")을 읽고, 도구를 몇 번, 어떤 값으로 부를지 스스로 정한 것입니다. Step 1에서 사람이 주소와 위도·경도를 직접 넣던 것과 가장 크게 달라지는 지점이 바로 여기입니다.

AI가 고른다는 건, 내 도구를 안 고를 수도 있다는 뜻입니다. 같은 질문을 웹 검색을 켠 채로 실행했더니, Codex는 이번에는 korea-weather 대신 웹 검색으로 기상청 페이지를 찾아 답했습니다. 쓸 수 있는 도구가 여러 개면 AI는 그중 하나를 고릅니다. 내 도구를 확실히 쓰게 하려면 위처럼 다른 도구를 끄거나, 질문에 "korea-weather 도구로 ~ 알려줘"처럼 도구 이름을 넣으면 됩니다. 도구 이름을 넣은 질문은 웹 검색을 켠 상태에서도 korea-weather를 두 번 불러 같은 답을 냈습니다.

Step 5. 내 상황에 API와 MCP 중 무엇이 맞는지 정합니다​

직접 해본 걸 바탕으로 정리하면, 두 방식의 차이는 "누가 언제 부를지 정하는가" 입니다.

구분APIMCP
누가 부르나사람이 짠 코드가 정해진 순서대로AI가 대화 내용을 보고 골라서
무엇을 보고 부르나사람이 읽는 API 문서서버가 직접 내보내는 도구 설명서(tools/list)
주고받는 형식REST, GraphQL 등 서비스마다 다름JSON-RPC 2.0으로 통일
연결 방식앱마다 따로 연동 코드 작성서버 하나를 MCP 지원 앱 여러 곳에서 재사용

아래 기준으로 고르면 됩니다.

API를 직접 쓰는 게 맞는 경우

  • 결제 승인, 회원가입, 매일 정해진 시각의 데이터 수집처럼 언제나 같은 순서로 실행돼야 하는 일
  • AI의 판단 없이 서버끼리 빠르게 데이터를 주고받아야 하는 일

MCP로 감싸는 게 맞는 경우

  • AI가 대화 중에 필요할 때 알아서 꺼내 쓰게 하고 싶은 사내 데이터나 도구
  • 같은 도구를 여러 AI 앱에서 코드 수정 없이 쓰고 싶을 때. AI 앱이 3개, 연결할 서비스가 4개라면 따로 연동하면 3×4=12번 만들어야 하지만, 서비스마다 MCP 서버를 하나씩 만들면 4개로 끝납니다
  • AI에게 전체 권한을 주기 싫을 때. Step 2의 서버는 서울·부산·제주 날씨 조회 하나만 열어 둡니다. 이렇게 AI가 할 수 있는 일을 서버 코드에서 좁힐 수 있습니다

정리하면 "API냐 MCP냐"가 아니라 "MCP 안에서 API를 부른다" 가 정답에 가깝습니다. 이미 쓰고 있는 API가 있다면 버릴 필요 없이, Step 2처럼 설명서를 붙여 감싸기만 하면 AI가 쓰는 도구가 됩니다.

오류가 나면 여기부터 확인하세요​

증상·메시지원인해결
command not found: uvuv가 설치되지 않았거나 터미널이 설치 전 상태준비물의 설치 명령을 실행하고 터미널을 새로 엽니다
No module named 'mcp.server.fastmcp'. This is mcp 2.x ...MCP 파이썬 SDK 2.x가 설치됨. 2.x에서는 FastMCP가 MCPServer로 이름이 바뀌었습니다이 글처럼 --with "mcp<2"로 1.x를 씁니다. 2.x로 옮기려면 공식 마이그레이션 가이드를 따릅니다
Step 3에서 응답이 두 줄만 나오고 날씨 결과가 없음날씨를 받아오기 전에 입력이 끝나 서버가 종료됨명령의 sleep 3을 빼지 않았는지 확인하고, 인터넷이 느리면 sleep 5로 늘립니다
지원하지 않는 도시입니다CITIES에 없는 도시 이름을 넣음CITIES에 "대구": (35.8714, 128.6014)처럼 위도·경도를 추가합니다
MCP tool call requires approval, but approval policy is nevercodex exec는 실행 중에 승인을 물을 수 없는데, 도구 승인 설정이 없음Step 4 ②처럼 default_tools_approval_mode = "approve" 줄을 넣거나, codex를 대화형으로 실행합니다
답은 나오는데 mcp: korea-weather/... 줄이 없음AI가 내 도구 대신 웹 검색 같은 다른 도구를 고름-c web_search='"disabled"'로 웹 검색을 끄거나, 질문에 "korea-weather 도구로"를 넣습니다

정리​

curl로 API 직접 호출 → 같은 호출을 파이썬 파일 하나로 MCP 도구로 감싸기 → tools/list로 AI가 보는 설명서 확인 → AI 앱에 연결 → 내 상황에 맞는 방식 고르기, 이 다섯 단계면 API와 MCP의 차이를 말로 외우지 않고 직접 확인할 수 있습니다. 다음에는 Open-Meteo 대신 평소 쓰던 공공데이터 API 하나를 골라 Step 2의 함수 안쪽만 바꿔 보세요. 설명 문장을 어떻게 쓰느냐에 따라 AI가 도구를 얼마나 잘 골라 쓰는지도 직접 비교해볼 수 있습니다.

참고 자료​