AI 에이전트는 LLM이 도구를 골라 호출하고, 그 결과를 보고 다음 행동을 다시 정하는 과정을 목표를 이룰 때까지 반복하는 시스템입니다. MCP(Model Context Protocol)는 AI 애플리케이션이 이런 도구와 데이터를 연결하는 방식을 표준화한 개방형 프로토콜로, 도구를 MCP 서버로 한 번 만들어 두면 MCP를 지원하는 여러 애플리케이션에서 쓸 수 있습니다. 모델은 도구 호출을 요청할 뿐이고 실제 실행은 MCP 서버가 자신의 계정과 토큰으로 하기 때문에, 에이전트가 할 수 있는 일의 한계는 서버에 준 권한이 정합니다.
1. AI 에이전트란
LLM 자체는 텍스트를 입력받아 텍스트를 생성할 뿐, 서버에 접속하거나 명령을 실행하지 못합니다. 여기에 검색, 도구, 메모리를 붙이면 할 수 있는 일이 늘어나는데, Anthropic의 Building effective agents 글은 이것을 확장된 LLM(augmented LLM)이라 부르고 모든 에이전트 시스템의 기본 단위로 설명합니다.
같은 글은 LLM과 도구를 쓰는 시스템을 두 가지로 구분합니다. 워크플로(workflow)는 LLM과 도구가 미리 정한 코드 경로를 따라 움직이는 시스템이고, 에이전트(agent)는 LLM이 스스로 다음 과정과 사용할 도구를 정하는 시스템입니다. 인프라 업무에 대입하면 차이가 분명해집니다.
| 구분 | 다음 단계를 정하는 주체와 예시 |
| 챗봇 | 사람이 질문하고 모델은 답만 함, 로그를 붙여 넣고 원인을 묻는 방식 |
| 워크플로 | 코드가 정함, 경보가 오면 정해진 스크립트로 로그를 모으고 모델이 요약해 메신저로 전송 |
| 에이전트 | 모델이 정함, "디스크 경보 원인을 찾아 줘"라고 하면 모델이 df, du, 로그 조회 중 무엇을 먼저 할지 스스로 선택 |
Anthropic은 복잡성은 결과가 분명히 좋아질 때만 더하라고 권하며, 에이전트는 더 나은 결과를 얻는 대신 지연 시간과 비용이 늘어난다고 설명합니다. 저도 절차가 정해진 반복 작업은 워크플로로 만들고, 조사 순서가 상황마다 달라지는 작업에만 에이전트를 검토합니다. 워크플로는 어떤 순서로 무엇이 실행될지 미리 알 수 있어 검증과 장애 대응이 쉽기 때문입니다.
2. 에이전트는 어떻게 동작하나
에이전트는 반복(loop) 구조로 동작합니다. 모델이 다음에 쓸 도구와 인자를 정하면 애플리케이션이 도구를 실행하고, 실행 결과를 다시 모델에 넘깁니다. 모델은 이 결과를 실제 환경에서 온 근거(ground truth)로 삼아 다음 행동을 정하고, 목표를 이루거나 정해 둔 반복 한도에 닿으면 멈춥니다.

도구 실행 결과가 다시 모델로 돌아가는 반복이 에이전트의 핵심입니다
여기서 중요한 점은 모델이 도구를 직접 실행하지 않는다는 것입니다. 모델은 "disk_usage 도구를 path=/var로 호출해 달라"는 구조화된 요청만 출력하고, 실제 실행은 애플리케이션이나 MCP 서버가 합니다. 그래서 모델이 무엇을 요청하든 실제로 일어날 수 있는 일은 실행하는 쪽의 권한으로 제한되며, 이 점이 뒤에서 다룰 권한 설계의 출발점입니다.
반복 구조에는 비용도 따릅니다. 한 번 도구를 호출할 때마다 이전 대화와 도구 결과가 모두 다시 입력으로 들어가므로 입력 토큰이 계속 쌓이고, Anthropic은 에이전트의 자율성이 높은 비용과 오류 누적(compounding errors)으로 이어질 수 있다며 샌드박스 환경에서 충분히 시험하고 안전장치를 두라고 권합니다. 토큰이 쌓이는 방식은 LLM 토큰과 컨텍스트 윈도우 개념 정리에서 자세히 다루었습니다.
3. MCP란
MCP 이전에는 AI 애플리케이션마다 도구 연결 방식이 달라서, 같은 사내 DB 조회 기능도 애플리케이션별로 따로 만들어야 했습니다. MCP 명세는 MCP를 LLM 애플리케이션과 외부 데이터, 도구를 연결하는 표준 방식을 제공하는 개방형 프로토콜로 정의하고, 여러 편집기가 하나의 방식으로 언어 기능을 지원하게 만든 LSP(Language Server Protocol)에서 영감을 받았다고 설명합니다. 도구를 MCP 서버로 한 번 만들면 MCP를 지원하는 여러 애플리케이션이 같은 서버를 쓸 수 있습니다.
MCP는 JSON-RPC 2.0 메시지를 사용하며, 구성 요소는 호스트, 클라이언트, 서버 세 가지입니다.

