오늘도 공부
구글 Connected Apps Platform 완전 분석: MCP로 Gemini와 검색에 내 앱 연결하기 본문
공식 발표 2026.10.28 · 내용 확인 2026.10.29 · 개발자 관점 해설

검색과 대화에서 외부 앱의 기능으로 이어지는 사용자 경험 · 출처: Google
구글이 이번에 발표한 Connected Apps Platform(커넥티드 앱 플랫폼)은 단순한 앱 연결 기능이 아닙니다. 앞으로 AI 에이전트가 외부 앱의 데이터를 읽고, 실제 기능을 실행할 수 있도록 만드는 통합 앱 연결 플랫폼입니다.
특히 개발자 관점에서는 상당히 중요한 발표입니다. 구글이 MCP(Model Context Protocol)를 공식적인 앱 통합 방식으로 채택하고, 개발자가 만든 서비스를 Gemini와 Google 검색에 연결할 수 있는 경로를 제공하기 시작했기 때문입니다.
1. 무엇을 발표한 것인가?
핵심은 한 문장입니다.
"개발자가 자신의 앱을 한 번 연결하면, 사용자가 Gemini나 Google 검색에서 대화만으로 그 앱을 이용할 수 있게 하겠다."
예를 들어 지금까지는 사용자가 어떤 작업을 수행하려면 서비스에 직접 방문해야 했습니다.
그림 1. 대화가 앱의 기능으로 이어지는 구조
| 사용자 요청 “내 운동 목표에 맞는 수업을 찾아 줘.” |
| ↓ |
| Gemini / Google Search 요청 해석 · 사용할 서비스와 도구 선택 |
| ↓ |
| Connected Apps Platform MCP 연결 · 계정 인증 · 허용된 범위의 실행 |
| ↓ |
| 앱의 기능 운동 수업 조회 · 예약 서비스 연결 · 결과 반환 |
공식 발표를 바탕으로 재구성한 개념도. 앱·제품·지역별 지원 범위는 다릅니다.
즉, AI가 설명만 해주는 단계를 넘어 실제 서비스의 기능을 사용하는 단계로 확장되는 것입니다.
구글의 발표에는 중요한 요소 네 가지가 있습니다.
- 통합 개발 플랫폼: 하나의 연동을 Gemini와 Search에서 재사용
- MCP 공식 지원: 기존 MCP 서버를 활용한 서비스 기능 노출
- Android AppFunctions 지원: 안드로이드 앱의 기능을 기기 안에서 호출
- Google Connected Console: 앱 등록, 테스트, 심사, 운영 지표를 한곳에서 관리
다만 2026년 10월 29일 현재 개발 플랫폼은 프리뷰 단계입니다. 모든 개발자와 모든 국가에 즉시 개방된 상태는 아닙니다.
2. 실제로 어떤 일을 할 수 있을까?
구글에 따르면 Gemini와 Search를 합쳐 이미 50개 이상의 Connected Apps가 제공되고 있습니다.
이번 발표에서 언급된 서비스들을 보면 구글이 어떤 방향으로 가려는지 명확해집니다.
Adobe — 디자인·이미지 작업
Gemini에서 Adobe 계열 도구의 기능을 활용해 디자인이나 이미지 작업을 진행합니다. 현재 Gemini 연동을 지원하며 영어 사용 조건이 있습니다.
Peloton — 운동 수업
운동 수업을 검색하거나 예약하고 여러 날에 걸친 훈련 계획을 만들 수 있습니다.
Experian — 신용 정보
미국의 FICO 신용점수와 신용보고서에 영향을 주는 요소를 조회할 수 있습니다.
Localiza — 렌터카
브라질 렌터카를 검색하고 차량별 가격을 비교한 뒤 예약을 완료할 수 있도록 서비스로 연결합니다.
Calm — 명상·휴식
새로 발표된 연동 파트너입니다. Gemini와 Search 양쪽에서의 연결이 예정되어 있으며, 발표 시점에는 출시 예정 상태입니다.
각 앱의 지원 기능과 국가 조건은 서로 다릅니다.
검색창 자체가 앱의 입구가 된다
예를 들어 미국의 Google 검색 AI 모드에서는 다음과 같은 작업이 지원됩니다.
| 사용자의 요청 | 연결되는 서비스 | 결과 |
| "8명에게 줄 건강 간식 장바구니 만들어 줘" | Instacart | 쇼핑 장바구니 구성 |
| "복고풍 플리마켓 전단지 디자인해 줘" | Canva | 디자인 초안 제작 |
| "최근 10년간 인기 있었던 노래로 플레이리스트 만들어 줘" | YouTube Music | 음악 목록 생성 |
쇼핑 결제나 최종 디자인 수정처럼 특정 작업은 해당 앱으로 이동해 완료해야 할 수도 있습니다. 모든 과정을 Gemini 안에서 끝낸다는 뜻은 아닙니다.
이 점이 중요한 이유는 사용자가 서비스를 찾아가는 대신, 서비스가 사용자의 요청을 처리하는 도구로 선택될 수 있기 때문입니다.
3. 핵심 기술은 두 가지: MCP 서버와 Android MCP
구글은 앱을 연결하는 방법을 크게 두 가지로 나눴습니다.
| 클라우드 MCP 서버 | Android MCP · AppFunctions |
| Gemini / Search ↓ HTTPS · MCP 서비스의 MCP 서버 ↓ 기존 API · 데이터베이스 |
허가된 Android 에이전트 ↓ Android 기능 레지스트리 앱이 공개한 함수 ↓ 기기 내부 데이터 · 앱 상태 |
| 웹·iOS·Android 공통 백엔드 기능 | Android 기기와 긴밀하게 연결된 기능 |
그림 2. 서로 보완하는 두 가지 연결 경로. Android MCP가 그대로 Search에서도 실행된다는 의미는 아닙니다.
A. MCP 서버 방식
개발자라면 이 방법이 가장 직접적입니다.
예를 들어 내가 쇼핑몰을 운영 중이라고 가정하겠습니다. 기존에는 다음 API가 있습니다.
GET /api/products
GET /api/orders
POST /api/cart
이 API들을 MCP 서버의 도구로 제공할 수 있습니다.
@mcp.tool()
def search_products(query: str):
"""상품을 검색합니다."""
return product_service.search(query)
@mcp.tool()
def get_my_orders():
"""현재 인증된 사용자의 주문 내역을 조회합니다."""
return order_service.list_current_user()
@mcp.tool()
def add_to_cart(product_id: str, quantity: int):
"""지정한 상품을 장바구니에 추가합니다."""
return cart_service.add(product_id, quantity)
작동 원리를 설명하기 위한 단순화한 Python 예제입니다. 실제 배포에는 MCP 초기화, 인증, 스키마 및 보안 설정 등이 필요합니다.
이렇게 연결하면 Gemini가 사용자의 요청을 이해하고 적절한 도구를 선택할 수 있습니다.
그림 3. “지난번 커피를 다시 담아 줘”의 실행 순서
| ① 요청 해석 과거 주문에서 커피 상품을 찾아야 한다고 판단 |
| ↓ |
| ② 주문 내역 조회 get_my_orders() |
| ↓ |
| ③ 상품 확인 주문 결과의 실제 상품 ID 사용 후보가 여러 개라면 사용자에게 확인 |
| ↓ |
| ④ 장바구니 변경 add_to_cart(product_id, 1) |
| ↓ |
| ⑤ 실행 결과 전달 서버가 성공을 반환한 뒤 사용자에게 안내 |
설명을 위한 가상 시나리오. AI가 상품 ID나 성공 여부를 만들어 내면 안 됩니다.
여기서 AI는 상품 정보를 직접 보관하거나 주문 시스템을 직접 구현하는 것이 아닙니다. 기존 서비스의 백엔드를 MCP를 통해 호출하는 역할을 합니다.
공식 개발 가이드는 MCP 서버를 크로스플랫폼 통합의 기본 권장 경로로 설명합니다.
B. Android MCP(AppFunctions) 방식
두 번째 방식은 조금 더 흥미롭습니다.
일반적인 MCP 서버는 인터넷에 연결된 서버가 필요하지만, AppFunctions는 앱의 기능을 안드로이드 운영체제 수준에서 AI에게 노출합니다.
구글이 공개한 코드 예제를 핵심만 줄이면 이런 구조입니다.
@AppFunction(isDescribedByKDoc = true)
suspend fun createTask(
title: String,
dueDateTime: LocalDateTime? = null
): Task {
// 앱 내부에서 작업 생성
}
사용자가 Gemini에 "오늘 오후 5시에 택배 찾으라고 알려 줘"라고 요청하면, 승인된 AI 호출자가 할 일 앱의 createTask()를 실행하는 방식입니다.
핵심은 앱의 화면을 억지로 조작하는 것이 아니라 앱 개발자가 공식적으로 공개한 함수를 호출한다는 것입니다.
Android 앱 개발자 입장에서는 UI 자동화보다 안정적이고 구조화된 연결 방식을 만들 수 있습니다.
다만 AppFunctions는 Android 16 이상을 대상으로 하며, 2026년 10월 기준 아직 실험적 기능입니다. 공식 문서는 Gemini 연동을 2026년 5월 기준 비공개 프리뷰로 설명하고 있습니다. 전체 연결은 제한된 테스트 단계여서 앱에 함수를 구현했다고 누구나 즉시 Gemini에서 실행할 수 있는 것은 아닙니다.
4. 개발자는 어떻게 자신의 앱을 등록할까?
구글은 앱 등록을 위한 Google Connected Console도 함께 공개했습니다.

