개발자
Sonny MCP Beta
Claude를 비롯해 Model Context Protocol을 지원하는 모든 AI 어시스턴트를 공개 API와 같은 범위와 경계로 워크스페이스에 연결하세요.
공개 API 가이드 읽기빠른 시작
- 01
Claude에 Sonny 추가
Claude나 Cowork에서 URL
https://www.usesonny.com/api/mcp로 사용자 지정 커넥터를 추가하세요. Sonny는 자동 클라이언트 등록을 지원하므로 복사할 클라이언트 ID나 시크릿이 없어요. - 02
워크스페이스 접근 승인
Claude가 브라우저에서 Sonny를 열어요. 로그인하고, 요청된 권한을 검토하고, 연결할 워크스페이스를 고르세요. PKCE를 사용하는 OAuth 2.1이 발급된 접근 토큰과 갱신 토큰을 승인한 범위로 제한해요.
- 03
어시스턴트에게 Sonny 사용 요청
도구가 스스로를 설명하므로 “열린 대화 목록을 보여 줘” 같은 프롬프트면 충분해요. 어시스턴트는 어떤 도구가 읽기 전용이고 어떤 도구가 파괴적인지 알 수 있어서, 좋은 클라이언트는 무언가를 바꾸기 전에 확인을 요청해요.
Claude Code
claude mcp add --transport http sonny https://www.usesonny.com/api/mcpJSON 클라이언트 구성
{
"mcpServers": {
"sonny": {
"url": "https://www.usesonny.com/api/mcp"
}
}
}API 키 호환성
클라이언트가 OAuth를 완료할 수 없다면 설정 → 개발자에서 범위 지정 키를 만들어 Authorization Bearer 헤더로 보내세요. 서버 간 통신과 기존 클라이언트를 위해 API 키도 계속 완전히 지원돼요.
"Authorization": "Bearer sonny_your_key"Sonny가 도구 호출을 안전하게 지키는 방법
- 워크스페이스 하나, 선택한 범위만
- 모든 호출은 OAuth 동의 중에 고른 워크스페이스나 API 키를 소유한 워크스페이스 안에서 실행돼요. 도구는 자격 증명에 필요한 범위가 있을 때만 작동해요.
- 정직한 도구 주석
- 읽기 전용 도구는 읽기 전용으로, 업데이트와 삭제 도구는 파괴적인 도구로 표시되어 클라이언트가 실행 전에 확인할 수 있어요.
- 같은 비즈니스 규칙
- 도구는 공개 API와 똑같은 워크플로를 실행해요. 감사 기록, 알림, 웹훅 모두 팀원이 변경한 것처럼 동작해요.
어시스턴트를 받은편지함 하나에 묶어 두기
API 키에 선택한 채널은 모든 도구 호출에 자동으로 적용돼요. API 키와 OAuth 연결은 연결된 팀원의 현재 채널 접근 권한도 따라요. 모든 채널에 접근할 수 있는 OAuth 연결이나 키라면, 워크스페이스에 제품이나 브랜드별로 여러 소스가 있는 경우가 많아요. 어시스턴트가 list_sources를 한 번 호출해 소스를 찾은 뒤 list_conversations에 sourceId를 넘기게 하면, 한 제품에 대한 질문에는 그 제품의 대화만 반환돼요. 모든 대화에도 자체 sourceId가 있어서 결과를 검증할 수 있어요.
저비용 고객 지원 루프 실행하기
- 변경 사항 찾기: 안정적인
sync피드로 시작하고, 각 페이지를 처리한 뒤 nextCursor를 저장하고, 이벤트 ID 중복을 제거하세요. 처리할 업무를 고르려면 sourceId, awaitingReply: true, snoozed: "false", compact: true로list_conversations를 호출하세요. 내부 메모가 있어도 답변하지 않은 고객 메시지가 숨겨지지 않아요. - 새 텍스트만 읽기: 바뀐 대화마다 마지막 메시지 ID나 ISO 타임스탬프를
after에 넣어list_messages를 호출하고, 이메일 HTML이 꼭 필요한 게 아니라면includeHtml: false로 설정하세요. - 이미지와 동영상 기다리기:
list_messages가readsInProgress를 반환하면nextStep의 호출을 실행하세요. 그waitSeconds가 이미지 판독과 동영상 자막이 준비될 때까지 응답을 붙잡고 있으므로 따로 대기할 필요가 없어요. - 고객 정보 불러오기:
get_conversation은identityVerified, 서명된verifiedTraits, 대화의 시작 페이지와 클라이언트 정보를 반환해요.contact.id가 있으면 그 ID를list_conversations에 넘겨 고객의 이전 대화를 불러오세요. - 필요할 때 깨우기:
message.created에 대한 소스 필터 웹훅으로 에이전트를 즉시 깨운 뒤 sync로 따라잡으세요. 안정적인 피드는 웹훅 전송과 별개로 작동해요. 웹훅 생성에는 모든 채널 자격 증명을 쓰고 소스 ID를 제한하세요. 에이전트는 소스 범위의 런타임 자격 증명을 그대로 유지해요.
도구 카탈로그
모든 공개 API 작업을 도구로 쓸 수 있어요. 각 도구 옆에 필요한 범위가 표시돼 있어요.
- get_connection_info
- Read connection access
conversations:read- get_conversation_context
- Read support context
conversations:read- list_conversation_checks
- Read conversation checks
conversations:read- record_conversation_check
- Record a conversation check
conversations:write- get_status
- Check Sonny status
conversations:read- create_conversation
- Create a conversation from a form
conversations:write- upload_attachment
- Upload a message attachment
attachments:write- list_properties
- List custom properties
contacts:read- get_contact_properties
- Read contact properties
contacts:read- set_contact_property
- Set a contact property
contacts:write- list_contact_memories
- Read customer memories
contact-memory:read- create_contact_memory
- Save a customer memory
contact-memory:write- delete_contact_memory
- Remove a customer memory
contact-memory:write- get_report
- Read a support report
reporting:read- sync
- Read workspace changes
conversations:read- batch_update_conversations
- Update conversations in a batch
conversations:write- list_members
- List members
members:read- list_teams
- List teams
members:read- list_tags
- List tags
tags:read- create_tag
- Create a tag
tags:write- get_tag
- Get a tag
tags:read- update_tag
- Update a tag
tags:write- delete_tag
- Delete a tag
tags:write- add_conversation_tag
- Add a conversation tag
conversations:write- remove_conversation_tag
- Remove a conversation tag
conversations:write- list_contacts
- List contacts
contacts:read- create_contact
- Create a contact
contacts:write- get_contact
- Get a contact
contacts:read- update_contact
- Update a contact
contacts:write- archive_contact
- Archive a contact
contacts:write- erase_contact
- Permanently erase a contact
contacts:write- list_channels
- List conversation channels
conversations:read- list_sources
- List sources
conversations:read- list_conversations
- List conversations
conversations:read- get_conversation
- Get a conversation
conversations:read- update_conversation
- Update a conversation
conversations:write- list_messages
- List messages
messages:read- create_internal_note
- Create an internal note
messages:write- edit_message
- Edit a sent reply
messages:send- send_message
- Send a reply to the customer
messages:send- list_webhooks
- List webhook endpoints
webhooks:read- create_webhook
- Create a webhook endpoint
webhooks:write- list_webhook_events
- List webhook event types
webhooks:read- update_webhook
- Update a webhook endpoint
webhooks:write- delete_webhook
- Delete a webhook endpoint
webhooks:write- test_webhook
- Queue a test event
webhooks:write- list_webhook_deliveries
- List webhook deliveries
webhooks:read- retry_webhook_delivery
- Retry a failed delivery
webhooks:write- list_kb_articles
- List knowledge base articles
kb:read- create_kb_article
- Create a knowledge base article
kb:write- get_kb_article
- Get a knowledge base article
kb:read- update_kb_article
- Update a knowledge base article
kb:write- delete_kb_article
- Delete a knowledge base article
kb:write- list_kb_categories
- List knowledge base categories
kb:read- create_kb_category
- Create a knowledge base category
kb:write- update_kb_category
- Update a knowledge base category
kb:write- delete_kb_category
- Delete a knowledge base category
kb:write- get_csat_summary
- Get CSAT scores
csat:read- list_csat_ratings
- List CSAT ratings
csat:read- get_conversation_csat
- Get a conversation's CSAT rating
csat:read- reorder_kb_articles
- Reorder knowledge base articles
kb:write- upsert_kb_article
- Sync a knowledge base article
kb:write- reorder_kb_categories
- Reorder knowledge base categories
kb:write- upsert_kb_category
- Sync a knowledge base category
kb:write- get_kb_category
- Get a knowledge base category
kb:read- get_help_center
- Get help center settings
kb:read- update_help_center
- Update help center settings
kb:write- upload_kb_media
- Upload a help center image
kb:write- list_kb_audiences
- List audiences
kb:read- create_kb_audience
- Create audience
kb:write- update_kb_audience
- Update audience
kb:write- delete_kb_audience
- Delete audience
kb:write
에이전트 워크플로
분류하고, 처리하고, 동기화 상태 유지하기
REST와 MCP는 같은 권한과 워크플로를 공유해요. 자격 증명은 현재 채널 접근 권한을 좁힐 수만 있어요. 멤버십에서 채널을 빼면 통합에서도 그 채널이 빠져요.
확인이 필요한 대화 찾기
awaitingReply, unread, unassigned, assigneeId, agentGroupId, snoozed, priority, tagIds로 필터링하세요. 답장 대기는 내부 메모를 무시하고, 읽지 않음은 인증된 팀원 기준이에요. 미배정은 팀이 배정돼 있어도 개인 담당자가 없다는 뜻이에요. 태그는 전달한 ID 중 하나라도 일치하면 돼요.
list_conversations({ status: "open", awaitingReply: true, compact: true, sort: "waitingSince", direction: "asc" })waitingSince, lastMessageAt, createdAt 또는 업무 우선순위로 정렬하고 방향은 asc나 desc로 정하세요. 값이 같으면 ID로 순서를 정해요. 필터를 생략하면 compact=false와 snoozed=any가 유지돼요. REST tagIds는 쉼표로 구분된 ID를 받고, MCP는 배열도 받아요. waitingSince는 마지막 답장 이후 첫 수신 메시지부터 시작하며, 후속 메시지나 내부 메모로 초기화되지 않아요. 웹훅이 오지 않을 때도 오래된 스레드가 다시 드러나도록 이 대기열 검사를 예약 실행하세요.
받은편지함을 다시 읽지 않고 따라잡기
conversations:read로 sync를 쓰세요. 안정적인 피드에는 대화 변경, 태그, 메시지, 연락처 속성, 메모리, 삭제 기록이 포함돼요. 페이로드마다 자체 읽기 범위도 필요해요. 메시지 본문에는 messages:read, 메모리에는 contact-memory:read가 필요해요. 제한된 자격 증명은 허용된 채널만 받아요.
- 커서 없이 시작해 hasMore가 false가 될 때까지 nextCursor를 따라가고, 그 커서를 저장하세요.
- 초기 상태에 필요한 현재 대화/연락처 목록과 기록을 읽으세요.
- 저장한 커서부터 재생해 읽는 동안 생긴 변경을 따라잡으세요. 페이지마다 처리한 뒤 nextCursor를 저장하세요.
이벤트 id로 중복을 제거하세요. 재생은 최소 한 번 전달이므로 후속 작업에도 자체 중복 방지가 필요해요. 커서 없는 요청은 전체 스냅샷이 아니라 최근 1시간을 다뤄요. 이벤트는 30일 동안 보관되며, HTTP 410 resync_required가 오면 처음부터 다시 불러오세요. 범위나 채널 접근 권한을 넓힌 뒤에도 다시 불러오세요. limit은 최대 100, maxBodyChars는 최대 10,000(기본값 500)까지 쓸 수 있어요. compact=true로 설정하면 body/bodyTruncated 대신 200자로 제한된 메시지 textPreview/textTruncated 필드를 받아요. 웹훅으로 에이전트를 깨울 수 있고, 웹훅 구독이 없거나 웹훅 전송이 밀려도 피드는 계속 쓸 수 있어요.
확인 결과를 한 번 기록하고 공유하기
조사를 반복하기 전에 list_conversation_checks(GET /api/v1/conversations/{conversationId}/checks)를 읽으세요. 결과는 record_conversation_check(같은 경로로 PUT)로 저장하며, key, result, checkedBy와 카드 ID나 URL을 위한 선택적 reference를 넣으세요. 예: key=product-version, result=Shopstar Go verified, checkedBy=Engineer, reference=card-X. Sonny가 인증된 actorId와 checkedAt 타임스탬프를 기록해요. 같은 key를 다시 쓰면 그 확인만 바뀌어요. 기록 로그가 아니라 현재 상태예요. 읽기에는 conversations:read, 쓰기에는 conversations:write가 필요하며 둘 다 대화의 채널 범위로 제한돼요. 이 호출은 답장을 보내거나 판매자가 답변한 것으로 표시하지 않아요.
업무를 배정하고 일괄 업데이트하기
list_members / list_teams(members:read)로 활성 상태이고 배정 가능한 팀원과 팀을 찾으세요. 응답에는 이메일 주소 없이 응대 가능 상태와 실제 채널 접근 권한이 포함돼요. conversations:write로 status, priority, assigneeId, agentGroupId, snoozedUntil, snoozedUntilReply, addTagIds, removeTagIds를 바꾸세요.
batch_update_conversations({
conversationIds: ["conversation_1", "conversation_2"],
updates: { agentGroupId: "team_1", assignment: "round_robin" }
})라운드 로빈은 대화의 채널에 접근할 수 있는 응대 가능한 팀 멤버를 골라요. 해당하는 멤버가 없으면 단일 업데이트는 409를 반환하고 일괄 항목은 실패해요. 일괄 요청마다 고유 ID를 최대 100개 받고, 대화별로 패치 하나를 원자적으로 적용해요. 일부 항목이 실패할 수 있으니 모든 { id, ok, error? } 결과를 확인하세요. 일괄 요청은 항목 수에 따른 가중치 없이 현재 요청 기반 한도를 써요.
Sonny AI와 고객 정보 공유하기
contact-memory:read/write로 연락처 메모리를 나열하고, 저장하고, 제거하세요. contactId와 접근 가능한 sourceId를 모두 넣어야 하며, 연락처에 그 소스의 대화가 있어야 해요. 저장된 사실은 앱과 같은 검증, 중복 처리, 한도를 따르고 수동 메모리로 기록돼요.
/api/v1/properties에서 속성 정의를 읽고, /api/v1/contacts/{contactId}/properties에서 값을 읽거나 설정하세요. MCP는 list_properties, get_contact_properties, set_contact_property를 제공해요. contacts:read/write와 모든 채널 접근 권한이 필요해요. propertyId나 propertyName 중 정확히 하나를 지정하고, 값은 문자열로, 지우려면 null로 보내세요. 텍스트, 숫자, URL, 날짜, 선택 값은 필드 정의에 따라 검증돼요.
set_contact_property({ contactId: "contact_1", propertyName: "Plan", value: "Pro" })
list_contacts({ property: { Plan: "Pro" } })속성 필터는 저장된 문자열과 정확히 일치해야 하며, 여러 속성은 모두 일치해야 해요. API로 작성된 값은 Co-Pilot과 자동 응답기에서 API 데이터로 표시돼요. 기존 인증된 고객 및 소스 규칙은 그대로 적용돼요. 일반적인 수동 내부 필드 값은 이 AI 맥락에서 계속 제외돼요.
팀과 같은 리포트 읽기
reporting:read로 get_report({ kind, filters })를 호출하세요. 종류는 overview, volume, response-times, agents, sources, tags, csat, ai, knowledge, leads, online-hours예요. overview는 건수, 응답 시간, CSAT를 합쳐 보여 줘요. 필터는 period(1–365일, 기본값 30), 짝을 이루는 from/to 날짜(to는 제외), granularity(day/month), source, assigneeId, tagId예요. source는 all, all-chat, all-email, website:{id}, email:{id}를 받아요.
리포트는 대시보드와 같은 쿼리와 현재 접근 권한 확인을 사용해요. knowledge는 선택한 소스, 담당자, 태그와 관계없이 날짜와 허용된 채널을 써요. online-hours는 접근 가능한 팀원의 워크스페이스 접속 시간을 측정하고, 대화 수는 채널 범위로 유지돼요. 기존 /csat 엔드포인트는 별도의 csat:read 범위를 유지하며 다른 집단을 기준으로 할 수 있어요.
답장이나 내부 메모와 함께 파일 보내기
attachments:write를 부여하고 대화에 최대 25MB의 파일을 업로드하세요. upload_attachment는 conversationId, fileName, contentType, dataBase64를 받아요. 응답에는 id와 expiresAt이 들어 있어요. 1시간 안에 attachmentIds를 최대 10개까지 답장이나 메모에 넘기세요. 업로드는 내 사용자와 대화에 묶이고 한 번만 쓸 수 있어요. 사용하지 않은 업로드는 만료 후 정리돼요.
send_message({ conversationId: "conversation_1", attachmentIds: ["upload_1"] })답장에는 messages:send가, 내부 메모에는 messages:write가 필요하며 내부 메모는 고객에게 절대 전달되지 않아요. 첨부 파일만 있는 메시지도 지원해요. 이메일 답장은 이메일 크기 한도 안에서 파일을 첨부하고 나머지는 다운로드 링크로 넣어요. 오프라인 채팅 이메일에는 파일 링크가 들어가요. 이메일 속 링크는 첨부 파일이 있는 동안 계속 쓸 수 있어 수신자가 나중에 열 수 있어요. 이메일을 전달하면 그 파일에 대한 접근도 공유돼요. 전송 실패는 emailDeliveryStatus로 확인하세요.
권한이 있는 메시지 읽기에는 downloadUrl, downloadExpiresAt, aiStatus, aiDescription, aiExtractedText와 링크된 동영상(Loom, Vimeo 등)의 videoTranscripts가 포함돼요. 다운로드 링크는 15분 동안 유효하며, 새 링크가 필요하면 메시지를 다시 읽으세요. 새 API/MCP 업로드는 비공개 저장소에 저장돼요. 예전 첨부 파일은 공개 상태로 남고 access=legacy_public으로 표시되며, 원래 URL은 만료되지 않아요. 워크스페이스에 Sonny AI가 있으면 메시지를 읽을 때 이미지 판독이 시작돼요. 이미지 판독과 동영상 자막은 메시지 도착 직후 완료돼요. 아직 진행 중인 것이 있으면 응답이 readsInProgress로 시작하고, 그 nextStep에 정확히 어떤 호출을 할지 나와요. waitSeconds(최대 30)를 넘기면 한 번의 요청으로 기다릴 수 있어요. 고객용 위젯과 실시간 메시지에는 추출 결과나 자막이 절대 포함되지 않아요.
지식 베이스
외부 소스에서 동기화하기
고정 외부 ID로 아티클과 카테고리를 동기화하고, Markdown이나 HTML을 가져오고, 이미지를 업로드하고, 순서를 정하고, 독자 대상 그룹을 관리하세요. upsert를 반복하면 기존 콘텐츠가 업데이트돼요.
- 채널의 sourceId를 고르고 kb:read와 kb:write를 부여하세요. 선택 사항인 탐색을 위해
list_sources에는 conversations:read도 필요해요. - 카테고리를 만든 뒤 아티클을 초안으로 동기화하세요. 게시하기 전에 서식과 접근 권한을 검토하세요.
- 도움말 센터 접근 권한을 구성하고, 게시하고, 독자 화면을 테스트하세요. 이후 업데이트에는 페이지 나눔과 고정 외부 ID를 쓰세요.
고객 대상 그룹 관리
인증된 고객 특성으로 그룹을 만들어 도움말 센터, 카테고리, 아티클에 적용하세요. 상속된 모든 제한을 만족해야 해요. API와 MCP 자격 증명은 범위 안에서 직원으로 동작하므로, 독자 접근 권한은 미리보기와 실제 고객 세션으로 테스트하세요.
도움말 센터 대상 그룹 설정하고 테스트하기