@deadragdoll/tellymcp 0.0.13 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/.env.example.client +5 -1
  2. package/.env.example.gateway +16 -1
  3. package/CHANGELOG.md +30 -0
  4. package/README-ru.md +14 -0
  5. package/README.md +14 -0
  6. package/TOOLS.md +182 -10
  7. package/config/templates/env.both.template +15 -2
  8. package/config/templates/env.client.template +5 -2
  9. package/config/templates/env.gateway.template +15 -2
  10. package/dist/cli.js +28 -1
  11. package/dist/services/features/telegram-mcp/browser.service.js +18 -0
  12. package/dist/services/features/telegram-mcp/file-content.service.js +94 -0
  13. package/dist/services/features/telegram-mcp/gateway-delivery.service.js +5 -1
  14. package/dist/services/features/telegram-mcp/gateway-socket.service.js +43 -11
  15. package/dist/services/features/telegram-mcp/mcp-http.service.js +1 -0
  16. package/dist/services/features/telegram-mcp/mcp-server.service.js +18 -0
  17. package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +9 -1
  18. package/dist/services/features/telegram-mcp/src/app/config/env.js +119 -2
  19. package/dist/services/features/telegram-mcp/src/app/http.js +139 -99
  20. package/dist/services/features/telegram-mcp/src/app/oauthFacade.js +642 -0
  21. package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +151 -170
  22. package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +96 -99
  23. package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +62 -19
  24. package/dist/services/features/telegram-mcp/src/features/browser/model/browserAttachActiveTabTool.js +28 -0
  25. package/dist/services/features/telegram-mcp/src/features/browser/model/browserAttachTabTool.js +28 -0
  26. package/dist/services/features/telegram-mcp/src/features/browser/model/browserDetachTabTool.js +28 -0
  27. package/dist/services/features/telegram-mcp/src/features/browser/model/browserListAttachedInstancesTool.js +1 -1
  28. package/dist/services/features/telegram-mcp/src/features/browser/model/browserListTabsTool.js +1 -1
  29. package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +410 -27
  30. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/browserRecordingBundle.js +37 -3
  31. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachRegistry.js +7 -6
  32. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachServer.js +214 -37
  33. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/types.js +186 -0
  34. package/dist/services/features/telegram-mcp/src/features/collaboration/model/collaborationService.js +2 -0
  35. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +6 -3
  36. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +4 -1
  37. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +33 -35
  38. package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileListTool.js +33 -0
  39. package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileService.js +327 -0
  40. package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileTool.js +81 -0
  41. package/dist/services/features/telegram-mcp/src/features/file-content/model/temporaryFileLinkStore.js +307 -0
  42. package/dist/services/features/telegram-mcp/src/features/file-content/model/workspaceFilePolicy.js +115 -0
  43. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +5 -1
  44. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +3 -0
  45. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +6 -3
  46. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +29 -6
  47. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +100 -2
  48. package/dist/services/features/telegram-mcp/src/shared/lib/bodyLimits.js +63 -0
  49. package/dist/services/features/telegram-mcp/src/shared/lib/gatewayAuth.js +13 -0
  50. package/dist/services/features/telegram-mcp/src/shared/lib/time/localTimestamp.js +21 -0
  51. package/docs/CHAT_CONNECTOR.md +134 -0
  52. package/docs/STANDALONE-ru.md +13 -0
  53. package/docs/STANDALONE.md +13 -0
  54. package/package.json +5 -3
  55. package/packages/chrome-attach-extension/dist/background.js +572 -163
  56. package/packages/chrome-attach-extension/dist/manifest.json +2 -1
  57. package/packages/chrome-attach-extension/dist/options.js +15 -2
  58. package/packages/chrome-attach-extension/dist/recorder-content.js +14 -1
  59. package/packages/chrome-attach-extension/dist/recorder-page.js +34 -18
  60. package/packages/firefox-attach-extension/dist/background.js +413 -33
  61. package/packages/firefox-attach-extension/dist/manifest.json +0 -12
  62. package/packages/firefox-attach-extension/dist/options.js +14 -1
  63. package/packages/firefox-attach-extension/dist/recorder-content.js +14 -1
  64. package/packages/firefox-attach-extension/dist/recorder-page.js +34 -18
@@ -29,7 +29,7 @@ GATEWAY_WS_URL=wss://your-domain.example/api/gateway/ws
29
29
  GATEWAY_WS_PATH=/api/gateway/ws
30
30
  GATEWAY_TOKEN=change_me_gateway_token
31
31
  GATEWAY_USER_UUID=
32
- # GATEWAY_AUTH_TOKEN=
32
+ GATEWAY_AUTH_TOKEN=
33
33
 
34
34
  TERMINAL_SHELL=bash
35
35
  TERMINAL_COLS=120
@@ -71,6 +71,10 @@ BROWSER_WAIT_UNTIL=load
71
71
  # BROWSER_EXECUTABLE_PATH=
72
72
  # BROWSER_CHANNEL=chrome
73
73
  BROWSER_SLOW_MO_MS=0
