콘텐츠로 이동
Study Notekagent · kmcp

Tool 연결 — MCP 서버와 다른 Agent

결론부터
  • Agent의 tool은 MCP 서버이거나 다른 Agent다. MCP 서버는 RemoteMCPServer(이미 있는 서버), MCPServer(kmcp가 띄우는 서버), Service 중 하나로 가리킨다.
  • 서버를 가리키는 것만으로는 tool을 쓸 수 없다. toolNames에 적은 tool만 Agent에 주어진다.
  • tool 호출에 붙는 header는 두 종류다. headersFrom은 모든 호출에 같은 값을, allowedHeaders는 호출한 사용자의 요청에서 온 값을 싣는다.
  • 다른 namespace의 서버는 그 서버가 allowedNamespaces로 허용해야 참조할 수 있다.
이 장에서 처음 나오는 말4개
MCP 서버Model Context Protocol Server
tool 목록과 실행을 제공하는 서버다. Agent는 MCP client로서 이 서버에 접속해 tool을 부른다.
Streamable HTTP
MCP 서버가 HTTP endpoint 하나로 요청을 받는 전송 방식이다. kagent가 원격 MCP 서버에 접속할 때의 기본값이다.
allowlist
허용할 항목만 명시하고 나머지는 전부 막는 방식이다. toolNames가 tool의 allowlist다.
sub-agent
다른 Agent가 tool처럼 호출하는 Agent다. 호출하는 쪽은 coordinator 역할을 한다.

Agent의 tools는 “이 Agent가 무엇을 할 수 있는가”의 전부다. 지시문은 행동을 유도할 뿐이고, 실제로 할 수 있는 일은 연결된 tool이 정한다. 이 페이지는 tool을 가리키는 방법과 좁히는 방법, 그리고 tool 호출에 인증 정보를 싣는 두 가지 방법을 본다.

tool 서버를 가리키는 세 가지 방법

섹션 제목: “tool 서버를 가리키는 세 가지 방법”

type: McpServer인 tool은 mcpServer.kind로 대상을 고른다 (Tools).

kind가리키는 것누가 서버를 띄우나쓰는 경우
RemoteMCPServerURL을 적어 둔 리소스우리 또는 외부이미 떠 있는 서버, 클러스터 밖 서버, 직접 Deployment로 관리하는 서버
MCPServerkmcp 리소스kmcp controller클러스터 안에서 image나 package로 띄울 서버
ServiceMCP용 표시가 붙은 Kubernetes Service우리기존 Service를 리소스 추가 없이 연결할 때. 이름만 알아 둔다

어느 쪽이든 Agent Pod는 결국 URL 하나로 MCP 서버에 접속한다. MCPServer를 가리키면 controller가 http://<이름>.<namespace>:<port>/mcp 주소를 만들어 넣는다(소스에서 확인).

chart가 설치하는 내장 tool(k8s_get_resources 등)도 같은 구조다. kagent-tools Deployment가 떠 있고 kagent-tool-server라는 RemoteMCPServer가 그것을 가리킨다.

# 설명용 예제
apiVersion: kagent.dev/v1alpha2
kind: RemoteMCPServer
metadata:
name: wiki-search
namespace: agents
spec:
description: 사내 위키 검색 MCP 서버
protocol: STREAMABLE_HTTP
url: https://wiki-mcp.example.com/mcp
timeout: 30s
tls:
caCertSecretRef: corp-ca
caCertSecretKey: ca.crt

protocol은 STREAMABLE_HTTP(기본) 또는 SSE다. tls는 ModelConfig와 같은 구조로 사내 CA를 지정한다(API reference).

MCP 서버 하나가 tool을 스무 개 제공해도 Agent는 toolNames에 적힌 것만 받는다.

# 발췌
tools:
- type: McpServer
mcpServer:
name: portal-api-mcp
kind: MCPServer
toolNames:
- get_my_leave_requests
- create_leave_request
requireApproval:
- create_leave_request
  • toolNames는 allowlist다. 서버에 tool이 추가되어도 Agent의 능력은 PR 없이 늘지 않는다.
  • requireApproval은 toolNames 중 사람 승인이 필요한 것을 고른다(Agent의 HITL).
  • 서버가 실제로 제공하는 tool 이름은 controller가 주기적으로 조회한다. RemoteMCPServer는 그 목록을 status에 기록하므로, toolNames를 적을 때 kubectl get remotemcpserver <이름> -o yaml로 실제 이름과 대조한다.

