@deadragdoll/tellymcp 0.0.11 → 0.0.13

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 (62) hide show
  1. package/README-ru.md +48 -0
  2. package/README.md +47 -0
  3. package/TOOLS.md +232 -3
  4. package/VERSION.md +2 -2
  5. package/dist/cli.js +109 -1
  6. package/dist/services/features/telegram-mcp/browser.service.js +38 -1
  7. package/dist/services/features/telegram-mcp/gateway-socket.service.js +10 -0
  8. package/dist/services/features/telegram-mcp/mcp-server.service.js +12 -0
  9. package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +14 -0
  10. package/dist/services/features/telegram-mcp/src/app/config/env.js +13 -0
  11. package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +151 -2
  12. package/dist/services/features/telegram-mcp/src/features/browser/model/browserClickTool.js +1 -1
  13. package/dist/services/features/telegram-mcp/src/features/browser/model/browserDomTool.js +1 -1
  14. package/dist/services/features/telegram-mcp/src/features/browser/model/browserFillTool.js +1 -1
  15. package/dist/services/features/telegram-mcp/src/features/browser/model/browserInjectScriptTool.js +28 -0
  16. package/dist/services/features/telegram-mcp/src/features/browser/model/browserListAttachedInstancesTool.js +33 -0
  17. package/dist/services/features/telegram-mcp/src/features/browser/model/browserListTabsTool.js +33 -0
  18. package/dist/services/features/telegram-mcp/src/features/browser/model/browserOpenTool.js +1 -1
  19. package/dist/services/features/telegram-mcp/src/features/browser/model/browserPressTool.js +1 -1
  20. package/dist/services/features/telegram-mcp/src/features/browser/model/browserRecordingStartTool.js +28 -0
  21. package/dist/services/features/telegram-mcp/src/features/browser/model/browserRecordingStatusTool.js +28 -0
  22. package/dist/services/features/telegram-mcp/src/features/browser/model/browserRecordingStopTool.js +28 -0
  23. package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +1 -1
  24. package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +543 -9
  25. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/browserRecordingBundle.js +502 -0
  26. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachRegistry.js +79 -0
  27. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachServer.js +559 -0
  28. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/types.js +2 -0
  29. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +48 -0
  30. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +5 -1
  31. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +5 -1
  32. package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +56 -0
  33. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +37 -0
  34. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +13 -7
  35. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +9 -0
  36. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuShell.js +3 -0
  37. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPayloadState.js +7 -0
  38. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalActions.js +231 -34
  39. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +61 -6
  40. package/dist/services/features/telegram-mcp/src/shared/lib/terminalPromptDetection.js +200 -28
  41. package/docs/STANDALONE-ru.md +42 -6
  42. package/docs/STANDALONE.md +42 -6
  43. package/package.json +6 -3
  44. package/packages/chrome-attach-extension/dist/background.js +1326 -0
  45. package/packages/chrome-attach-extension/dist/icon.svg +6 -0
  46. package/packages/chrome-attach-extension/dist/manifest.json +36 -0
  47. package/packages/chrome-attach-extension/dist/options.html +312 -0
  48. package/packages/chrome-attach-extension/dist/options.js +593 -0
  49. package/packages/chrome-attach-extension/dist/popup.html +93 -0
  50. package/packages/chrome-attach-extension/dist/popup.js +79 -0
  51. package/packages/chrome-attach-extension/dist/recorder-content.js +83 -0
  52. package/packages/chrome-attach-extension/dist/recorder-page.js +266 -0
  53. package/packages/firefox-attach-extension/README.md +13 -0
  54. package/packages/firefox-attach-extension/dist/background.js +1242 -0
  55. package/packages/firefox-attach-extension/dist/icon.svg +6 -0
  56. package/packages/firefox-attach-extension/dist/manifest.json +56 -0
  57. package/packages/firefox-attach-extension/dist/options.html +312 -0
  58. package/packages/firefox-attach-extension/dist/options.js +527 -0
  59. package/packages/firefox-attach-extension/dist/popup.html +93 -0
  60. package/packages/firefox-attach-extension/dist/popup.js +64 -0
  61. package/packages/firefox-attach-extension/dist/recorder-content.js +77 -0
  62. package/packages/firefox-attach-extension/dist/recorder-page.js +302 -0