74
+ # BROWSER_ATTACH_ENABLED=true
75
+ # BROWSER_ATTACH_WS_HOST=127.0.0.1
76
+ # BROWSER_ATTACH_WS_PORT=9999
77
+ # BROWSER_ATTACH_WS_PATH=/browser-attach/ws
74
78
 
75
79
  NAMESPACE=mcp
76
80
  NODE_ID=agent
@@ -29,12 +29,27 @@ MCP_HTTP_PATH=/mcp
29
29
  MCP_HTTP_ENABLE_DEBUG_ROUTES=false
30
30
  MCP_HTTP_ENABLE_PRUNE_ROUTE=false
31
31
 
32
+ # ChatGPT / Claude OAuth connector. Setting any OAuth value enables the facade.
33
+ # TELLYMCP_PUBLIC_URL=https://your-domain.example/api
34
+ # TELLYMCP_OAUTH_ISSUER=https://your-domain.example/api
35
+ # TELLYMCP_OAUTH_AUDIENCE=https://your-domain.example/api
36
+ # TELLYMCP_MAGIC_TOKEN=change_me_private_connector_token
37
+ # TELLYMCP_MAGIC_TOKEN_HASH=sha256:<hex>
38
+ # TELLYMCP_OAUTH_CLIENT_ID=tellymcp
39
+ # TELLYMCP_OAUTH_CLIENT_SECRET=
40
+ # TELLYMCP_ALLOWED_REDIRECT_URIS=https://chatgpt.com/connector/oauth/...,https://claude.ai/api/mcp/auth_callback
41
+ # TELLYMCP_OAUTH_PRIVATE_KEY_PEM="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
42
+ # TELLYMCP_AUTH_CODE_TTL_SECONDS=300
43
+ # TELLYMCP_OAUTH_SCOPES=tellymcp:read tellymcp:write
44
+ # TELLYMCP_OAUTH_KEY_ID=tellymcp-oauth
45
+
32
46
  DISTRIBUTED_MODE=gateway
47
+ # Also used to derive short-lived file URLs under /api/files/.
33
48
  GATEWAY_PUBLIC_URL=https://your-domain.example/api/gateway
34
49
  GATEWAY_WS_URL=wss://your-domain.example/api/gateway/ws
35
50
  GATEWAY_WS_PATH=/api/gateway/ws
36
51
  GATEWAY_TOKEN=change_me_gateway_token
37
- # GATEWAY_AUTH_TOKEN=
52
+ GATEWAY_AUTH_TOKEN=
38
53
 
39
54
  ROOT_PREFIX=/api
40
55
  PORT=8080
package/CHANGELOG.md CHANGED
@@ -3,6 +3,27 @@
3
3
  ## Unreleased
4
4
 
5
5
  ### Added
6
+
7
+ - Добавлены связанные MCP tools `get_file_list` и `get_file` для получения
8
+ файлов из workspace выбранной live-консоли через gateway. Первый возвращает
9
+ список managed files и точные пути, второй принимает `file_path` либо
10
+ `selector=latest_screenshot`. По умолчанию `get_file(type="url")` возвращает
11
+ короткоживущую download-ссылку в `data`; временная gateway-копия хранится в
12
+ `.tellymcp/tmp/file-links`, а `type="base64"` остаётся fallback.
13
+ - Добавлен явный режим `get_file(type="image")`: download URL остаётся в
14
+ `structuredContent.data`, сам structured type равен `image`, а изображение
15
+ возвращается отдельным нативным MCP-блоком, чтобы Claude и другие совместимые
16
+ клиенты могли рендерить его inline.
17
+ - Для Claude.ai сохранён совместимый `type="base64"`: полный JSON вместе с raw
18
+ base64 в `data` возвращается обычным MCP text-блоком без native image, поскольку
19
+ некоторые MCP-host адаптеры заменяют изображение на `[image]` и скрывают
20
+ structured output от модели.
21
+ - Добавлен `get_file(type="text")` для прямого чтения UTF-8 Markdown и исходников
22
+ через native MCP text-блок. Для `.ts`, `.tsx` и других source-расширений добавлены
23
+ текстовые MIME overrides.
24
+ - Доступ к live `.env`, credential stores, private-key расширениям и чувствительным
25
+ директориям теперь блокируется на клиенте до чтения или отправки файла; выход
26
+ за workspace и через symlink по-прежнему запрещён.
6
27
  - Перенос `telegram_mcp` на сервисную архитектуру `Moleculer`:
7
28
  - `telegramMcp.runtime`
8
29
  - `telegramMcp.http`
@@ -74,6 +95,14 @@
74
95
  - безопасные packaged templates для `.env`
75
96
 
76
97
  ### Changed
98
+
99
+ - Общее чтение workspace-файлов теперь проверяет реальный путь после разрешения
100
+ symlink и не позволяет выйти за пределы workspace.
101
+ - Telegram Mini App Live Console переведена на WS-only rendering:
102
+ - HTTP polling и `/api/view` удалены
103
+ - после разрыва WebSocket автоматически восстанавливается с exponential backoff
104
+ - размеры xterm рассчитываются официальным `@xterm/addon-fit`
105
+ - resize колонок и строк передаётся локальным и relay PTY
77
106
  - Полностью убран legacy standalone MCP transport. `telegram_mcp` работает только через REST/MCP over HTTP.