호스트는 서버마다 클라이언트를 하나씩 두고, 각 서버는 다른 서버나 전체 대화를 볼 수 없습니다
| 구성 요소 | 역할 |
| Host | Claude Desktop, IDE, 사내 에이전트처럼 사용자가 쓰는 AI 애플리케이션, 클라이언트를 만들고 관리하며 보안 정책과 사용자 승인을 처리 |
| Client | 호스트 안에서 서버 하나와 1:1로 연결되어 메시지를 주고받음 |
| Server | 도구, 리소스, 프롬프트를 제공하는 프로그램, 로컬 프로세스나 원격 서비스로 동작 |
명세의 설계 원칙 중 운영자가 기억할 것은 "서버는 전체 대화를 읽거나 다른 서버를 들여다볼 수 없어야 한다"는 항목입니다. 전체 대화는 호스트가 보관하고 서버에는 필요한 정보만 전달되며, 서버 사이의 상호작용도 호스트가 통제합니다. 그래서 어떤 서버에 무엇을 넘길지 결정하는 호스트가 보안의 중심이 됩니다.
4. MCP 서버가 제공하는 것
MCP 서버는 세 가지 기능을 제공할 수 있고, 각각 누가 사용을 결정하는지가 다릅니다.
| 기능 | 설명 |
| Tools | 모델이 실행하는 함수, 모델이 상황을 보고 스스로 찾아 호출 (예: 디스크 사용량 조회, 티켓 생성) |
| Resources | 사용자나 모델이 참고할 데이터 (예: 설정 파일, 런북 문서) |
| Prompts | 사용자가 골라 쓰는 메시지 템플릿과 작업 흐름 (예: 장애 보고서 양식) |
반대로 서버가 클라이언트에 요청하는 기능도 있습니다. 대표적인 것이 elicitation으로, 서버가 작업 도중 사용자에게 추가 정보를 요청할 때 씁니다. 도구 호출은 JSON-RPC의 tools/call 메서드로 이루어지며, 명세의 형식에 이 글의 실습 도구를 넣으면 다음과 같습니다. 실제 요청에는 프로토콜 버전 같은 메타데이터가 함께 들어가지만 여기서는 생략했습니다.
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "disk_usage",
"arguments": { "path": "/var" }
}
}
도구 실행 중 입력값 오류나 API 실패가 나면 서버는 결과에 isError: true를 담아 돌려줍니다. 명세는 이런 실행 오류를 모델에 전달해 모델이 인자를 고쳐 다시 시도할 수 있게 하라고 권합니다.
5. 전송 방식: stdio와 Streamable HTTP
MCP 명세는 표준 전송 방식으로 두 가지를 정의합니다. 어느 방식이든 주고받는 메시지의 의미는 같고, 메시지를 실어 나르는 방법만 다릅니다.
| 전송 방식 | 동작과 쓰임 |
| stdio | 클라이언트가 서버를 하위 프로세스로 실행하고 표준 입출력으로 메시지를 주고받음, 개인 PC의 로컬 도구에 주로 사용 |
| Streamable HTTP | 서버가 하나의 HTTP 엔드포인트를 열고 요청마다 POST로 받음, 응답은 JSON이나 요청 단위 SSE 스트림, 여러 사용자가 쓰는 원격 서버에 사용 |
Streamable HTTP로 서버를 운영할 때 명세가 요구하는 보안 사항은 세 가지입니다. DNS 리바인딩 공격을 막기 위해 모든 요청의 Origin 헤더를 검증해야 하고(MUST), 로컬에서 실행할 때는 0.0.0.0이 아니라 127.0.0.1에만 바인딩해야 하며(SHOULD), 모든 연결에 인증을 적용해야 합니다(SHOULD). 이를 지키지 않으면 공격자가 웹사이트를 통해 사용자 PC의 로컬 MCP 서버에 접근할 수 있다고 명세는 경고합니다.
인프라 관점에서 눈여겨볼 변화도 있습니다. 2026-07-28 버전 명세는 프로토콜 수준의 세션을 없애고 모든 요청이 프로토콜 버전과 클라이언트 기능 정보를 스스로 담는 무상태(stateless) 방식으로 바뀌었습니다. 또 Streamable HTTP 요청에는 Mcp-Method, Mcp-Name 같은 헤더에 메서드와 도구 이름을 복사해 두도록 해서, 로드밸런서나 게이트웨이가 본문을 해석하지 않고도 라우팅, 요청 제한, 모니터링을 할 수 있게 했습니다. 서버가 SSE 스트림을 열 때는 X-Accel-Buffering: no 헤더를 넣어 nginx 같은 리버스 프록시가 응답을 버퍼링하지 않게 하라는 권고도 있어, 프록시 뒤에 MCP 서버를 둘 때 확인할 부분입니다.
6. 실습: 읽기 전용 MCP 서버 만들기
개념을 확인하기 위해 공식 Python SDK(mcp 1.27.0)로 디스크 사용량만 조회하는 MCP 서버를 만들어 보았습니다. 이 SDK는 세션을 여는 initialize 과정이 있는 2025-11-25 버전 프로토콜을 사용하지만, 도구를 정의하고 호출하는 흐름은 같습니다. 조회할 수 있는 경로를 목록으로 제한하고, 값을 읽기만 하도록 만들었습니다.
pip install mcp
# disk_server.py: 허용된 경로의 디스크 사용량만 조회하는 읽기 전용 MCP 서버
import shutil
from mcp.server.fastmcp import FastMCP
ALLOWED = {"/", "/var", "/home"} # 조회를 허용할 경로만 명시
mcp = FastMCP("disk-check")
@mcp.tool()
def disk_usage(path: str) -> str:
"""지정한 경로가 속한 파일 시스템의 사용률과 남은 용량을 반환합니다."""
if path not in ALLOWED:
raise ValueError(f"허용되지 않은 경로입니다: {path}")
u = shutil.disk_usage(path)
pct = u.used / (u.used + u.free) * 100 # df의 Use%와 같은 방식
return f"{path}: {pct:.0f}% used, {u.free / 1024**3:.1f}GB free"
if __name__ == "__main__":
mcp.run() # 기본값은 stdio 전송
함수에 붙인 docstring이 도구 설명(description)이 되고, 타입 힌트가 입력 스키마(inputSchema)가 됩니다. 모델은 이 설명과 스키마를 보고 언제 어떤 인자로 도구를 부를지 판단하므로, 설명은 짧더라도 도구가 하는 일과 반환 형식을 분명히 적는 편이 좋습니다. 아래 클라이언트는 서버를 stdio로 실행해 도구 목록을 조회하고, 허용된 경로와 허용되지 않은 경로로 한 번씩 호출합니다.
# client.py: stdio로 서버를 실행하고 도구 목록 조회와 호출을 테스트
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main():
params = StdioServerParameters(command="python3", args=["disk_server.py"])
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
init = await session.initialize()
print("protocol:", init.protocolVersion)
tools = await session.list_tools()
for t in tools.tools:
print("tool:", t.name, "|", t.description)
print("input:", t.inputSchema["properties"], t.inputSchema["required"])
for p in ["/var", "/etc"]:
r = await session.call_tool("disk_usage", {"path": p})
print("isError:", r.isError, "|", r.content[0].text)
asyncio.run(main())
protocol: 2025-11-25
tool: disk_usage | 지정한 경로가 속한 파일 시스템의 사용률과 남은 용량을 반환합니다.
input: {'path': {'title': 'Path', 'type': 'string'}} ['path']
isError: False | /var: 29% used, 29.7GB free
isError: True | Error executing tool disk_usage: 허용되지 않은 경로입니다: /etc
허용 목록에 없는 /etc 조회는 서버가 거부했고, 오류는 isError: True인 결과로 돌아왔습니다. 모델이 어떤 경로를 요청하든 서버 코드가 허용한 범위를 넘을 수 없다는 점이 이 실습의 핵심입니다. 실제 서버에서는 여기에 더해 서버 프로세스를 권한이 낮은 전용 계정으로 실행해, 코드에 실수가 있더라도 운영체제 권한에서 한 번 더 막히게 합니다.
7. 권한 문제가 생기는 지점
생성형 AI 업무 활용 시 보안 주의점 정리에서 에이전트와 커넥터의 간접 프롬프트 인젝션을 다루었는데, 그 문제가 심각해지는 이유가 이 구조에 있습니다. 모델은 요청만 하고 실행은 서버가 서버의 권한으로 하므로, 모델이 조작된 문서나 도구 결과에 속더라도 실제 피해의 크기는 서버에 준 권한이 결정합니다.