package/README-ru.md CHANGED
@@ -29,6 +29,9 @@
29
29
  - позволяет одной консоли агента ставить задачу другой консоли
30
30
  - хранит structured xchange records в `.mcp-xchange`
31
31
  - поддерживает browser automation через Playwright
32
+ - умеет attach к уже открытому Firefox или Chrome через bundled local extensions
33
+ - умеет писать structured browser bundles в `.mcp-xchange/web/...` с HTML, network и console артефактами
34
+ - умеет инжектить helper scripts в attached tabs или Playwright pages через `browser_inject_script`
32
35
  - отдаёт Telegram Mini App / Live View с gateway
33
36
  - поддерживает polling и webhook на gateway
34
37
  - поставляет встроенный Codex plugin со skills под типовые workflow
@@ -76,9 +79,13 @@ Gateway
76
79
  - `browser_open`
77
80
  - `browser_click`
78
81
  - `browser_fill`
82
+ - `browser_inject_script`
79
83
  - `browser_press`
80
84
  - `browser_wait_for`
81
85
  - `browser_screenshot`
86
+ - `browser_recording_start`
87
+ - `browser_recording_stop`
88
+ - `browser_recording_status`
82
89
 
83
90
  Синхронизация инструкций:
84
91
 
@@ -105,6 +112,18 @@ npm install -g @deadragdoll/tellymcp
105
112
  tellymcp browser install
106
113
  ```
107
114
 
115
+ Если нужны attach extensions для существующего Firefox/Chrome:
116
+
117
+ ```bash
118
+ tellymcp extension firefox
119
+ tellymcp extension chrome
120
+ ```
121
+
122
+ Команда выгружает готовые unpacked bundles в текущий каталог:
123
+
124
+ - `./tellymcp-firefox-attach`
125
+ - `./tellymcp-chrome-attach`
126
+
108
127
  Если используешь Codex:
109
128
 
110
129
  ```bash
@@ -272,6 +291,35 @@ tellymcp browser install
272
291
 
273
292
  Не подменяй browser workflow ad hoc shell-командами с Playwright, кроме случаев, когда ты отлаживаешь сам browser runtime.
274
293
 
294
+ ## Terminal Blockers
295
+
296
+ Gateway prompt scanner теперь живёт от live-client lifecycle:
297
+
298
+ - на старте gateway scanner только armed, но не крутится вхолостую
299
+ - реальная работа начинается после подключения live client
300
+ - relay console materialization идёт из `hello` и owner-route hydration, а не из `/menu`
301
+ - детект работает по хвосту захваченного terminal buffer
302
+
303
+ Основная эвристика blocker-а:
304
+
305
+ - подряд идущие numbered choices: `1.`, `2.`, `3.`
306
+ - рядом есть action hints вроде `press`, `input`, `choose`, `enter`, `esc`, `yes`, `no`
307
+ - в Telegram notice попадают и 1-2 строки контекста выше menu block
308
+
309
+ Когда blocker найден, gateway может отправить inline-кнопки:
310
+
311
+ - `1..N`
312
+ - `Enter`
313
+ - `Esc`
314
+
315
+ Эти кнопки отправляют в консоль ровно цифру или terminal action. Навигация маркером не используется.
316
+
317
+ Операционные заметки:
318
+
319
+ - одинаковый blocker fingerprint не перевысылается повторно
320
+ - relay capture miss для offline agent считается debug-only шумом
321
+ - `Storage` и `Screenshots` на gateway теперь relay-aware и читают metadata через gateway routes, а не через filesystem самого gateway
322
+
275
323
  ## Collaboration
276
324
 
277
325
  Проекты:
package/README.md CHANGED
@@ -29,6 +29,9 @@ The current model is gateway-first:
29
29
  - lets one agent ask another agent to do work and return files or notes
30
30
  - stores structured xchange records in `.mcp-xchange`
31
31
  - supports browser automation with Playwright