78
107
  - Локальный standalone HTTP listener убран; `telegram_mcp` больше не поднимает отдельный сервер вне Moleculer gateway.
79
108
  - UI Telegram переосмыслен по двум режимам:
@@ -113,6 +142,7 @@
113
142
  - старый `go/node terminal-proxy` path полностью удалён, поддерживается только прямой локальный terminal runtime
114
143
 
115
144
  ### Fixed
145
+
116
146
  - Исправлен `Headers have already sent` при работе MCP/WebApp через общий HTTP runtime.
117
147
  - Исправлены route/alias проблемы после перехода под `${ROOT_PREFIX}`.
118
148
  - Исправлены зависания Mini App bootstrap и проблемы с relative WebApp routes.
package/README-ru.md CHANGED
@@ -27,6 +27,7 @@
27
27
 
28
28
  - даёт MCP tools для human-in-the-loop через Telegram
29
29
  - позволяет одной консоли агента ставить задачу другой консоли
30
+ - позволяет MCP chat-клиенту получать проектный текст, изображения и артефакты выбранной консоли
30
31
  - хранит structured xchange records в `.mcp-xchange`
31
32
  - поддерживает browser automation через Playwright
32
33
  - умеет attach к уже открытому Firefox или Chrome через bundled local extensions
@@ -66,6 +67,7 @@ Gateway
66
67
  - `telegram_message`
67
68
  - `notify_telegram`
68
69
  - `browser_screenshot(send_to_telegram=true)`
70
+ - `get_file` для возврата скриншотов и артефактов в MCP chat-клиент
69
71
 
70
72
  Для agent-to-agent:
71
73
 
@@ -87,6 +89,15 @@ Gateway
87
89
  - `browser_recording_stop`
88
90
  - `browser_recording_status`
89
91
 
92
+ Файлы:
93
+
94
+ - `get_file_list(source=..., limit=...)`
95
+ - `get_file(file_path=..., type="url")`
96
+ - `get_file(file_path=..., type="image")`
97
+ - `get_file(file_path=..., type="text")`
98
+ - `get_file(file_path=..., type="base64")`
99
+ - `get_file(selector="latest_screenshot")`
100
+
90
101
  Синхронизация инструкций:
91
102
 
92
103
  - `refresh_tools_markdown`
@@ -157,6 +168,7 @@ tellymcp init gateway
157
168
  - `GATEWAY_PUBLIC_URL`
158
169
  - `GATEWAY_WS_URL`
159
170
  - `GATEWAY_TOKEN`
171
+ - `GATEWAY_AUTH_TOKEN`
160
172
 
161
173
  Запуск:
162
174
 
@@ -183,6 +195,7 @@ tellymcp init client
183
195
  - `GATEWAY_PUBLIC_URL`
184
196
  - `GATEWAY_WS_URL`
185
197
  - `GATEWAY_TOKEN`
198
+ - `GATEWAY_AUTH_TOKEN` (тот же transport-токен, который задан на gateway)
186
199
  - `GATEWAY_USER_UUID`, если консоль должна быть видна конкретному владельцу в gateway-боте
187
200
 
188
201
  Рекомендуется:
@@ -375,6 +388,7 @@ tellymcp system-prune --env .env --yes
375
388
  - [README.md](./README.md)
376
389
  - [STANDALONE.md](./docs/STANDALONE.md)
377
390
  - [STANDALONE-ru.md](./docs/STANDALONE-ru.md)
391
+ - [CHAT_CONNECTOR.md](./docs/CHAT_CONNECTOR.md) — OAuth-коннектор ChatGPT/Claude
378
392
  - [TOOLS.md](./TOOLS.md)
379
393
  - [screenshots/README.md](./screenshots/README.md)
380
394
 
package/README.md CHANGED
@@ -27,6 +27,7 @@ The current model is gateway-first:
27
27
 
28
28
  - exposes MCP tools for human Telegram interaction
29
29
  - lets one agent ask another agent to do work and return files or notes
30
+ - lets MCP chat clients retrieve project text, images, and artifacts from a selected console
30
31
  - stores structured xchange records in `.mcp-xchange`
31
32
  - supports browser automation with Playwright
32
33
  - can attach to an already running Firefox or Chrome tab through bundled local extensions
@@ -66,6 +67,7 @@ Human-facing:
66
67
  - `telegram_message` records
67
68
  - `notify_telegram`
68
69
  - `browser_screenshot(send_to_telegram=true)`
70
+ - `get_file` for returning screenshots and artifacts to MCP chat clients
69
71
 
70
72
  Agent-to-agent:
71
73
 
@@ -87,6 +89,15 @@ Browser:
87
89
  - `browser_recording_stop`
88
90
  - `browser_recording_status`
89
91
 
92
+ Files:
93
+
94
+ - `get_file_list(source=..., limit=...)`
95
+ - `get_file(file_path=..., type="url")`
96
+ - `get_file(file_path=..., type="image")`
97
+ - `get_file(file_path=..., type="text")`
98
+ - `get_file(file_path=..., type="base64")`
99
+ - `get_file(selector="latest_screenshot")`
100
+
90
101
  Tools sync:
91
102
 
92
103
  - `refresh_tools_markdown`
@@ -157,6 +168,7 @@ Required gateway values:
157
168
  - `GATEWAY_PUBLIC_URL`
158
169
  - `GATEWAY_WS_URL`
159
170
  - `GATEWAY_TOKEN`
171
+ - `GATEWAY_AUTH_TOKEN`
160
172
 
161
173
  Then run:
162
174
 
@@ -183,6 +195,7 @@ Required client values:
183
195
  - `GATEWAY_PUBLIC_URL`
184
196
  - `GATEWAY_WS_URL`
185
197
  - `GATEWAY_TOKEN`
198
+ - `GATEWAY_AUTH_TOKEN` (the same transport token configured on the gateway)
186
199
  - `GATEWAY_USER_UUID` if this console should be scoped to a specific Telegram owner
187
200
 
188
201
  Recommended:
@@ -374,6 +387,7 @@ tellymcp system-prune --env .env --yes
374
387
  - [README-ru.md](./README-ru.md)
375
388
  - [STANDALONE.md](./docs/STANDALONE.md)
376
389
  - [STANDALONE-ru.md](./docs/STANDALONE-ru.md)
390
+ - [CHAT_CONNECTOR.md](./docs/CHAT_CONNECTOR.md) — ChatGPT/Claude OAuth connector
377
391
  - [TOOLS.md](./TOOLS.md)
378
392
  - [screenshots/README.md](./screenshots/README.md)
379
393
 
package/TOOLS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Tools
2
2
 
3
- Version: `2026-06-06.1`
3
+ Version: `2026-06-06.2`
4
4
 
5
5
  Gateway/client runtime compatibility:
6
6
 
@@ -18,6 +18,9 @@ Browser tools:
18
18
 
19
19
  - `browser_list_attached_instances`
20
20
  - `browser_list_tabs`
21
+ - `browser_attach_active_tab`
22
+ - `browser_attach_tab`
23
+ - `browser_detach_tab`
21
24
  - `browser_recording_start`
22
25
  - `browser_recording_stop`
23
26
  - `browser_recording_status`
@@ -44,8 +47,8 @@ Browser runtime rule:
44
47
  - attached browser tab backend for a real user Firefox or Chrome session
45
48
  - isolated Playwright Chromium backend
46
49
  - `browser_open` is only for the isolated Playwright backend.
47
- - `browser_list_attached_instances` and `browser_list_tabs` are for the attached browser backend.
48
- - if the local attach extension is connected and a tab was selected from the browser control panel, `browser_click`, `browser_fill`, `browser_inject_script`, `browser_press`, `browser_dom`, and `browser_screenshot` use that attached browser tab for the current session without requiring `browser_open`
50
+ - `browser_list_attached_instances`, `browser_list_tabs`, `browser_attach_active_tab`, `browser_attach_tab`, and `browser_detach_tab` are for the attached browser backend.
51
+ - after a tab is attached for the current session, `browser_click`, `browser_fill`, `browser_inject_script`, `browser_press`, `browser_wait_for`, `browser_wait_for_url`, `browser_dom`, `browser_computed_style`, `browser_reload`, `browser_screenshot`, `browser_console`, `browser_errors`, `browser_network_failures`, `browser_clear_logs`, and `browser_close` use that attached browser tab without requiring `browser_open`
49
52
  - `browser_recording_start`, `browser_recording_stop`, and `browser_recording_status` are also for the attached browser backend
50
53
  - browser recordings are written under `.mcp-xchange/web/{tab-title-slug}-{timestamp}/`
51
54
  - each recording bundle contains `session.json`, `timeline.ndjson`, `pages/`, `network/`, and `console/`
@@ -80,13 +83,16 @@ Collaboration tools:
80
83
 
81
84
  Utility tools:
82
85
 
86
+ - `get_file_list`
87
+ - `get_file`
83
88
  - `refresh_tools_markdown`
84
89
 
85
90
  ## Console model
86
91
 
87
92
  Gateway-first runtime model:
88
93
 
89
- - agents register themselves on the gateway automatically through `GATEWAY_TOKEN`
94
+ - agents authenticate the gateway HTTP/WS transport through `GATEWAY_AUTH_TOKEN`
95
+ and register into their gateway scope through `GATEWAY_TOKEN`
90
96
  - Telegram no longer links sessions with pair codes
91
97
  - `/menu` in the gateway bot shows available remote consoles directly
92
98
  - one running agent console is one logical session/console target
@@ -111,7 +117,18 @@ Preferred order for cross-console work:
111
117
  - `send_partner_note`
112
118
  - `send_partner_file`
113
119
  - browser tools
