MCP i połączone narzędzia
Połącz Nessie z serwerami MCP i sparuj zewnętrznego agenta, aby mógł pracować w Nessie w twoim imieniu.
Czym jest MCP
Model Context Protocol to mała, otwarta konwencja opisywania narzędzi modelowi językowemu i ich wywoływania. Serwer deklaruje, co potrafi — listę nazwanych narzędzi, każde ze schematem JSON swoich argumentów — a klient odkrywa tę listę i wywołuje narzędzia w imieniu modelu. Jest celowo nudny: jego wartość polega na tym, że jedna integracja napisana raz działa z każdym modelem i każdym produktem, który mówi tym protokołem.
Nessie działa po obu stronach
Warto to ująć precyzyjnie, bo obie strony łatwo pomylić, a biegną one celowo różnymi ścieżkami.
- Wychodząco. Nessie działa jako klient MCP. Podłączasz serwery prowadzone przez kogoś innego, a narzędzia, które udostępniają, stają się narzędziami dostępnymi dla agentów. Powierzchnia zarządzania to
/api/mcp/*. - Przychodząco. Nessie działa też jako serwer MCP. Agent działający gdzie indziej — Claude Code lub Codex na komputerze dewelopera — może wywoływać tablice i dokumenty w twoim Nessie. Ten punkt końcowy to
POST /mcp, celowo poza/api, żeby dwa przeciwstawne znaczenia nie leżały od siebie o jeden segment ścieżki.
Podłączanie serwera MCP do Nessie
Wpisy w katalogu i instancje
Są dwa obiekty i ich rozróżnienie ma znaczenie:
- Wpis w katalogu to definicja serwera — jego nazwa, transport i sposób uwierzytelniania. Jest zapisywany raz i może być współdzielony.
- Instancja to ten wpis zainstalowany w jednym zakresie, z poświadczeniami, które do niego docierają. Zainstalowanie tego samego wpisu dla dwóch różnych zespołów tworzy dwie instancje.
Większość osób nie dotyka żadnego z nich bezpośrednio. Wejściem w panelu jest sklep z aplikacjami pod /admin/apps: przegląda ten sam katalog z ukrytymi szczegółami połączenia, a Connect przy ofercie tworzy instancję. Operatorzy, którzy chcą surowych obiektów, używają /api/mcp/catalog i /api/mcp/instances.
Jeśli serwera nie ma jeszcze w katalogu, POST /api/mcp/discover przyjmuje adres URL i zwraca to, co serwer mówi o sobie, a POST /api/mcp/library/import pobiera wpis z publicznej biblioteki serwerów. Połączenie przy pierwszym uruchomieniu można też utworzyć wprost z adresu URL przez POST /api/apps/custom.
Transporty
Nessie łączy się ze zdalnymi serwerami przez HTTP. Działają dwa transporty: streamable HTTP (obecny transport MCP) oraz starszy HTTP+SSE. Wybierz http, chyba że serwer oferuje tylko sse.
Transport stdio jest odrzucany dla łączników, które sam tworzysz. stdio oznacza, że serwer MCP jest lokalnym procesem uruchamianym przez hosta, a uruchamianie dowolnych programów wewnątrz serwera Nessie nie jest czymś, co operator mógłby sensownie przejrzeć. Serwery opublikowane wyłącznie jako pakiet do lokalnego uruchomienia są z tego samego powodu pomijane przy importach z biblioteki. Wartość ws istnieje w polu protokołu i nie jest zaimplementowana — połączenie z jej użyciem kończy się błędem, gdy Nessie próbuje je otworzyć.
Jak Nessie uwierzytelnia się wobec serwera
Wpis w katalogu deklaruje jedną z pięciu metod: none, api_key, bearer, basic lub oauth2.
api_key to wstrzykiwanie nagłówka, a wpis określa, który nagłówek i jaki prefiks — więc Authorization: Bearer …, X-API-Key: … i X-Auth-Token: Token … to ta sama metoda, tylko skonfigurowana inaczej. Klucz wkleja się raz przez POST /api/mcp/instances/:instanceId/secret i nigdy później nie da się go odczytać; żadna odpowiedź z tras instancji nie zawiera odwołania do poświadczenia.
oauth2 występuje w dwóch postaciach. Serwer ze stałymi punktami końcowymi ma je w swoim wpisie w katalogu. Serwer, który publikuje standardowe metadane, nie wymaga żadnej konfiguracji: Nessie odczytuje dokumenty chronionego zasobu i serwera autoryzacji, a klienta tworzy sobie przez dynamiczną rejestrację klienta lub przez dokument metadanych identyfikatora klienta, który publikuje pod własną ścieżką well-known. W obu przypadkach uzgadnianie przebiega przez POST /api/mcp/instances/:instanceId/oauth/start, a następnie przekierowanie dostawcy z powrotem na GET /api/mcp/oauth/callback. Token state jest jednorazowy, przechowywany w bazie i ważny przez dziesięć minut, a PKCE jest używane zawsze.
Jedna zasada zaskakuje ludzi: nawet właściciel organizacji nie może przypisać komuś innemu osobistego tokena ani tokena OAuth. Współdzielone poświadczenie jest możliwe tylko dla wpisu z kluczem API, który został zweryfikowany jako taki; wszystko inne jest odrzucane. Poświadczenie należące do osoby pozostaje poświadczeniem tej osoby.
Gdzie przechowywane są poświadczenia
Sekrety łączników i pakiety tokenów OAuth są przechowywane we własnej bazie Postgres, w kopertach AES-256-GCM przypisanych do konkretnego celu, pod niezależnie wersjonowanym pierścieniem kluczy szyfrujących wdrożenia, i są adresowane wyłącznie nieprzezroczystymi odwołaniami secret_*. Celowo nie znajdują się w zewnętrznym sejfie sekretów, który przechowuje inne sekrety Nessie. Produkcja, w której nie skonfigurowano zaszyfrowanego magazynu, odmawia startu zamiast dokończyć uzgadnianie OAuth, które i tak trzeba byłoby odrzucić.
Dokąd sięga połączenie
Instancja jest zainstalowana w jednym z sześciu zakresów: system, organization, project, team, channel lub user. Zakres jest twardym limitem tego, które uruchomienia mogą z niej korzystać, a przyznania mogą go tylko zawęzić, nigdy poszerzyć — więc łącznik zainstalowany na własnym koncie nie może po cichu stać się łącznikiem dla całej organizacji.
Kto może instalować gdzie, wygląda tak samo: właściciele i administratorzy organizacji zarządzają instalacjami na każdym zakresie; wszyscy pozostali instalują łączniki w swoim zakresie user i widzą współdzielone instalacje, do których mają dostęp.
Przyznawanie agentowi narzędzia
Podłączenie serwera nie przekazuje jego narzędzi nikomu. Gdy instancja jest zainstalowana, Nessie ją sprawdza i rzutuje każde ogłaszane przez nią narzędzie do rejestru narzędzi — to ten rejestr administrator widzi pod /admin/advanced/tools: narzędzia wbudowane, narzędzia MCP, narzędzia pakietów i narzędzia executorów na jednej liście, każde ze źródłem i statusem.
Rzutowane narzędzie ma jeden z trzech statusów: active, pending_review lub disabled. Narzędzia z instalacji o zakresie współdzielonym trafiają jako pending_review i muszą zostać zatwierdzone na tej stronie, zanim agent je zobaczy; narzędzia z własnej instalacji o zakresie user są od razu aktywne, bo jedyną osobą, której to dotyczy, jest właściciel połączenia. Przegląd jest cykliczny, a nie jednorazowy: jeśli późniejsze sprawdzenie wykryje, że opis lub schemat narzędzia się zmienił, narzędzie wraca do pending_review i nie jest oferowane, dopóki ktoś nie sprawdzi zmiany.
O tym, którzy agenci mogą wywołać aktywne narzędzie, decyduje jeden z dwóch sposobów:
- Połączenie utworzone przez sklep z aplikacjami wymaga jawnego przyznania. Agent otrzymuje narzędzie tylko wtedy, gdy przyznanie je wymienia, a przyznanie jest sprawdzane względem bieżącego odcisku narzędzia, więc zmienione narzędzie wymaga nowej decyzji.
- W przeciwnym razie narzędzie jest domyślnie włączone dla agentów w zasięgu jego zakresu, a poszczególnych agentów wyłącza się w panelu szczegółów narzędzia.
Przyznanie wskazuje dokładnie jednego podmiota — rolę albo agenta, nigdy oba — a odmowa bije zezwolenie. Dla połączenia o zakresie user pytanie się nie pojawia: każdy agent, z którym rozmawia ta osoba, może z niego korzystać, a jedynym, co to wstrzymuje, jest jawne wyłączenie.
Jedna rzecz, której łatwo szukać w złym miejscu: /settings/accounts w panelu to połączone konta — Slack, skrzynki pocztowe, subskrypcje modeli oraz linki OAuth do Linear, Jira, GitHub i Trello, które zasilają zewnętrzne tablice. Łączniki MCP są pod /admin/apps, a narzędzia, które tworzą, są pod /admin/advanced/tools.
Bramki zatwierdzania wywołań narzędzi
Niektóre wywołania narzędzi zatrzymują się i czekają na człowieka. Gdy tak się dzieje, uruchomienie nie kończy się błędem: wywołanie jest zamrożone — nazwa narzędzia, skrót jego argumentów i stan wystarczający do wznowienia — a prośba o zatwierdzenie pojawia się pod /api/approvals, żeby ktoś na nią odpowiedział. Wznowienie jest idempotentne, więc zduplikowane zatwierdzenie nie może wykonać wywołania dwa razy. Osoba decydująca widzi ograniczone podsumowanie tego, o co się pyta; dokładne argumenty i uruchomienie, które je wywołało, pozostają po stronie serwera.
Są dwie odrębne bramki i konfiguruje się je inaczej.
- Bramki strukturalne są właściwością pewnych wbudowanych narzędzi i nie podlegają konfiguracji. W ten sposób są bramkowane: wysyłanie poczty ze skrzynki agenta lub podłączonej skrzynki, wysyłanie szkicu Gmail, odłączanie konta pocztowego, tworzenie, zmienianie lub anulowanie wydarzenia w kalendarzu oraz działanie w przeglądarce, które zapisałoby dane na stronie, do której przeglądarka nie jest zalogowana. Na odpowiedź mają 24 godziny zamiast zwykłych 30 minut.
- Bramki polityki pochodzą z reguł polityki dla pary
tool/invoke. Reguła zezwalająca na wywołanie może miećrequiresApproval; bez zweryfikowanego zatwierdzenia ocena zwracaAPPROVAL_REQUIREDzamiast uruchomić wywołanie. Reguły są oceniane najpierw pod kątem odmowy i uporządkowane według zakresu.
Nie udało się potwierdzić, który ekran w panelu tworzy regułę polityki z requiresApproval dla narzędzia — model danych i egzekwowanie są oba na miejscu, ale nie znamy ekranu, który taką regułę zapisuje.
Podłączanie zewnętrznego agenta do Nessie
Kierunek przeciwny. Nessie uruchamia własny serwer MCP pod POST /mcp, przez streamable HTTP, i jest bezstanowy: każde wywołanie niesie własne poświadczenie i samo ustala swojego aktora, więc nie ma sesji, którą można by przypiąć klienta do jednej repliki. ChatGPT, Claude, Claude Code, Codex lub agent na czyimś laptopie mogą pracować na twoich tablicach, dokumentach i klientach z poziomu narzędzia, którego dana osoba już używa. Instrukcja krok po kroku dla każdej aplikacji to Połączenie ChatGPT, Claude i innych aplikacji AI.
Czym naprawdę jest sparowane poświadczenie
To część, którą trzeba dobrze zrozumieć, bo oczywisty model mentalny — klucz API z uprawnieniami dołączonymi do niego — jest błędny.
Sparowane poświadczenie nigdy nie jest tożsamością. Wskazuje człowieka, a każde wywołanie narzędzia działa jako ten człowiek, wobec tych samych funkcji serwisowych, które wywołują trasy HTTP. Agent więc nie może dosięgnąć niczego, czego osoba, która je udostępniła, nie mogłaby osiągnąć, klikając. Zakresy mogą tylko zawęzić ten zasięg; nie ma zakresu, który by go poszerzał.
Ważność jest sprawdzana przy każdym wywołaniu, nigdy nie jest przejmowana z tokena: unieważnienie, wygaśnięcie, wersja tokena użytkownika, członkostwo w organizacji i bieżąca rola. Degradacja, dezaktywacja lub „wyloguj mnie wszędzie” działają przy następnym wywołaniu agenta, a nie dopiero przy wygaśnięciu poświadczenia.
Token jest nieprzezroczysty, z prefiksem nag1_, przechowywany wyłącznie jako skrót SHA-256 i żyje 90 dni. Jest odrzucany z konkretnym 403 na każdej trasie innej niż punkt końcowy MCP — przedstawienie go w innym miejscu nie jest częściowym sukcesem do ponowienia, i to właśnie sprawia, że „użyczyłem agentowi swoich tablic” nie znaczy „użyczyłem mu swojego konta”.
Dwa sposoby połączenia
Aplikacja, która potrafi otworzyć przeglądarkę — ChatGPT, Claude, Claude Code, Codex — korzysta z profilu autoryzacji MCP: OAuth 2.1 z PKCE (S256), dynamiczną rejestracją klienta pod POST /mcp/oauth/register, tokenami odświeżania i wskaźnikami zasobów. Aplikacja kieruje osobę do /settings/security, ta wybiera, co aplikacja może robić i do których zespołów ma dostęp, a przeglądarka wraca do aplikacji z kodem. Jej token dostępu żyje godzinę i jest odświeżany; połączenie trwa 90 dni.
Agent wiersza poleceń nie steruje przeglądarką i nie może hostować adresu callback, więc paruje się zamiast tego przez autoryzację urządzenia (device authorization grant, RFC 8628).
- Agent wywołuje
POST /mcp/auth/devicezclientNameiscopes, których potrzebuje. Dostaje z powrotemdevice_code, krótkiuser_code,verification_uriorazverification_uri_completez już wpisanym kodem w zapytaniu, a także interwał odpytywaniaintervaliexpires_in. Wypisuje adres URI. - Osoba otwiera ten adres URI, będąc zalogowaną, pod
/settings/security. Widzi, który agent pyta, na czyim koncie by działał, do kiedy i dokładnie co mógłby robić — po czym wybiera Allow albo Don’t allow. - Agent odpytuje
POST /mcp/auth/tokenzdeviceCode, respektującauthorization_pending,slow_down,expired_tokeniaccess_denied. Po sukcesie otrzymuje{ access_token, token_type, scope, expires_at }.
W obu przypadkach jest krok człowieka, bo poświadczenie dziedziczy uprawnienia osoby, więc osoba musi zdecydować się je udostępnić. Nic tu nie wytwarza dostępu z niczego. Podłączanie można też wyłączyć dla całej organizacji pod /admin/security?tab=programs, a ta odpowiedź jest sprawdzana wtedy, gdy ktoś zezwala na połączenie, a nie wtedy, gdy agent je rozpoczyna.
Odkrywanie
Nieuwierzytelnione POST /mcp odpowiada 401 z nagłówkiem WWW-Authenticate wskazującym na /.well-known/oauth-protected-resource (RFC 9728), który nazywa ten origin serwerem autoryzacji; jego metadane pod /.well-known/oauth-authorization-server (RFC 8414) wymieniają punkty końcowe rejestracji, autoryzacji, tokenu i unieważniania. Ten łańcuch to wszystko, czego klient potrzebuje, gdy ma już adres. Aby znaleźć adres po domenie, agent czyta /.well-known/ai-catalog.json, który wskazuje Server Card pod /mcp/server-card (MCP Server Cards, SEP-2127). Punkty końcowe grantu urządzenia są wymienione w dokumencie chronionego zasobu pod kluczem x-nessie-device-authorization.
Wdrożenie może też odpowiadać pod drugim, krótszym adresem: https://nessie.works/mcp w Nessie Cloud jest przekazywany do API, a klient, który przyszedł tą drogą, dostaje ten adres z powrotem jako zasób, podczas gdy logowanie pozostaje pod API. Przekierowanie by nie wystarczyło, bo klient odrzuca metadane wskazujące inny adres niż ten, który mu podano. Operator wymienia te originy w NESSIE_MCP_ALIAS_ORIGINS.
Zakresy i narzędzia
Zakresy są celowo grube — zakres, którego nikt nie potrafi wyjaśnić, nikt nie ustawi poprawnie. Połączenie obejmujące więcej niż jeden zespół wymienia je poleceniem nessie_team_list, a każde inne narzędzie wskazuje wtedy swój teamId.
| Zakres | Dotyczy |
|---|---|
boards_read | Projekty, tablice i zgłoszenia wraz z ich komentarzami, plikami, etykietami, typami i listami kontrolnymi |
boards_write | Tworzenie, edytowanie i przenoszenie zgłoszeń oraz wszystko, co się na nich znajduje |
documents_read | Przestrzenie wiedzy, dokumenty i arkusze kalkulacyjne |
documents_write | Pisanie i edytowanie ich oraz proszenie o publikację dokumentu |
clients_read | Skrzynka odbiorcza klientów, kontakty, listy kontaktów, newslettery i formularze kontaktowe |
clients_write | Notatki, przejmowanie, przypisywanie i zamykanie rozmów, listy kontaktów oraz przygotowywanie newsletterów |
clients_send | Wszystko, co dostaje klient: odpowiedź, pierwszy e-mail albo SMS. Nigdy nie jest zaznaczone, dopóki osoba tego nie zaznaczy |
website_tools | Narzędzia stron zarejestrowanej witryny twojego zespołu, obsługiwane w przeglądarce hostowanej, którą możesz kontrolować. Nigdy nie jest zaznaczone, dopóki osoba tego nie zaznaczy |
Wywołanie bez zakresu, którego potrzebuje, wraca jako wynik narzędzia wskazujący zakres, o który trzeba poprosić, a nie jako błąd transportu, więc model może zgłosić coś użytecznego zamiast ponawiać w ścianę.
Nie ma osobnej rodziny narzędzi dla zewnętrznych systemów zgłoszeń. Tablica jest tablicą niezależnie od tego, czy jej zadania pochodzą z Nessie, czy są lustrzane z Linear, Jira, GitHub lub Trello, więc jeden zestaw narzędzi obejmuje oba przypadki, a każde zgłoszenie mówi, skąd pochodzi. Różnica dotyczy zapisu: tablica zlustrzana ze źródła tylko do odczytu odrzuca zapis słownie, informując agenta, że zgłoszenie należy do innego systemu i ponawianie nie pomoże.
Publikacja dokumentu to zatwierdzenie, a nigdy zakres
Agenci tworzą szkice; publikuje człowiek. Ta zasada jest egzekwowana dla agentów Nessie przez całkowite odrzucenie aktora-agenta — ale sparowane poświadczenie jest rozpoznawane jako osoba, więc to odrzucenie go nie złapie. Bramka musi znajdować się gdzie indziej.
Dlatego nessie_doc_publish nie publikuje. Otwiera zatwierdzenie knowledge.page.publish — to samo, które otwiera agent Nessie — i zwraca { status: "awaiting_approval", approvalId }. Odpytywanie zwraca tę samą prośbę zamiast otwierać drugą. Decyzja zapada tak samo jak każda inna decyzja o publikacji w Nessie: przez człowieka, o tym konkretnym dokumencie, w chwili, gdy on istnieje.
Celowo nie ma zakresu publikacji. Kiedyś był — zaznaczenie przy parowaniu, że agent może publikować — i został wycofany. Rozstrzygał raz i na dziewięćdziesiąt dni pytanie, które produkt wszędzie indziej zadaje dla każdego dokumentu, i rozstrzygał je, zanim dokument w ogóle istniał, więc osoba zaznaczająca nie mogła wiedzieć, na co się zgadza. nessie_doc_publish wymaga documents_write, bo proszenie nie jest darmowe — czyta stronę i stawia decyzję przed kimś — ale ten zakres nie daje żadnego uprawnienia do publikacji.
Na prośbie zapisywane są dwie tożsamości, a rozróżnienie ma znaczenie. Wnioskodawcą jest poświadczenie, nigdy człowiek, w którego imieniu działa. Wymaganym zatwierdzającym jest ten człowiek i tylko on może odpowiedzieć. Gdyby prośba wskazywała osobę jako wnioskodawcę, reguła zabraniająca zatwierdzania własnej prośby wykluczyłaby jedyną osobę uprawnioną do decyzji.
Podgląd i unieważnianie sparowanych poświadczeń
Sparowani agenci danej osoby są widoczni pod /settings/security, z etykietą i kontrolką unieważnienia przy każdym z nich. Właściciel albo administrator organizacji widzi każde poświadczenie w organizacji pod /admin/security?tab=programs — jak się nazywa, co może robić, czy jest aktywne i czyje konto pożycza — i może unieważnić dowolne z nich. Osobista lista pozostaje wyłącznie własna: lista aktywnych poświadczeń to lista przyczółków, a nie ogólny podgląd.
Zapisy wykonane przez poświadczenie są przypisywane pożyczającemu człowiekowi i niosą identyfikator poświadczenia w metadanych audytu, więc dziennik potrafi odróżnić edycję osoby od edycji, którą jej agent wykonał w jej imieniu.
Czego jeszcze nie ma
Mówimy to wprost, bo to właśnie w luce między możliwościami protokołu a możliwościami konkretnego serwera dokumentacja zwykle zawodzi:
- Czat, kanały, uruchomienia i zarządzanie agentami nie są udostępnione przez MCP.
- Agent przygotowuje newsletter, a wysyła go człowiek: nic nie wysyła, nie planuje ani nie usuwa kampanii, a sam e-mail pisze się w edytorze.
- Łączenie i scalanie kontaktów, zmiany schematu CRM, importy i konfiguracja kanałów pozostają po stronie człowieka w przeglądarce.
- Przełącznik podłączania jest ustawieniem na poziomie organizacji. Ustawień na poziomie zespołu i osobistych nadpisań nie może dziś ustawić ani zespół, ani osoba.