튜토리얼
AI Agent Skills vs MCP vs Plugins: 2026년 개발자는 무엇을 써야 하나. 발견부터 JSON Schema까지
「어느 것을 고를까」라고 묻지 마라. 내는 것이 설명서인지, 손인지, 함께 가야 하는 상자인지 먼저 물어라.
어제 Google Agent Plugins 2026은 상자 모양을 봤다. 오늘은 리뷰에서 가장 잘못 묻는 문장에 답한다. 「Skills, MCP, Plugins, 뭘 쓰지?」 틀렸다. 셋은 경쟁 제품이 아니다. Skill은 모델이 읽는 설명서이고 형식은 Agent Skills. MCP는 런타임이 쓰는 손이고 프로토콜은 MCP란. Plugin은 2026년 8월의 포장 형식이고 규격은 Agent Plugins 1.0.0. Google도 썼다. 단일 Skill, 단일 MCP, 단일 클라이언트는 상자에 넣지 마라. 이 글은 발견과 JSON Schema로 결정 나무를 걷고 MCP와 JSON Schema 검증 사슬로 넘긴다. Cloud 표본은 google-cloud-developer.
질문이 틀렸다: 같은 층의 라이벌이 아니다
리뷰에서 흔한 실패는 카드 세 장을 펼쳐 한 표를 던지는 것이다. Skill은 tools/list를 내지 않고 tools/call도 받지 않는다. 디렉터리와 SKILL.md다. 시작 때는 name과 description만 맥락에 들어간다(대략 백 토큰). 본문과 scripts/, references/는 필요할 때 읽는다. JSON-RPC도 핸드셰이크도, 선상의 「스킬 입력 Schema」도 없다. MCP는 반대다. 맞은편은 프로세스나 HTTP 끝점이고 인자는 검증 가능한 JSON이어야 한다. Plugin은 둘 다 하지 않는다. 디렉터리와 닫힌 Manifest 두 장만 정한다. Plugin을 「더 강한 MCP」로 보는 것은 종이 상자를 엔진으로 보는 것이다.
발견도 한 길이 아니다. Skill의 발견면은 설명 문자열이다. 「무엇을 + 언제」를 쓰지 않으면 모델이 고르지 않는다. MCP의 발견면은 tools/list의 이름과 inputSchema. Plugin의 발견면은 루트 plugin.json이고 그다음 고정 skills/와 mcp.json. 셋은 겹칠 수 있다. 클라이언트는 상자를 보고, 스킬 메타를 보고, MCP 도구 목록을 얻는다. 겹친다고 대체되는 것은 아니다. 손이 없을 때 더 긴 Skill을 쓰면 모델이 셸로 API를 흉내 내길 거는 것이다. 환각이지 통합이 아니다.
옆 위임도 이 세 장에 없다. 다른 Agent를 어떻게 찾고 Task를 넘기는지는 A2A Agent Card다. A2A vs MCP를 보라. 오늘 정하는 것은 이 저장소에 설명서가 필요한지, 손이 필요한지, 둘을 하나의 이식 디렉터리에 잠글지다. 층을 먼저 나누고 그다음 고른다.
| 고르는 것 | 무엇을 푸나 | 발견면 |
|---|---|---|
| Skill | 재사용 가능한 흐름, 형식, 가드레일. 선택적 로컬 스크립트 | SKILL.md의 name / description |
| MCP Server | 살아있는 계(DB, API, 클라우드)에 대한 확정적 호출 | tools/list + inputSchema |
| Plugin | 클라이언트가 바뀌어도 Skill과 MCP가 갈라지지 않게 | plugin.json, 그다음 고정 디렉터리 |
네 질문으로 결정 나무를 걷는다
선택지를 네 물음으로 접는다. 순서대로 답하고 건너뛰지 마라. 첫째, 모델이 저장소 밖 살아있는 계를 만져야 하는가. 데이터베이스, 공식 문서 검색, 결제 API, gcloud. 필요하면 최소한 MCP(또는 이미 있는 네이티브 도구, 예: 로컬 gh). 아니면 「전문적으로 보이게」 빈 Server를 세우지 마라. 둘째, 「먼저 프로젝트를 보고, 그다음 billing, 키를 git에 넣지 마라」 같은 흐름을 세션을 넘어 남기고 싶은가. 필요하면 Skill을 써라. 시스템 프롬프트에 붙인 한 단락은 창이 줄어들면 사라진다.
셋째, 첫째와 둘째가 함께 배포되어야 하는가. 인보이스를 조회하는 MCP는 주간 보고 Skill이 없으면 오용된다. 주간 보고 Skill은 MCP가 없으면 가짜 데이터로만 시연한다. 함께 갈 때만 Plugin을 생각해라. 넷째, 클라이언트가 둘 이상인가. Cursor, Claude Code, Antigravity, Codex. IDE 하나이고 이미 네이티브 MCP / Skills 설치가 있으면 네이티브 설정이 더 짧다. Google은 Developers Blog에서 이것을 못 박았다. Plugin이 값을 갖는 때는 부품이 같은 목표에 속하고 함께 여행해야 할 때다.
아래는 저장소에 넣을 수 있는 결정 기록이다. 규격 필드가 아니다. 리뷰가 남기는 JSON 픽스처다. 네 답, 선택, 상자에 넣을 컴포넌트 이름. 먼저 parse되게 하고 CI에서 choice가 네 질문과 싸우지 않는지 단언하라. mustTravelTogether가 false인데 plugin이면 너무 이른 포장이다.
{
"task": "weekly-invoice-summary",
"needRuntimeTools": true,
"needReusableBrief": true,
"mustTravelTogether": true,
"clients": ["cursor", "claude-code", "antigravity"],
"choice": "plugin",
"components": [
"skill:write-weekly-summary",
"mcp:invoice-tools"
]
}
Skill만: 발견은 description, tools/call은 없다
Skill이 이기는 것은 셋이다. 핸드셰이크 없음, 필요할 때 읽음, 사람이 diff할 수 있음. 시작 때는 메타만 넣는다. 모델은 description의 방아쇠에 맞은 뒤에 본문을 읽는다. 그래서 설명은 「무엇을」와 「언제」를 함께 쓰고, 3인칭, 키워드, 길이 상한이 있다(name 64, description 1024). 내부 코드명이나 1인칭 구호는 발견면이 0이다. 형식의 원본은 Agent Skills. Plugins는 skills/<name>/SKILL.md에 둔다는 것만 정한다.
Skill은 scripts/를 가질 수 있다. 새 MCP 도구가 아니다. 「이미 있는 셸로 이것을 실행하라」다. 로컬 CLI에 맞다. gh, gcloud, 자체 lint.sh. 스크립트는 확정 계산을 프로세스 밖에 두고 요약만 맥락으로 돌려준다. 그래도 전송 층이 아니다. OAuth 발견도 inputSchema도 없다. 인자 검증은 모델과 스크립트 argv의 일이다. 안정적인 JSON 입력이나 원격 인증이 필요하면 스크립트를 MCP로 가장하지 마라.
Skill만의 전형은 출력 형식(PR 본문, 사고 보고), 로컬 CLI 흐름, 영역 가드레일(「먼저 이 checklist를 읽어라」). 반례는 「프로덕션 DB를 조회하라」를 Skill로 쓰고 모델에게 SQL을 만들어 일반 셸에 넣는 것이다. 설명서가 손인 척한다. 발견 단계에서 인자 모양도 검증할 수 없다. Schema가 없다.
MCP만: 발견은 tools/list, 계약은 inputSchema
MCP가 이기는 것은 Skill이 줄 수 없는 셋이다. 살아있는 연결, 구조화된 입력, 실패 경계. 클라이언트가 붙고 tools/list가 이름과 inputSchema를 주고 모델이 arguments를 채우며 런타임이 tools/call한다. 통과하는지는 JSON Schema의 일이지 「모델이 자신 있어 보여서」가 아니다. 인증, 할당, 전송 버전은 MCP 규격. 2026-07-28 무상태 판은 평범한 HTTP 로드밸런서 뒤에 둘 수 있다. Skill은 그 어떤 층도 못 한다.
클라이언트 하나, Server 하나면 그 클라이언트의 네이티브 MCP 설정을 먼저 써라. Plugin을 먼저 만들지 마라. mcp.json은 Agent Plugins의 이식 가능한 쓰기이고 필드가 Cursor나 Gemini CLI 방언과 같을 필요는 없다. 클라이언트가 옮긴다. IDE 하나면 매핑 층은 잉여다. 두 번째 클라이언트가 나타나면 같은 연결을 루트 mcp.json에 넣고 plugin.json을 더한다. skills/는 아직 없어도 된다. 없는 위치는 오류가 아니다. 규격은 건너뛰라고 한다.
여기 발견 사슬은 짧다. 연결 → tools/list → inputSchema로 채운다. OpenAPI 전체를 MCP Client에 도구 목록으로 던지지 마라. Plugin Manifest 필드를 inputSchema에 복사하지 마라. 포장 계약은 「상자가 있는가」에 답한다. 도구 계약은 「이 hop의 arguments가 합법인가」에 답한다. 둘 다 JSON Schema지만 층이 하나 다르다. 아래는 「MCP만 먼저 내고 아직 상자 안 함」일 때 적어 둘 수 있는 이식 조각이다. 상자에 넣으면 플러그인 루트에 그대로 둔다.
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
"mcpServers": {
"invoice-tools": {
"type": "stdio",
"command": "./bin/invoice-mcp",
"args": ["--data", "${PLUGIN_DATA}/invoices"],
"cwd": "${PLUGIN_ROOT}"
}
}
}
언제 상자인가: 여러 컴포넌트, 여러 클라이언트일 때
Plugin이 값을 갖는 때는 결정 나무 셋째와 넷째가 동시에 켜질 때다. 전형은 숫자를 조회하는 MCP와 사람용 주간 보고를 쓰는 Skill. 또는 Google 조합——gcloud 가드레일 스킬과 Developer Knowledge MCP. 한쪽이 없으면 오용된다. 손만 있으면 주간 보고를 지어낸다. 설명서만 있으면 접지된 문서 검색이 없다. 상자에 넣은 뒤 Antigravity, Claude Code, Codex에서 디렉터리가 갈라지지 않는다. plugin.json은 닫혀 있고 mcp.json은 따로, 비밀은 환경 변수이며 headers에 쓰지 않는다.
너무 이른 포장의 대가는 유지할 Manifest가 늘고 「Plugin이 있다」는 환각이다. 상자는 Skill을 도구로 만들지 않고 MCP에 설명서를 주지 않는다. 독립 컴포넌트는 독립적으로 실패한다. mcp.json의 한 대가 안 떠도 스킬은 남는다. 어떤 SKILL.md frontmatter가 깨져도 나머지 스킬과 MCP는 올라간다. 규격이지 슬로건이 아니다. CI가 「알 수 없는 최상위 필드 하나」로 패키지 전체를 거절하면 클라이언트보다 엄하다. 스스로 알라.
A2A 경계를 다시 긋는다. Plugin이 답하는 것은 「이 Agent가 한 묶음 스킬과 도구를 어떻게 얻는가」. 다른 팀의 인보이스 Agent를 어떻게 찾는지는 Agent Card이지 상대를 mcp.json의 도구 하나에 넣는 것이 아니다. 여러 턴의 확인과 비동기 콜백이 함수 호출 모양을 찢는다. 순서는 한 문장. 먼저 손, 그다음 설명서, 마지막이 상자. 손이 없는데 Plugin을 먼저 만드는 것은 팔 물건을 정하기 전에 종이 상자를 주문하는 것이다.
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "reports-plugin",
"version": "1.0.0",
"description": "Invoice MCP plus the weekly-summary skill, shipped together"
}
| 장면 | 기본 선택 | 하지 마라 |
|---|---|---|
| PR 본문 형식, 사고 보고 템플릿 | Skill만 | 빈 MCP Server를 세운다 |
| IDE 하나만을 위한 인보이스 조회 API | 그 IDE의 네이티브 MCP 설정 | Plugin을 먼저 만들고 한 클라이언트로 되돌린다 |
| 조회 MCP + 주간 보고 Skill을 클라이언트 셋에 | Plugin(plugin.json + skills/ + mcp.json) | 원격 Agent 전체를 도구 하나에 넣는다 |
Schema 셋, 발견 셋을 JSONVue로 본다
계약을 hop으로 펼친다. 첫째는 plugin.schema.json. 상자를 발견할 수 있는가. $schema는 https://agent-plugins.org/schemas/1.0.0/plugin.schema.json에 고정. 둘째는 mcp.schema.json. 어떻게 붙는가. type은 명시. 셋째는 각 도구의 inputSchema. arguments가 통과하는가. Skill frontmatter는 YAML이지 이 셋이 아니다. SKILL.md 전체를 JSON Schema로 「검증」하지 마라. 발견은 첫째와 둘째, 호출은 셋째.
리뷰 픽스처는 적어도 다섯. 위의 결정 기록, 합법 plugin.json, 최상위 필드를 하나 더한 Manifest, 이식 가능한 mcp.json, 실제 tools/call arguments. 기록은 네 질문과 choice의 싸움을 잡는다. Manifest는 포장 계약. arguments는 도구 계약. Developer Knowledge API 키는 클라이언트 런타임 이야기다. git에서 보는 mcp.json에 비밀을 넣지 마라.
브라우저면 된다.JSON 포맷으로 결정 기록과 Manifest 둘이 parse되는지 보고,JSON Schema 검증으로 $schema, name, mcpServers, inputSchema를 보고,JSON Diff로 이식 mcp.json과 클라이언트 네이티브보내기를 비교한다. 데이터는 이 기기를 떠나지 않는다. 이어서MCP와 JSON Schema, Plugins 총람, A2A와 MCP의 분업.
관련: Google Agent Plugins 2026, MCP와 JSON Schema, MCP란, A2A vs MCP.
자주 묻는 질문 FAQ
Skill 안의 스크립트가 MCP를 대신할 수 있나?
로컬 CLI가 있고 인자가 argv이며 원격 인증 발견이 필요 없으면 된다. 안정적인 JSON 입력, OAuth, 기계를 넘는 HTTP 도구가 필요하면 안 된다. 스크립트는 Skill의 첨부이지 tools/list의 일등 도구가 아니다.
MCP만 있고 Skill이 없다. Plugin을 만들어야 하나?
클라이언트 하나: 만들지 말고 네이티브 설정을 써라. 둘 이상이고 같은 연결 설명을 공유하고 싶다: mcp.json만 있는 Plugin은 합법이고 skills/는 없어도 된다. 트리를 예쁘게 보이려고 빈 Skill을 넣지 마라.
Plugin이 MCP나 Skills를 대체하나?
하지 않는다. 1.0이 인정하는 컴포넌트는 이 둘뿐이고 설치, 권한, 샌드박스는 정의하지 않는다. 대체하는 것은 「각 클라이언트가 자기 포장을 발명하는 일」이다. 실행 계약은 여전히 MCP와 Agent Skills.
JSON Schema 셋을 한 파일로 합칠 수 있나?
업무 필드는 하나의 canonical Schema에 두고 MCP inputSchema를 생성해도 된다. plugin.json 필드와 도구 arguments를 「범용 검증」 한 파일에 넣지 마라. 발견 실패와 호출 실패의 처리가 다르다.
요약과 다음 단계
2026년 Skills, MCP, Plugins 선택은 한 문장으로 접힌다. 손이 필요한가, 설명서가 필요한가, 둘은 함께 가야 하는가, 클라이언트는 여럿인가. 삼택이 아니다. 층을 겹친다.
내는 순서: 네 답을 결정 기록 JSON으로 쓴다. 손이 필요하면 먼저 inputSchema. 설명서가 필요하면 먼저 description. 둘 다 켜지고 클라이언트를 넘으면 plugin.json을 더한다. 세 계약은 JSONVue에서 본다. 상자 모양은 Plugins 총람. 선 프로토콜은 MCP 글. Agent 횡단은 A2A 글.