32
+ - can attach to an already running Firefox or Chrome tab through bundled local extensions
33
+ - records browser sessions into structured `.mcp-xchange/web/...` bundles with HTML, network and console artifacts
34
+ - can inject helper scripts into attached tabs or Playwright pages through `browser_inject_script`
32
35
  - serves the Telegram Mini App / Live View from the gateway
33
36
  - supports Telegram polling or webhook mode on the gateway
34
37
  - ships a bundled Codex workflow plugin for better agent behavior
@@ -76,9 +79,13 @@ Browser:
76
79
  - `browser_open`
77
80
  - `browser_click`
78
81
  - `browser_fill`
82
+ - `browser_inject_script`
79
83
  - `browser_press`
80
84
  - `browser_wait_for`
81
85
  - `browser_screenshot`
86
+ - `browser_recording_start`
87
+ - `browser_recording_stop`
88
+ - `browser_recording_status`
82
89
 
83
90
  Tools sync:
84
91
 
@@ -105,6 +112,18 @@ Optional browser runtime:
105
112
  tellymcp browser install
106
113
  ```
107
114
 
115
+ Optional attached-browser extensions:
116
+
117
+ ```bash
118
+ tellymcp extension firefox
119
+ tellymcp extension chrome
120
+ ```
121
+
122
+ This exports unpacked extension bundles into the current directory:
123
+
124
+ - `./tellymcp-firefox-attach`
125
+ - `./tellymcp-chrome-attach`
126
+
108
127
  Optional Codex workflow plugin:
109
128
 
110
129
  ```bash
@@ -272,6 +291,34 @@ tellymcp browser install
272
291
 
273
292
  Do not replace browser workflows with ad hoc shell Playwright commands unless you are debugging the runtime itself.
274
293
 
294
+ ## Terminal Blockers
295
+
296
+ Gateway prompt scanning is now live-client driven:
297
+
298
+ - the scanner is armed on gateway startup but starts working only after a live client connects
299
+ - relay console materialization happens from gateway hello/owner-route hydration, not from `/menu`
300
+ - prompt detection works on the tail of the captured terminal buffer
301
+
302
+ Primary blocker heuristic:
303
+
304
+ - contiguous numbered choices like `1.`, `2.`, `3.`
305
+ - nearby action hints such as `press`, `input`, `choose`, `enter`, `esc`, `yes`, `no`
306
+ - optional context lines above the menu block are included in the Telegram notice
307
+
308
+ When a blocker is detected, the gateway can send inline Telegram buttons for:
309
+
310
+ - `1..N`
311
+ - `Enter`
312
+ - `Esc`
313
+
314
+ Those buttons send exactly the digit or terminal action to the target console. No marker navigation is used.
315
+
316
+ Operational notes:
317
+
318
+ - repeated scans of the same blocker fingerprint do not resend the notice
319
+ - relay capture misses for offline agents are treated as debug-only noise
320
+ - `Storage` and `Screenshots` on the gateway are relay-aware and read console metadata through gateway routes instead of the gateway filesystem
321
+
275
322
  ## Collaboration Model
276
323
 
277
324
  Projects:
package/TOOLS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Tools
2
2
 
3
- Version: `2026-05-22.1`
3
+ Version: `2026-06-06.1`
4
4
 
5
5
  Gateway/client runtime compatibility:
6
6
 
@@ -16,10 +16,16 @@ This MCP server currently exposes the following tools.
16
16
 
17
17
  Browser tools:
18
18
 
19
+ - `browser_list_attached_instances`
20
+ - `browser_list_tabs`
21
+ - `browser_recording_start`
22
+ - `browser_recording_stop`
23
+ - `browser_recording_status`
19
24
  - `browser_open`
20
25
  - `browser_reload`
21
26
  - `browser_click`
22
27
  - `browser_fill`
28
+ - `browser_inject_script`
23
29
  - `browser_press`
24
30
  - `browser_wait_for`
25
31
  - `browser_wait_for_url`
@@ -34,10 +40,35 @@ Browser tools:
34
40
 
35
41
  Browser runtime rule:
36
42
 