114
- with explicit `session_id` for the current console or explicit target routing fields for another console.
120
+ with explicit `session_id` for the current console or explicit target routing fields for another console.
121
+
122
+ Preferred file-return flow for MCP chat clients:
123
+
124
+ 1. Resolve the selected live console and keep its canonical `session_id`.
125
+ 2. If the user refers to an existing managed file without an exact path, call `get_file_list` and select the matching `file_path`.
126
+ 3. If creating a screenshot now, call `browser_screenshot` and keep its returned `file_path`.
127
+ 4. For an exact Markdown, source-code, or other UTF-8 project path, call `get_file(type = "text")`; arbitrary project files are not discovered by `get_file_list`.
128
+ 5. For binary files, call `get_file` with the selected or newly returned `file_path`; default to `type = "url"`.
129
+ 6. If the chat cannot fetch an image URL, repeat the same call with `type = "image"` for a native inline MCP image block.
130
+ 7. If a host such as Claude.ai replaces the native block with `[image]`, retry with `type = "base64"`; this host-independent fallback returns the complete JSON, including raw `data`, in a regular MCP text block.
131
+ 8. If the user asks for the most recent existing screenshot, `get_file(selector = "latest_screenshot")` is the direct shortcut.
115
132
 
116
133
  ## `set_session_context`
117
134
 
@@ -190,6 +207,99 @@ Output:
190
207
  - `terminal?`
191
208
  Terminal runtime metadata for the console.
192
209
 
210
+ ## `get_file_list`
211
+
212
+ Purpose:
213
+
214
+ - List managed files available in a selected console workspace before calling `get_file`.
215
+ - Return exact `file_path` values accepted by `get_file`.
216
+
217
+ Input:
218
+
219
+ - `session_id`
220
+ - `source?`
221
+ - `telegram-upload`
222
+ - `browser-screenshot`
223
+ - `partner-artifact`
224
+ - `limit?`
225
+ - default: `50`
226
+ - maximum: `200`
227
+
228
+ Output:
229
+
230
+ - `total`
231
+ - `files[]`
232
+ - `file_path`
233
+ - `filename`
234
+ - `mimetype`
235
+ - `source`
236
+ - `size_bytes?`
237
+ - `created_at`
238
+
239
+ Behavior:
240
+
241
+ - results are ordered newest first
242
+ - `total` is the number of matching managed files before `limit` is applied
243
+ - this tool lists TellyMCP-managed Telegram uploads, browser screenshots, and partner artifacts; it does not recursively enumerate arbitrary source files in the workspace
244
+ - in gateway mode, always pass the canonical `session_id = client_uuid:local_session_id`
245
+ - pass the chosen `files[].file_path` unchanged to `get_file`
246
+
247
+ ## `get_file`
248
+
249
+ Purpose:
250
+
251
+ - Return the actual content of a file from a selected console workspace to an MCP chat client.
252
+ - URL mode creates a bounded temporary gateway copy; text and base64 modes relay content directly.
253
+
254
+ Input:
255
+
256
+ - `session_id`
257
+ - `type?`
258
+ - `url` (default)
259
+ - `image` (native inline image plus download URL)
260
+ - `text` (native UTF-8 MCP text content)
261
+ - `base64` (fallback)
262
+ - exactly one of:
263
+ - `file_path`
264
+ - `selector = "latest_screenshot"`
265
+
266
+ Output:
267
+
268
+ - `type`
269
+ - `data`
270
+ - short-lived HTTPS URL when `type = "url"`
271
+ - short-lived HTTPS URL when `type = "image"`; the actual pixels are in the native MCP image content block
272
+ - decoded UTF-8 file content when `type = "text"`
273
+ - base64 payload when `type = "base64"`
274
+ - `mimetype`
275
+ - `filename`
276
+ - `size_bytes`
277
+ - `expires_at?`
278
+
279
+ Behavior:
280
+
281
+ - in gateway mode, always pass the canonical `session_id = client_uuid:local_session_id` returned by `list_gateway_sessions`
282
+ - `file_path` may be the exact path returned by `browser_screenshot`, so the human does not need to know generated filenames
283
+ - `selector = "latest_screenshot"` selects the newest file metadata with `source = "browser-screenshot"` for that session
284
+ - file reads are limited to the selected console workspace, including after symlink resolution
285
+ - exact project-relative paths such as `README.md` or `src/test.ts` are accepted even though `get_file_list` only discovers managed artifacts
286
+ - text mode returns the decoded file directly as a native MCP text content block and rejects invalid UTF-8 or binary NUL content
287
+ - source extensions such as `.ts` and `.tsx` use text MIME overrides instead of the generic MPEG/octet-stream mappings
288
+ - sensitive paths including live `.env` files, credential stores, private-key extensions, and secret directories are rejected server-side; documented `.env.example`/`.env.sample`/`.env.template` files remain readable
289
+ - URL mode uploads the file as a binary stream to `.tellymcp/tmp/file-links` on the gateway and returns a link valid for 10 minutes
290
+ - image mode is explicit: `structuredContent.type` is `image`, `structuredContent.data` contains the URL, and the native top-level MCP `image` is the first content block without duplicating base64 into structured output
291
+ - image mode accepts only `image/*` files up to the safe native-inline limit; use `url` for larger images
292
+ - URL links allow up to three GET downloads; HEAD requests do not consume the limit
293
+ - if URL fetching fails for an image, retry with `type = "image"`
294
+ - base64 mode is the compatibility fallback for hosts that replace native images with `[image]` or hide `structuredContent`: it returns the complete JSON payload, including raw base64 in `data`, as a regular MCP text block and does not emit a native image
295
+ - base64 mode is bounded by the final MCP response body limit
296
+ - do not attempt to bypass the sensitive-file policy or retrieve renamed secrets
297
+
298
+ Screenshot examples:
299
+
300
+ - "take a screenshot and send it": call `browser_screenshot`, then pass its returned `file_path` to `get_file`
301
+ - "send the latest screenshot": call `get_file` with `selector = "latest_screenshot"`
302
+
193
303
  ## `refresh_tools_markdown`
