Skip to content

Cursor

네이티브 ConnectRPC 어댑터를 통해 Cursor 구독에 도달하기 — 로그인, 에이전트 모드, 모델 id, 도구, 이미지, 오버라이드.

Updated View as Markdown

내장 cursor 프로바이더는 Cursor 자체의 ConnectRPC/protobuf AgentService를 통해 Cursor 구독에 도달합니다. kind = "cursor" 네이티브 어댑터가 이를 Anthropic Messages API로 브리지하며 — 스트리밍, 스트리밍 응답에서의 추론, 네이티브 도구 호출, 인라인 이미지를 포함합니다. 로그인과 토큰 갱신은 api2.cursor.sh를 사용하고, 에이전트 턴은 Cursor의 현재 에이전트 호스트(agentn.global.api5.cursor.sh)를 상대로 HTTP/2 위에서 실행됩니다.

빠른 시작

코딩 에이전트가 대신 구성하도록 하세요 — shunt add는 내장된 설정 블루프린트를 출력합니다 (오프라인·읽기 전용이며, 구성은 에이전트가 편집하고 이 명령은 절대 편집하지 않습니다):

shunt add upstream cursor --print | claude

또는 아래의 수동 단계를 따르세요.

1. 로그인

shunt login cursor

이는 Cursor OAuth 플로우를 실행하고 ~/.shunt/cursor-auth.json을 기록하며, shunt는 이 파일을 읽고 자동 갱신합니다. 파일이 없거나 만료되면, shunt는 shunt login cursor를 다시 실행하라는 authentication_error를 반환합니다.

2. 업스트림 구성

프로바이더는 기본으로 시드되므로 테이블이 필요 없습니다 — cursor:* 모델 id를 라우팅하면 끝입니다. 명시적으로 선언하려면(순서가 있는 페일오버를 위해), cursor 프리셋이 네이티브 어댑터, base_url = "https://api2.cursor.sh", auth = "cursor_oauth"를 제공합니다:

[[upstreams]]
name = "anthropic"
provider = "anthropic"   # 라우트가 없는 모델(예: claude-*)의 기본값으로 Anthropic을 유지

[[upstreams]]
name = "cursor"
provider = "cursor"

순서가 있는 [[upstreams]]는 shunt의 내장 프로바이더(시드된 cursor 포함)를 대체하므로, 명시적 구성은 여전히 폴백 대상인 anthropic 기본값도 함께 선언해야 합니다(server.default_provider의 기본값은 anthropic입니다).

레거시 [providers.cursor] 테이블 형식도 계속 지원됩니다 — 다만 한 파일에서 [[upstreams]]와 [providers.*]를 섞지 마세요.

3. 모델 id와 에이전트 모드

프리픽스가 Cursor의 에이전트 모드(Agent / Plan / Ask)를 선택하고, 접미사는 보통 Cursor 모델 id입니다. cursor-agent models의 표시 이름이 아니라 와이어 id를 사용하세요: Auto는 default입니다 (cursor:auto를 라우팅하면 Unknown model ID: auto로 실패합니다). 이름이 있는 모델(예: cursor:gpt-5.2)은 해당 모델에 대한 자격을 부여하는 유료 플랜이 필요하며, 무료 플랜은 cursor:default로 제한됩니다.

Cursor 선택기의 composer-2.5-fast 항목은 와이어 id가 아니라 매개변수화된 별칭입니다. cursor:composer-2.5-fast(또는 cursor:composer-2.5[fast=true])를 라우팅하면 shunt는 공식 CLI와 동일하게 composer-2.5 와이어 id를 fast=true 모델 메타데이터와 함께 전송합니다.

형식 에이전트 모드 예시
cursor:<id> / cursor-agent:<id> Agent cursor:default
cursor-plan:<id> Plan cursor-plan:default
cursor-ask:<id> Ask cursor-ask:default

레거시 맨 이름도 받아들여집니다: cursor, cursor-agent, cursor-composer, cursor-composer-fast(Agent); cursor-plan, composer-2.5(Plan); cursor-ask, composer-2.5-fast(Ask). 그 외의 모델 id는 invalid_request_error로 거부됩니다.

직접 라우팅하거나, Claude 이름의 별칭을 모델 디스커버리에 노출하세요:

[[routes]]
model = "cursor:default"
provider = "cursor"

# 또는: 노출 + 라우팅을 한 선언으로
[[models]]
id = "claude-cursor-default"
display_name = "Cursor Auto"

[models.upstream_model]
cursor = "cursor:default"

어댑터가 전달하는 것

어댑터는 어시스턴트의 텍스트와 추론을 스트리밍하고, 클라이언트의 도구를 네이티브 Cursor MCP 도구 호출로 브리지하며(모델이 호출한 도구는 stop_reason: "tool_use"가 붙은 Anthropic tool_use 블록으로 드러나고, 사용자가 그것을 실행해 tool_result를 돌려보내면 shunt가 그 결과를 히스토리에 담아 턴을 다시 실행합니다), 인라인 이미지를 전달합니다(base64 소스이며, URL 이미지는 건너뜁니다). Cursor 자체의 에이전틱 파일/셸 도구는 노출되지 않습니다 — 요청이 광고하는 도구만 사용됩니다.

tool_use.id는 불투명한 값으로 다루세요. Cursor가 와이어에서 호출 식별자를 함께 보내면 shunt는 그 식별자를 그대로 전달하므로, id는 Anthropic 업스트림이 발급하는 toolu_<uuid>가 아니라 Cursor 고유의 tool_<uuid> 형태를 띱니다. 식별자가 없으면 shunt가 직접 toolu_<uuid>를 발급합니다. 어느 쪽이든 id는 왕복만 하면 되며, tool_result의 tool_use_id로 변경 없이 되돌려주면 됩니다.

또한 턴은 Cursor가 보내는 정식 종료 프레임에서만 끝납니다. 그 종료 프레임이 도착하기 전에 업스트림 스트림이 끊기면(연결 유실, 잘린 응답 본문 등) shunt는 부분 답변을 완결된 답변처럼 돌려주지 않고 턴을 실패 처리합니다.

{"type":"error","error":{"type":"api_error","message":"cursor: upstream EOF without an authoritative terminal"}}

예외는 이미 출력을 낸 뒤 조용해진 턴입니다. Cursor는 무상태 브리지가 결코 보내지 않는 도구 결과를 기다리며 응답을 열어 두므로, 이때의 유휴 스트림은 끊긴 것이 아니라 정상적인 턴 종료입니다.

검증

shunt check    # -> config ok
shunt run
curl -sS http://127.0.0.1:3001/v1/messages \
  -H 'anthropic-version: 2023-06-01' \
  -H 'content-type: application/json' \
  -d '{"model":"cursor:default","max_tokens":16,"messages":[{"role":"user","content":"Reply with OK."}]}'

응답의 x-gateway-upstream 헤더가 cursor를 가리키는지 확인한 다음, Claude Code를 shunt로 지정하세요.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close