37
- - Browser tools use Playwright Chromium.
43
+ - Browser tools now have two backends:
44
+ - attached browser tab backend for a real user Firefox or Chrome session
45
+ - isolated Playwright Chromium backend
46
+ - `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`
49
+ - `browser_recording_start`, `browser_recording_stop`, and `browser_recording_status` are also for the attached browser backend
50
+ - browser recordings are written under `.mcp-xchange/web/{tab-title-slug}-{timestamp}/`
51
+ - each recording bundle contains `session.json`, `timeline.ndjson`, `pages/`, `network/`, and `console/`
52
+ - inside `network/`, use `index.ndjson` as the thin search index and `requests/{seq}-{request_id}/` as the per-request artifact bundle
53
+ - otherwise those tools use the Playwright backend after `browser_open`
38
54
  - If browser tools fail because the Playwright browser runtime is missing, install it with `tellymcp browser install`.
39
55
  - Do not stop at the installation error itself. Install the browser runtime first, then retry the browser tool.
40
56
 
57
+ Terminal prompt scan rules:
58
+
59
+ - gateway prompt scan is driven by live client lifecycle, not by manual menu entry
60
+ - the scanner works on the tail of the captured terminal buffer
61
+ - the main blocker signal is:
62
+ - a contiguous numbered choice block like `1.`, `2.`, `3.`
63
+ - nearby action-hint language such as `press`, `input`, `choose`, `enter`, `esc`, `yes`, `no`
64
+ - exact footer text is helpful but not required
65
+ - when a blocker notice contains inline buttons, those buttons intentionally send only:
66
+ - a digit `1..N`
67
+ - `Enter`
68
+ - `Esc`
69
+ - do not assume marker navigation
70
+ - do not reinterpret those buttons as alternate hotkeys like `(y)` or `(p)`
71
+
41
72
  Collaboration tools:
42
73
 
43
74
  - `list_gateway_sessions`
@@ -725,6 +756,8 @@ Input:
725
756
 
726
757
  - `session_id?`
727
758
  - `url`
759
+ - `width?`
760
+ - `height?`
728
761
  - `wait_until?`
729
762
  - `reset_context?`
730
763
 
@@ -735,12 +768,162 @@ Output:
735
768
  - `created_context`
736
769
  - `url`
737
770
  - `title?`
771
+ - `viewport_width?`
772
+ - `viewport_height?`
738
773
 
739
774
  Notes:
740
775
 
741
776
  - each session gets its own isolated browser context and page
742
- - call this first before reading console, DOM, styles, or screenshots
777
+ - call this first only when you want the isolated Playwright backend
778
+ - do not call this just to work with an already selected Firefox attached tab
743
779
  - `url` may be an absolute URL, or a relative path when `BROWSER_ADDRESS` is configured