194
304
 
195
305
  Purpose:
@@ -447,7 +557,7 @@ Required agent practice:
447
557
  - "tell frontend what changed"
448
558
  - "send the error to your teammate"
449
559
  - "tell the other agent what's new"
450
- then the correct path is `send_partner_note`
560
+ then the correct path is `send_partner_note`
451
561
 
452
562
  How to find the partner correctly:
453
563
 
@@ -507,7 +617,7 @@ Reply rule for project asks:
507
617
  - `Reply project_uuid: ...`
508
618
  - `Reply target_client_uuid: ...`
509
619
  - `Reply target_local_session_id: ...`
510
- or a `Reply Params` section with the same data
620
+ or a `Reply Params` section with the same data
511
621
  - then reply with those exact values
512
622
  - if `in_reply_to` is available, prefer `Reply message_uuid`
513
623
  - if only the note `share_id` is available, gateway now also accepts that value in `in_reply_to`
@@ -608,7 +718,7 @@ How the receiving agent must react:
608
718
  - `проверь xchange records`
609
719
  - `telegram_message`
610
720
  - `partner_note`
611
- then do not start with a legacy inbox-specific tool
721
+ then do not start with a legacy inbox-specific tool
612
722
  - instead:
613
723
  1. call `list_xchange_records`
614
724
  2. identify the newest relevant record by category:
@@ -836,10 +946,68 @@ Output:
836
946
  Notes:
837
947
 
838
948
  - if only one attached browser instance is connected, `instance_id` can be omitted
839
- - current tab selection for the attach backend is done from the browser extension control panel
949
+ - tab selection for the attach backend can be done either from the browser extension control panel or through `browser_attach_active_tab` / `browser_attach_tab`
840
950
  - `active=true` means the tab is active in its browser window; there may be more than one such tab across multiple windows
841
951
  - for the tab currently selected for this MCP session, prefer `selected=true`
842
952
 
953
+ ## `browser_attach_active_tab`
954
+
955
+ Purpose:
956
+
957
+ - attach the current MCP session to the active tab of a connected attached browser instance
958
+
959
+ Input:
960
+
961
+ - `session_id?`
962
+ - `instance_id?`
963
+
964
+ Output:
965
+
966
+ - `session_id`
967
+ - `backend`
968
+ - `instance_id`
969
+ - `tab_id`
970
+ - `attached_at`
971
+ - `title?`
972
+ - `url?`
973
+
974
+ ## `browser_attach_tab`
975
+
976
+ Purpose:
977
+
978
+ - attach the current MCP session to a specific attached browser tab by `tab_id`
979
+
980
+ Input:
981
+
982
+ - `session_id?`
983
+ - `instance_id?`
984
+ - `tab_id`
985
+
986
+ Output:
987
+
988
+ - `session_id`
989
+ - `backend`
990
+ - `instance_id`
991
+ - `tab_id`
992
+ - `attached_at`
993
+ - `title?`
994
+ - `url?`
995
+
996
+ ## `browser_detach_tab`
997
+
998
+ Purpose:
999
+
1000
+ - detach the current MCP session from the currently selected attached browser tab
1001
+
1002
+ Input:
1003
+
1004
+ - `session_id?`
1005
+
1006
+ Output:
1007
+
1008
+ - `session_id`
1009
+ - `detached`
1010
+
843
1011
  ## `browser_recording_start`
844
1012
 
845
1013
  Purpose:
@@ -1227,6 +1395,8 @@ Output:
1227
1395
  Purpose:
1228
1396
 
1229
1397
  - inspect computed styles and box metrics for a DOM element in the session browser tab
1398
+ - if the session has a selected attached browser tab, inspect that real browser tab
1399
+ - otherwise inspect the isolated Playwright page
1230
1400
 
1231
1401
  Input:
1232
1402
 
@@ -1284,7 +1454,9 @@ Notes:
1284
1454
 
1285
1455
  Purpose:
1286
1456
 
1287
- - close the isolated browser context for the current session
1457
+ - close the current browser target for the session
1458
+ - if the session has a selected attached browser tab, close that real browser tab and clear the attach state
1459
+ - otherwise close the isolated Playwright browser context
1288
1460
 
1289
1461
  Input:
1290
1462
 
@@ -29,13 +29,27 @@ MCP_HTTP_PATH=/mcp
29
29
  MCP_HTTP_ENABLE_DEBUG_ROUTES=false
30
30
  MCP_HTTP_ENABLE_PRUNE_ROUTE=false
31
31
 
