MCP 커넥터
Claude 같은 MCP 클라이언트에 번호를 붙여 대화로 전화를 거는 방법.
언어 값을 지정하려면 통화 언어 코드에서 전체 코드 표와 REST 생성·통화 중 변경·MCP 요청 예시를 확인하세요.
gateway는 MCP(Model Context Protocol) 서버를 함께 제공합니다. Claude 같은 MCP 클라이언트에 번호를 붙이면 대화로 전화를 걸고, 결과를 조회하고, 통화를 끊을 수 있습니다.
서버 주소
https://vox-gateway-prod.fly.dev/mcp/끝 슬래시가 계약입니다. /mcp로 접속하는 클라이언트도 있어 서버가 정규화해 주지만, 설정에는
슬래시까지 넣으세요.
연결하기
연결 방법은 셋이고, 클라이언트가 헤더를 넣을 수 있는지에 따라 갈립니다. 헤더를 지정할 수 있으면 번호 API 키 하나로 끝나고, 그렇지 않은 클라이언트(Claude 웹·데스크톱의 커넥터 화면에는 임의 헤더 칸이 없습니다)를 위해 나머지 둘이 있습니다.
| 방법 | 정체성 | 쓸 수 있는 조건 |
|---|---|---|
| 헤더에 번호 API 키 | 그 번호 | 언제나 — 헤더를 지정할 수 있는 클라이언트라면 추가 설정이 필요 없습니다. |
| 계정으로 로그인 (OAuth) | 여러분의 계정 | 플랫폼에서 켜져 있어야 합니다. |
| 커넥터 전용 주소 | 그 번호 | 운영자가 번호 단위로 열어 준 경우에만 — 기본은 닫혀 있습니다. |
헤더에 번호 API 키
인증은 REST와 같은 번호 API 키입니다. 그대로 Bearer로 넘기면 됩니다.
{
"mcpServers": {
"vox-gateway": {
"url": "https://vox-gateway-prod.fly.dev/mcp/",
"headers": { "Authorization": "Bearer tg_live_..." }
}
}
}계정으로 로그인 (OAuth)
커넥터가 OAuth로 연결되면 키가 아니라 여러분의 계정이 정체성이 됩니다. 접근 가능한 워크스페이스의
번호가 모두 보이고, 도구에 번호 선택 인자가 추가됩니다(from_number · number). 이 방식은 플랫폼에서
켜져 있을 때만 나타납니다 — 커넥터를 추가해도 로그인 화면으로 넘어가지 않으면 꺼져 있는 것입니다.
커넥터 전용 주소
기본적으로 닫혀 있는 제한 기능입니다. 운영자가 번호 단위로 열어 준 경우에만 동작하고, 열려 있지 않은 번호의 주소는 형식이 맞아도 404입니다. 열려 있는지는 번호 상세에서 확인하세요 — 주소가 보이지 않으면 아직 열려 있지 않은 것이고, 주소를 직접 만들어 붙여넣는 것으로는 열리지 않습니다.
https://vox-gateway-prod.fly.dev/mcp/t/{번호 API 키}/번호 상세 › 아웃바운드에서는 앞부분만 마스킹되어 보이고, 복사를 누르면 그때 완성 주소를 가져옵니다(워크스페이스 관리자만, 가져간 기록이 남습니다). 2026년 8월 20일 이전에 발급한 키는 복사할 수 없어 재발급이 필요합니다.
이 URL 자체가 자격증명입니다. 주소를 아는 사람은 그 번호로 전화를 걸고 통화 이력을 볼 수 있습니다. 여러 사람에게 같은 주소를 주면 서로의 통화 이력이 보이므로, 격리가 필요하면 번호를 따로 발급하세요. 무효화는 키 재발급입니다.
제공 도구
| 도구 | 인자 | 하는 일 |
|---|---|---|
make_call | phone_number 필수instruction 필수language 34개 언어 (언어별 공급자) (미지정=저장된 통화 언어)from_number (OAuth 연결 시) | 전화를 겁니다. call_id · status · from · from_number를 돌려줍니다. |
get_call | call_id 필수 | 통화 하나의 상태·요약·시각·녹음 유무를 조회합니다. |
list_my_calls | limit (기본 20) | 최근 통화를 최신순으로 나열합니다. 전문·재생 링크는 싣지 않습니다. |
get_transcript | call_id 필수 | 통화에서 오간 말을 turn 단위로 읽습니다. 통화의 status가 함께 옵니다. |
get_recording_link | call_id 필수 | 녹음을 들을 수 있는 시한부 링크를 발급합니다. |
end_call | call_id 필수number (OAuth 연결 시) | 진행 중인 통화를 즉시 끊습니다. |
list_my_numbers | 없음 | 발신 가능한 번호를 나열합니다. OAuth로 연결했을 때만 제공됩니다. |
make_call.language는 이번 통화에만 적용됩니다. 생략하면 번호 → 워크스페이스 → 한국어 순으로 설정을 사용합니다. 중국어(zh)는 xAI를 사용할 수 있습니다. 태국어(th)처럼 xAI 사용 불가능 언어를 지정하면 OpenAI STT·Google TTS로 전환하므로 해당 공급자의 키가 필요합니다. 자세한 조합과 통화 중 변경 제한은 언어별 공급자를 참고하세요.
- REST와 달리
make_call은instruction이 필수입니다. MCP는 "임무를 말로 시키는" 표면이라 임무 없이 거는 것이 의미가 없기 때문입니다. 반대로 REST는 agent가 이미 임무를 아는 연동을 상정해to만 필수입니다(Create Call). end_call은 통화 밖에서 부르는 도구라 기다리지 않고 즉시 끊습니다. 통화 중인 agent가 작별 인사를 하고 끊으려면 MCP가 아니라 Hang Up Call을 쓰세요 — MCP로 부르면 인사가 잘립니다.- 조회 도구(
get_call·list_my_calls·get_transcript·get_recording_link)는 그 키의 번호로 건 통화만 돌려줍니다. 남의 통화는 존재 여부도 알려주지 않고call not found가 됩니다. summary는 통화 전체를 한 줄로 줄인 값입니다. "상대가 뭐라고 했어?"처럼 실제로 오간 말(날짜·금액·약속)을 물으면 요약에서 추측하지 말고get_transcript를 부르게 하세요.
통화 결과 확인
통화가 끝나면 세 가지를 볼 수 있습니다 — 요약 한 줄(get_call), 오간 말 전문(get_transcript),
녹음(get_recording_link). 셋은 서로 대체재가 아닙니다.
전문 읽기
get_transcript은 turn 배열과 함께 통화의 status를 돌려줍니다. 빈 배열의 뜻이 그 값으로
갈립니다 — 진행 중이면 "아직 아무도 말하지 않았다"이고, 끝난 통화면 "전사본이 없는 통화"(받지
않았거나 말 없이 끝남)입니다. 후자를 "상대가 아무 말도 안 했다"고 옮기면 사실과 다릅니다.
상대 쪽 텍스트는 음성 인식 결과라 잘못 들은 말이 섞일 수 있고 숫자가 말로 풀려 나오기도 합니다 — 원문이 아니라 "들린 것"으로 다루세요. 진행 중에 불러도 그 시점까지의 턴을 돌려줍니다.
녹음 듣기
오디오는 커넥터로 오갈 수 없습니다 — 이 연결은 텍스트만 주고받습니다. 그래서 get_recording_link은
파일이 아니라 브라우저에서 열 링크를 돌려줍니다(url · expires_at). 녹음을 듣는 유일한
길입니다.
get_call과 list_my_calls의 각 통화에는 recording이 함께 옵니다. get_recording_link는 이 값이
available일 때만 링크를 내주므로, 링크를 찍어보기 전에 여기부터 읽는 편이 빠릅니다.
| recording | 뜻 | 링크 요청 시 |
|---|---|---|
available | 녹음 파일이 있습니다. | 링크를 발급합니다. |
pending | 통화가 방금 끝나 파일을 마감하는 중입니다. | 거절 — 몇 초 뒤 다시 부르세요(없다고 단정하지 마세요). |
none | 이 통화는 녹음되지 않았습니다. | 거절 — 지난 통화를 소급해 녹음할 수는 없습니다. |
failed | 녹음을 시도했지만 파일이 남지 않았습니다. | 거절 — 재시도해도 같습니다. |
녹음은 번호 단위 설정입니다 — 번호 관리 › 번호 › 음성 탭의 "통화 녹음" 토글이고, 다음 통화부터 적용됩니다. 통화 한 건만 켜고 끌 수는 없습니다.
재생 링크는 로그인 없이 열립니다. 주소를 가진 사람은 만료 전까지 누구나 녹음을 들을 수 있으니
자격증명처럼 다루고, 요청한 본인에게만 건네세요. 기본 유효기간은 24시간이며 응답의
expires_at이 정확한 만료 시각입니다. 같은 통화로 다시 발급해도 안전하지만 이미 나간 링크가
무효가 되지는 않습니다 — 링크는 무상태 서명이라 개별 회수가 없고, 만료를 기다리는 것 외에는
운영자가 서명 키를 갈아 그 시점의 모든 링크를 한꺼번에 죽이는 방법뿐입니다.
번호 결정
번호 API 키나 커넥터 전용 주소로 연결했다면 그 키의 번호로 고정됩니다 — 고를 것이 없고, 아래 인자도 나타나지 않습니다.
OAuth로 연결했다면 정체성이 계정이라 번호가 자동으로 정해지지 않습니다. 규칙은 다음 순서입니다.
- 번호를 지정했으면 그 번호 — 거는 도구는
from_number, 끊는 도구는number입니다. 접근 권한이 없으면 403number_not_allowed. - 지정하지 않았고 접근 가능한 번호가 정확히 하나면 그 번호.
- 둘 이상이면 임의로 고르지 않고 거절합니다 — 후보 목록을 함께 돌려주니 하나를 골라 다시 부르세요.
{
"ok": false,
"reason": "from_number_required",
"candidates": [
{ "number_id": "6b2e…", "phone": "07079193558", "workspace_name": "우리 팀" },
{ "number_id": "8c41…", "phone": "07079193559", "workspace_name": "지원팀" }
]
}end_call도 같은 상황에서 같은 모양으로 거절하는데, 사유 이름만 number_required입니다 — 그 도구의
인자 이름이 number이기 때문입니다.
조회 도구는 접근 가능한 워크스페이스를 가로질러 통화를 찾지만, 끊는 표면은 번호 단위로 좁아집니다 —
그래서 list_my_calls로 찾은 통화를 끊을 때 번호를 함께 넘겨야 할 수 있습니다. 값은 후보 목록이나
조회 결과의 number_id를 그대로 쓰면 됩니다.
발신 번호가 없을 때는 422 no_number_available입니다. 전체 코드는 에러 코드를
보세요.