780
+ - in headed mode the browser window is started maximized by default
781
+ - in headed mode a fresh browser context is created without a fixed viewport unless you explicitly pass `width` and `height`
782
+ - if you want page content to grow and shrink together with the outer browser window, do not pass `width` and `height`
783
+ - if you pass viewport size, pass both `width` and `height` together
784
+ - use explicit `width` and `height` when the task depends on a specific responsive breakpoint or working area
785
+
786
+ ## `browser_list_attached_instances`
787
+
788
+ Purpose:
789
+
790
+ - list browser instances currently connected through the local attach extension bridge
791
+
792
+ Input:
793
+
794
+ - `session_id?`
795
+
796
+ Output:
797
+
798
+ - `session_id?`
799
+ - `total`
800
+ - `instances[]`
801
+ - `instance_id`
802
+ - `browser`
803
+ - `extension_version`
804
+ - `profile_name?`
805
+ - `connected_at`
806
+ - `last_seen_at`
807
+ - `capabilities[]`
808
+ - `tab_count`
809
+ - `active_tab?`
810
+
811
+ ## `browser_list_tabs`
812
+
813
+ Purpose:
814
+
815
+ - list tabs from an attached browser instance
816
+
817
+ Input:
818
+
819
+ - `session_id?`
820
+ - `instance_id?`
821
+
822
+ Output:
823
+
824
+ - `session_id?`
825
+ - `instance_id`
826
+ - `total`
827
+ - `tabs[]`
828
+ - `tab_id`
829
+ - `window_id?`
830
+ - `active`
831
+ - `selected?`
832
+ - `title`
833
+ - `url`
834
+ - `status?`
835
+
836
+ Notes:
837
+
838
+ - 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
840
+ - `active=true` means the tab is active in its browser window; there may be more than one such tab across multiple windows
841
+ - for the tab currently selected for this MCP session, prefer `selected=true`
842
+
843
+ ## `browser_recording_start`
844
+
845
+ Purpose:
846
+
847
+ - start a structured browser recording bundle for the attached browser tab currently selected for this MCP session
848
+
849
+ Input:
850
+
851
+ - `session_id?`
852
+ - `instance_id?`
853
+
854
+ Output:
855
+
856
+ - `session_id`
857
+ - `backend`
858
+ - `started`
859
+ - `recording_id`
860
+ - `instance_id`
861
+ - `tab_id`
862
+ - `tab_title?`
863
+ - `tab_url?`
864
+ - `bundle_dir_name`
865
+ - `bundle_relative_path`
866
+ - `bundle_path`
867
+ - `started_at`
868
+
869
+ Notes:
870
+
871
+ - this works only with the attached browser backend, not Playwright
872
+ - select the target tab first from the browser extension control panel
873
+ - the bundle is created under `.mcp-xchange/web/{tab-title-slug}-{timestamp}/`
874
+ - the recording captures page snapshots, console events, request metadata, headers, cookies snapshots, and available request/response bodies
875
+ - for network analysis, read `network/index.ndjson` first, then open the matching `network/requests/{seq}-{request_id}/meta.json`
876
+ - use `request.json`, `response.json`, and optional body files only when deeper detail is needed
877
+
878
+ ## `browser_recording_stop`
879
+
880
+ Purpose:
881
+
882
+ - stop the active structured browser recording for this MCP session
883
+
884
+ Input:
885
+
886
+ - `session_id?`
887
+
888
+ Output:
889
+
890
+ - `session_id`
891
+ - `stopped`
892
+ - `recording_id?`
893
+ - `bundle_dir_name?`
894
+ - `bundle_relative_path?`
895
+ - `bundle_path?`
896
+ - `stopped_at?`
897
+
898
+ ## `browser_recording_status`
899
+
900
+ Purpose:
901
+
902
+ - inspect whether a structured browser recording is active and where its bundle is being written
903
+
904
+ Input:
905
+
906
+ - `session_id?`
907
+
908
+ Output:
909
+
910
+ - `session_id`
911
+ - `active`
912
+ - `recording?`
913
+ - `backend`
914
+ - `recording_id`
915
+ - `instance_id`
916
+ - `tab_id`
917
+ - `tab_title?`
918
+ - `tab_url?`
919
+ - `bundle_dir_name`
920
+ - `bundle_relative_path`
921
+ - `bundle_path`
922
+ - `started_at`
923
+ - `stopped_at?`
924
+ - `status`
925
+ - `event_count`
926
+ - `last_event_at?`
744
927
 
745
928
  ## `browser_console`
746
929
 
@@ -782,6 +965,8 @@ Output:
782
965
  Purpose:
783
966
 
784
967
  - click an element in the current session page
968
+ - if the session has a selected attached browser tab, click there
969
+ - otherwise click in the isolated Playwright page
785
970
 
786
971
  Input:
787
972
 
@@ -807,6 +992,8 @@ Output:
807
992
  Purpose:
808
993
 
809
994
  - fill an input or textarea in the current session page
995
+ - if the session has a selected attached browser tab, fill there
996
+ - otherwise fill in the isolated Playwright page
810
997
 
811
998
  Input:
812
999
 
@@ -834,6 +1021,8 @@ Output:
834
1021
  Purpose:
835
1022
 
836
1023
  - send a key press to the page or a targeted element
1024
+ - if the session has a selected attached browser tab, press there
1025
+ - otherwise press in the isolated Playwright page
837
1026
 
838
1027
  Input:
839
1028
 
@@ -856,6 +1045,38 @@ Output:
856
1045
  - `url`
857
1046
  - `title?`
858
1047
 