32
+ # ChatGPT / Claude OAuth connector. Setting any OAuth value enables the facade.
33
+ # TELLYMCP_PUBLIC_URL=https://your-domain.example/api
34
+ # TELLYMCP_OAUTH_ISSUER=https://your-domain.example/api
35
+ # TELLYMCP_OAUTH_AUDIENCE=https://your-domain.example/api
36
+ # TELLYMCP_MAGIC_TOKEN=change_me_private_connector_token
37
+ # TELLYMCP_MAGIC_TOKEN_HASH=sha256:<hex>
38
+ # TELLYMCP_OAUTH_CLIENT_ID=tellymcp
39
+ # TELLYMCP_OAUTH_CLIENT_SECRET=
40
+ # TELLYMCP_ALLOWED_REDIRECT_URIS=https://chatgpt.com/connector/oauth/...,https://claude.ai/api/mcp/auth_callback
41
+ # TELLYMCP_OAUTH_PRIVATE_KEY_PEM="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
42
+ # TELLYMCP_AUTH_CODE_TTL_SECONDS=300
43
+ # TELLYMCP_OAUTH_SCOPES=tellymcp:read tellymcp:write
44
+ # TELLYMCP_OAUTH_KEY_ID=tellymcp-oauth
45
+
32
46
  DISTRIBUTED_MODE=both
33
47
  GATEWAY_PUBLIC_URL=
34
48
  GATEWAY_WS_URL=
35
49
  GATEWAY_WS_PATH=/api/gateway/ws
36
50
  GATEWAY_TOKEN=
37
51
  GATEWAY_USER_UUID=
38
- # GATEWAY_AUTH_TOKEN=
52
+ GATEWAY_AUTH_TOKEN=
39
53
 
40
54
  ROOT_PREFIX=/api
41
55
  PORT=8080
@@ -63,7 +77,6 @@ WEBAPP_INITDATA_TTL_SECONDS=300
63
77
  WEBAPP_SESSION_TTL_SECONDS=900
64
78
  WEBAPP_LAUNCH_MODE=fullscreen
65
79
  WEBAPP_VISIBLE_SCREENS=10
66
- WEBAPP_POLL_INTERVAL_MS=2000
67
80
  WEBAPP_ACTION_COOLDOWN_MS=150
68
81
 
69
82
  MCP_XCHANGE_DIR=.mcp-xchange
@@ -24,7 +24,7 @@ GATEWAY_WS_URL=
24
24
  GATEWAY_WS_PATH=/api/gateway/ws
25
25
  GATEWAY_TOKEN=
26
26
  GATEWAY_USER_UUID=
27
- # GATEWAY_AUTH_TOKEN=
27
+ GATEWAY_AUTH_TOKEN=
28
28
 
29
29
  TERMINAL_SHELL=bash
30
30
  TERMINAL_COLS=120
@@ -51,7 +51,6 @@ WEBAPP_INITDATA_TTL_SECONDS=300
51
51
  WEBAPP_SESSION_TTL_SECONDS=900
52
52
  WEBAPP_LAUNCH_MODE=fullscreen
53
53
  WEBAPP_VISIBLE_SCREENS=10
54
- WEBAPP_POLL_INTERVAL_MS=2000
55
54
  WEBAPP_ACTION_COOLDOWN_MS=150
56
55
 
57
56
  MCP_XCHANGE_DIR=.mcp-xchange
@@ -66,6 +65,10 @@ BROWSER_WAIT_UNTIL=load
66
65
  # BROWSER_EXECUTABLE_PATH=
67
66
  # BROWSER_CHANNEL=chrome
68
67
  BROWSER_SLOW_MO_MS=0
68
+ # BROWSER_ATTACH_ENABLED=true
69
+ # BROWSER_ATTACH_WS_HOST=127.0.0.1
70
+ # BROWSER_ATTACH_WS_PORT=9999
71
+ # BROWSER_ATTACH_WS_PATH=/browser-attach/ws
69
72
 
70
73
  NAMESPACE=mcp
71
74
  NODE_ID=agent
@@ -25,12 +25,26 @@ MCP_HTTP_PATH=/mcp
25
25
  MCP_HTTP_ENABLE_DEBUG_ROUTES=false
26
26
  MCP_HTTP_ENABLE_PRUNE_ROUTE=false
27
27
 
28
+ # ChatGPT / Claude OAuth connector. Setting any OAuth value enables the facade.
29
+ # TELLYMCP_PUBLIC_URL=https://your-domain.example/api
30
+ # TELLYMCP_OAUTH_ISSUER=https://your-domain.example/api
31
+ # TELLYMCP_OAUTH_AUDIENCE=https://your-domain.example/api
32
+ # TELLYMCP_MAGIC_TOKEN=change_me_private_connector_token
33
+ # TELLYMCP_MAGIC_TOKEN_HASH=sha256:<hex>
34
+ # TELLYMCP_OAUTH_CLIENT_ID=tellymcp
35
+ # TELLYMCP_OAUTH_CLIENT_SECRET=
36
+ # TELLYMCP_ALLOWED_REDIRECT_URIS=https://chatgpt.com/connector/oauth/...,https://claude.ai/api/mcp/auth_callback
37
+ # TELLYMCP_OAUTH_PRIVATE_KEY_PEM="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
38
+ # TELLYMCP_AUTH_CODE_TTL_SECONDS=300
39
+ # TELLYMCP_OAUTH_SCOPES=tellymcp:read tellymcp:write
40
+ # TELLYMCP_OAUTH_KEY_ID=tellymcp-oauth
41
+
28
42
  DISTRIBUTED_MODE=gateway
