MCP dla agentów programistycznych
text mcp: pozwól agentom programistycznym nawigować, naciskać klawisze i odczytywać klatki przez Model Context Protocol.
text mcp uruchamia katalog app/ bez interfejsu graficznego, wewnątrz procesu, i udostępnia go przez Model Context Protocol, aby agenci programistyczni mogli z niego korzystać bez DevTools. Agent nawiguje, naciska klawisze, odczytuje klatki jako zwykły tekst i wywołuje handlery tras.
bunx --bun text mcp # serve ./app over stdiobunx --bun text mcp apps/console # another projecttext mcp wymaga środowiska Bun. Po uruchomieniu w Node uruchamia się ponownie w Bun, jeśli bun znajduje się w PATH, a w przeciwnym razie kończy się błędem TX019. Klienty MCP uruchamiają je za ciebie, więc rzadko uruchamiasz je ręcznie.
Konfiguracja
Każdy klient uruchamia text mcp z katalogu twojego projektu. Użyj bunx --bun, aby pliki tras uruchamiały się jako TypeScript.
OpenCode
{ "$schema": "https://opencode.ai/config.json", "mcp": { "textjs": { "type": "local", "command": ["bunx", "--bun", "text", "mcp"], "enabled": true } }}Claude Code
claude mcp add textjs -- bunx --bun text mcpLub zapisz konfigurację w repozytorium dla zespołu:
{ "mcpServers": { "textjs": { "command": "bunx", "args": ["--bun", "text", "mcp"] } }}Cursor
{ "mcpServers": { "textjs": { "command": "bunx", "args": ["--bun", "text", "mcp"] } }}VS Code
{ "servers": { "textjs": { "type": "stdio", "command": "bunx", "args": ["--bun", "text", "mcp"] } }}Dla projektu w podkatalogu dopisz ścieżkę: ["--bun", "text", "mcp", "apps/console"].
Narzędzia
| Narzędzie | Opis |
|---|---|
list_routes | Strony i handlery tras w app/ oraz bieżąca lokalizacja |
navigate | Dodanie lub zastąpienie ścieżki albo przejście back / forward |
read_frame | Klatka jako tekst, z trasą, rozmiarem, fokusem i kursorem. styles: true dodaje kolory i atrybuty dla każdego spanu |
press | Kombinacje klawiszy: "down", "ctrl+k", "shift+tab", "tab tab enter", "down*3" |
type | Wpisywanie tekstu po jednym klawiszu na znak (do 2000; dla większej liczby użyj paste). submit: true naciska potem Enter |
paste | Jedno zdarzenie wklejania, jak ⌘V |
scroll | Przewijanie kółkiem myszy o rows (i cols). Komponent <ScrollBox> przewija się kółkiem bez fokusu klawiatury |
resize | Ustawienie rozmiaru siatki w kolumnach i wierszach |
inspect_tree | Drzewo komponentów z granicami na ekranie oraz wszystkimi identyfikatorami elementów mogących otrzymać fokus |
find | Granice każdego dopasowania i komponent pod nim |
wait_for | Oczekiwanie na pojawienie się lub zniknięcie tekstu albo na stan bezczynności aplikacji |
logs | Przechwycone wyjście console.* i błędy React |
fetch | Wywołanie handlera route.ts wewnątrz procesu. Treści są odczytywane do maxBytes; strumienie zdarzeń przez streamMs, po czym są anulowane |
reload | Ponowny import aplikacji po edycji plików |
Narzędzia wejścia zwracają nową klatkę, więc agent nie potrzebuje osobnego read_frame po każdym klawiszu. Bieżąca klatka i lista tras są też dostępne jako zasoby text://frame i text://routes.
Typowa wymiana:
→ navigate { "path": "/deployments" }→ press { "keys": "down down enter" }← route: /deployments/dpl_6m3ty8 (route /deployments/[id]) title: "Deployment dpl_6m3ty8 · Edge Console" size: 100×32 frame: 6 idle focus: _txr_c_ ScrollBox [4,12 92×18] ▼ Edge Console Overview Deployments Logs Settings ← Deployments / dpl_6m3ty8 Ready Production …Klatki i bezczynność
Zanim dowolne narzędzie odczyta klatkę, czeka na stan bezczynności aplikacji: brak zaplanowanej klatki, brak trwającego fetch oraz brak zatwierdzenia zmian lub klatki przez 50 ms. Agent widzi więc wynik swojego wejścia, a nie klatkę w połowie aktualizacji.
Komponent <Spinner> lub wykres aktualizowany raz na sekundę nadal uznaje się za bezczynny między aktualizacjami, więc strony z animacjami pozostają czytelne. Aplikacja renderująca częściej niż co 50 ms nigdy nie przechodzi w stan bezczynności. Odczyty przestają czekać po 1,5 sekundy (settleMs to zmienia), zapisują najnowszą klatkę i oznaczają ją jako busy. wait_for bez tekstu czeka na bezczynność, z własnym quietMs, i zwraca błąd, jeśli bezczynność nigdy nie nastąpi.
Współrzędne oznaczają komórki numerowane od zera: x to kolumna, y to wiersz. Szerokie znaki, takie jak CJK i emoji, zajmują dwie kolumny.
Błędy i logi
stdout przenosi protokół. Wyjście console.* twojej aplikacji, przypadkowe wywołania process.stdout.write i błędy React trafiają zamiast tego do logs, ponumerowane tak, aby agent mógł zażądać tylko nowych wpisów za pomocą since. Jeśli od ostatniego odczytu zapisano błędy, nagłówek następnej klatki o tym informuje.
Niepowodzenia są zwracane jako błędy narzędzi, nigdy jako awaria procesu. Narzędzie, które przekroczy limit czasu, jest anulowane przed uruchomieniem następnego wywołania, więc wolne wywołanie nigdy nie wpisuje tekstu do klatki następnego wywołania. Błędy z kodem Text.js zachowują go, na przykład TX007 dla nieznanego klawisza. Jeśli aplikacja nie zdoła się załadować, każde narzędzie wyjaśnia przyczynę. Popraw plik i wywołaj reload.
Opcje
| Opcja | Opis |
|---|---|
--path <pathname> | Pierwsza trasa (domyślnie /) |
--cols / --rows | Rozmiar siatki (domyślnie: viewport w text.config.ts, w przeciwnym razie 100×32) |
--theme <name> | Gotowy motyw |
--no-config | Pominięcie text.config.ts |
--verbose | Zapisywanie przechwyconych logów także do stderr |
Sposób działania
text mcp uruchamia twoją aplikację tak samo jak text run: każdy moduł trasy jest importowany z góry, App Router używa historii w pamięci, a wywołania fetch("/api/…") do tego samego źródła uruchamiają twoje handlery wewnątrz procesu. Klatki trafiają do pozaekranowej siatki komórek zamiast do terminala. Strony renderowane po stronie serwera (export const runtime = "server") i ich komponenty async function renderują się wewnątrz procesu, jak w text dev, a klatka jest odczytywana po zakończeniu ich działania.
reload odmontowuje aplikację, usuwa wszystkie moduły projektu z pamięci podręcznej modułów środowiska Bun (w tym pliki spoza app/), ponownie skanuje app/ i montuje aplikację w bieżącej lokalizacji.
Aby osadzić serwer we własnym procesie lub użyć innego transportu:
import { createTextMcpServer } from "@textjs/app/mcp";import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";const { server, controller } = createTextMcpServer({ root: process.cwd() });await server.connect(new StdioServerTransport());void controller.start();Ograniczenia
- Aplikacja działa w środowisku Bun, nie w przeglądarce.
windowidocumentsą niezdefiniowane, jak wtext run. - Każdy serwer uruchamia jedną aplikację z jedną siatką. Każdy klient MCP uruchamia własny serwer.
text mcpuruchamia własną kopię aplikacji bez interfejsu graficznego. Nie może dołączyć do karty przeglądarki otwartej wtext dev.