어시스턴트 클라이언트 만들기

OAuth 로그인

어시스턴트가 API 키 없이 로그인하는 방법이에요. 나만의 클라이언트를 만들 때 필요한 탐색, 등록, 동의, 토큰을 설명해요.

AI 어시스턴트는 API 키 대신 OAuth로 Setherion에 로그인해요. 사람이 Setherion 페이지에서 Allow를 누르면 어시스턴트가 토큰을 받아요. 이 페이지는 나만의 클라이언트를 만들 때 따라야 하는 명세예요. Claude, ChatGPT, Cursor, VS Code만 연결하고 싶다면 MCP: AI 어시스턴트 연결하기를 따라 하세요.

이 흐름은 MCP 인증 사양(2025-06-18)이 요구하는 OAuth 2.1이에요.

  • 인증 코드 흐름을 쓰며, PKCE (S256) 검증은 항상 필수예요.
  • 공개 클라이언트만 허용하고, 클라이언트 시크릿은 없어요.
  • 동적 클라이언트 등록(RFC 7591)을 쓰기 때문에, 클라이언트 id를 어디에도 붙여 넣을 필요가 없어요.
  • 토큰은 하나의 리소스, 곧 MCP 엔드포인트에 묶여요(RFC 8707).

이 토큰은 MCP 서버에서만 쓸 수 있고 다른 곳에서는 쓸 수 없어요. 이 레퍼런스의 REST 엔드포인트는 API 키를 받아요.

항목값
발급자https://www.setherion.com
리소스https://www.setherion.com/api/mcp
스코프mcp
액세스 토큰sto_로 시작하고, 1시간 동안 유효해요
리프레시 토큰str_로 시작하고, 30일 동안 유효하며, 쓸 때마다 새것으로 바뀌어요
인증 코드stc_로 시작하고, 10분 동안 유효하며, 한 번만 쓸 수 있어요

1. 탐색하기

자격 증명 없이 MCP 엔드포인트에 요청을 보내세요. 401 응답이 WWW-Authenticate 헤더에서 리소스 메타데이터(RFC 9728)를 가리켜요:

bash
curl https://www.setherion.com/.well-known/oauth-protected-resource/api/mcp
json
{
  "resource": "https://www.setherion.com/api/mcp",
  "authorization_servers": ["https://www.setherion.com"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["mcp"],
  "resource_name": "Setherion"
}

같은 문서가 /.well-known/oauth-protected-resource에도 있어요. 그다음 인증 서버 메타데이터(RFC 8414)를 읽으세요:

bash
curl https://www.setherion.com/.well-known/oauth-authorization-server
json
{
  "issuer": "https://www.setherion.com",
  "authorization_endpoint": "https://www.setherion.com/oauth/authorize",
  "token_endpoint": "https://www.setherion.com/api/oauth/token",
  "registration_endpoint": "https://www.setherion.com/api/oauth/register",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["none"],
  "scopes_supported": ["mcp"]
}

두 문서와 등록 엔드포인트, 토큰 엔드포인트는 모든 출처에 응답하므로(Access-Control-Allow-Origin: *), 브라우저 페이지의 클라이언트도 호출할 수 있어요.

2. 등록하기

POSThttps://www.setherion.com/api/oauth/register

요금제: 모든 요금제

설치할 때마다 한 번 등록하세요. 등록만으로는 아무 권한도 주어지지 않아요. 사람이 여전히 Allow를 눌러야 하고, 코드는 여기에 등록한 정확한 주소로만 되돌아가요.

bash
curl -X POST https://www.setherion.com/api/oauth/register \
  -H "Content-Type: application/json" \
  -d '{ "client_name": "My assistant", "redirect_uris": ["http://localhost:8787/callback"] }'
필드의미
redirect_uris필수예요. 주소 1개에서 10개까지이고, 각각 최대 2,000자예요. 중복은 제거돼요.
client_name선택이에요. 동의 페이지에서 사람에게 보여 줘요. 100자까지만 남기고, 빼면 An AI assistant가 쓰여요.
grant_types선택이에요. authorization_code와 refresh_token만 받아요.
response_types선택이에요. code만 받아요.

리다이렉트 주소는 https여야 하고, 이 컴퓨터로 되돌아오는 경우에만 http도 쓸 수 있어요(localhost, 127.0.0.1, [::1]). 프래그먼트나 사용자 이름이 있으면 안 돼요. https나 http가 아닌 유일한 주소는 오래된 Cursor 앱을 위한 cursor://anysphere.cursor-mcp/oauth/callback이에요.

클라이언트가 어떤 인증 방식을 요청하든, 비밀 없는 공개 클라이언트로 등록되며 응답도 그렇게 알려 줘요:

json
{
  "client_id": "5f0c2a9d-4e30-4d7f-b8a5-6f1c2a9d4e30",
  "client_id_issued_at": 1790000000,
  "client_name": "My assistant",
  "redirect_uris": ["http://localhost:8787/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}

상태 코드는 201이에요. 등록은 네트워크 주소당 한 시간에 20번으로 제한돼요.

등록 오류

모든 오류는 { "error": "...", "error_description": "..." } 형태예요.

상태errorerror_description
400invalid_redirect_uriSend between one and ten redirect_uris.
400invalid_redirect_uriRedirect URIs must be HTTPS, or HTTP back to localhost.
400invalid_client_metadataOnly authorization_code and refresh_token are supported.
400invalid_client_metadataOnly the code response type is supported.
429slow_downToo many registrations. Try again later.
503temporarily_unavailableNot configured. 또는 Connecting assistants is not switched on yet.

3. 사람에게 물어보기

사람의 브라우저에서 인증 엔드포인트를 여세요. 이 엔드포인트는 API가 아니라 페이지예요. 사람이 아직 로그인하지 않았다면 Setherion에 로그인하고, 내가 등록한 이름과 다시 돌아갈 곳을 확인한 다음 Allow 또는 Cancel을 눌러요.

text
https://www.setherion.com/oauth/authorize
  ?response_type=code
  &client_id=5f0c2a9d-4e30-4d7f-b8a5-6f1c2a9d4e30
  &redirect_uri=http%3A%2F%2Flocalhost%3A8787%2Fcallback
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256
  &state=af0ifjsldkj
  &resource=https%3A%2F%2Fwww.setherion.com%2Fapi%2Fmcp
파라미터의미
response_type필수예요. 값은 code예요.
client_id필수예요. 등록할 때 받은 값이에요.
redirect_uri등록한 주소 중 하나이고, 정확히 일치해야 해요. 정확히 하나만 등록했을 때만 생략할 수 있어요.
code_challenge필수예요. 검증값의 S256 해시를 base64url로 나타낸 값이고, 43자에서 128자예요.
code_challenge_method필수예요. S256이에요. plain은 받지 않아요.
state권장해요. 그대로 돌려보내요. 최대 1,000자예요.
resource선택이에요. 보내는 경우 https://www.setherion.com/api/mcp여야 해요(끝의 슬래시와 스킴, 호스트의 대소문자는 상관없어요).

검증값은 A-Z a-z 0-9 - . _ ~ 중에서 43자에서 128자로 만들고, 4단계까지 보관하세요.

사람은 다음 값과 함께 redirect_uri로 되돌아가요.

  • Allow를 누르면 code, state, iss(발급자)가 붙어요.
  • Cancel을 누르면 error=access_denied, error_description=The request was declined., state, iss가 붙어요.
  • 요청에 문제가 있고 클라이언트와 주소가 진짜임이 확인된 경우에는 error, error_description, state, iss가 붙어요. error는 unsupported_response_type, invalid_request(PKCE가 없거나 방식이 S256이 아닌 경우), invalid_target(리소스가 MCP 엔드포인트가 아닌 경우) 중 하나예요.

클라이언트를 모르거나 주소가 등록된 주소가 아니면 페이지가 사람에게 그렇게 알려 주고 아무 곳으로도 보내지 않아요. 그래서 이 페이지로 내가 등록하지 않은 주소로 누군가를 리다이렉트할 수는 절대 없어요.

4. 코드 교환하기

POSThttps://www.setherion.com/api/oauth/token

요금제: 모든 요금제

OAuth 사양대로 폼 인코딩된 필드를 보내세요. 같은 이름의 JSON도 받아요.

bash
curl -X POST https://www.setherion.com/api/oauth/token \
  -d grant_type=authorization_code \
  -d code=stc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
  -d client_id=5f0c2a9d-4e30-4d7f-b8a5-6f1c2a9d4e30 \
  -d redirect_uri=http://localhost:8787/callback \
  -d code_verifier=YOUR_VERIFIER
필드의미
grant_typeauthorization_code예요.
code리다이렉트로 받은 코드예요.
client_id코드를 발급받은 클라이언트예요.
redirect_uri3단계와 같은 주소예요.
code_verifierS256 해시를 code_challenge로 보낼 때 쓴 그 검증값이에요.
resource선택이에요. 보내는 경우 코드의 리소스와 일치해야 해요.
json
{
  "access_token": "sto_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "str_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "scope": "mcp"
}

액세스 토큰은 Authorization: Bearer sto_... 형태로 MCP 서버에 보내세요. 토큰은 절대 캐시되지 않아요. 응답에 Cache-Control: no-store가 들어 있어요.

5. 갱신하기

액세스 토큰은 한 시간 동안 유효해요. 만료되기 전에, 또는 MCP 서버가 401로 응답하면 리프레시 토큰을 교환하세요:

bash
curl -X POST https://www.setherion.com/api/oauth/token \
  -d grant_type=refresh_token \
  -d refresh_token=str_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
  -d client_id=5f0c2a9d-4e30-4d7f-b8a5-6f1c2a9d4e30

응답은 4단계와 같지만 새 리프레시 토큰이 들어 있어요. 이전 토큰은 더 이상 작동하지 않으니, 매번 새 토큰을 저장하세요.

리프레시 토큰을 다시 쓰면 연결이 끝나요

리프레시 토큰을 두 번째로 쓰면 도난당한 복사본으로 간주되고, Setherion은 연결 전체를 끝내요. 그 동의에서 나온 모든 토큰이 작동을 멈추고, 사람이 Allow를 다시 눌러야 해요. 한 가지 예외는, 연결이 아직 열려 있는 동안 같은 클라이언트가 60초 안에 같은 토큰을 내미는 경우예요. 한 어시스턴트의 프로세스 두 개, 예를 들어 창 두 개가 동시에 갱신할 수 있는 이유가 이거예요. 코드를 두 번 쓰면 같은 방식으로 그 연결이 끝나요.

오류

토큰 엔드포인트의 모든 오류는 상태 코드가 400이고(server_error만 예외예요), 본문은 { "error": "...", "error_description": "..." } 형태예요.

토큰 오류
errorerror_description
unsupported_grant_typeUse authorization_code or refresh_token.
invalid_grantUnknown code.
invalid_grantThis code was already used.
invalid_grantThis code has expired.
invalid_grantThis code was issued to another application.
invalid_grantredirect_uri does not match the one the code was issued for.
invalid_grantPKCE verification failed.
invalid_grantUnknown refresh token.
invalid_grantThis refresh token has expired.
invalid_grantThis token was issued to another application.
invalid_grantThis refresh token was already used. The connection has been ended for safety.
invalid_targetThis code was issued for another resource. 또는 This token was issued for another resource.
server_error (상태 500)Not configured. 또는 Could not issue tokens.

연결 끝내기

사람은 Settings, AI assistants and MCP 순서로 열어서 어시스턴트의 연결을 끊을 수 있어요. 그 연결의 모든 토큰, 즉 액세스 토큰과 리프레시 토큰이 한 시간이 지나기를 기다리지 않고 바로 다음 요청에서 작동을 멈춰요. 연결을 보고 끝내는 일은 로그인된 Setherion 세션에서만 할 수 있어서, 어시스턴트가 가진 어떤 것으로도 할 수 없어요.

대신 API 키 쓰기

고정된 헤더만 보낼 수 있는 클라이언트는 이 모든 과정을 건너뛰고 MCP 서버에 API 키를 보낼 수 있어요. 인증을 보세요.

이 페이지가 도움이 됐나요?

커뮤니티 참여하기

질문, 아이디어, 그리고 다른 사람들이 만들고 있는 것.