29
43
  GATEWAY_PUBLIC_URL=
30
44
  GATEWAY_WS_URL=
31
45
  GATEWAY_WS_PATH=/api/gateway/ws
32
46
  GATEWAY_TOKEN=
33
- # GATEWAY_AUTH_TOKEN=
47
+ GATEWAY_AUTH_TOKEN=
34
48
 
35
49
  ROOT_PREFIX=/api
36
50
  PORT=8080
@@ -58,7 +72,6 @@ WEBAPP_INITDATA_TTL_SECONDS=300
58
72
  WEBAPP_SESSION_TTL_SECONDS=900
59
73
  WEBAPP_LAUNCH_MODE=fullscreen
60
74
  WEBAPP_VISIBLE_SCREENS=10
61
- WEBAPP_POLL_INTERVAL_MS=2000
62
75
  WEBAPP_ACTION_COOLDOWN_MS=150
63
76
 
64
77
  MCP_XCHANGE_DIR=.mcp-xchange
package/dist/cli.js CHANGED
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const node_child_process_1 = require("node:child_process");
10
+ const node_crypto_1 = require("node:crypto");
10
11
  const node_net_1 = __importDefault(require("node:net"));
11
12
  const dotenv_1 = require("dotenv");
12
13
  const ioredis_1 = __importDefault(require("ioredis"));
@@ -77,6 +78,7 @@ function printHelp() {
77
78
  " tellymcp codex-plugin install",
78
79
  " tellymcp codex-plugin status",
79
80
  " tellymcp mcp [--url <url>] [--bearer <token>] [--format claude|legacy]",
81
+ " tellymcp oauth key",
80
82
  " tellymcp help",
81
83
  ]);
82
84
  printSection("Examples", [
@@ -94,6 +96,7 @@ function printHelp() {
94
96
  " tellymcp codex-plugin install",
95
97
  " tellymcp codex-plugin status",
96
98
  " tellymcp mcp --help",
99
+ " tellymcp oauth key",
97
100
  ]);
98
101
  printSection("terminal", [
99
102
  `${picocolors_1.default.green(" OK")} built-in PTY runtime`,
@@ -238,6 +241,26 @@ function printMcpHelp() {
238
241
  " tellymcp mcp --url https://builder.undoo.ru/api/mcp --format legacy",
239
242
  ]);
240
243
  }
244
+ function runOAuthCommand(args) {
245
+ const [subcommand] = args;
246
+ if (!subcommand || subcommand === "--help" || subcommand === "-h") {
247
+ printBanner("OAuth helper", "Generate connector signing material");
248
+ printSection("Usage", [" tellymcp oauth key"]);
249
+ printSection("Output", [
250
+ " Prints a dotenv-ready TELLYMCP_OAUTH_PRIVATE_KEY_PEM value.",
251
+ " Store it only on the gateway and never expose it to chat clients.",
252
+ ]);
253
+ return;
254
+ }
255
+ if (subcommand !== "key") {
256
+ fail("Supported OAuth subcommands: key");
257
+ }
258
+ const privateKeyPem = (0, node_crypto_1.generateKeyPairSync)("rsa", { modulusLength: 2048 })
259
+ .privateKey.export({ type: "pkcs8", format: "pem" })
260
+ .toString()
261
+ .replace(/\n/gu, "\\n");
262
+ process.stdout.write(`TELLYMCP_OAUTH_PRIVATE_KEY_PEM="${privateKeyPem}"\n`);
263
+ }
241
264
  function printBrowserHelp() {
242
265
  printBanner("browser helper", "Manage Playwright browser binaries used by browser_* tools");
243
266
  printSection("Usage", [
@@ -1045,7 +1068,7 @@ async function runRuntime(args) {
1045
1068
  }
1046
1069
  async function main(argv) {
1047
1070
  const [rawCommand, firstArg, secondArg] = argv;
1048
- const command = rawCommand === "init" || rawCommand === "run" || rawCommand === "help" || rawCommand === "mcp" || rawCommand === "doctor" || rawCommand === "browser" || rawCommand === "system-prune"
1071
+ const command = rawCommand === "init" || rawCommand === "run" || rawCommand === "help" || rawCommand === "mcp" || rawCommand === "oauth" || rawCommand === "doctor" || rawCommand === "browser" || rawCommand === "system-prune"
1049
1072
  || rawCommand === "codex-plugin" || rawCommand === "extension"
1050
1073
  ? rawCommand
1051
1074
  : "help";
@@ -1061,6 +1084,10 @@ async function main(argv) {
1061
1084
  printMcpConfig(argv.slice(1));
1062
1085
  return;
1063
1086
  }
1087
+ if (command === "oauth") {
1088
+ runOAuthCommand(argv.slice(1));
1089
+ return;
1090
+ }
1064
1091
  if (command === "doctor") {
1065
1092
  await runDoctor(argv.slice(1));
1066
1093
  return;