1048
+ ## `browser_inject_script`
1049
+
1050
+ Purpose:
1051
+
1052
+ - inject JavaScript into the current session browser target
1053
+ - if the session has a selected attached browser tab, inject into that real browser tab
1054
+ - otherwise inject into the isolated Playwright page
1055
+ - the script is wrapped so `window[namespace]` exists; default namespace is `TELLY`
1056
+
1057
+ Input:
1058
+
1059
+ - `session_id?`
1060
+ - `source?`
1061
+ - `file_path?`
1062
+ - `namespace?`
1063
+
1064
+ Rules:
1065
+
1066
+ - provide either `source` or `file_path`
1067
+ - prefer `file_path` for local reusable scripts and larger payloads
1068
+ - injected scripts can use both `window.TELLY` and local `TELLY` when `namespace` is left at the default
1069
+
1070
+ Output:
1071
+
1072
+ - `session_id`
1073
+ - `injected`
1074
+ - `namespace`
1075
+ - `source_type`
1076
+ - `bytes`
1077
+ - `url`
1078
+ - `title?`
1079
+
859
1080
  ## `browser_wait_for`
860
1081
 
861
1082
  Purpose:
@@ -897,6 +1118,7 @@ Browser target rules for `browser_click`, `browser_fill`, `browser_press`, `brow
897
1118
  - `div[data-testid="save"]`
898
1119
  - use `text` only when there is no reliable selector
899
1120
  - do not mix ambiguous hashed CSS classes with fuzzy text guessing when a stable selector exists
1121
+ - for the attached browser backend, prefer `selector` first; `ai_tag` and `text` still work, but the attach executor is intentionally lighter than full Playwright
900
1122
 
901
1123
  ## `browser_wait_for_url`
902
1124
 
@@ -978,6 +1200,8 @@ Output:
978
1200
  Purpose:
979
1201
 
980
1202
  - inspect a DOM element in the session browser tab
1203
+ - if the session has a selected attached browser tab, inspect that real browser tab
1204
+ - otherwise inspect the isolated Playwright page
981
1205
 
982
1206
  Input:
983
1207
 
@@ -1026,6 +1250,8 @@ Output:
1026
1250
  Purpose:
1027
1251
 
1028
1252
  - capture a screenshot from the session browser tab
1253
+ - if the session has a selected attached browser tab, capture from that real browser tab
1254
+ - otherwise capture from the isolated Playwright page
1029
1255
 
1030
1256
  Input:
1031
1257
 
@@ -1052,6 +1278,7 @@ Notes:
1052
1278
  - they are tracked separately from Telegram-uploaded files
1053
1279
  - they appear under Telegram `Browser -> Screenshots`
1054
1280
  - if `send_to_telegram=true`, the saved screenshot is also sent into the bound Telegram chat for that session
1281
+ - for the attached browser backend, the screenshot comes from the selected tab in the user browser session
1055
1282
 
1056
1283
  ## `browser_close`
1057
1284
 
@@ -1083,6 +1310,8 @@ Telegram UI summary:
1083
1310
  - default logical console identity comes from `.mcpsession.json` in the workspace or explicit `-s`
1084
1311
  - terminal runtime metadata does not change `session_id`
1085
1312
  - `Browser -> Screenshots` lists screenshots created by `browser_screenshot`
1313
+ - `Storage` and `Screenshots` are relay-aware on the gateway
1314
+ - for relay consoles they read file metadata through gateway routes, not through the gateway filesystem
1086
1315
  - `Storage` browses `.mcp-xchange` for the active console and can send stored notes/files back into Telegram
1087
1316
  - `Settings` contains `Info`, `Rename`, `Unpair`, `Back`
1088
1317
  - project/collab work is the only supported user-facing collaboration path in Telegram UI
package/VERSION.md CHANGED
@@ -100,8 +100,8 @@ For detailed engineering history, refactors, and internal development notes, see
100
100
  - `tellymcp doctor`
101
101
  - `tellymcp mcp --help`
102
102
  - Standalone and public installation guides:
103
- - [STANDALONE.md](STANDALONE.md)
104
- - [STANDALONE-ru.md](STANDALONE-ru.md)
103
+ - [STANDALONE.md](docs/STANDALONE.md)
104
+ - [STANDALONE-ru.md](docs/STANDALONE-ru.md)
105
105
  - Browser runtime helper:
106
106
  - `tellymcp browser install`
107
107
  - Public README set for GitHub and npm:
package/dist/cli.js CHANGED
@@ -72,6 +72,8 @@ function printHelp() {
72
72
  " tellymcp doctor [--env <file>]",
73
73
  " tellymcp system-prune [--env <file>] --yes",
74
74
  " tellymcp browser install",
75
+ " tellymcp extension firefox",
76
+ " tellymcp extension chrome",
75
77
  " tellymcp codex-plugin install",
76
78
  " tellymcp codex-plugin status",
77
79
  " tellymcp mcp [--url <url>] [--bearer <token>] [--format claude|legacy]",
@@ -87,6 +89,8 @@ function printHelp() {
87
89
  " tellymcp doctor --env .env.client",
88
90
  " tellymcp system-prune --env .env.gateway --yes",
89
91
  " tellymcp browser install",
92
+ " tellymcp extension firefox",
93
+ " tellymcp extension chrome ./tellymcp-chrome-attach",
90
94
  " tellymcp codex-plugin install",
91
95
  " tellymcp codex-plugin status",
92
96
  " tellymcp mcp --help",
@@ -245,6 +249,27 @@ function printBrowserHelp() {
245
249
  " Avoids generic npx warnings about missing local project dependencies.",
246
250
  ]);
247
251
  }
252
+ function printExtensionHelp() {
253
+ printBanner("extension helper", "Export bundled browser attach extensions into a local directory");
254
+ printSection("Usage", [
255
+ " tellymcp extension firefox [output-directory]",
256
+ " tellymcp extension ff [output-directory]",
257
+ " tellymcp extension chrome [output-directory]",
258
+ " tellymcp extension <firefox|ff|chrome> --out-dir <directory>",
259
+ " tellymcp extension <firefox|ff|chrome> --force",
260
+ ]);
261
+ printSection("What this command does", [
262
+ " Copies the packaged unpacked extension bundle out of the installed tellymcp package.",
263
+ " By default exports into the current directory.",
264
+ " Creates a browser-specific folder you can load into Firefox or Chrome.",
265
+ ]);
266
+ printSection("Examples", [
267
+ " tellymcp extension firefox",
268
+ " tellymcp extension chrome",
269
+ " tellymcp extension firefox ./tellymcp-firefox-attach",
270
+ " tellymcp extension chrome --out-dir ./browser-addon",
271
+ ]);
272
+ }
248
273
  function printCodexPluginHelp() {
249
274
  printBanner("codex plugin", "Install or inspect the bundled Codex workflow plugin");
250
275
  printSection("Usage", [
@@ -684,6 +709,39 @@ async function runDoctor(args) {
684
709
  function hasFlag(args, flagName) {
685
710
  return args.includes(flagName);
686
711
  }
712
+ function normalizeExtensionFlavor(rawValue) {
713
+ if (rawValue === "firefox" || rawValue === "ff") {
714
+ return "firefox";
715
+ }
716
+ if (rawValue === "chrome") {
717
+ return "chrome";
718
+ }
719
+ return null;
720
+ }
721
+ function getBundledExtensionDir(flavor) {
722
+ return node_path_1.default.join(packageRoot, "packages", flavor === "firefox" ? "firefox-attach-extension" : "chrome-attach-extension", "dist");
723
+ }
724
+ function getDefaultExtensionTargetDir(flavor) {
725
+ return node_path_1.default.resolve(process.cwd(), flavor === "firefox" ? "tellymcp-firefox-attach" : "tellymcp-chrome-attach");
726
+ }
727
+ function resolveExtensionTargetDir(args, flavor) {
728
+ const explicitOutDir = readFlagValue(args, "--out-dir");
729
+ if (explicitOutDir) {
730
+ return node_path_1.default.resolve(process.cwd(), explicitOutDir);
731
+ }
732
+ const positionalOutDir = args.find((value, index) => {
733
+ if (index === 0 || !value) {
734
+ return false;
735
+ }
736
+ if (value === "--force") {
737
+ return false;
738
+ }
739
+ return !value.startsWith("--out-dir=");
740
+ });
741
+ return positionalOutDir
742
+ ? node_path_1.default.resolve(process.cwd(), positionalOutDir)
743
+ : getDefaultExtensionTargetDir(flavor);
744
+ }
687
745
  async function runSystemPrune(args) {
688
746
  const confirmed = hasFlag(args, "--yes");
689
747
  if (!confirmed) {
@@ -821,6 +879,52 @@ function runBrowserCommand(args) {
821
879
  process.exit(code ?? 0);
822
880
  });
823
881
  }
882
+ function runExtensionCommand(args) {
883
+ const [rawFlavor] = args;
884
+ if (!rawFlavor || rawFlavor === "--help" || rawFlavor === "-h") {
885
+ printExtensionHelp();
886
+ return;
887
+ }
888
+ const flavor = normalizeExtensionFlavor(rawFlavor);
889
+ if (!flavor) {
890
+ fail("Supported extension targets: firefox, ff, chrome");
891
+ }
892
+ const sourceDir = getBundledExtensionDir(flavor);
893
+ const sourceManifestPath = node_path_1.default.join(sourceDir, "manifest.json");
894
+ if (!(0, node_fs_1.existsSync)(sourceManifestPath)) {
895
+ fail(`Missing bundled ${flavor} extension. Reinstall or republish tellymcp with packaged extension bundles.`);
896
+ }
897
+ const targetDir = resolveExtensionTargetDir(args, flavor);
898
+ const force = hasFlag(args, "--force");
899
+ if ((0, node_fs_1.existsSync)(targetDir)) {
900
+ if (!force) {
901
+ fail(`Refusing to overwrite existing directory: ${targetDir}. Re-run with --force.`);
902
+ }
903
+ (0, node_fs_1.rmSync)(targetDir, { recursive: true, force: true });
904
+ }
905
+ (0, node_fs_1.mkdirSync)(node_path_1.default.dirname(targetDir), { recursive: true });
906
+ (0, node_fs_1.cpSync)(sourceDir, targetDir, { recursive: true });
907
+ printBanner(`extension ${flavor}`, "Bundled attach extension exported");
908
+ printSection("result", [
909
+ ` source: ${sourceDir}`,
910
+ ` target: ${targetDir}`,
911
+ ` manifest: ${node_path_1.default.join(targetDir, "manifest.json")}`,
912
+ ]);
913
+ if (flavor === "firefox") {
914
+ printSection("next", [
915
+ " 1. Open about:debugging#/runtime/this-firefox",
916
+ " 2. Click 'Load Temporary Add-on'",
917
+ ` 3. Choose ${node_path_1.default.join(targetDir, "manifest.json")}`,
918
+ ]);
919
+ return;
920
+ }
921
+ printSection("next", [
922
+ " 1. Open chrome://extensions",
923
+ " 2. Enable Developer mode",
924
+ " 3. Click 'Load unpacked'",
925
+ ` 4. Choose ${targetDir}`,
926
+ ]);
927
+ }
824
928
  function runCodexPluginCommand(args) {
825
929
  const [subcommand] = args;
826
930
  if (!subcommand || subcommand === "--help" || subcommand === "-h") {
@@ -942,7 +1046,7 @@ async function runRuntime(args) {
942
1046
  async function main(argv) {
943
1047
  const [rawCommand, firstArg, secondArg] = argv;
944
1048
  const command = rawCommand === "init" || rawCommand === "run" || rawCommand === "help" || rawCommand === "mcp" || rawCommand === "doctor" || rawCommand === "browser" || rawCommand === "system-prune"
945
- || rawCommand === "codex-plugin"
1049
+ || rawCommand === "codex-plugin" || rawCommand === "extension"
946
1050
  ? rawCommand
947
1051
  : "help";
948
1052
  if (command === "help" || !rawCommand || rawCommand === "--help" || rawCommand === "-h") {
@@ -965,6 +1069,10 @@ async function main(argv) {
965
1069
  runBrowserCommand(argv.slice(1));
966
1070
  return;
967
1071
  }
1072
+ if (command === "extension") {
1073
+ runExtensionCommand(argv.slice(1));
1074
+ return;
1075
+ }
968
1076
  if (command === "codex-plugin") {
969
1077
  runCodexPluginCommand(argv.slice(1));
970
1078
  return;