nessie

MCP와 연결된 도구

Nessie를 MCP 서버에 연결하고, 외부 에이전트를 페어링해 사용자를 대신해 Nessie에서 일하게 하세요.

MCP란 무엇인가

Model Context Protocol(MCP)은 도구를 언어 모델에 설명하고 호출하기 위한 작고 공개된 규약입니다. 서버는 자신이 할 수 있는 일을 선언합니다. 인자용 JSON 스키마가 붙은 이름 있는 도구 목록입니다. 클라이언트는 이 목록을 찾아내고 모델을 대신해 도구를 호출합니다. 규약은 의도적으로 단순하게 설계되었습니다. 가치는 한 번 작성한 연동이 이를 지원하는 모든 모델과 모든 제품에서 작동한다는 데 있습니다.

Nessie는 양쪽에 모두 위치합니다

두 방향은 쉽게 혼동되며, 실제로 경로도 의도적으로 다르므로 이를 정확히 짚어 둘 가치가 있습니다.

  • 아웃바운드. Nessie는 MCP 클라이언트입니다. 다른 사람이 운영하는 서버를 연결하면, 그 서버가 노출하는 도구를 에이전트가 사용할 수 있게 됩니다. 관리 인터페이스는 /api/mcp/*입니다.
  • 인바운드. Nessie는 MCP 서버이기도 합니다. 다른 곳에서 실행되는 에이전트, 예를 들어 개발자의 컴퓨터에서 실행되는 Claude Code나 Codex가 여러분의 보드와 문서에 접근할 수 있습니다. 이 엔드포인트는 POST /mcp이며, 두 상반된 의미가 경로 세그먼트 하나 차이로 나란히 놓이지 않도록 /api 바깥에 의도적으로 두었습니다.

MCP 서버를 Nessie에 연결하기

카탈로그 항목과 인스턴스

객체는 두 가지이며, 이 둘을 구분하는 것이 중요합니다.

  • 카탈로그 항목은 서버의 정의입니다. 이름, 전송 방식, 인증 방법을 담습니다. 한 번 작성하며 공유할 수 있습니다.
  • 인스턴스는 그 카탈로그 항목을 특정 범위에 설치한 것이며, 서버에 접근하는 자격 증명을 포함합니다. 같은 항목을 서로 다른 두 팀에 설치하면 인스턴스가 두 개 생깁니다.

대부분의 사람은 둘 중 어느 것도 직접 다루지 않습니다. 관리자 화면의 입구는 /admin/apps에 있는 앱 스토어입니다. 같은 카탈로그를 연결 세부 정보를 숨긴 채 보여 주며, 목록에서 Connect를 누르면 인스턴스가 만들어집니다. 원시 객체가 필요한 운영자는 /api/mcp/catalog와 /api/mcp/instances를 사용합니다.

서버가 아직 카탈로그에 없다면 URL을 POST /api/mcp/discover에 보내세요. 서버가 자신에 대해 말하는 내용을 돌려줍니다. POST /api/mcp/library/import는 공개 서버 라이브러리에서 항목을 가져옵니다. 처음 설정할 때는 POST /api/apps/custom으로 URL만 가지고 바로 연결을 만들 수도 있습니다.

전송 방식

Nessie는 원격 서버에 HTTP로 연결합니다. 두 가지 전송 방식이 동작합니다. 스트리머블 HTTP(현재 MCP 전송 방식)와 이전의 HTTP+SSE 전송 방식입니다. 서버가 sse만 제공하지 않는 한 http를 선택하세요.

직접 작성한 커넥터에는 stdio 전송이 허용되지 않습니다. stdio는 MCP 서버가 호스트에서 시작하는 로컬 프로세스라는 뜻이며, Nessie 서버 안에서 임의의 프로그램을 실행하는 것은 운영자가 의미 있게 검토할 수 없기 때문입니다. 로컬에서 실행하도록 패키지로만 배포되는 서버도 같은 이유로 라이브러리 가져오기에서 제외됩니다. 프로토콜 필드에 ws 값이 있지만 구현되어 있지 않으며, 이 값을 사용하는 연결은 Nessie가 열려고 할 때 실패합니다.

Nessie가 서버에 인증하는 방법

카탈로그 항목은 다섯 가지 방법 중 하나를 선언합니다. none, api_key, bearer, basic, oauth2입니다.

api_key는 헤더 주입 방식입니다. 항목에 어떤 헤더와 어떤 접두사를 쓸지 적혀 있습니다. 따라서 Authorization: Bearer …, X-API-Key: …, X-Auth-Token: Token …은 모두 같은 방식을 서로 다르게 설정한 것입니다. 키 자체는 POST /api/mcp/instances/:instanceId/secret으로 한 번 붙여 넣으며, 이후에는 다시 읽을 수 없습니다. 인스턴스 라우트의 어떤 응답에도 자격 증명 참조가 포함되지 않습니다.

oauth2에는 두 가지 형태가 있습니다. 엔드포인트가 고정된 서버는 그 엔드포인트를 카탈로그 항목에 적어 둡니다. 표준 메타데이터를 게시하는 서버는 아무것도 설정할 필요가 없습니다. Nessie가 보호된 리소스와 권한 서버 문서를 읽고, 동적 클라이언트 등록을 통하거나 Nessie가 자신의 well-known 경로에 게시하는 클라이언트 ID 메타데이터 문서를 통해 클라이언트를 직접 만듭니다. 어느 쪽이든 핸드셰이크는 POST /api/mcp/instances/:instanceId/oauth/start로 시작해서, 제공자가 GET /api/mcp/oauth/callback으로 리디렉션하며 끝납니다. state 토큰은 한 번만 쓸 수 있고, 데이터베이스에 보관되며, 10분 동안 유효합니다. PKCE는 항상 사용합니다.

한 가지 규칙은 사람들을 자주 놀라게 합니다. 조직 소유자라도 개인 토큰이나 OAuth 토큰을 다른 사람에게 붙일 수 없습니다. 공유 자격 증명은 검증된 API 키 항목에서만 가능하며, 그 밖의 경우는 거부됩니다. 개인에게 속한 자격 증명은 계속 그 개인에게 속한 자격 증명으로 남습니다.

자격 증명이 저장되는 곳

커넥터 비밀과 OAuth 토큰 묶음은 여러분 자신의 Postgres 데이터베이스에 저장됩니다. 목적별로 묶인 AES-256-GCM 봉투에 담기며, 배포의 독립적으로 버전이 관리되는 암호화 키 링 아래에 있습니다. 주소는 불투명한 secret_* 참조로만 지정합니다. 이 자격 증명은 Nessie의 다른 비밀을 담는 외부 비밀 저장소에 의도적으로 들어 있지 않습니다. 암호화 저장소를 설정하지 않은 운영 배포는, 완료하고도 결과를 잃어버릴 OAuth 핸드셰이크를 진행하느니 시작을 거부합니다.

연결이 닿는 범위

인스턴스는 여섯 범위 중 하나에 설치됩니다. system, organization, project, team, channel, user입니다. 이 범위는 어떤 실행이 인스턴스를 사용할 수 있는지에 대한 엄격한 상한이며, 권한 부여는 이를 더 좁힐 수만 있고 넓힐 수는 없습니다. 따라서 여러분의 계정으로 설치한 커넥터가 몰래 조직 전체의 커넥터가 되는 일은 없습니다.

누가 어디에 설치할 수 있는지도 같은 형태를 따릅니다. 조직의 소유자와 관리자는 모든 범위의 설치를 관리하고, 그 밖의 사람들은 자신의 user 범위에 커넥터를 설치하며, 접근할 자격이 있는 공유 설치는 볼 수 있습니다.

에이전트에 도구 주기

서버를 연결한다고 그 도구가 누구에게나 전달되는 것은 아닙니다. 인스턴스를 설치하면 Nessie가 프로브를 실행하고, 서버가 광고하는 각 도구를 도구 레지스트리에 등록합니다. 이 레지스트리는 /admin/advanced/tools에 표시되며, 내장 도구, MCP 도구, 번들 도구, 실행기 도구가 출처와 상태와 함께 하나의 목록에 나타납니다.

등록된 도구는 세 가지 상태 중 하나입니다. active, pending_review, disabled입니다. 공유 범위 설치에서 온 도구는 pending_review로 들어오며, 에이전트가 보기 전에 이 페이지에서 승인해야 합니다. 여러분의 user 범위 설치에서 온 도구는 바로 활성 상태가 되는데, 노출되는 사람이 여러분뿐이기 때문입니다. 검토는 한 번 하고 끝나는 형식적 절차가 아니라 계속 이어집니다. 나중의 프로브에서 도구의 설명이나 스키마가 달라졌다는 것이 확인되면, 도구는 다시 pending_review로 돌아가고 누군가 변경 사항을 확인할 때까지 제공되지 않습니다.

활성 도구를 호출할 수 있는 에이전트는 두 가지 방식 중 하나로 정해집니다.

  • 앱 스토어를 통해 만든 연결은 명시적 권한 부여가 필요합니다. 에이전트는 권한 부여가 해당 도구를 지정한 경우에만 그 도구를 받습니다. 권한 부여는 도구의 현재 지문과 대조되므로, 바뀐 도구에는 새로운 결정이 필요합니다.
  • 그 밖의 경우에는 해당 범위에 닿는 에이전트에게 도구가 기본으로 켜져 있으며, 개별 에이전트는 도구의 상세 패널에서 끌 수 있습니다.

권한 부여는 정확히 하나의 주체, 즉 역할이나 에이전트 중 하나를 지정하며 둘을 동시에 지정하지 않습니다. 거부가 허용보다 우선합니다. user 범위 연결에서는 이 문제가 생기지 않습니다. 그 사람과 대화하는 모든 에이전트가 사용할 수 있으며, 명시적으로 끄는 것만이 이를 막습니다.

잘못된 곳에서 찾기 쉬운 것이 하나 있습니다. 관리자 화면의 /settings/accounts는 연결된 계정입니다. Slack, 메일함, 모델 구독, 그리고 외부 보드를 뒷받침하는 Linear, Jira, GitHub, Trello용 OAuth 연결이 여기에 있습니다. MCP 커넥터는 /admin/apps에 있으며, 그 커넥터가 만든 도구는 /admin/advanced/tools에 있습니다.

도구 호출의 승인 게이트

일부 도구 호출은 멈춰 서서 사람을 기다립니다. 이때 실행이 실패하지는 않습니다. 호출은 동결되며, 도구 이름, 인자의 해시, 재개에 필요한 상태가 함께 보존됩니다. 승인 요청은 /api/approvals에 나타나 누군가 응답하기를 기다립니다. 재개는 멱등하므로 중복된 승인이 같은 호출을 두 번 실행하지 않습니다. 결정하는 사람은 요청 내용의 제한된 요약을 봅니다. 정확한 인자와 원래 실행 정보는 서버에 남아 있습니다.

승인 게이트는 두 종류이며, 설정 방식도 다릅니다.

  • 구조적 게이트는 특정 내장 도구의 속성이며 설정할 수 없습니다. 에이전트의 메일함이나 연결된 메일함에서 메일을 보내는 것, Gmail 초안을 보내는 것, 메일 계정 연결을 끊는 것, 캘린더 일정을 만들고 바꾸고 취소하는 것, 그리고 브라우저가 로그인하지 않은 사이트에 쓰기를 시도하는 브라우저 동작이 모두 이 방식으로 게이트됩니다. 이들은 보통의 30분 대신 24시간 동안 응답을 기다릴 수 있습니다.
  • 정책 게이트는 tool/invoke 쌍에 대한 정책 규칙에서 옵니다. 호출을 허용하는 규칙에는 requiresApproval을 붙일 수 있으며, 검증된 승인이 없으면 평가 결과는 실행 대신 APPROVAL_REQUIRED가 됩니다. 규칙은 거부를 먼저 평가하며, 범위 순서대로 정렬됩니다.

도구에 대해 requiresApproval 정책 규칙을 작성하는 관리자 화면이 어디인지는 확인하지 못했습니다. 데이터 모델과 적용 로직은 모두 갖춰져 있지만, 그런 규칙을 쓰는 화면은 확인되지 않았습니다.


외부 에이전트를 Nessie에 연결하기

반대 방향입니다. Nessie는 자체 MCP 서버를 POST /mcp에서 스트리머블 HTTP로 실행합니다. 이 서버는 상태를 갖지 않습니다. 모든 호출이 자신의 자격 증명을 가지고 오고 자신의 행위자를 스스로 확인하므로, 클라이언트를 특정 레플리카에 고정할 세션이 없습니다. ChatGPT, Claude, Claude Code, Codex, 또는 누군가의 노트북에 있는 에이전트가, 그 사람이 이미 쓰고 있는 도구 안에서 보드, 문서, 고객 정보에 접근할 수 있습니다. 앱별 단계별 안내는 ChatGPT, Claude 등 AI 앱 연결하기에 있습니다.

페어링된 자격 증명이란 실제로 무엇인가

이 부분을 정확히 이해하는 것이 중요합니다. 흔히 떠올리는 모델, 즉 권한이 붙은 API 키라는 생각은 잘못된 모델이기 때문입니다.

페어링된 자격 증명은 신원이 아닙니다. 이 자격 증명은 한 사람을 가리키며, 모든 도구 호출은 그 사람의 이름으로 실행되고 HTTP 라우트가 호출하는 것과 같은 서비스 함수를 사용합니다. 그러므로 에이전트는 자격 증명을 빌려준 사람이 클릭해서 접근할 수 없는 것에는 접근할 수 없습니다. 범위는 접근을 좁힐 수만 있으며, 넓히는 범위는 없습니다.

유효성은 토큰에서 믿지 않고 모든 호출마다 다시 읽습니다. 취소, 만료, 사용자의 토큰 버전, 조직 소속, 현재 역할이 여기에 해당합니다. 강등, 비활성화, “모든 기기에서 로그아웃”은 자격 증명의 만료 시점이 아니라 에이전트의 다음 호출에서 바로 반영됩니다.

토큰은 불투명하며 nag1_ 접두사가 붙고, SHA-256 해시로만 저장되며, 90일 동안 유효합니다. MCP 엔드포인트 외의 다른 라우트에서는 특정 403으로 거부됩니다. 다른 곳에 제시하는 것은 재시도하면 되는 부분적 성공이 아닙니다. 이 규칙 덕분에 “내 보드를 에이전트에 빌려주었다”가 “내 계정을 빌려주었다”를 뜻하지 않습니다.

연결하는 두 가지 방법

브라우저를 열 수 있는 앱, 즉 ChatGPT, Claude, Claude Code, Codex는 MCP 인증 프로필을 사용합니다. PKCE(S256)를 쓰는 OAuth 2.1, POST /mcp/oauth/register에서의 동적 클라이언트 등록, 새로 고침 토큰, 리소스 지시자를 사용합니다. 앱이 사용자를 /settings/security로 보내면, 사용자는 앱이 할 수 있는 일과 앱이 접근할 팀을 고르고, 브라우저가 코드와 함께 앱으로 돌아갑니다. 액세스 토큰은 1시간 동안 유효하며 새로 고쳐집니다. 연결 자체는 90일 동안 유지됩니다.

커맨드라인 에이전트는 브라우저를 제어하지 못하고 콜백 URL도 가질 수 없으므로, 대신 기기 인증 부여(RFC 8628)로 페어링합니다.

  1. 에이전트가 clientName과 원하는 scopes를 담아 POST /mcp/auth/device를 호출합니다. 응답으로 device_code, 짧은 user_code, verification_uri, 쿼리에 코드가 이미 들어 있는 verification_uri_complete, 그리고 폴링 interval과 expires_in을 받습니다. 에이전트는 이 URI를 출력합니다.
  2. 사람은 로그인한 상태에서 그 URI를 /settings/security에서 엽니다. 어떤 에이전트가 요청하는지, 그 에이전트가 누구의 계정으로 작동할지, 언제까지인지, 무엇을 할 수 있는지를 정확히 확인하고 허용 또는 허용하지 않음을 선택합니다.
  3. 에이전트는 deviceCode를 담아 POST /mcp/auth/token을 폴링하며, authorization_pending, slow_down, expired_token, access_denied를 처리합니다. 성공하면 { access_token, token_type, scope, expires_at }을 받습니다.

어느 방식이든 사람이 직접 하는 단계가 있습니다. 자격 증명은 사람의 권한을 그대로 물려받으므로, 사람이 빌려주기로 선택해야 합니다. 여기서는 아무것도 없는 데서 접근 권한을 만들어 내지 않습니다. 연결 기능은 /admin/security?tab=programs에서 조직 전체에 대해 끌 수도 있으며, 이 설정은 에이전트가 연결을 시작할 때가 아니라 누군가 연결을 허용할 때 확인됩니다.

탐색

인증되지 않은 POST /mcp는 401을 응답하며, WWW-Authenticate 헤더가 /.well-known/oauth-protected-resource(RFC 9728)를 가리킵니다. 이 문서는 이 출처를 권한 서버로 지정합니다. 그 메타데이터인 /.well-known/oauth-authorization-server(RFC 8414)는 등록, 인증, 토큰, 취소 엔드포인트를 알려 줍니다. 클라이언트가 주소를 알고 나면 필요한 것은 이것이 전부입니다. 도메인에서 주소를 찾으려면 에이전트가 /.well-known/ai-catalog.json을 읽습니다. 이 파일은 /mcp/server-card의 서버 카드를 가리킵니다(MCP Server Cards, SEP-2127). 기기 인증 부여의 엔드포인트는 보호된 리소스 문서의 x-nessie-device-authorization 아래에 나열되어 있습니다.

배포는 두 번째의 더 짧은 주소에서도 응답할 수 있습니다. Nessie Cloud의 https://nessie.works/mcp는 API로 프록시됩니다. 그 주소로 들어온 클라이언트는 리소스로 그 주소를 다시 받게 되며, 로그인은 API에 그대로 남습니다. 리디렉션으로는 안 되는데, 클라이언트는 자신이 받은 주소 외의 다른 주소를 지정한 메타데이터를 거부하기 때문입니다. 운영자는 이런 출처를 NESSIE_MCP_ALIAS_ORIGINS에 나열합니다.

범위와 도구

범위는 의도적으로 거칠게 나눕니다. 아무도 설명할 수 없는 범위는 아무도 올바르게 설정하지 못하기 때문입니다. 둘 이상의 팀에 닿는 연결은 nessie_team_list로 팀을 나열하며, 그 밖의 모든 도구는 teamId를 지정합니다.

범위접근 대상
boards_read프로젝트, 보드, 티켓과 그 댓글, 파일, 레이블, 유형, 체크리스트
boards_write티켓을 만들고, 편집하고, 옮기며, 티켓의 모든 항목
documents_read지식 공간, 문서, 스프레드시트
documents_write초안 작성과 편집, 그리고 문서 게시 요청
clients_read고객 받은편지함, 연락처, 연락처 목록, 뉴스레터, 연락처 양식
clients_write메모, 대화 가져오기·배정·종료, 연락처 목록, 뉴스레터 준비
clients_send고객이 받는 모든 것: 답장, 첫 이메일, 문자. 사람이 직접 체크하지 않는 한 절대 선택되지 않습니다.
website_tools팀에 등록된 웹사이트의 페이지 도구를, 여러분이 제어할 수 있는 호스팅 브라우저에서 조작합니다. 사람이 직접 체크하지 않는 한 절대 선택되지 않습니다.

필요한 범위 없이 호출하면 전송 오류가 아니라, 필요한 범위를 요청하라고 알려 주는 도구 결과로 돌아옵니다. 그래야 모델이 쓸모 있는 내용을 보고할 수 있고, 벽에 부딪히며 계속 재시도하는 일을 피할 수 있습니다.

외부 트래커용 도구 세트는 따로 없습니다. 보드는 그 작업이 Nessie에서 시작되었든 Linear, Jira, GitHub, Trello에서 미러링되었든 보드이므로, 하나의 도구 세트가 둘 다 다룹니다. 모든 작업에는 어디에서 왔는지가 표시됩니다. 차이는 쓰기에 있습니다. 읽기 전용 원본에서 미러링된 보드는 쓰기를 거부하며, 다른 시스템이 그 티켓을 소유하고 있으니 재시도해도 소용없다고 에이전트에게 설명합니다.

문서 게시는 권한이 아니라 승인입니다

에이전트는 초안을 작성하고, 게시는 사람이 합니다. 이 규칙은 Nessie 자체 에이전트에 대해서는 에이전트 행위자를 아예 거부하는 방식으로 강제됩니다. 그러나 페어링된 자격 증명은 사람으로 확인되므로, 그 거부로는 이를 잡아낼 수 없습니다. 따라서 게이트를 다른 곳에 두어야 합니다.

그래서 nessie_doc_publish는 게시하지 않습니다. 대신 knowledge.page.publish 승인을 엽니다. Nessie 에이전트가 여는 것과 같은 승인입니다. 그리고 { status: "awaiting_approval", approvalId }를 반환합니다. 폴링하면 두 번째 요청을 만들지 않고 같은 요청을 돌려줍니다. 이 게시 결정은 Nessie의 다른 모든 게시 결정과 같은 방식으로 내려집니다. 즉 문서가 존재하는 바로 그 순간에, 그 문서에 대해 사람이 결정합니다.

게시 권한은 의도적으로 없습니다. 예전에는 있었습니다. 페어링할 때 이 에이전트가 게시할 수 있다는 체크 항목이 있었지만, 폐지되었습니다. 그것은 90일 동안 한 번에 결정해 버렸는데, 제품이 다른 모든 곳에서는 문서마다 묻는 질문이었고, 문서가 존재하기도 전에 결정해 버렸습니다. 그래서 이 항목을 체크하는 사람은 자신이 무엇의 게시에 동의하는지 알 수 없었습니다. nessie_doc_publish에는 documents_write가 필요합니다. 요청하는 행위에도 비용이 들기 때문입니다. 페이지를 읽고 결정을 사람 앞에 올려 놓아야 합니다. 하지만 이 범위는 게시에 대해 아무 권한도 주지 않습니다.

요청에는 두 가지 신원이 기록되며, 이 구분은 매우 중요합니다. 요청자는 자격 증명이며, 그 자격 증명이 대신하는 사람이 아닙니다. 필요한 승인자는 그 사람이며, 그 사람만 응답할 수 있습니다. 만약 요청이 그 사람을 요청자로 기록한다면, 자기 요청을 스스로 승인하지 못하게 하는 규칙이 결정할 자격이 있는 유일한 사람을 걸러 내 버리게 됩니다.

페어링된 항목 보기와 취소하기

사람은 자신의 페어링된 에이전트 목록을 /settings/security에서 볼 수 있으며, 각 항목에 이름과 취소 컨트롤이 있습니다. 소유자나 조직 관리자는 /admin/security?tab=programs에서 조직의 모든 자격 증명을 봅니다. 각 자격 증명의 이름, 할 수 있는 일, 유효 여부, 그리고 어떤 계정을 빌렸는지가 보이며, 어느 것이든 취소할 수 있습니다. 개인 목록은 본인만 볼 수 있도록 유지됩니다. 살아 있는 자격 증명의 목록은 일반 열람용 정보가 아니라 발판 목록이기 때문입니다.

자격 증명을 통해 이루어진 쓰기는 그것을 빌려준 사람에게 귀속되며, 감사 메타데이터에 자격 증명의 ID가 담깁니다. 그래서 감사 기록는 사람이 직접 한 편집과 에이전트가 그 사람을 대신해 한 편집을 구별할 수 있습니다.

아직 제공되지 않는 기능

명확하게 밝혀 둡니다. 프로토콜이 할 수 있는 것과 특정 서버가 하는 것 사이의 간극은 문서가 흔히 어긋나는 지점이기 때문입니다:

  • 채팅, 채널, 실행, 에이전트 관리는 MCP로 노출되지 않습니다.
  • 외부 에이전트는 뉴스레터를 준비하고, 발송은 사람이 합니다. 캠페인을 보내거나, 예약하거나, 삭제하는 기능은 없으며, 이메일 본문 자체는 디자이너에서 작성합니다.
  • 연락처 병합과 연결, CRM 스키마 변경, 가져오기, 채널 설정은 여전히 브라우저에서 사람이 직접 합니다.
  • 연결 허용 스위치는 조직 수준의 설정입니다. 팀 수준이나 개인 수준의 재정의는 지금은 팀이나 개인이 설정할 수 없습니다.