Connected Apps를 등록하고 테스트하는 관리 화면 · 출처: Google
이것은 일종의 AI 에이전트용 개발자 콘솔입니다. 일반 앱스토어처럼 APK를 업로드하는 구조가 아니라, 개발자가 구현한 MCP 도구를 등록하고 테스트한 후 심사를 받는 방식입니다.
공식 문서를 기준으로 실제 등록 절차를 정리하면 다음과 같습니다.
| 단계 | 개발자가 하는 일 |
| 1. MCP 개발 | 기존 API를 MCP 도구로 구현 |
| 2. 서버 배포 | 공개 HTTPS 주소에 MCP 서버 배포 |
| 3. 앱 등록 | Connected Console에서 이름·카테고리·아이콘 설정 |
| 4. 인증 연결 | 도메인 소유권 확인 및 OAuth 설정 |
| 5. 도구 동기화 | MCP 도구 목록과 스키마 등록 |
| 6. 테스트 | Gemini Developer Mode와 테스트 계정으로 검증 |
| 7. 심사 | Google에 앱 검토 요청 |
| 8. 출시 | 승인 후 Gemini, Search 또는 양쪽에 공개 |
| 9. 운영 | 트래픽·응답 지연·오류율 확인 |
MCP 서버에 필요한 기술 조건
공식 개발 문서에는 생각보다 구체적인 요구사항이 있습니다.
| 항목 | 요구사항 |
| 서버 주소 | 외부에서 접근 가능한 HTTPS |
| MCP 전송 | Streamable HTTP |
| MCP 프로토콜 | 최대 2025-11-25 버전 지원 |
| 인증 | 사용자별 OAuth 또는 지원되는 서비스 인증 방식 |
| 도메인 | 소유권 검증 필요 |
| 앱 등록 | Google Connected Console |
| 위험한 작업 | 사용자 확인 단계 설정 |
| UI 확장 | MCP Apps 기반 UI, 지원 범위·제약 확인 |
특히 기존 MCP의 레거시 HTTP+SSE 방식은 지원되지 않으며, Streamable HTTP를 이용해야 합니다.
계정 연결은 어떻게 할까?
가령 사용자가 Gemini와 내 서비스를 연결한다고 가정하겠습니다.
그림 4. 계정 연결과 실제 실행은 다르다
| 계정 연결 사용자가 서비스에 로그인하고 OAuth 접근 권한 승인 |
| ↓ |
| 도구 호출 Gemini가 허용된 사용자 권한으로 요청 |
| ↓ |
| 서버 검증 토큰 · 접근 범위 · 대상 데이터의 소유권 확인 |
| ↓ |
| 처리 및 응답 중요한 변경은 필요한 확인을 거쳐 실행 후 결과 반환 |
연결 동의가 모든 미래 작업의 무제한 실행 권한을 뜻하지는 않습니다.
사용자의 서비스 비밀번호를 Gemini에 직접 알려주는 방식은 아닙니다.
공식 문서는 OAuth 2.1과 PKCE를 권장합니다. 필요한 권한만 허용하고, 사용자는 나중에 계정 연결을 해제할 수 있습니다.
또한 중요한 작업을 처리하는 도구에는 확인 절차를 설정할 수 있습니다. 예를 들어 계정 삭제, 구매, 예약 변경 같은 기능은 단순 정보 조회와 구분해서 설계해야 합니다.
5. Gemini에서 직접 MCP 테스트까지 가능하다
이번 발표에서 개발자에게 특히 유용한 부분은 Gemini Apps Developer Mode입니다.
구글은 MCP 서버를 실제 Gemini 대화 환경에서 시험할 수 있는 개발자 모드를 문서화했습니다.
여기에서는 모델이 도구를 올바르게 선택하는지, JSON 파라미터를 정확하게 만드는지, 서버 응답을 제대로 해석하는지 확인할 수 있습니다.
| 디버깅 메뉴 | 기능 |
| Event Log | 도구 호출·응답과 HTTP 상태, 지연 시간 |
| Tool Schemas | 도구 설명, 파라미터, 권한 및 안전성 |
| Environment | 테스트용 날짜·시간·위치 시뮬레이션 |
| Authentication | 서버 인증 및 OAuth 연결 확인 |
더 중요한 점은 Connected Console에 정식 등록하기 전에 공개 HTTPS MCP 서버를 직접 연결해 테스트할 수도 있다는 것입니다. 다만 개발자 모드가 계정에 제공되어야 합니다.
공식 진입점: Gemini Developer Mode 열기
6. 기존 MCP나 ChatGPT 앱 연결과는 무엇이 다를까?
여기가 이번 발표의 핵심적인 의미입니다.
MCP 자체가 새로 나온 것은 아닙니다. MCP는 AI 모델이나 에이전트가 외부 도구를 이용하기 위한 개방형 프로토콜입니다.
이번에 구글이 새로 제공하는 것은 MCP 서버를 Gemini와 Google 검색이라는 대규모 사용자 접점에 연결하고, 등록·심사·운영할 수 있는 플랫폼입니다.
| 비교 | 일반 MCP 서버 | Google Connected Apps |
| 주요 역할 | AI와 외부 도구 연결 | Google 제품에 서비스 배포 |
| 개발 방식 | MCP 도구 구현 | MCP 구현 + 플랫폼 등록 |
| 사용자 접점 | 연결한 AI 클라이언트 | Gemini 및 지원되는 Google 제품 |
| 서비스 발견 | 클라이언트별 구성에 의존 | Google의 Connected Apps 기능 |
| 출시 심사 | MCP 규격 자체에는 없음 | Google 심사 필요 |
| 운영 분석 | 자체 구축하는 경우가 많음 | Console에서 기본 운영 지표 제공 |
ChatGPT의 앱·커넥터 기능과도 사용자 경험상 유사합니다. 사용자는 AI와 대화하고, AI는 외부 서비스에 접근해 작업을 수행합니다.
구글의 특징은 그 통합 대상을 Gemini에만 한정하지 않고 Search까지 확장하려는 것입니다.
왜 Google Search 연동이 중요할까?
가령 어떤 사용자가 다음과 같이 검색한다고 가정하겠습니다.
"내가 이번 주말에 참여할 수 있는 걷기 챌린지를 찾아 줘."
기존에는 검색 결과에 웹사이트들이 표시되고, 사용자가 클릭해서 가입해야 했습니다.
새로운 연결 구조에서는 지원되는 앱이 선택되어 챌린지를 검색하고, 조건을 보여주고, 사용자의 의사에 따라 가입 처리를 할 가능성이 생깁니다.
이 변화가 확산된다면 앞으로 앱의 유입 경로는 다음과 같이 바뀔 수 있습니다.
| 기존 유입 경로 | AI를 통한 추가 경로 |
| 검색 결과 → 웹사이트 방문 → 가입 · 기능 사용 |
자연어 요청 → 지원 앱 선택 → 허용된 MCP 도구 실행 |
물론 이것이 기존 검색을 대체한다는 뜻은 아닙니다. 또한 구글이 어떤 Connected App을 우선 선택하는지에 관한 상세한 랭킹 기준까지 발표한 것은 아닙니다.
하지만 개발자에게는 새로운 유입 전략이 생기는 셈입니다. 웹사이트의 검색 최적화뿐 아니라 AI가 서비스의 기능을 정확하게 이해하고 호출할 수 있도록 만드는 일이 중요해질 수 있습니다.
이 앱에서는 어떤 MCP 기능부터 만들면 좋을까?
| 도구 | 기능 | 권장 우선순위 |
| get_walking_summary | 누적 운동 기록 조회 | 높음 |
| get_badge_collection | 획득한 뱃지 목록 | 높음 |
| get_unvisited_landmarks | 미방문 명소 검색 | 높음 |
| set_next_destination | 다음 목적지 설정 | 중간 |
| join_walking_challenge | 팀·길드 챌린지 참여 | 이후 확장 |
특히 지금 구상하는 SNS 공유 중심의 초기 버전에서는 걷기 기록 조회와 뱃지 조회만 있어도 충분히 흥미로운 실험이 됩니다.
다만 운동 기록의 원본은 앱 또는 검증된 운동 데이터 시스템에서 관리해야 합니다. AI의 대화 결과를 근거로 실제 걸은 거리를 증가시키거나 뱃지를 발급하면 부정 이용 위험이 생깁니다.
또한 MCP 서버는 Google만을 위한 별도 서버로 만들기보다, 공통 비즈니스 로직 위에 표준 MCP 인터페이스를 두는 편이 좋습니다. 그러면 나중에 다른 AI 클라이언트와 연결할 때도 핵심 코드를 재사용할 수 있습니다.
8. 아직 해결되지 않은 문제들
이번 발표가 중요한 것은 맞지만, 실서비스에 적용하기 전에 확인해야 할 제약도 있습니다.
| 항목 | 2026년 10월 29일 기준 |
| 개발자 등록 | 프리뷰, 단계적 확대 |
| Google Search에서 사용 | AI Mode 미국·영어 중심 |
| Gemini에서 사용 | 앱마다 국가·언어·기기 조건이 다름 |
| 개발자 수익 배분 | 발표문에서 구체적 모델 미공개 |
| 앱 호출 우선순위 | 상세 선택·노출 기준 미공개 |
| 앱 심사 | 정식 공개 전 Google 심사 필요 |
| MCP Apps의 화면 UI | 지원 제품·여정에 따라 제한 존재 |
특히 주의할 점: MCP만 만들면 자동으로 등록되는 것은 아니다
Google Connected Console은 MCP 서버에서 가져온 도구 목록과 설명을 버전별로 저장합니다. 정식 배포 후 도구 스키마를 변경할 때는 새 앱 버전을 만들고 검토받는 절차가 필요합니다.
구글은 도구 설명을 통한 모델 조작, 다른 앱보다 자기 앱을 우선 선택하도록 유도하는 행위, 불필요한 개인정보 수집 등을 정책으로 제한하고 있습니다.
즉 MCP가 개방형 표준이라는 것과, Google이 모든 MCP 서버의 공개 배포를 허용한다는 것은 전혀 다른 이야기입니다.
9. 개발자에게 어떤 의미가 있을까?
저는 이번 발표의 의미를 크게 세 가지로 봅니다.
첫째, AI 에이전트가 앱의 또 다른 사용자 인터페이스가 됩니다.
기존에는 개발자가 사용자를 위해 화면, 메뉴, 버튼, 내비게이션을 설계했습니다. 앞으로는 사람뿐 아니라 AI 모델이 사용할 수 있도록 앱 기능의 스키마와 도구 설명도 설계해야 합니다.
둘째, 앱의 핵심 비즈니스 로직과 사용자 인터페이스의 분리가 더욱 중요해집니다.
같은 백엔드 서비스를 모바일 앱, 웹, Gemini, 다른 에이전트에 제공할 수 있도록 구성하는 방향이 유리해집니다. 이미 API 중심으로 설계된 서비스라면 상대적으로 진입하기 쉽습니다.
셋째, 검색·마케팅 환경이 달라질 가능성이 있습니다.
사용자가 어떤 앱을 설치할지 선택하기 전에 AI가 작업에 적합한 서비스를 발견할 수 있기 때문입니다. 따라서 앞으로는 '검색 결과에 잘 노출되는가'와 더불어 'AI가 내 서비스를 정확하게 이해하고 호출할 수 있는가'도 경쟁 요소가 될 수 있습니다.
다만 새로운 유입 경로가 곧바로 높은 사용자 전환율이나 매출을 보장하는 것은 아닙니다. 현재 공식 발표는 앱 연결 인프라와 파트너 확대에 초점이 맞춰져 있습니다.
10. 직접 확인할 공식 링크
Google 공식 발표 — Build and manage Connected Apps in one place
Android AppFunctions 개요 및 지원 조건
Connected Apps Platform 공식 개발자 사이트
기능 소개 및 프리뷰 신청 진입점
MCP 구현, 검증, 배포 가이드
인증, 도구 등록, 테스트 및 심사
서비스별 국가, 언어, 계정 및 지원 기능
개발자가 지금 준비할 일
이번 발표를 단순히 "Gemini에서 외부 앱을 더 많이 사용할 수 있게 됐다" 정도로 해석하면 중요한 부분을 놓치게 됩니다.
구글은 MCP를 활용해 외부 서비스가 Gemini와 Google Search의 AI 에이전트 생태계에 참여할 수 있는 공식적인 배포 경로를 만들고 있습니다.
개발자 입장에서는 앱을 새로 만들기보다 이미 운영 중인 서비스의 핵심 기능을 MCP로 잘 노출하는 전략이 중요해질 수 있습니다.
지금 당장 모든 기능을 AI에 공개할 필요는 없습니다. 기존 앱의 핵심 기능 3~5개를 독립적인 MCP 도구로 구현하고 Gemini 개발자 모드에서 검증하는 것부터 시작하면 충분합니다.
11. 실습: Android AppFunctions로 스마트폰에 MCP 기능 등록하기
Android 16 이상에서는 AppFunctions를 이용해 설치된 앱이 로컬 MCP 도구 제공자처럼 동작하도록 만들 수 있습니다. 앱의 함수를 Android OS에 공개하면, 허가된 에이전트가 그 기능을 발견하고 실행합니다.
| 구분 | 무엇을 연결하나? |
| AppFunctions · Android MCP | 내가 개발한 Android 앱의 기능을 기기 내 도구로 등록 |
| 일반적인 Remote MCP | 외부 MCP 서버의 HTTPS 주소를 지원 AI 클라이언트에 연결 |
AppFunctions는 휴대폰 설정에 MCP 서버 URL을 입력하는 기능이 아닙니다. 앱에 함수를 구현하고 메타데이터와 서비스를 함께 등록하는 개발 방식입니다. 별도 HTTP 서버를 띄우거나 포트를 열 필요는 없습니다.
11-1. 전체 구조와 준비물
그림 5. 스마트폰 안에서 AppFunctions가 실행되는 과정
| 사용자 → 허가된 에이전트 “내 메모 앱에 회의 내용을 저장해 줘.” |
| ↓ |
| Android OS · AppFunctions 레지스트리 공개된 함수 탐색 · 호출 권한 검증 · 실행 중개 |
| ↓ |
| 내 Android 앱의 서비스 createNote() · searchNotes() · getTasks() · saveTask() |
| ↓ |
| 앱 내부 코드와 저장소 실제 작업 수행 후 결과 반환 |
Gemini 연동은 아래의 별도 등록·테스트 조건을 충족해야 합니다. 앱을 설치했다고 모든 Gemini 사용자에게 도구가 자동 표시되는 것은 아닙니다.
| 항목 | 요구사항 |
| 기기 | Android 16(API 36) 이상, 해당 AppFunctions 기능 지원 확인 |
| 개발 환경 | Android Studio · Kotlin |
| 컴파일 SDK | 이 실습의 최신 라이브러리 기준 compileSdk 37 이상 |
| 대상 SDK | targetSdk 36 이상 |
| 라이브러리 | Jetpack AppFunctions 1.0.0-beta01 |
| 코드 생성 | 프로젝트 Kotlin 환경과 호환되는 KSP 플러그인 |
| 로컬 테스트 | ADB 또는 공식 AppFunctions Testing Agent |
| Gemini 연동 | Connected Console 접근 권한 · 연결할 Play 앱 · 테스터 설정 |
버전 기준: 2026년 10월 29일. 최신 릴리스는 10월 21일 공개된 1.0.0-beta01입니다. @AppFunction은 alpha13에서 @AppFunctionDeclaration으로 바뀌었고, beta01에서는 isDescribedByKDoc을 명시해야 합니다. 앱 메타데이터 속성도 description 대신 instructions를 사용합니다.
앞 절의 @AppFunction 코드는 공식 개요 문서에 남아 있는 구버전 표현입니다. 새 프로젝트를 작성할 때는 아래 최신 표기를 기준으로 맞추세요. 공식 릴리스 노트
11-2. Android Studio에서 배터리 조회 도구 만들기
첫 예제는 getBatteryLevel()입니다. 앱이 휴대폰 배터리 잔량을 정수로 반환하도록 만들고, OS 등록과 실행부터 확인합니다. 아래 코드는 기존 Android 앱에 추가하는 핵심 구성으로, 이 글에서 실기기 빌드·실행까지 검증한 완성 프로젝트는 아닙니다.
STEP 1 — Gradle 설정
app/build.gradle.kts에 다음 설정을 적용합니다. 프로젝트 저장소에는 google()이 필요합니다.
plugins {
// 기존 Android / Kotlin 플러그인 설정 유지
id("com.google.devtools.ksp")
}
android {
compileSdk = 37
defaultConfig {
targetSdk = 36
}
}
dependencies {
implementation(
"androidx.appfunctions:appfunctions:1.0.0-beta01"
)
ksp(
"androidx.appfunctions:appfunctions-compiler:1.0.0-beta01"
)
}
KSP 플러그인 버전은 루트 프로젝트 또는 버전 카탈로그에서 지정해야 합니다. 위 블록만으로 플러그인 버전이 설정되지는 않습니다. 프로젝트의 Kotlin·Gradle 환경에 맞는 버전을 선택하세요. 아래 서비스 예제는 Kotlin Coroutines를 사용하므로 해당 의존성도 프로젝트에 준비되어 있어야 합니다.
STEP 2 — 기능 구현
BasePhoneMcpService.kt를 생성합니다. 공식 구현 가이드에 맞춰 suspend와 백그라운드 디스패처를 사용합니다.
package com.example.phonemcp
import android.content.Context
import android.os.BatteryManager
import androidx.annotation.RequiresApi
import androidx.appfunctions.AppFunctionDeclaration
import androidx.appfunctions.AppFunctionService
import androidx.appfunctions.AppFunctionServiceEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@RequiresApi(36)
@AppFunctionServiceEntryPoint(
serviceName = "PhoneMcpService",
appFunctionXmlFileName = "phone_mcp_service"
)
abstract class BasePhoneMcpService : AppFunctionService() {
/**
* Returns the battery percentage of this Android phone.
*
* @return A value from 0 to 100, or -1 if unavailable.
*/
@AppFunctionDeclaration(isDescribedByKDoc = true)
suspend fun getBatteryLevel(): Int =
withContext(Dispatchers.IO) {
val manager = getSystemService(
Context.BATTERY_SERVICE
) as? BatteryManager
val level = manager?.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CAPACITY
) ?: -1
if (level in 0..100) level else -1
}
}
@AppFunctionDeclaration이 붙은 함수의 설명과 타입을 KSP가 메타데이터로 생성합니다. 반환값 -1은 배터리를 조회하지 못했다는 뜻이며, 에이전트가 이를 실제 배터리 비율로 해석하지 않도록 KDoc에 명시했습니다.
STEP 3 — Manifest 등록
AndroidManifest.xml의 <application> 안에 추가합니다.
<service
android:name=".PhoneMcpService"
android:permission="android.permission.BIND_APP_FUNCTION_SERVICE"
android:exported="true">
<property
android:name="android.app.appfunctions.schema"
android:value="app_functions_schema.xsd" />
<property
android:name="android.app.appfunctions.v2"
android:value="phone_mcp_service.xml" />
<intent-filter>
<action
android:name="android.app.appfunctions.AppFunctionService" />
</intent-filter>
</service>
<property
android:name="android.app.appfunctions.app_metadata"
android:resource="@xml/app_metadata" />
PhoneMcpService는 KSP가 생성하는 구체 서비스 클래스입니다. 직접 작성한 추상 클래스는 BasePhoneMcpService이며, 두 이름의 역할이 다릅니다. phone_mcp_service.xml은 appFunctionXmlFileName과 일치해야 합니다.
STEP 4 — 앱 메타데이터
res/xml/app_metadata.xml을 생성합니다.
| <?xml version="1.0" encoding="utf-8"?> <AppFunctionAppMetadata xmlns:appfn="http://schemas.android.com/apk/androidx.appfunctions" appfn:instructions="This app provides phone battery information. Use getBatteryLevel to read the current battery percentage. A result of -1 means the battery level is unavailable." /> |
서비스 클래스·Manifest·메타데이터를 설정한 뒤 Gradle 동기화와 빌드를 수행합니다. 생성된 서비스나 XML을 찾지 못하면 KSP 적용 여부와 파일명 일치부터 확인하세요. 공식 구현·설정 가이드
11-3. 실제 스마트폰에 설치하고 등록 확인하기
휴대폰의 개발자 옵션에서 USB 디버깅을 켜고 PC 또는 Mac과 연결합니다. Android Studio에서 앱을 설치한 뒤 터미널에서 다음 명령을 실행합니다.
adb devices
# Android API 수준 확인: 36 = Android 16, 37 = Android 17
adb shell getprop ro.build.version.sdk
# 이 기기에서 제공되는 AppFunctions 명령 확인
adb shell cmd app_function help
# 등록된 함수 목록
adb shell cmd app_function list-app-functions
# 내 앱의 함수만 확인
adb shell cmd app_function list-app-functions \
| grep -A 10 com.example.phonemcp
이 예제의 함수 식별자는 보통 com.example.phonemcp.BasePhoneMcpService#getBatteryLevel 형태입니다. 실행 전에는 목록에 표시된 실제 식별자를 확인해 사용하세요.
adb shell "cmd app_function execute-app-function \
--package com.example.phonemcp \
--function 'com.example.phonemcp.BasePhoneMcpService#getBatteryLevel' \
--parameters '{}'"
정상적으로 호출되면 함수 결과에 배터리 비율 정수가 포함됩니다. 목록에 나타나는 것과 실제 실행에 성공하는 것을 각각 확인해야 합니다. 기기 OS·시스템 구현에 따라 ADB 하위 명령 지원이 다를 수 있으므로, 먼저 help로 지원 명령을 확인하세요.
ADB 실행 기능을 사용할 수 없다면 공식 AppFunctions Testing Agent를 검토할 수 있습니다. 저장소 안내에 따르면 일부 API 테스트에는 권한을 높여 실행하는 run_privileged.sh 절차가 필요합니다. 일반 앱을 설치하기만 하면 모든 앱의 도구를 호출할 수 있다는 뜻은 아닙니다.
공식 샘플 저장소에는 ChatApp 예제와 Testing Agent가 함께 있습니다. android/appfunctions · AppFunctions 추가·검증 가이드
11-4. Gemini에서 사용할 수 있도록 연결하기
휴대폰 안에 함수가 등록된 상태와 Gemini가 그 함수를 사용할 수 있는 상태는 별개입니다. Connected Console에 접근할 수 있다면 아래 순서로 진행합니다.
그림 6. 로컬 개발에서 Gemini 연결까지
| ① 로컬 AppFunctions 구현·검증 앱 설치 → 등록 확인 → 함수 직접 실행 |
| ↓ |
| ② Android MCP 앱 생성 Connected Console → Create app → Connected app Android MCP 선택 → 기존 Play 앱 연결 |
| ↓ |
| ③ 앱 정보 저장 후 AAB 업로드 이름·아이콘·설명·기능·예시 명령 설정 AppFunctions가 포함된 앱 번들 업로드 |
| ↓ |
| ④ 테스트용 버전 제출 Submit connected app and continue Available to testers 상태 확인 |
| ↓ |
| ⑤ Gmail 테스터 등록·기기 테스트 등록한 계정 + 제출 버전과 일치하는 앱 빌드 Gemini에서 @앱이름 호출 |
@PhoneMcp 내 휴대폰 배터리는 몇 퍼센트야?처럼 요청할 수 있습니다. PhoneMcp는 Kotlin 클래스명이 아니라 Console에 설정한 Connected App의 표시 이름입니다.
| 확인할 항목 | 설명 |
| 앱 정보와 업로드 순서 | App details를 먼저 저장한 뒤 AAB를 업로드 |
| Play 앱 연결 | 같은 개발자 계정의 Play 앱 필요. 연결한 앱·연결 유형 변경 제약 확인 |
| 테스터 계정 | 공식 가이드는 @gmail.com 계정을 요구 |
| 기기 설치 버전 | 제출한 번들의 versionCode와 동일한 빌드 사용 |
| 기능·예시 명령 | 등록 시 각각 3개 이상 요구. 배터리 함수 하나는 로컬 실습용 |
| 일반 사용자 공개 | 테스트 후 Play 프로덕션 출시의 심사·배포 절차와 연동 |
이 실습의 배터리 조회 함수 하나만으로 공개 등록 요건까지 충족한다고 볼 수는 없습니다. 현재 계정의 접근 권한과 카테고리 요건을 확인하고, 실제 앱이 제공하는 기능과 사용자용 설명을 준비해야 합니다. Connected Console 공식 등록 가이드
11-5. 기존 MCP 서버를 스마트폰에서 쓰려는 경우
| 원하는 작업 | 적합한 방식 |
| 내가 만든 Android 앱 기능을 에이전트에서 실행 | AppFunctions · 지원되는 호출자 |
| 외부 MCP 서버를 Gemini에 연결 | Remote MCP · 지원되는 개발자 모드 또는 Connected Apps 경로 |
| 스마트폰 안에 로컬 도구 구현 | AppFunctions |
| PC의 Codex에서 스마트폰 기능 원격 실행 | 별도의 Android 브리지 앱과 인증 통신 설계 |
| 다른 회사 앱을 제한 없이 제어 | AppFunctions만으로는 불가능 |
다른 앱의 AppFunctions를 탐색·실행하는 호출자에는 EXECUTE_APP_FUNCTIONS 권한이 필요합니다. 일반 앱이 이 권한을 자유롭게 얻어 모든 설치 앱의 기능을 호출할 수 있는 구조는 아닙니다. 앱이 공개하지 않은 기능까지 임의로 만들어 호출할 수도 없습니다.
11-6. 첫 실습의 완료 기준
먼저 getBatteryLevel처럼 읽기 전용 함수 하나를 구현하고, ① 앱 빌드와 설치 ② OS의 함수 목록에 표시 ③ 실제 호출과 반환값 확인까지 마치는 것이 좋습니다. 이후 getDeviceInfo 같은 기능을 추가하고 Gemini 연결로 확장합니다.
로컬 도구 등록 성공과 Gemini 서비스 등록 성공을 따로 기록하세요. 이렇게 나누면 코드·메타데이터 문제인지, 계정·테스터·플랫폼 지원 문제인지 구별하기 쉽습니다.
