@deadragdoll/tellymcp 0.0.1 → 0.0.3
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.
- package/README-ru.md +1 -1
- package/README.md +10 -1
- package/STANDALONE-ru.md +8 -0
- package/STANDALONE.md +8 -0
- package/TOOLS.md +9 -0
- package/dist/cli.js +93 -1
- package/dist/services/features/telegram-mcp/gateway-delivery.service.js +1 -1
- package/dist/services/features/telegram-mcp/gateway-socket.service.js +1 -1
- package/dist/services/features/telegram-mcp/src/app/http.js +1 -1
- package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +7 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +1 -1
- package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +3 -1
- package/package.json +3 -1
- package/scripts/postinstall.js +5 -0
package/README-ru.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TellyMCP
|
|
2
2
|
|
|
3
|
-
[English](README.md) | [Русский](README-ru.md)
|
|
3
|
+
[English](README.md) | [Русский](README-ru.md) | [Standalone Guide](STANDALONE.md) | [Standalone RU](STANDALONE-ru.md)
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@deadragdoll/tellymcp)
|
|
6
6
|
[](https://www.npmjs.com/package/@deadragdoll/tellymcp)
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TellyMCP
|
|
2
2
|
|
|
3
|
-
[English](README.md) | [Русский](README-ru.md)
|
|
3
|
+
[English](README.md) | [Русский](README-ru.md) | [Standalone Guide](STANDALONE.md) | [Standalone RU](STANDALONE-ru.md)
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@deadragdoll/tellymcp)
|
|
6
6
|
[](https://www.npmjs.com/package/@deadragdoll/tellymcp)
|
|
@@ -60,6 +60,7 @@ Current tools:
|
|
|
60
60
|
- a Telegram bot token from BotFather
|
|
61
61
|
- for `gateway` / `both`: Postgres
|
|
62
62
|
- optional for durable fanout on gateway: RabbitMQ
|
|
63
|
+
- for `browser_*` tools: Playwright Chromium browser binaries
|
|
63
64
|
|
|
64
65
|
## tmux is strongly recommended
|
|
65
66
|
|
|
@@ -145,6 +146,12 @@ Typical local MCP endpoint in `client` mode:
|
|
|
145
146
|
|
|
146
147
|
- `http://127.0.0.1:8787/mcp`
|
|
147
148
|
|
|
149
|
+
If you plan to use `browser_*` tools, install Chromium once:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
tellymcp browser install
|
|
153
|
+
```
|
|
154
|
+
|
|
148
155
|
Detailed step-by-step guide:
|
|
149
156
|
|
|
150
157
|
- [STANDALONE.md](STANDALONE.md)
|
|
@@ -519,6 +526,8 @@ Recommended local dev settings:
|
|
|
519
526
|
- `BROWSER_ADDRESS=http://localhost:5173`
|
|
520
527
|
- start your SPA dev server on `0.0.0.0:5173`
|
|
521
528
|
- open it through `browser_open`
|
|
529
|
+
- install browser binaries once with `npx playwright install chromium`
|
|
530
|
+
- install browser binaries once with `tellymcp browser install`
|
|
522
531
|
|
|
523
532
|
Recommended Docker settings:
|
|
524
533
|
|
package/STANDALONE-ru.md
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
2. `tmux`
|
|
21
21
|
3. Redis
|
|
22
22
|
4. Telegram bot token из BotFather
|
|
23
|
+
5. опционально для `browser_*` tools: Playwright Chromium browser binaries
|
|
23
24
|
|
|
24
25
|
Зачем это нужно:
|
|
25
26
|
|
|
@@ -46,6 +47,12 @@ redis-cli ping
|
|
|
46
47
|
- `tmux -V` показывает версию
|
|
47
48
|
- `redis-cli ping` возвращает `PONG`
|
|
48
49
|
|
|
50
|
+
Если планируешь использовать browser automation tools, один раз выполни ещё:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
tellymcp browser install
|
|
54
|
+
```
|
|
55
|
+
|
|
49
56
|
## Шаг 2. Создать Telegram-бота
|
|
50
57
|
|
|
51
58
|
В Telegram:
|
|
@@ -156,6 +163,7 @@ tellymcp doctor --env .env
|
|
|
156
163
|
- `.env`
|
|
157
164
|
- Redis
|
|
158
165
|
- локальный MCP bind
|
|
166
|
+
- Playwright Chromium, если browser tools включены
|
|
159
167
|
|
|
160
168
|
## Шаг 8. Запустить сервис
|
|
161
169
|
|
package/STANDALONE.md
CHANGED
|
@@ -20,6 +20,7 @@ Before installation, make sure you have:
|
|
|
20
20
|
2. `tmux`
|
|
21
21
|
3. Redis
|
|
22
22
|
4. a Telegram bot token from BotFather
|
|
23
|
+
5. optional for `browser_*` tools: Playwright Chromium browser binaries
|
|
23
24
|
|
|
24
25
|
Why these matter:
|
|
25
26
|
|
|
@@ -46,6 +47,12 @@ Expected:
|
|
|
46
47
|
- `tmux -V` prints a version
|
|
47
48
|
- `redis-cli ping` returns `PONG`
|
|
48
49
|
|
|
50
|
+
If you plan to use browser automation tools later, also run:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
tellymcp browser install
|
|
54
|
+
```
|
|
55
|
+
|
|
49
56
|
## Step 2. Create a Telegram bot
|
|
50
57
|
|
|
51
58
|
In Telegram:
|
|
@@ -156,6 +163,7 @@ In standalone `client` mode it should verify:
|
|
|
156
163
|
- `.env`
|
|
157
164
|
- Redis
|
|
158
165
|
- local MCP bind
|
|
166
|
+
- Playwright Chromium when browser tools are enabled
|
|
159
167
|
|
|
160
168
|
## Step 8. Run the service
|
|
161
169
|
|
package/TOOLS.md
CHANGED
|
@@ -30,6 +30,12 @@ Browser tools:
|
|
|
30
30
|
- `browser_screenshot`
|
|
31
31
|
- `browser_close`
|
|
32
32
|
|
|
33
|
+
Browser runtime rule:
|
|
34
|
+
|
|
35
|
+
- Browser tools use Playwright Chromium.
|
|
36
|
+
- If browser tools fail because the Playwright browser runtime is missing, install it with `tellymcp browser install`.
|
|
37
|
+
- Do not stop at the installation error itself. Install the browser runtime first, then retry the browser tool.
|
|
38
|
+
|
|
33
39
|
Collaboration tools:
|
|
34
40
|
|
|
35
41
|
- `send_partner_note`
|
|
@@ -702,6 +708,9 @@ Input:
|
|
|
702
708
|
|
|
703
709
|
Notes:
|
|
704
710
|
|
|
711
|
+
- Browser tools require Playwright Chromium browser binaries.
|
|
712
|
+
- If the runtime is missing, run `tellymcp browser install`, then retry `browser_open`.
|
|
713
|
+
|
|
705
714
|
- the server always uses `TELEGRAM_INBOX_BATCH_SIZE`
|
|
706
715
|
- the agent should not try to choose its own batch size
|
|
707
716
|
|
package/dist/cli.js
CHANGED
|
@@ -50,6 +50,34 @@ function getTmuxInstallHints() {
|
|
|
50
50
|
"Arch: sudo pacman -S tmux",
|
|
51
51
|
];
|
|
52
52
|
}
|
|
53
|
+
async function getPlaywrightBrowserStatus(browserEnabled) {
|
|
54
|
+
if (!browserEnabled) {
|
|
55
|
+
return { enabled: false };
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const playwright = await import("playwright");
|
|
59
|
+
const executablePath = playwright.chromium.executablePath();
|
|
60
|
+
if (executablePath && (0, node_fs_1.existsSync)(executablePath)) {
|
|
61
|
+
return {
|
|
62
|
+
enabled: true,
|
|
63
|
+
installed: true,
|
|
64
|
+
executablePath,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
enabled: true,
|
|
69
|
+
installed: false,
|
|
70
|
+
message: "Chromium browser binaries are missing.",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
return {
|
|
75
|
+
enabled: true,
|
|
76
|
+
installed: false,
|
|
77
|
+
message: error instanceof Error ? error.message : String(error),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
53
81
|
function printHelp() {
|
|
54
82
|
const tmux = getTmuxStatus();
|
|
55
83
|
printBanner("CLI", "Telegram Human-in-the-Loop MCP server");
|
|
@@ -58,6 +86,7 @@ function printHelp() {
|
|
|
58
86
|
" tellymcp run [--env <file>]",
|
|
59
87
|
" tellymcp run --env=<file>",
|
|
60
88
|
" tellymcp doctor [--env <file>]",
|
|
89
|
+
" tellymcp browser install",
|
|
61
90
|
" tellymcp mcp [--url <url>] [--bearer <token>] [--format claude|legacy]",
|
|
62
91
|
" tellymcp help",
|
|
63
92
|
]);
|
|
@@ -67,6 +96,7 @@ function printHelp() {
|
|
|
67
96
|
" tellymcp run",
|
|
68
97
|
" tellymcp run --env .env.client",
|
|
69
98
|
" tellymcp doctor --env .env.client",
|
|
99
|
+
" tellymcp browser install",
|
|
70
100
|
" tellymcp mcp --help",
|
|
71
101
|
]);
|
|
72
102
|
if (tmux.found) {
|
|
@@ -146,6 +176,17 @@ function printMcpHelp() {
|
|
|
146
176
|
" tellymcp mcp --url https://builder.undoo.ru/api/mcp --format legacy",
|
|
147
177
|
]);
|
|
148
178
|
}
|
|
179
|
+
function printBrowserHelp() {
|
|
180
|
+
printBanner("browser helper", "Manage Playwright browser binaries used by browser_* tools");
|
|
181
|
+
printSection("Usage", [
|
|
182
|
+
" tellymcp browser install",
|
|
183
|
+
]);
|
|
184
|
+
printSection("What this command does", [
|
|
185
|
+
" Installs the bundled Playwright Chromium browser.",
|
|
186
|
+
" Uses the Playwright dependency shipped with TellyMCP.",
|
|
187
|
+
" Avoids generic npx warnings about missing local project dependencies.",
|
|
188
|
+
]);
|
|
189
|
+
}
|
|
149
190
|
function fail(message) {
|
|
150
191
|
process.stderr.write(`${message}\n`);
|
|
151
192
|
process.exit(1);
|
|
@@ -439,6 +480,7 @@ async function runDoctor(args) {
|
|
|
439
480
|
const gatewayWsUrl = parsed.GATEWAY_WS_URL?.trim();
|
|
440
481
|
const publicWebappUrl = parsed.WEBAPP_PUBLIC_URL?.trim();
|
|
441
482
|
const mcpBearerToken = parsed.MCP_HTTP_BEARER_TOKEN?.trim();
|
|
483
|
+
const browserEnabled = (parsed.BROWSER_ENABLED || "true").trim().toLowerCase() !== "false";
|
|
442
484
|
const externalHealthUrl = deriveGatewayHealthUrlFromPublicUrl(publicGatewayUrl || "") ??
|
|
443
485
|
deriveGatewayHealthUrlFromPublicUrl(publicWebappUrl || "");
|
|
444
486
|
printSection("env", [
|
|
@@ -455,6 +497,19 @@ async function runDoctor(args) {
|
|
|
455
497
|
]);
|
|
456
498
|
const checks = [];
|
|
457
499
|
const capabilities = [];
|
|
500
|
+
const playwrightStatus = await getPlaywrightBrowserStatus(browserEnabled);
|
|
501
|
+
if (!playwrightStatus.enabled) {
|
|
502
|
+
checks.push(`${picocolors_1.default.dim(" SKIP")} playwright: browser tools are disabled`);
|
|
503
|
+
capabilities.push(`${picocolors_1.default.dim(" SKIP")} browser tools: disabled`);
|
|
504
|
+
}
|
|
505
|
+
else if (playwrightStatus.installed) {
|
|
506
|
+
checks.push(`${picocolors_1.default.green(" OK")} playwright chromium: ${playwrightStatus.executablePath}`);
|
|
507
|
+
capabilities.push(`${picocolors_1.default.green(" OK")} browser tools: available`);
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
checks.push(`${picocolors_1.default.red(" ERROR")} playwright chromium: ${playwrightStatus.message}`);
|
|
511
|
+
capabilities.push(`${picocolors_1.default.red(" ERROR")} browser tools: browsers are not installed`);
|
|
512
|
+
}
|
|
458
513
|
const redisHost = (parsed.REDIS_HOST || "127.0.0.1").trim();
|
|
459
514
|
const redisPort = Number(parsed.REDIS_PORT || 6379);
|
|
460
515
|
const redisCheck = await checkTcpPort(redisHost, redisPort);
|
|
@@ -560,6 +615,39 @@ async function runDoctor(args) {
|
|
|
560
615
|
else {
|
|
561
616
|
printSection("notes", [`${picocolors_1.default.green(" OK")} No obvious local config issues detected.`]);
|
|
562
617
|
}
|
|
618
|
+
if (browserEnabled && (!playwrightStatus.enabled || !playwrightStatus.installed)) {
|
|
619
|
+
printSection("playwright", [
|
|
620
|
+
`${picocolors_1.default.yellow(" ACTION")} Install browser binaries before using browser_* tools:`,
|
|
621
|
+
" tellymcp browser install",
|
|
622
|
+
]);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
function runBrowserCommand(args) {
|
|
626
|
+
const [subcommand] = args;
|
|
627
|
+
if (!subcommand || subcommand === "--help" || subcommand === "-h") {
|
|
628
|
+
printBrowserHelp();
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
if (subcommand !== "install") {
|
|
632
|
+
fail("Supported browser subcommands: install");
|
|
633
|
+
}
|
|
634
|
+
const cliPath = node_path_1.default.join(packageRoot, "node_modules", "playwright", "cli.js");
|
|
635
|
+
if (!(0, node_fs_1.existsSync)(cliPath)) {
|
|
636
|
+
fail(`Missing bundled Playwright CLI: ${cliPath}`);
|
|
637
|
+
}
|
|
638
|
+
printBanner("browser install", "Installing bundled Playwright Chromium");
|
|
639
|
+
const child = (0, node_child_process_1.spawn)(process.execPath, [cliPath, "install", "chromium"], {
|
|
640
|
+
cwd: process.cwd(),
|
|
641
|
+
stdio: "inherit",
|
|
642
|
+
env: process.env,
|
|
643
|
+
});
|
|
644
|
+
child.on("exit", (code, signal) => {
|
|
645
|
+
if (signal) {
|
|
646
|
+
process.kill(process.pid, signal);
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
process.exit(code ?? 0);
|
|
650
|
+
});
|
|
563
651
|
}
|
|
564
652
|
function runRuntime(args) {
|
|
565
653
|
const envPath = resolveRunEnvPath(args);
|
|
@@ -612,7 +700,7 @@ function runRuntime(args) {
|
|
|
612
700
|
}
|
|
613
701
|
async function main(argv) {
|
|
614
702
|
const [rawCommand, firstArg, secondArg] = argv;
|
|
615
|
-
const command = rawCommand === "init" || rawCommand === "run" || rawCommand === "help" || rawCommand === "mcp" || rawCommand === "doctor"
|
|
703
|
+
const command = rawCommand === "init" || rawCommand === "run" || rawCommand === "help" || rawCommand === "mcp" || rawCommand === "doctor" || rawCommand === "browser"
|
|
616
704
|
? rawCommand
|
|
617
705
|
: "help";
|
|
618
706
|
if (command === "help" || !rawCommand || rawCommand === "--help" || rawCommand === "-h") {
|
|
@@ -631,6 +719,10 @@ async function main(argv) {
|
|
|
631
719
|
await runDoctor(argv.slice(1));
|
|
632
720
|
return;
|
|
633
721
|
}
|
|
722
|
+
if (command === "browser") {
|
|
723
|
+
runBrowserCommand(argv.slice(1));
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
634
726
|
runRuntime(argv.slice(1));
|
|
635
727
|
}
|
|
636
728
|
void main(process.argv.slice(2));
|
|
@@ -278,7 +278,7 @@ const TelegramMcpGatewayDeliveryService = {
|
|
|
278
278
|
try {
|
|
279
279
|
await runtime.telegramTransport.sendNotification({
|
|
280
280
|
sessionId: targetSession.sessionId,
|
|
281
|
-
|
|
281
|
+
sessionLabel: delivery.source_session_label,
|
|
282
282
|
recipient: {
|
|
283
283
|
telegramChatId: targetBinding.telegramChatId,
|
|
284
284
|
telegramUserId: targetBinding.telegramUserId,
|
|
@@ -554,7 +554,7 @@ const TelegramMcpGatewaySocketService = {
|
|
|
554
554
|
const action = typeof request.payload?.action === "string"
|
|
555
555
|
? request.payload.action
|
|
556
556
|
: "";
|
|
557
|
-
if (!["up", "down", "enter", "slash", "delete", "tab", "escape"].includes(action)) {
|
|
557
|
+
if (!["up", "down", "enter", "slash", "delete", "tab", "escape", "interrupt"].includes(action)) {
|
|
558
558
|
throw new Error("Unsupported action");
|
|
559
559
|
}
|
|
560
560
|
const sessionId = request.local_session_id.trim();
|
|
@@ -428,7 +428,7 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
428
428
|
typeof Reflect.get(body, "action") === "string"
|
|
429
429
|
? String(Reflect.get(body, "action"))
|
|
430
430
|
: "";
|
|
431
|
-
if (!["up", "down", "enter", "slash", "delete", "tab", "escape"].includes(action)) {
|
|
431
|
+
if (!["up", "down", "enter", "slash", "delete", "tab", "escape", "interrupt"].includes(action)) {
|
|
432
432
|
writeText(res, 400, "Unsupported action");
|
|
433
433
|
return;
|
|
434
434
|
}
|
|
@@ -168,6 +168,7 @@ const elements = {
|
|
|
168
168
|
session: document.querySelector("[data-role=session]"),
|
|
169
169
|
status: document.querySelector("[data-role=status]"),
|
|
170
170
|
updated: document.querySelector("[data-role=updated]"),
|
|
171
|
+
interrupt: document.querySelector("[data-role=interrupt]"),
|
|
171
172
|
esc: document.querySelector("[data-role=escape]"),
|
|
172
173
|
tab: document.querySelector("[data-role=tab]"),
|
|
173
174
|
slash: document.querySelector("[data-role=slash]"),
|
|
@@ -597,6 +598,10 @@ function startPolling() {
|
|
|
597
598
|
}
|
|
598
599
|
|
|
599
600
|
function bindUi() {
|
|
601
|
+
elements.interrupt.addEventListener("click", () => {
|
|
602
|
+
sendAction("interrupt").catch((error) => setStatus(error.message || String(error), true));
|
|
603
|
+
});
|
|
604
|
+
|
|
600
605
|
elements.esc.addEventListener("click", () => {
|
|
601
606
|
sendAction("escape").catch((error) => setStatus(error.message || String(error), true));
|
|
602
607
|
});
|
|
@@ -664,6 +669,7 @@ async function main() {
|
|
|
664
669
|
bootstrapPayload.session_label || bootstrapPayload.session_id;
|
|
665
670
|
|
|
666
671
|
if (!bootstrapPayload.tmux_target) {
|
|
672
|
+
elements.interrupt.disabled = true;
|
|
667
673
|
elements.esc.disabled = true;
|
|
668
674
|
elements.tab.disabled = true;
|
|
669
675
|
elements.slash.disabled = true;
|
|
@@ -704,6 +710,7 @@ function renderWebAppHtml(input) {
|
|
|
704
710
|
<body>
|
|
705
711
|
<div class="app">
|
|
706
712
|
<div class="toolbar">
|
|
713
|
+
<button class="btn compact danger" data-role="interrupt" type="button">Ctrl+C</button>
|
|
707
714
|
<button class="btn compact" data-role="escape" type="button">Esc</button>
|
|
708
715
|
<button class="btn compact" data-role="tab" type="button">Tab</button>
|
|
709
716
|
<button class="btn compact" data-role="slash" type="button">/</button>
|
|
@@ -248,7 +248,7 @@ class LocalCollaborationBackend {
|
|
|
248
248
|
await this.inboxStore.createInboxMessage(inboxMessage);
|
|
249
249
|
await this.telegramTransport.sendNotification({
|
|
250
250
|
sessionId: targetSession.sessionId,
|
|
251
|
-
|
|
251
|
+
sessionLabel: sourceLabel,
|
|
252
252
|
recipient: {
|
|
253
253
|
telegramChatId: targetBinding.telegramChatId,
|
|
254
254
|
telegramUserId: targetBinding.telegramUserId,
|
|
@@ -253,7 +253,9 @@ async function sendAllowedTmuxAction(config, target, action) {
|
|
|
253
253
|
? "Tab"
|
|
254
254
|
: action === "escape"
|
|
255
255
|
? "Escape"
|
|
256
|
-
: "
|
|
256
|
+
: action === "interrupt"
|
|
257
|
+
? "C-c"
|
|
258
|
+
: "Enter";
|
|
257
259
|
await execFileAsync("tmux", buildTmuxArgs(config, ["send-keys", "-t", target, key]));
|
|
258
260
|
}
|
|
259
261
|
async function sendTmuxLiteralLine(config, target, text) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deadragdoll/tellymcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "TellyMCP - Telegram Human-in-the-Loop MCP Server",
|
|
5
5
|
"main": "dist/services/features/telegram-mcp/runtime.service.js",
|
|
6
6
|
"bin": {
|
|
@@ -34,6 +34,8 @@
|
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"postinstall": "node ./scripts/postinstall.js",
|
|
37
|
+
"prepack": "yarn build",
|
|
38
|
+
"prepublishOnly": "yarn build && yarn lint && yarn test",
|
|
37
39
|
"mcp:local": "codex mcp add telegramHuman --url http://127.0.0.1:8787/mcp",
|
|
38
40
|
"dev:gw": "TS_NODE_TRANSPILE_ONLY=1 TS_NODE_EXPERIMENTAL_RESOLVER=1 NODE_OPTIONS=--openssl-legacy-provider ts-node ./node_modules/moleculer/bin/moleculer-runner.js src/services --config src/moleculer.config.ts --envfile ./.env-dev --hot --mask \"**/*.service.ts\"",
|
|
39
41
|
"dev:builder": "TS_NODE_TRANSPILE_ONLY=1 TS_NODE_EXPERIMENTAL_RESOLVER=1 NODE_OPTIONS=--openssl-legacy-provider ts-node ./node_modules/moleculer/bin/moleculer-runner.js src/services --config src/moleculer.config.ts --envfile ./.env-builder --hot --mask \"**/*.service.ts\"",
|
package/scripts/postinstall.js
CHANGED
|
@@ -53,6 +53,11 @@ if (tmux.found) {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
line();
|
|
57
|
+
line(`${pc.yellow("INFO")} Browser tools need Playwright browser binaries.`);
|
|
58
|
+
line("If you plan to use browser_* tools, run:");
|
|
59
|
+
line(` ${pc.bold("tellymcp browser install")}`);
|
|
60
|
+
|
|
56
61
|
line();
|
|
57
62
|
line(`Check your local setup: ${pc.bold("tellymcp doctor")}`);
|
|
58
63
|
line(`General help: ${pc.bold("tellymcp help")}`);
|