어시스턴트 클라이언트 만들기
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)를 가리켜요:
curl https://www.setherion.com/.well-known/oauth-protected-resource/api/mcp{
"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)를 읽으세요:
curl https://www.setherion.com/.well-known/oauth-authorization-server{
"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. 등록하기
https://www.setherion.com/api/oauth/register요금제: 모든 요금제
설치할 때마다 한 번 등록하세요. 등록만으로는 아무 권한도 주어지지 않아요. 사람이 여전히 Allow를 눌러야 하고, 코드는 여기에 등록한 정확한 주소로만 되돌아가요.
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이에요.
클라이언트가 어떤 인증 방식을 요청하든, 비밀 없는 공개 클라이언트로 등록되며 응답도 그렇게 알려 줘요:
{
"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": "..." } 형태예요.
| 상태 | error | error_description |
|---|---|---|
400 | invalid_redirect_uri | Send between one and ten redirect_uris. |
400 | invalid_redirect_uri | Redirect URIs must be HTTPS, or HTTP back to localhost. |
400 | invalid_client_metadata | Only authorization_code and refresh_token are supported. |
400 | invalid_client_metadata | Only the code response type is supported. |
429 | slow_down | Too many registrations. Try again later. |
503 | temporarily_unavailable | Not configured. 또는 Connecting assistants is not switched on yet. |
3. 사람에게 물어보기
사람의 브라우저에서 인증 엔드포인트를 여세요. 이 엔드포인트는 API가 아니라 페이지예요. 사람이 아직 로그인하지 않았다면 Setherion에 로그인하고, 내가 등록한 이름과 다시 돌아갈 곳을 확인한 다음 Allow 또는 Cancel을 눌러요.
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. 코드 교환하기
https://www.setherion.com/api/oauth/token요금제: 모든 요금제
OAuth 사양대로 폼 인코딩된 필드를 보내세요. 같은 이름의 JSON도 받아요.
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_type | authorization_code예요. |
code | 리다이렉트로 받은 코드예요. |
client_id | 코드를 발급받은 클라이언트예요. |
redirect_uri | 3단계와 같은 주소예요. |
code_verifier | S256 해시를 code_challenge로 보낼 때 쓴 그 검증값이에요. |
resource | 선택이에요. 보내는 경우 코드의 리소스와 일치해야 해요. |
{
"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로 응답하면 리프레시 토큰을 교환하세요:
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": "..." } 형태예요.
토큰 오류
error | error_description |
|---|---|
unsupported_grant_type | Use authorization_code or refresh_token. |
invalid_grant | Unknown code. |
invalid_grant | This code was already used. |
invalid_grant | This code has expired. |
invalid_grant | This code was issued to another application. |
invalid_grant | redirect_uri does not match the one the code was issued for. |
invalid_grant | PKCE verification failed. |
invalid_grant | Unknown refresh token. |
invalid_grant | This refresh token has expired. |
invalid_grant | This token was issued to another application. |
invalid_grant | This refresh token was already used. The connection has been ended for safety. |
invalid_target | This 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 키를 보낼 수 있어요. 인증을 보세요.
이 페이지가 도움이 됐나요?
