{"id":478174,"date":"2026-04-30T19:02:32","date_gmt":"2026-04-30T19:02:32","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=478174"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=478174","title":{"rendered":"Per-user OAuth \u0434\u043b\u044f MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432: Keycloak, n8n \u0438 Telegram-\u0431\u043e\u0442 \u0447\u0435\u0440\u0435\u0437 \u043e\u0434\u0438\u043d Auth Proxy"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0435 MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u044b, AI-\u0430\u0433\u0435\u043d\u0442 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0432 Telegram. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 Keycloak, \u0430 \u0430\u0433\u0435\u043d\u0442 \u2014 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0442 \u0435\u0433\u043e \u0438\u043c\u0435\u043d\u0438. \u0417\u0434\u0435\u0441\u044c \u0441\u043e\u0431\u0440\u0430\u043d\u044b \u0433\u0440\u0430\u0431\u043b\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u043b\u0438, \u0438 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u0440\u0438\u0448\u043b\u0438.<\/p>\n<h3>\u041a\u043e\u043c\u0443 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u0438\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0435\u0442\u0435 OAuth\/OIDC \u043a \u0447\u0435\u043c\u0443-\u0442\u043e, \u0447\u0442\u043e \u043d\u0430 \u044d\u0442\u043e \u043d\u0435 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u043e<\/p>\n<\/li>\n<li>\n<p>\u0421\u0442\u0440\u043e\u0438\u0442\u0435 \u043c\u0443\u043b\u044c\u0442\u0438\u0442\u0435\u043d\u0430\u043d\u0442\u043d\u043e\u0433\u043e AI-\u0430\u0433\u0435\u043d\u0442\u0430, \u0433\u0434\u0435 \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441\u0432\u043e\u0438 \u043f\u0440\u0430\u0432\u0430<\/p>\n<\/li>\n<li>\n<p>\u041f\u044b\u0442\u0430\u0435\u0442\u0435\u0441\u044c \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u044b \u0441 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u043c IdP<\/p>\n<\/li>\n<li>\n<p>\u041f\u0438\u0448\u0435\u0442\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043d\u043e\u0434\u044b \u0434\u043b\u044f n8n<\/p>\n<\/li>\n<\/ul>\n<h3>\u0418\u0441\u0445\u043e\u0434\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h3>\n<p>MCP (Model Context Protocol) \u2014 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u043e\u0442 Anthropic \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f AI-\u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u043a \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c. \u0423 \u043d\u0430\u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432, \u043f\u0435\u0440\u0435\u0434 \u043d\u0438\u043c\u0438 \u2014 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u043a\u0441\u0438 \u043d\u0430 FastMCP, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435 \u0432 \u0435\u0434\u0438\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b75\/b20\/a41\/b75b20a41af83793f151eb18614cd7c8.png\" alt=\"\u0421\u0445\u0435\u043c\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b\" title=\"\u0421\u0445\u0435\u043c\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b\" width=\"761\" height=\"591\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/b75\/b20\/a41\/b75b20a41af83793f151eb18614cd7c8.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b75\/b20\/a41\/b75b20a41af83793f151eb18614cd7c8.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0445\u0435\u043c\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b<\/figcaption><\/div>\n<\/figure>\n<p>\u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u043a\u0441\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u043b, \u043d\u043e \u043d\u0435 \u0437\u043d\u0430\u043b, \u043a\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441. \u041b\u044e\u0431\u043e\u0439, \u043a\u0442\u043e \u0434\u043e\u0441\u0442\u0443\u0447\u0438\u0442\u0441\u044f \u0434\u043e \u043f\u043e\u0440\u0442\u0430, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u043e \u0432\u0441\u0435\u043c\u0443. \u0414\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u044d\u0442\u043e \u0442\u0435\u0440\u043f\u0438\u043c\u043e, \u043d\u043e \u0434\u043b\u044f \u0431\u043e\u0442\u0430 \u0441 \u0441\u043e\u0442\u043d\u044f\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u2014 \u0443\u0436\u0435 \u043d\u0435\u0442.<\/p>\n<h3>\u0412\u044b\u0431\u043e\u0440 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b: \u043f\u043e\u0447\u0435\u043c\u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441<\/h3>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u043f\u043e\u0440\u044b\u0432 \u2014 \u0437\u0430\u0441\u0443\u043d\u0443\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0442\u043e\u043a\u0435\u043d\u0430 \u043f\u0440\u044f\u043c\u043e \u0432 \u043f\u0440\u043e\u043a\u0441\u0438. \u0411\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u043d\u044f\u043b\u0438, \u0447\u0442\u043e \u043d\u0435 \u0445\u043e\u0442\u0438\u043c \u043c\u0435\u0448\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044e \u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435. Gateway \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432, \u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u2014 \u0448\u0442\u0443\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043b\u0443\u0447\u0448\u0435 \u043c\u0435\u043d\u044f\u0442\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0436\u0435.<\/p>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u2014 \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 MCP-\u0441\u0435\u0440\u0432\u0435\u0440. \u041d\u043e \u0438\u0445 \u0443 \u043d\u0430\u0441 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0443\u0447\u0438\u0442\u044c \u0445\u043e\u0434\u0438\u0442\u044c \u0432 Keycloak. \u0410 \u0435\u0441\u043b\u0438 \u0437\u0430\u0432\u0442\u0440\u0430 \u043c\u044b \u0441\u043c\u0435\u043d\u0438\u043c IdP \u2014 \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435.<\/p>\n<p>\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c Auth Proxy \u043f\u0435\u0440\u0435\u0434 Gateway. \u0414\u0430, \u044d\u0442\u043e \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0441\u0435\u0440\u0432\u0438\u0441 \u0432 \u0434\u0435\u043f\u043b\u043e\u0435 \u0438 \u043b\u0438\u0448\u043d\u0438\u0435 3-5 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441. \u041d\u043e \u043a\u043e\u0433\u0434\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0443\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 LLM (2-4 \u0441\u0435\u043a\u0443\u043d\u0434\u044b), \u044d\u0442\u0438 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u044b \u0440\u043e\u043b\u0438 \u043d\u0435 \u0438\u0433\u0440\u0430\u044e\u0442. \u0417\u0430\u0442\u043e Gateway \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0447\u0438\u0441\u0442\u044b\u043c \u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043e\u0440\u043e\u043c, \u0430 \u0432\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0436\u0438\u0432\u0435\u0442 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f07\/5d2\/997\/f075d2997368f8df2681162ba112965b.png\" alt=\"\u0421\u0445\u0435\u043c\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0441 per-user OAuth\" title=\"\u0421\u0445\u0435\u043c\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0441 per-user OAuth\" width=\"1052\" height=\"772\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/f07\/5d2\/997\/f075d2997368f8df2681162ba112965b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f07\/5d2\/997\/f075d2997368f8df2681162ba112965b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0445\u0435\u043c\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0441 per-user OAuth<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 FastMCP \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c <code>OAuthProxy<\/code> \u2014 \u043e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f MCP-\u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u043a\u0430\u043a \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 OAuth-\u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 Dynamic Client Registration, \u0430 \u0437\u0430 \u043a\u0443\u043b\u0438\u0441\u0430\u043c\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 credentials \u0441 Keycloak. \u041f\u0430\u0440\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 Keycloak \u2014 Auth Proxy \u0435\u0433\u043e \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0432\u0438\u0434\u0438\u0442.<\/p>\n<h3>\u0413\u0440\u0430\u0431\u043b\u0438 OAuth<\/h3>\n<p>\u0418\u0437 \u0434\u0435\u0441\u044f\u0442\u043a\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c, 2 \u043e\u0442\u043d\u044f\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438.<\/p>\n<h4>\u041a\u0442\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443<\/h4>\n<p>\u041f\u0440\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 n8n \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u0438\u00a0<code>invalid_scope: Client was not registered with scope openid<\/code>. \u041f\u043e\u043b\u0435\u0437\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 Keycloak \u2014 scope\u00a0<code>openid<\/code>\u00a0\u0442\u0430\u043c \u0431\u044b\u043b. \u0421\u0442\u0430\u043b\u0438 \u0433\u0440\u0435\u0448\u0438\u0442\u044c \u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e realm. <\/p>\n<p>\u0410 \u043f\u043e\u0442\u043e\u043c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u043d\u0430 \u0434\u043e\u043c\u0435\u043d \u0432 URL \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u0430. \u0422\u0430\u043c \u0431\u044b\u043b\u00a0<strong>\u043d\u0430\u0448 \u0434\u043e\u043c\u0435\u043d<\/strong>, \u0430 \u043d\u0435 Keycloak. \u041e\u0448\u0438\u0431\u043a\u0443 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b OAuthProxy \u2014 scope\u00a0<code>openid<\/code>\u00a0\u043d\u0435 \u0431\u044b\u043b \u0432 \u0435\u0433\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u043c \u0441\u043f\u0438\u0441\u043a\u0435\u00a0<code>valid_scopes<\/code>, \u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442\u043a\u043b\u043e\u043d\u044f\u043b\u0441\u044f \u0435\u0449\u0435 \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0434\u043e\u0448\u0451\u043b \u0434\u043e Keycloak.<\/p>\n<p>\u0421 \u0442\u0435\u0445 \u043f\u043e\u0440 \u043f\u0440\u0430\u0432\u0438\u043b\u043e: \u043f\u0440\u0438 OAuth-\u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0434\u043e\u043c\u0435\u043d \u0432 URL \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u0430 \u2014 \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u043d\u043e, \u043a\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u0442\u043a\u043b\u043e\u043d\u0438\u043b \u0437\u0430\u043f\u0440\u043e\u0441.<\/p>\n<h4>\u041a\u043b\u0438\u0435\u043d\u0442\u044b \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0430\u0445 OAuth<\/h4>\n<p>n8n MCP Client Tool \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 PKCE (<code>code_challenge<\/code>), \u0430 OAuthProxy \u0435\u0433\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442. \u0415\u0449\u0435 n8n \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 credentials \u0447\u0435\u0440\u0435\u0437 Basic Auth header, \u0430 OAuthProxy \u043e\u0436\u0438\u0434\u0430\u0435\u0442 <code>client_id<\/code> \u0432 \u0442\u0435\u043b\u0435 POST.<\/p>\n<p>\u041f\u0430\u0442\u0447\u0438\u0442\u044c n8n \u0438\u043b\u0438 \u043b\u0435\u0437\u0442\u044c \u0432 \u043a\u0438\u0448\u043a\u0438 OAuthProxy \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u2014 \u043e\u0431\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e. \u041d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 middleware-\u043f\u0440\u043e\u0441\u043b\u043e\u0439\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u044f:<\/p>\n<pre><code class=\"python\"># single-worker, \u0434\u043b\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0443\u0436\u0435\u043d Redisclass PKCEInjectorMiddleware(BaseHTTPMiddleware):    \"\"\"    \u041f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 PKCE \u0437\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0433\u043e \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442.    \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442 Basic Auth \u0432 POST-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438    \u0441 OAuthProxy.    \"\"\"    verifiers: dict[str, str] = {}    async def dispatch(self, request, call_next):        if request.url.path == \"\/authorize\":            params = dict(request.query_params)            if \"code_challenge\" not in params:                # \u041a\u043b\u0438\u0435\u043d\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 PKCE \u2014 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0437\u0430 \u043d\u0435\u0433\u043e                verifier = secrets.token_urlsafe(64)                challenge = base64.urlsafe_b64encode(                    hashlib.sha256(verifier.encode()).digest()                ).rstrip(b\"=\").decode()                state = params.get(\"state\", \"\")                if state:                    self.verifiers[state] = verifier                params[\"code_challenge\"] = challenge                params[\"code_challenge_method\"] = \"S256\"                # \u041f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c query string                ...        if request.url.path == \"\/token\":            body = await request.body()            body_str = body.decode()            # \u041f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0439 code_verifier            if \"code_verifier\" not in body_str and self.verifiers:                for sv, ver in list(self.verifiers.items()):                    body_str += f\"&amp;code_verifier={ver}\"                    del self.verifiers[sv]                    break            # \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c Basic Auth \u2192 POST body            if \"client_id\" not in body_str:                auth_header = request.headers.get(\"authorization\", \"\")                if auth_header.startswith(\"Basic \"):                    decoded = base64.b64decode(auth_header[6:]).decode()                    client_id, client_secret = decoded.split(\":\", 1)                    body_str += f\"&amp;client_id={client_id}\"                    body_str += f\"&amp;client_secret={client_secret}\"            ...        return await call_next(request)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Middleware \u043c\u0435\u0436\u0434\u0443 OAuth-\u043f\u0440\u043e\u043a\u0441\u0438 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043d\u0430 \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u043c. \u041e\u0434\u0438\u043d \u043a\u043b\u0430\u0441\u0441 \u0437\u0430\u043a\u0440\u044b\u043b \u0434\u0432\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0438 \u0435\u0441\u043b\u0438 \u0437\u0430\u0432\u0442\u0440\u0430 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442 \u0441 \u0435\u0449\u0435 \u043a\u0430\u043a\u0438\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u00ab\u0434\u0438\u0430\u043b\u0435\u043a\u0442\u043e\u043c\u00bb \u2014 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0442\u0443\u0434\u0430 \u0436\u0435, \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u044f \u043d\u0438 OAuthProxy, \u043d\u0438 \u043a\u043b\u0438\u0435\u043d\u0442.<\/p>\n<h3>Per-user \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f: \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/h3>\n<p>OAuth \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b, \u043d\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b\u0430\u0441\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043d\u0435 \u0440\u0435\u0448\u0438\u0442\u044c.<\/p>\n<p>n8n MCP Client Tool \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0443\u0435\u0442\u0441\u044f <strong>\u043e\u0434\u0438\u043d \u0440\u0430\u0437<\/strong> \u2014 \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 credential. \u0412\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0447\u0435\u0440\u0435\u0437 workflow \u0438\u0434\u0443\u0442 \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u0442\u043e\u0433\u043e, \u043a\u0442\u043e \u043f\u0440\u043e\u0448\u0435\u043b OAuth.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cbb\/391\/87f\/cbb39187fbe9c216e3513ddbab72254b.png\" alt=\"\u0441\u0445\u0435\u043c\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 n8n \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438\" title=\"\u0441\u0445\u0435\u043c\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 n8n \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438\" width=\"472\" height=\"82\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/cbb\/391\/87f\/cbb39187fbe9c216e3513ddbab72254b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cbb\/391\/87f\/cbb39187fbe9c216e3513ddbab72254b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0441\u0445\u0435\u043c\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 n8n \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0418\u0432\u0430\u043d\u043e\u0432 \u043f\u0438\u0448\u0435\u0442 \u0431\u043e\u0442\u0443, MCP-\u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0438\u0434\u0438\u0442 \u043d\u0435 \u0418\u0432\u0430\u043d\u043e\u0432\u0430, \u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0432\u0448\u0435\u0433\u043e credential. \u0414\u043b\u044f \u0431\u043e\u0442\u0430 \u0441 \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u0430\u0432 \u044d\u0442\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041d\u0443\u0436\u043d\u0430 \u0434\u0440\u0443\u0433\u0430\u044f \u0441\u0445\u0435\u043c\u0430:<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e81\/e6a\/ad4\/e81e6aad440fbb92a8b8f4209c4e4fd2.png\" alt=\"\u0421\u0445\u0435\u043c\u0430 \u0441 per-user \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432 n8n\" title=\"\u0421\u0445\u0435\u043c\u0430 \u0441 per-user \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432 n8n\" width=\"692\" height=\"171\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e81\/e6a\/ad4\/e81e6aad440fbb92a8b8f4209c4e4fd2.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e81\/e6a\/ad4\/e81e6aad440fbb92a8b8f4209c4e4fd2.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0445\u0435\u043c\u0430 \u0441 per-user \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432 n8n<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0432 Auth Proxy \u043d\u0430\u0431\u043e\u0440 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u2014 User Auth API. \u041f\u043e\u043b\u043d\u044b\u0439 flow:<\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0438\u0448\u0435\u0442 \u0431\u043e\u0442\u0443 \u00ab\u043f\u0440\u0438\u0432\u0435\u0442\u00bb<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u0442 \u2192 POST \/user-auth\/start {\u201cuser_id\u201d: \u201ctelegram_12345\u201d}<\/p>\n<\/li>\n<li>\n<p>Auth Proxy \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442: \u0435\u0441\u0442\u044c \u043b\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0441\u0435\u0441\u0441\u0438\u044f? <\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0432\u0430\u043b\u0438\u0434\u0435\u043d \u2192 {status: \u201ccompleted\u201d, session_id: \u201cabc\u201d}<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0438\u0441\u0442\u0435\u043a \u2192 \u043f\u0440\u043e\u0431\u0443\u0435\u0442 refresh_token<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 refresh \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u2192 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043d\u043e\u0432\u0443\u044e \u0441\u0435\u0441\u0441\u0438\u044e<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Auth Proxy \u2192 201 {session_id: \u201cabc\u201d, login_url: \u201c<a href=\"https:\/\/keycloak%E2%80%A6\/auth?..%E2%80%9D\" rel=\"noopener noreferrer nofollow\">https:\/\/keycloak\u2026\/auth?..\u201d<\/a>}<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u0441 login_url<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043a\u043b\u0438\u043a\u0430\u0435\u0442 \u2192 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u2192 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043b\u043e\u0433\u0438\u043d\u0430 Keycloak<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u0442 \u043b\u043e\u0433\u0438\u043d\/\u043f\u0430\u0440\u043e\u043b\u044c (\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 Keycloak, \u043d\u0435 \u0432 \u0431\u043e\u0442\u0435!)<\/p>\n<\/li>\n<li>\n<p>Keycloak \u2192 redirect \u043d\u0430 \/user-auth\/callback \u0441 \u043e\u0434\u043d\u043e\u0440\u0430\u0437\u043e\u0432\u044b\u043c code<\/p>\n<\/li>\n<li>\n<p>Auth Proxy \u043e\u0431\u043c\u0435\u043d\u0438\u0432\u0430\u0435\u0442 code \u043d\u0430 access_token + refresh_token, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u0442 \u2192 GET \/user-auth\/status\/abc \u2192 {status: \u201ccompleted\u201d, username: \u201c\u0418\u0432\u0430\u043d\u043e\u0432\u201d}<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u0442 \u2192 POST \/user-auth\/mcp (headers: x-session-id: abc) Body: {jsonrpc: \u201c2.0\u201d, method: \u201ctools\/call\u201d, params: {name: \u201cwhoami\u201d}}<\/p>\n<\/li>\n<li>\n<p>Auth Proxy \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Bearer token \u0418\u0432\u0430\u043d\u043e\u0432\u0430 \u2192 Gateway \u2192 MCP-\u0441\u0435\u0440\u0432\u0435\u0440<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u043e\u043a\u0435\u043d\u044b \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f <strong>\u0442\u043e\u043b\u044c\u043a\u043e \u0432 Auth Proxy<\/strong>. \u0411\u043e\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441 <code>session_id<\/code> \u2014 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u0435\u043d \u0431\u0435\u0437 Auth Proxy.<\/p>\n<h3>\u0422\u0440\u0438 \u043a\u0430\u043d\u0430\u043b\u0430 \u0447\u0435\u0440\u0435\u0437 \u043e\u0434\u043d\u0443 \u0434\u0432\u0435\u0440\u044c<\/h3>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 Auth Proxy \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u0440\u0438 \u0442\u0438\u043f\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 \u0435\u0434\u0438\u043d\u044b\u0439 Keycloak:<\/p>\n<p><strong>Claude Desktop<\/strong> \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u2014 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c URL\u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435. Claude \u0441\u0430\u043c \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 OAuth flow: \u0447\u0438\u0442\u0430\u0435\u0442 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 Dynamic Client Registration, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u043d\u0430 \u0432 Keycloak. Per-user \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438.<\/p>\n<p><strong>n8n MCP Client Tool<\/strong> \u2014 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 OAuth2 \u0441 Dynamic Client Registration. \u041e\u0434\u0438\u043d credential \u043d\u0430 workflow. \u041f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<p><strong>Telegram-\u0431\u043e\u0442<\/strong> \u2014 per-user \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 User Auth API. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 Keycloak.<\/p>\n<h3>\u041a\u0430\u0441\u0442\u043e\u043c\u043d\u0430\u044f \u043d\u043e\u0434\u0430 \u0434\u043b\u044f n8n: usableAsTool<\/h3>\n<p>\u0425\u043e\u0442\u0435\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c AI Tool-\u043d\u043e\u0434\u0443 \u0434\u043b\u044f n8n, \u0447\u0442\u043e\u0431\u044b AI Agent \u0432\u044b\u0437\u044b\u0432\u0430\u043b MCP-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u0438 \u0447\u0435\u0442\u044b\u0440\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u2014 <code>supplyData<\/code> \u0441 <code>DynamicTool<\/code>, <code>DynamicStructuredTool<\/code> \u0441 Zod, \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u044b n8n (<code>StructuredToolkit<\/code>, <code>logWrapper<\/code>), \u0440\u0443\u0447\u043d\u0443\u044e \u043f\u043e\u0434\u043c\u0435\u043d\u0443 schema \u0447\u0435\u0440\u0435\u0437 <code>Object.defineProperty<\/code>. \u041a\u0430\u0436\u0434\u044b\u0439 \u0443\u043f\u0438\u0440\u0430\u043b\u0441\u044f \u0432 \u043e\u0434\u043d\u043e: \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 AI tool-\u043d\u043e\u0434\u044b n8n \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u044b \u043c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u043c \u043d\u043e\u0434\u0430\u043c.<\/p>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u0432 community-\u043d\u043e\u0434\u0435 Merge Agent Handler \u2014 \u043e\u0434\u043d\u043e \u043d\u0435\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e:<\/p>\n<pre><code class=\"typescript\">description: INodeTypeDescription = {    usableAsTool: true,  \/\/ n8n \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043d\u043e\u0434\u0443 \u0432 AI Tool    inputs: [NodeConnectionTypes.Main],    outputs: [NodeConnectionTypes.Main],};<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>usableAsTool: true<\/code> \u0433\u043e\u0432\u043e\u0440\u0438\u0442 n8n: \u0432\u043e\u0437\u044c\u043c\u0438 \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u043d\u043e\u0434\u0443 \u0441 <code>execute()<\/code> \u0438 \u0441\u0434\u0435\u043b\u0430\u0439 \u0438\u0437 \u043d\u0435\u0435 AI Tool. \u0411\u0435\u0437 <code>supplyData<\/code>, \u0431\u0435\u0437 LangChain, \u0431\u0435\u0437 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u0434\u0432\u0430 \u0440\u0435\u0436\u0438\u043c\u0430 \u0447\u0435\u0440\u0435\u0437 <code>displayOptions<\/code> \u0441 <code>@tool<\/code>:<\/p>\n<pre><code class=\"typescript\">\/\/ Standalone \u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u0442 \u0432\u0440\u0443\u0447\u043d\u0443\u044e{ name: 'toolName', displayOptions: { hide: { '@tool': [true] } } }\/\/ Agent \u2014 AI Agent \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438{ name: 'toolNameAgent', displayOptions: { show: { '@tool': [true] } } }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 LangGraph<\/h3>\n<p>\u041a\u0430\u0441\u0442\u043e\u043c\u043d\u0430\u044f \u043d\u043e\u0434\u0430 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430. \u041d\u043e \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u0441 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 n8n \u0440\u0435\u0448\u0438\u0442\u044c \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c.<\/p>\n<h4>\u041e\u0434\u043d\u0430 tool \u0432\u043c\u0435\u0441\u0442\u043e \u0434\u0432\u0435\u043d\u0430\u0434\u0446\u0430\u0442\u0438<\/h4>\n<p>\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 MCP Client Tool \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 MCP-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043a\u0430\u043a <strong>\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e tool<\/strong> \u2014 \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0438 \u0441\u0445\u0435\u043c\u043e\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. <code>usableAsTool: true<\/code> \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u0437 \u043d\u043e\u0434\u044b <strong>\u043e\u0434\u043d\u0443<\/strong> tool. \u0412\u0441\u0435 12 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0432 \u00ab\u043c\u0435\u0442\u0430-\u0442\u0443\u043b\u0437\u0443\u00bb:<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f59\/be2\/7da\/f59be27da6b310f3c843bde42580e08e.png\" alt=\"\u0420\u0430\u0437\u043b\u0438\u0447\u0438\u044f \u043d\u043e\u0434 \u0432 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u0434\u043b\u044f \u0418\u0418-\u0430\u0433\u0435\u043d\u0442\u0430\" title=\"\u0420\u0430\u0437\u043b\u0438\u0447\u0438\u044f \u043d\u043e\u0434 \u0432 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u0434\u043b\u044f \u0418\u0418-\u0430\u0433\u0435\u043d\u0442\u0430\" width=\"882\" height=\"382\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/f59\/be2\/7da\/f59be27da6b310f3c843bde42580e08e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f59\/be2\/7da\/f59be27da6b310f3c843bde42580e08e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0430\u0437\u043b\u0438\u0447\u0438\u044f \u043d\u043e\u0434 \u0432 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u0434\u043b\u044f \u0418\u0418-\u0430\u0433\u0435\u043d\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e. \u041d\u0430 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u2014 LLM \u043f\u0443\u0442\u0430\u043b\u0430\u0441\u044c: \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 JSON, \u043f\u0443\u0442\u0430\u043b\u0430 \u0438\u043c\u0435\u043d\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043d\u0435 \u0432 \u0442\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u041a\u043e\u0433\u0434\u0430 \u0443 \u0430\u0433\u0435\u043d\u0442\u0430 12 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 tools \u0441 \u0447\u0435\u0442\u043a\u0438\u043c\u0438 \u0441\u0445\u0435\u043c\u0430\u043c\u0438 \u2014 \u043e\u043d \u0437\u043d\u0430\u0435\u0442, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c. \u041a\u043e\u0433\u0434\u0430 \u043e\u0434\u043d\u0430 \u00ab\u043c\u0435\u0442\u0430-\u0442\u0443\u043b\u0437\u0430\u00bb \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043d\u0430 \u043f\u043e\u043b\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u2014 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0438\u043c\u043f\u0440\u043e\u0432\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<h4>\u0427\u0442\u043e \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b\u0438 \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u0443\u0439\u0442\u0438<\/h4>\n<p>\u0424\u043e\u0440\u043a\u043d\u0443\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 MCP Client Tool \u2014 \u0437\u0430\u043c\u0430\u043d\u0447\u0438\u0432\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c <code>StructuredToolkit<\/code> \u0438 12 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 tools. \u041d\u043e \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043a \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c API n8n, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043e\u043c \u0438 \u043b\u043e\u043c\u0430\u044e\u0442\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438. \u0414\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0430 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0445\u0440\u0443\u043f\u043a\u043e.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u043d\u043e\u0434\u044b \u2014 \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u043d\u0430 MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043d\u0443\u0436\u043d\u043e \u0440\u0443\u043a\u0430\u043c\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0434\u0443 \u0432 workflow. \u0423 \u043d\u0430\u0441 12 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0447\u0438\u0441\u043b\u043e \u0440\u0430\u0441\u0442\u0435\u0442.<\/p>\n<p>LangGraph \u2014 \u0442\u0435\u0440\u044f\u0435\u043c \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 n8n. \u041d\u043e \u0434\u043b\u044f \u0431\u043e\u0442\u0430 \u0432 Telegram \u044d\u0442\u043e\u0442 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d: \u0432\u0435\u0441\u044c workflow \u2014 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0431\u043b\u043e\u043a \u00ab\u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430\u00bb. \u0410 \u0432\u043e\u0442 per-user state \u0438 12 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 tools \u0441 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c\u0438 \u0441\u0445\u0435\u043c\u0430\u043c\u0438 \u2014 \u043d\u0443\u0436\u043d\u044b. \u0412\u044b\u0431\u043e\u0440 \u0431\u044b\u043b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u0435\u043d.<\/p>\n<p>\u0412 LangGraph \u043a\u0430\u0436\u0434\u044b\u0439 MCP-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f tool \u0441 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u043e\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u0410\u0433\u0435\u043d\u0442 \u0441\u0430\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u044b, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u0441\u044b\u043b\u043a\u0438, \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0441\u0435\u0441\u0441\u0438\u0438. \u042d\u0442\u043e \u043a\u043e\u0434, \u0430 \u043d\u0435 \u043d\u0430\u0431\u043e\u0440 middleware \u0438 \u0445\u0430\u043a\u043e\u0432.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/73e\/398\/068\/73e398068d40530cab69e0f12e7a867e.png\" alt=\"User Flow \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 \u0431\u043e\u0442\u0435 \u0447\u0435\u0440\u0435\u0437 LangGraph\" title=\"User Flow \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 \u0431\u043e\u0442\u0435 \u0447\u0435\u0440\u0435\u0437 LangGraph\" width=\"1067\" height=\"557\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/73e\/398\/068\/73e398068d40530cab69e0f12e7a867e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/73e\/398\/068\/73e398068d40530cab69e0f12e7a867e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>User Flow \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 \u0431\u043e\u0442\u0435 \u0447\u0435\u0440\u0435\u0437 LangGraph<\/figcaption><\/div>\n<\/figure>\n<p>Auth Proxy \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u0432 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435 \u2014 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 Claude Desktop \u0438 n8n \u0447\u0435\u0440\u0435\u0437 OAuthProxy. LangGraph-\u0431\u043e\u0442 \u0445\u043e\u0434\u0438\u0442 \u043a \u043d\u0435\u043c\u0443 \u0447\u0435\u0440\u0435\u0437 User Auth API.<\/p>\n<h3>\u0427\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0432 \u0446\u0438\u0444\u0440\u0430\u0445<\/h3>\n<p>\u0422\u0440\u0438 \u043a\u0430\u043d\u0430\u043b\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u0430\u043c \u0447\u0435\u0440\u0435\u0437 \u043e\u0434\u0438\u043d Auth Proxy: Claude Desktop, n8n \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, Telegram-\u0431\u043e\u0442 \u0441 per-user \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439.<\/p>\n<p>\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u0435\u043a\u0443\u043d\u0434 15 \u2014 \u043a\u043b\u0438\u043a\u043d\u0443\u0442\u044c \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435, \u0432\u0432\u0435\u0441\u0442\u0438 \u043b\u043e\u0433\u0438\u043d-\u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 Keycloak, \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u0432 \u0447\u0430\u0442. \u041f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u043d \u043d\u0443\u0436\u0435\u043d \u0440\u0430\u0437 \u0432 30 \u0434\u043d\u0435\u0439 (\u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 Keycloak), \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0442\u043e\u043a\u0435\u043d\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 refresh_token.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u0441 n8n \u043d\u0430 LangGraph \u0437\u0430\u043d\u044f\u043b \u0442\u0440\u0438 \u0434\u043d\u044f. User Auth API \u0432 Auth Proxy \u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043c\u0435\u043d\u044f\u0442\u044c \u2014 \u043f\u043e\u043c\u0435\u043d\u044f\u043b\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043b\u0438\u0435\u043d\u0442. \u042d\u0442\u043e, \u043f\u043e\u0436\u0430\u043b\u0443\u0439, \u043b\u0443\u0447\u0448\u0435\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0431\u044b\u043b\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c.<\/p>\n<p>\u0412\u0441\u0435 12 MCP-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 tools \u0432 LangGraph \u2014 \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u043e \u0441\u0432\u043e\u0435\u0439 \u0441\u0445\u0435\u043c\u043e\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. LLM \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0430 \u043f\u0443\u0442\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439 JSON, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u0441 \u00ab\u043c\u0435\u0442\u0430-\u0442\u0443\u043b\u0437\u043e\u0439\u00bb \u0432 n8n.<\/p>\n<h3>\u0418\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f<\/h3>\n<p><strong>Session storage \u0432 \u043f\u0430\u043c\u044f\u0442\u0438.<\/strong> Auth Proxy \u0445\u0440\u0430\u043d\u0438\u0442 \u0441\u0435\u0441\u0441\u0438\u0438 in-memory. \u041f\u0440\u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0435 \u0432\u0441\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043d\u043e\u0432\u043e. \u0412 \u043f\u043b\u0430\u043d\u0430\u0445 \u2014 Redis.<\/p>\n<p><strong>\u041d\u0435\u0442 rate limiting.<\/strong> Auth Proxy \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0447\u0430\u0441\u0442\u043e\u0442\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u041f\u043e\u043a\u0430 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u043d\u043e \u043f\u0440\u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c.<\/p>\n<p><strong>PKCE Injector \u2014 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438.<\/strong> \u041c\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c PKCE \u0437\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0447\u0442\u043e \u043e\u0441\u043b\u0430\u0431\u043b\u044f\u0435\u0442 \u0437\u0430\u0449\u0438\u0442\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e PKCE \u043f\u0440\u0438\u0437\u0432\u0430\u043d \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e \u0434\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b, \u043d\u043e \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0443\u0436\u043d\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c PKCE \u043e\u0442 \u0441\u0430\u043c\u0438\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.<\/p>\n<h3>\u0412\u044b\u0432\u043e\u0434\u044b<\/h3>\n<p><strong>Middleware \u043c\u0435\u0436\u0434\u0443 OAuth-\u043f\u0440\u043e\u043a\u0441\u0438 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438<\/strong> \u2014 \u043d\u0430 \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d. \u041e\u0434\u0438\u043d \u043a\u043b\u0430\u0441\u0441 \u0437\u0430\u043a\u0440\u044b\u043b PKCE \u0438 Basic Auth, \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f OAuthProxy \u0438\u043b\u0438 \u0441\u0430\u043c\u0438\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p><code><strong>usableAsTool: true<\/strong><\/code><strong> \u0432 n8n<\/strong> \u2014 \u043d\u0435\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u043d\u043e\u0434\u0443 \u0432 AI Tool. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u043c: \u043e\u0434\u043d\u0430 tool, \u0430 \u043d\u0435 \u043d\u0430\u0431\u043e\u0440. \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0434\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u2014 LLM \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043f\u0443\u0442\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p><strong>\u0412\u044b\u0431\u043e\u0440 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b<\/strong> \u2014 n8n \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0439 \u0441 \u043e\u0434\u043d\u0438\u043c credential \u043d\u0430 workflow. \u0414\u043b\u044f per-user \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0441 \u0434\u0435\u0441\u044f\u0442\u043a\u043e\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0432\u0440\u043e\u0434\u0435 LangGraph \u0434\u0430\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u0438 \u043c\u0435\u043d\u044c\u0448\u0435 \u0431\u043e\u0440\u044c\u0431\u044b \u0441 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0439.<\/p>\n<hr\/>\n<p><strong>\u0421\u0441\u044b\u043b\u043a\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/modelcontextprotocol.io\/\" rel=\"noopener noreferrer nofollow\">\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f MCP<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/jlowin\/fastmcp\" rel=\"noopener noreferrer nofollow\">FastMCP<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/fuckseer\/n8n-nodes-mcp-auth-tool\" rel=\"noopener noreferrer nofollow\">\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u043a\u043e\u0434\u043e\u043c Auth Proxy \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u043d\u043e\u0434\u044b<\/a><\/p>\n<\/li>\n<\/ul>\n<p><em>P.S. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u043f\u043e\u0445\u043e\u0436\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u0438\u043b\u0438 \u0432\u044b \u043d\u0430\u0448\u043b\u0438 \u0441\u043f\u043e\u0441\u043e\u0431 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e tools \u0447\u0435\u0440\u0435\u0437 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0443\u044e \u043d\u043e\u0434\u0443 n8n \u2014 <\/em>\u0431\u0443\u0434\u0443 \u0440\u0430\u0434\u0430 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438 \u0447\u0435\u0440\u0435\u0437 Issues \u043d\u0430 GitHub<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1030302\/\">https:\/\/habr.com\/ru\/articles\/1030302\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0435 MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u044b, AI-\u0430\u0433\u0435\u043d\u0442 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0432 Telegram. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 Keycloak, \u0430 \u0430\u0433\u0435\u043d\u0442 \u2014 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0442 \u0435\u0433\u043e \u0438\u043c\u0435\u043d\u0438. \u0417\u0434\u0435\u0441\u044c \u0441\u043e\u0431\u0440\u0430\u043d\u044b \u0433\u0440\u0430\u0431\u043b\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u043b\u0438, \u0438 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u0440\u0438\u0448\u043b\u0438.\u041a\u043e\u043c\u0443 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0415\u0441\u043b\u0438 \u0432\u044b:\u041f\u0440\u0438\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0435\u0442\u0435 OAuth\/OIDC \u043a \u0447\u0435\u043c\u0443-\u0442\u043e, \u0447\u0442\u043e \u043d\u0430 \u044d\u0442\u043e \u043d\u0435 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u043e\u0421\u0442\u0440\u043e\u0438\u0442\u0435 \u043c\u0443\u043b\u044c\u0442\u0438\u0442\u0435\u043d\u0430\u043d\u0442\u043d\u043e\u0433\u043e AI-\u0430\u0433\u0435\u043d\u0442\u0430, \u0433\u0434\u0435 \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441\u0432\u043e\u0438 \u043f\u0440\u0430\u0432\u0430\u041f\u044b\u0442\u0430\u0435\u0442\u0435\u0441\u044c \u043f\u043e\u0434\u0440\u0443\u0436\u0438\u0442\u044c MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u044b \u0441 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u043c IdP\u041f\u0438\u0448\u0435\u0442\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043d\u043e\u0434\u044b \u0434\u043b\u044f n8n\u0418\u0441\u0445\u043e\u0434\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430MCP (Model Context Protocol) \u2014 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u043e\u0442 Anthropic \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f AI-\u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u043a \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c. \u0423 \u043d\u0430\u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432, \u043f\u0435\u0440\u0435\u0434 \u043d\u0438\u043c\u0438 \u2014 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u043a\u0441\u0438 \u043d\u0430 FastMCP, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435 \u0432 \u0435\u0434\u0438\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u0432\u0445\u043e\u0434\u0430.\u0421\u0445\u0435\u043c\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b\u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u043a\u0441\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u043b, \u043d\u043e \u043d\u0435 \u0437\u043d\u0430\u043b, \u043a\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441. \u041b\u044e\u0431\u043e\u0439, \u043a\u0442\u043e \u0434\u043e\u0441\u0442\u0443\u0447\u0438\u0442\u0441\u044f \u0434\u043e \u043f\u043e\u0440\u0442\u0430, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u043e \u0432\u0441\u0435\u043c\u0443. \u0414\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u044d\u0442\u043e \u0442\u0435\u0440\u043f\u0438\u043c\u043e, \u043d\u043e \u0434\u043b\u044f \u0431\u043e\u0442\u0430 \u0441 \u0441\u043e\u0442\u043d\u044f\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u2014 \u0443\u0436\u0435 \u043d\u0435\u0442.\u0412\u044b\u0431\u043e\u0440 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b: \u043f\u043e\u0447\u0435\u043c\u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441\u041f\u0435\u0440\u0432\u044b\u0439 \u043f\u043e\u0440\u044b\u0432 \u2014 \u0437\u0430\u0441\u0443\u043d\u0443\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0442\u043e\u043a\u0435\u043d\u0430 \u043f\u0440\u044f\u043c\u043e \u0432 \u043f\u0440\u043e\u043a\u0441\u0438. \u0411\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u043d\u044f\u043b\u0438, \u0447\u0442\u043e \u043d\u0435 \u0445\u043e\u0442\u0438\u043c \u043c\u0435\u0448\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044e \u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435. Gateway \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432, \u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u2014 \u0448\u0442\u0443\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043b\u0443\u0447\u0448\u0435 \u043c\u0435\u043d\u044f\u0442\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0436\u0435.\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u2014 \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 MCP-\u0441\u0435\u0440\u0432\u0435\u0440. \u041d\u043e \u0438\u0445 \u0443 \u043d\u0430\u0441 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0443\u0447\u0438\u0442\u044c \u0445\u043e\u0434\u0438\u0442\u044c \u0432 Keycloak. \u0410 \u0435\u0441\u043b\u0438 \u0437\u0430\u0432\u0442\u0440\u0430 \u043c\u044b \u0441\u043c\u0435\u043d\u0438\u043c IdP \u2014 \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435.\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c Auth Proxy \u043f\u0435\u0440\u0435\u0434 Gateway. \u0414\u0430, \u044d\u0442\u043e \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0441\u0435\u0440\u0432\u0438\u0441 \u0432 \u0434\u0435\u043f\u043b\u043e\u0435 \u0438 \u043b\u0438\u0448\u043d\u0438\u0435 3-5 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441. \u041d\u043e \u043a\u043e\u0433\u0434\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0443\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 LLM (2-4 \u0441\u0435\u043a\u0443\u043d\u0434\u044b), \u044d\u0442\u0438 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u044b \u0440\u043e\u043b\u0438 \u043d\u0435 \u0438\u0433\u0440\u0430\u044e\u0442. \u0417\u0430\u0442\u043e Gateway \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0447\u0438\u0441\u0442\u044b\u043c \u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043e\u0440\u043e\u043c, \u0430 \u0432\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0436\u0438\u0432\u0435\u0442 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435.\u0421\u0445\u0435\u043c\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0441 per-user OAuth\u0412 FastMCP \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c OAuthProxy \u2014 \u043e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f MCP-\u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u043a\u0430\u043a \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 OAuth-\u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 Dynamic Client Registration, \u0430 \u0437\u0430 \u043a\u0443\u043b\u0438\u0441\u0430\u043c\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 credentials \u0441 Keycloak. \u041f\u0430\u0440\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 Keycloak \u2014 Auth Proxy \u0435\u0433\u043e \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0432\u0438\u0434\u0438\u0442.\u0413\u0440\u0430\u0431\u043b\u0438 OAuth\u0418\u0437 \u0434\u0435\u0441\u044f\u0442\u043a\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c, 2 \u043e\u0442\u043d\u044f\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438.\u041a\u0442\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443\u041f\u0440\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 n8n \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u0438\u00a0invalid_scope: Client was not registered with scope openid. \u041f\u043e\u043b\u0435\u0437\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 Keycloak \u2014 scope\u00a0openid\u00a0\u0442\u0430\u043c \u0431\u044b\u043b. \u0421\u0442\u0430\u043b\u0438 \u0433\u0440\u0435\u0448\u0438\u0442\u044c \u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e realm. \u0410 \u043f\u043e\u0442\u043e\u043c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u043d\u0430 \u0434\u043e\u043c\u0435\u043d \u0432 URL \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u0430. \u0422\u0430\u043c \u0431\u044b\u043b\u00a0\u043d\u0430\u0448 \u0434\u043e\u043c\u0435\u043d, \u0430 \u043d\u0435 Keycloak. \u041e\u0448\u0438\u0431\u043a\u0443 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b OAuthProxy \u2014 scope\u00a0openid\u00a0\u043d\u0435 \u0431\u044b\u043b \u0432 \u0435\u0433\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u043c \u0441\u043f\u0438\u0441\u043a\u0435\u00a0valid_scopes, \u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442\u043a\u043b\u043e\u043d\u044f\u043b\u0441\u044f \u0435\u0449\u0435 \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0434\u043e\u0448\u0451\u043b \u0434\u043e Keycloak.\u0421 \u0442\u0435\u0445 \u043f\u043e\u0440 \u043f\u0440\u0430\u0432\u0438\u043b\u043e: \u043f\u0440\u0438 OAuth-\u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0434\u043e\u043c\u0435\u043d \u0432 URL \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u0430 \u2014 \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u043d\u043e, \u043a\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u0442\u043a\u043b\u043e\u043d\u0438\u043b \u0437\u0430\u043f\u0440\u043e\u0441.\u041a\u043b\u0438\u0435\u043d\u0442\u044b \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0430\u0445 OAuthn8n MCP Client Tool \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 PKCE (code_challenge), \u0430 OAuthProxy \u0435\u0433\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442. \u0415\u0449\u0435 n8n \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 credentials \u0447\u0435\u0440\u0435\u0437 Basic Auth header, \u0430 OAuthProxy \u043e\u0436\u0438\u0434\u0430\u0435\u0442 client_id \u0432 \u0442\u0435\u043b\u0435 POST.\u041f\u0430\u0442\u0447\u0438\u0442\u044c n8n \u0438\u043b\u0438 \u043b\u0435\u0437\u0442\u044c \u0432 \u043a\u0438\u0448\u043a\u0438 OAuthProxy \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u2014 \u043e\u0431\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e. \u041d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 middleware-\u043f\u0440\u043e\u0441\u043b\u043e\u0439\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u044f:# single-worker, \u0434\u043b\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0443\u0436\u0435\u043d Redisclass PKCEInjectorMiddleware(BaseHTTPMiddleware):    &#171;&#187;&#187;    \u041f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 PKCE \u0437\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0433\u043e \u043d\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442.    \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442 Basic Auth \u0432 POST-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438    \u0441 OAuthProxy.    &#171;&#187;&#187;    verifiers: dict[str, str] = {}    async def dispatch(self, request, call_next):        if request.url.path == &#171;\/authorize&#187;:            params = dict(request.query_params)            if &#171;code_challenge&#187; not in params:                # \u041a\u043b\u0438\u0435\u043d\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 PKCE \u2014 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0437\u0430 \u043d\u0435\u0433\u043e                verifier = secrets.token_urlsafe(64)                challenge = base64.urlsafe_b64encode(                    hashlib.sha256(verifier.encode()).digest()                ).rstrip(b&#187;=&#187;).decode()                state = params.get(&#171;state&#187;, &#171;&#187;)                if state:                    self.verifiers[state] = verifier                params[&#171;code_challenge&#187;] = challenge                params[&#171;code_challenge_method&#187;] = &#171;S256&#187;                # \u041f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c query string                &#8230;        if request.url.path == &#171;\/token&#187;:            body = await request.body()            body_str = body.decode()            # \u041f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0439 code_verifier            if &#171;code_verifier&#187; not in body_str and self.verifiers:                for sv, ver in list(self.verifiers.items()):                    body_str += f&#187;&amp;code_verifier={ver}&#187;                    del self.verifiers[sv]                    break            # \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c Basic Auth \u2192 POST body            if &#171;client_id&#187; not in body_str:                auth_header = request.headers.get(&#171;authorization&#187;, &#171;&#187;)                if auth_header.startswith(&#171;Basic &#171;):                    decoded = base64.b64decode(auth_header[6:]).decode()                    client_id, client_secret = decoded.split(&#171;:&#187;, 1)                    body_str += f&#187;&amp;client_id={client_id}&#187;                    body_str += f&#187;&amp;client_secret={client_secret}&#187;            &#8230;        return await call_next(request)Middleware \u043c\u0435\u0436\u0434\u0443 OAuth-\u043f\u0440\u043e\u043a\u0441\u0438 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043d\u0430 \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u043c. \u041e\u0434\u0438\u043d \u043a\u043b\u0430\u0441\u0441 \u0437\u0430\u043a\u0440\u044b\u043b \u0434\u0432\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0438 \u0435\u0441\u043b\u0438 \u0437\u0430\u0432\u0442\u0440\u0430 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442 \u0441 \u0435\u0449\u0435 \u043a\u0430\u043a\u0438\u043c-\u043d\u0438\u0431\u0443\u0434\u044c \u00ab\u0434\u0438\u0430\u043b\u0435\u043a\u0442\u043e\u043c\u00bb \u2014 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0442\u0443\u0434\u0430 \u0436\u0435, \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u044f \u043d\u0438 OAuthProxy, \u043d\u0438 \u043a\u043b\u0438\u0435\u043d\u0442.Per-user \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f: \u0444\u0443\u043d\u0434\u0430\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430OAuth \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b, \u043d\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b\u0430\u0441\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043d\u0435 \u0440\u0435\u0448\u0438\u0442\u044c.n8n MCP Client Tool \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u2014 \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 credential. \u0412\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0447\u0435\u0440\u0435\u0437 workflow \u0438\u0434\u0443\u0442 \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u0442\u043e\u0433\u043e, \u043a\u0442\u043e \u043f\u0440\u043e\u0448\u0435\u043b OAuth.\u0441\u0445\u0435\u043c\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 n8n \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438\u041a\u043e\u0433\u0434\u0430 \u0418\u0432\u0430\u043d\u043e\u0432 \u043f\u0438\u0448\u0435\u0442 \u0431\u043e\u0442\u0443, MCP-\u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0438\u0434\u0438\u0442 \u043d\u0435 \u0418\u0432\u0430\u043d\u043e\u0432\u0430, \u0430 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0432\u0448\u0435\u0433\u043e credential. \u0414\u043b\u044f \u0431\u043e\u0442\u0430 \u0441 \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u0430\u0432 \u044d\u0442\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041d\u0443\u0436\u043d\u0430 \u0434\u0440\u0443\u0433\u0430\u044f \u0441\u0445\u0435\u043c\u0430:\u0421\u0445\u0435\u043c\u0430 \u0441 per-user \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432 n8n\u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0432 Auth Proxy \u043d\u0430\u0431\u043e\u0440 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u2014 User Auth API. \u041f\u043e\u043b\u043d\u044b\u0439 flow:\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0438\u0448\u0435\u0442 \u0431\u043e\u0442\u0443 \u00ab\u043f\u0440\u0438\u0432\u0435\u0442\u00bb\u0411\u043e\u0442 \u2192 POST \/user-auth\/start {\u201cuser_id\u201d: \u201ctelegram_12345\u201d}Auth Proxy \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442: \u0435\u0441\u0442\u044c \u043b\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0441\u0435\u0441\u0441\u0438\u044f? \u0415\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0432\u0430\u043b\u0438\u0434\u0435\u043d \u2192 {status: \u201ccompleted\u201d, session_id: \u201cabc\u201d}\u0415\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0438\u0441\u0442\u0435\u043a \u2192 \u043f\u0440\u043e\u0431\u0443\u0435\u0442 refresh_token\u0415\u0441\u043b\u0438 refresh \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d \u2192 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043d\u043e\u0432\u0443\u044e \u0441\u0435\u0441\u0441\u0438\u044eAuth Proxy \u2192 201 {session_id: \u201cabc\u201d, login_url: \u201chttps:\/\/keycloak\u2026\/auth?..\u201d}\u0411\u043e\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u0441 login_url\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043a\u043b\u0438\u043a\u0430\u0435\u0442 \u2192 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u2192 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043b\u043e\u0433\u0438\u043d\u0430 Keycloak\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u0442 \u043b\u043e\u0433\u0438\u043d\/\u043f\u0430\u0440\u043e\u043b\u044c (\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 Keycloak, \u043d\u0435 \u0432 \u0431\u043e\u0442\u0435!)Keycloak \u2192 redirect \u043d\u0430 \/user-auth\/callback \u0441 \u043e\u0434\u043d\u043e\u0440\u0430\u0437\u043e\u0432\u044b\u043c codeAuth Proxy \u043e\u0431\u043c\u0435\u043d\u0438\u0432\u0430\u0435\u0442 code \u043d\u0430 access_token + refresh_token, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0411\u043e\u0442 \u2192 GET \/user-auth\/status\/abc \u2192 {status: \u201ccompleted\u201d, username: \u201c\u0418\u0432\u0430\u043d\u043e\u0432\u201d}\u0411\u043e\u0442 \u2192 POST \/user-auth\/mcp (headers: x-session-id: abc) Body: {jsonrpc: \u201c2.0\u201d, method: \u201ctools\/call\u201d, params: {name: \u201cwhoami\u201d}}Auth Proxy \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Bearer token \u0418\u0432\u0430\u043d\u043e\u0432\u0430 \u2192 Gateway \u2192 MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435\u0422\u043e\u043a\u0435\u043d\u044b \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 Auth Proxy. \u0411\u043e\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441 session_id \u2014 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u0435\u043d \u0431\u0435\u0437 Auth Proxy.\u0422\u0440\u0438 \u043a\u0430\u043d\u0430\u043b\u0430 \u0447\u0435\u0440\u0435\u0437 \u043e\u0434\u043d\u0443 \u0434\u0432\u0435\u0440\u044c\u0412 \u0438\u0442\u043e\u0433\u0435 Auth Proxy \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u0440\u0438 \u0442\u0438\u043f\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 \u0435\u0434\u0438\u043d\u044b\u0439 Keycloak:Claude Desktop \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u2014 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c URL\u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435. Claude \u0441\u0430\u043c \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 OAuth flow: \u0447\u0438\u0442\u0430\u0435\u0442 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 Dynamic Client Registration, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u043d\u0430 \u0432 Keycloak. Per-user \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438.n8n MCP Client Tool \u2014 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 OAuth2 \u0441 Dynamic Client Registration. \u041e\u0434\u0438\u043d credential \u043d\u0430 workflow. \u041f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447.Telegram-\u0431\u043e\u0442 \u2014 per-user \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 User Auth API. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 Keycloak.\u041a\u0430\u0441\u0442\u043e\u043c\u043d\u0430\u044f \u043d\u043e\u0434\u0430 \u0434\u043b\u044f n8n: usableAsTool\u0425\u043e\u0442\u0435\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c AI Tool-\u043d\u043e\u0434\u0443 \u0434\u043b\u044f n8n, \u0447\u0442\u043e\u0431\u044b AI Agent \u0432\u044b\u0437\u044b\u0432\u0430\u043b MCP-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.\u041f\u0435\u0440\u0435\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u0438 \u0447\u0435\u0442\u044b\u0440\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u2014 supplyData \u0441 DynamicTool, DynamicStructuredTool \u0441 Zod, \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u044b n8n (StructuredToolkit, logWrapper), \u0440\u0443\u0447\u043d\u0443\u044e \u043f\u043e\u0434\u043c\u0435\u043d\u0443 schema \u0447\u0435\u0440\u0435\u0437 Object.defineProperty. \u041a\u0430\u0436\u0434\u044b\u0439 \u0443\u043f\u0438\u0440\u0430\u043b\u0441\u044f \u0432 \u043e\u0434\u043d\u043e: \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 AI tool-\u043d\u043e\u0434\u044b n8n \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u044b \u043c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u043c \u043d\u043e\u0434\u0430\u043c.\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c \u0432 community-\u043d\u043e\u0434\u0435 Merge Agent Handler \u2014 \u043e\u0434\u043d\u043e \u043d\u0435\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e:description: INodeTypeDescription = {    usableAsTool: true,  \/\/ n8n \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043d\u043e\u0434\u0443 \u0432 AI Tool    inputs: [NodeConnectionTypes.Main],    outputs: [NodeConnectionTypes.Main],};usableAsTool: true \u0433\u043e\u0432\u043e\u0440\u0438\u0442 n8n: \u0432\u043e\u0437\u044c\u043c\u0438 \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u043d\u043e\u0434\u0443 \u0441 execute() \u0438 \u0441\u0434\u0435\u043b\u0430\u0439 \u0438\u0437 \u043d\u0435\u0435 AI Tool. \u0411\u0435\u0437 supplyData, \u0431\u0435\u0437 LangChain, \u0431\u0435\u0437 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u0434\u0432\u0430 \u0440\u0435\u0436\u0438\u043c\u0430 \u0447\u0435\u0440\u0435\u0437 displayOptions \u0441 @tool:\/\/ Standalone \u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u0442 \u0432\u0440\u0443\u0447\u043d\u0443\u044e{ name: &#8216;toolName&#8217;, displayOptions: { hide: { &#8216;@tool&#8217;: [true] } } }\/\/ Agent \u2014 AI Agent \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438{ name: &#8216;toolNameAgent&#8217;, displayOptions: { show: { &#8216;@tool&#8217;: [true] } } }\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 LangGraph\u041a\u0430\u0441\u0442\u043e\u043c\u043d\u0430\u044f \u043d\u043e\u0434\u0430 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430. \u041d\u043e \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u0441 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 n8n \u0440\u0435\u0448\u0438\u0442\u044c \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c.\u041e\u0434\u043d\u0430 tool \u0432\u043c\u0435\u0441\u0442\u043e \u0434\u0432\u0435\u043d\u0430\u0434\u0446\u0430\u0442\u0438\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 MCP Client Tool \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 MCP-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e tool \u2014 \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c, \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0438 \u0441\u0445\u0435\u043c\u043e\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. usableAsTool: true \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u0437 \u043d\u043e\u0434\u044b \u043e\u0434\u043d\u0443 tool. \u0412\u0441\u0435 12 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0432 \u00ab\u043c\u0435\u0442\u0430-\u0442\u0443\u043b\u0437\u0443\u00bb:\u0420\u0430\u0437\u043b\u0438\u0447\u0438\u044f \u043d\u043e\u0434 \u0432 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u0434\u043b\u044f \u0418\u0418-\u0430\u0433\u0435\u043d\u0442\u0430\u041d\u0430 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e. \u041d\u0430 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u2014 LLM \u043f\u0443\u0442\u0430\u043b\u0430\u0441\u044c: \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 JSON, \u043f\u0443\u0442\u0430\u043b\u0430 \u0438\u043c\u0435\u043d\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b\u0430 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043d\u0435 \u0432 \u0442\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. \u041a\u043e\u0433\u0434\u0430 \u0443 \u0430\u0433\u0435\u043d\u0442\u0430 12 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 tools \u0441 \u0447\u0435\u0442\u043a\u0438\u043c\u0438 \u0441\u0445\u0435\u043c\u0430\u043c\u0438 \u2014 \u043e\u043d \u0437\u043d\u0430\u0435\u0442, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c. \u041a\u043e\u0433\u0434\u0430 \u043e\u0434\u043d\u0430 \u00ab\u043c\u0435\u0442\u0430-\u0442\u0443\u043b\u0437\u0430\u00bb \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043d\u0430 \u043f\u043e\u043b\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u2014 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0438\u043c\u043f\u0440\u043e\u0432\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c.\u0427\u0442\u043e \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b\u0438 \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u0443\u0439\u0442\u0438\u0424\u043e\u0440\u043a\u043d\u0443\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 MCP Client Tool \u2014 \u0437\u0430\u043c\u0430\u043d\u0447\u0438\u0432\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c StructuredToolkit \u0438 12 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 tools. \u041d\u043e \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043a \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c API n8n, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043e\u043c \u0438 \u043b\u043e\u043c\u0430\u044e\u0442\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438. \u0414\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0430 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0445\u0440\u0443\u043f\u043a\u043e.\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u043d\u043e\u0434\u044b \u2014 \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u043d\u0430 MCP-\u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043d\u0443\u0436\u043d\u043e \u0440\u0443\u043a\u0430\u043c\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0434\u0443 \u0432 workflow&#8230;.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-478174","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/478174","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=478174"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/478174\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=478174"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=478174"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=478174"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}