이 구조 덕분에 manifest의 diff가 권한 변경 내역이 된다. GitOps PR 승인 배포에서 리뷰어가 볼 핵심이 이 목록이다.

tool 호출에 header를 싣는 두 방법

섹션 제목: “tool 호출에 header를 싣는 두 방법”

MCP 서버는 대개 “누가 호출했는가”를 알아야 한다. kagent는 성격이 다른 두 필드를 준다.

headersFromallowedHeaders
값의 출처Agent와 같은 namespace의 Secret·ConfigMapAgent를 호출한 A2A 요청의 header
값이 바뀌는 단위배포할 때 고정. 모든 사용자가 같은 값요청마다. 호출한 사용자에 따라 다름
표현하는 신원Agent(서비스)의 신원호출한 사람의 신원
대표 용도MCP 서버의 API key, 고정 tenant ID임직원 토큰, 사용자 ID
# 발췌 — 두 필드의 위치가 다르다
tools:
- type: McpServer
mcpServer:
name: portal-api-mcp
kind: MCPServer
toolNames: [get_my_leave_requests]
allowedHeaders: # mcpServer 아래 — 요청에서 넘길 header 이름
- Authorization
headersFrom: # tool 아래 — 고정으로 붙일 header
- name: X-Agent-Key
valueFrom:
type: Secret
name: portal-mcp-agent-key
key: api-key

headersFrom만 쓰면 backend는 “어느 Agent가 호출했는지”만 알고 “어느 임직원을 대신했는지”는 모른다. 그 Agent를 쓰는 모든 사람이 같은 권한으로 backend를 부르게 된다. 임직원별 권한이 필요하면 allowedHeaders가 필요하고, 그 전체 경로는 임직원 토큰 전파에서 다룬다.

같은 이름의 header가 겹치면 headersFrom의 고정값이 이긴다(Go runtime 소스에서 확인). 그러므로 Authorization을 임직원 토큰으로 전파하려면 같은 tool의 headersFrom에 Authorization을 두지 않는다.

Agent는 다른 Agent를 tool로 부를 수 있다. 전문 Agent를 따로 만들고 coordinator Agent가 일을 나누는 구조다.

# 발췌
tools:
- type: Agent
agent:
name: policy-search
isolateSessions: true

기본적으로 같은 sub-agent에 대한 호출은 session 하나를 공유한다. coordinator가 같은 sub-agent를 병렬로 여러 번 부르면 서로 간섭하므로, 그때 isolateSessions: true로 호출마다 새 session을 준다 (Per-call session isolation). 이 flag는 Go runtime에서만 동작한다(소스에서 확인).

팀마다 namespace를 나누면 공용 tool 서버를 namespace마다 복제하고 싶지 않다. mcpServer.namespace로 다른 namespace의 서버를 가리킬 수 있다 (Cross-namespace tool references).

단, 가리키는 쪽이 아니라 가리켜지는 쪽이 허용해야 한다. RemoteMCPServer와 Agent에는 allowedNamespaces가 있고, 지정하지 않으면 같은 namespace의 Agent만 참조할 수 있다. Gateway API의 cross-namespace 방식과 같다. 아무 namespace의 Agent나 민감한 tool 서버를 끌어다 쓰는 일을 막는 장치다.

기능무엇인가언제 필요한가
kagent.dev/discovery=disabled labelMCPServer를 kagent의 자동 발견에서 뺀다MCP 서버 앞에 gateway를 두고 그 gateway만 tool 서버로 등록할 때
proxy.url (Helm)Agent → Agent, Agent → MCP 트래픽을 지정한 proxy로 보낸다모든 tool 트래픽을 gateway에서 통제·기록할 때
MCP Appstool이 돌려준 UI를 kagent 채팅에 widget으로 그린다kagent UI를 최종 사용자 화면으로 쓸 때만
  • MCP 서버에 delete_everything tool이 새로 추가됐다. toolNames에 두 개만 적어 둔 Agent는 이 tool을 쓸 수 있는가? → 없다. allowlist에 없는 tool은 Agent에 주어지지 않는다.
  • headersFrom으로 Authorization에 서비스 계정 토큰을 넣고 allowedHeaders에도 Authorization을 적었다. MCP 서버가 받는 값은? → headersFrom의 고정값이다. 임직원 토큰은 덮어써진다.