모델이 무엇을 요청하든 실제로 할 수 있는 일은 MCP 서버의 계정과 토큰 권한까지입니다
OWASP LLM Top 10 2025의 LLM06(Excessive Agency)은 이 위험을 LLM의 예상치 못한, 모호하거나 조작된 출력에 따라 피해를 주는 행동이 실행될 수 있는 취약점으로 정의하고, 원인을 세 가지로 나눕니다.
| 원인 | 예시와 대응 |
| 과도한 기능 | 조회만 필요한데 셸 실행 도구까지 연결, 필요한 도구만 연결하고 도구 기능도 최소화 |
| 과도한 권한 | DB 조회 서버가 쓰기 권한이 있는 계정으로 접속, 읽기 전용 계정과 최소 범위의 토큰 사용 |
| 과도한 자율성 | 삭제나 재시작을 사람 확인 없이 실행, 영향이 큰 작업은 사람의 승인을 거치게 함 |
MCP 명세와 보안 모범 사례 문서도 같은 방향의 요구 사항을 담고 있습니다.
| 항목 | 명세 내용 |
| 도구는 코드 실행 | 도구는 임의 코드 실행과 같으므로 주의해서 다뤄야 하고, 호스트는 도구를 호출하기 전에 사용자의 명시적 동의를 받아야 함 |
| 설명은 신뢰하지 않음 | 도구 동작 설명(annotations)은 신뢰할 수 있는 서버에서 온 것이 아니면 신뢰하지 않음 |
| 사람의 개입 | 사용자가 도구 호출을 거부할 수 있어야 하고, 어떤 도구가 호출되는지 화면에 보여야 함 |
| 로컬 서버 | 로컬 MCP 서버는 클라이언트와 같은 권한으로 실행되므로 실행 명령을 그대로 보여 주고 승인받아야 하며, 샌드박스 실행을 권장 |
| 토큰 전달 금지 | MCP 서버는 자신에게 발급되지 않은 토큰을 받아서는 안 되고, 받은 토큰을 그대로 다른 API로 넘기는 것(token passthrough)을 금지 |
| 최소 범위 | 처음에는 읽기 같은 최소 범위(scope)만 받고, 권한이 필요한 작업을 할 때 단계적으로 추가 |
8. MCP 서버를 운영할 때 확인할 것
사내에서 MCP 서버를 직접 운영하거나 외부 MCP 서버를 도입할 때 저는 다음 항목을 확인합니다. 에이전트가 실수하거나 조작되는 상황을 막을 수는 없다고 보고, 그때 피해가 어디까지 번지는지를 줄이는 쪽에 초점을 둡니다.
| 항목 | 확인할 내용 |
| 출처 | 검증된 서버만 설치하고, 로컬 서버라면 실행 명령과 패키지를 직접 확인 |
| 실행 격리 | 컨테이너나 전용 계정으로 실행하고 접근 가능한 디렉터리와 네트워크를 제한 |
| 계정 권한 | 조회 도구는 읽기 전용 계정, 토큰은 필요한 범위만 |
| 네트워크 | 로컬 서버는 127.0.0.1 바인딩, HTTP 서버는 Origin 검증과 인증 적용 |
| 승인 | 쓰기, 삭제, 재시작 같은 도구는 사람이 승인해야 실행 |
| 감사 로그 | 누가 어떤 도구를 어떤 인자로 호출했는지와 결과를 기록 |
| 반복 한도 | 에이전트의 최대 반복 횟수와 도구 호출 타임아웃을 설정해 비용과 폭주를 제한 |
9. 정리
- 에이전트는 LLM이 도구를 고르고 결과를 보며 다음 행동을 정하는 반복 구조이고, 절차가 정해진 작업은 워크플로가 더 단순하고 검증하기 쉽습니다.
- MCP는 AI 애플리케이션과 도구를 연결하는 표준 프로토콜로, 호스트, 클라이언트, 서버로 구성되며 서버는 도구, 리소스, 프롬프트를 제공합니다.
- 전송 방식은 로컬용 stdio와 원격용 Streamable HTTP이며, HTTP 서버는 Origin 검증, 127.0.0.1 바인딩, 인증이 필요합니다.
- 모델은 요청만 하고 실행은 서버의 권한으로 이루어지므로, 최소 기능, 최소 권한, 사람 승인으로 피해 범위를 제한합니다.
참고
'AI > 개념' 카테고리의 다른 글
| [AI] 프롬프트, RAG, 파인튜닝 선택 기준 정리 (0) | 2026.09.26 |
|---|---|
| [AI] RAG 개념과 사내 문서 챗봇 구성 정리 (0) | 2026.09.26 |
| [AI] LLM 토큰과 컨텍스트 윈도우 개념 정리 (0) | 2026.09.26 |
| [AI] 머신러닝, 딥러닝, 생성형 AI 개념 정리 (0) | 2026.09.25 |