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 project

text 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

opencode.jsonjson
{  "$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 mcp

Lub zapisz konfigurację w repozytorium dla zespołu:

.mcp.jsonjson
{  "mcpServers": {    "textjs": { "command": "bunx", "args": ["--bun", "text", "mcp"] }  }}

Cursor

.cursor/mcp.jsonjson
{  "mcpServers": {    "textjs": { "command": "bunx", "args": ["--bun", "text", "mcp"] }  }}

VS Code

.vscode/mcp.jsonjson
{  "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ędzieOpis
list_routesStrony i handlery tras w app/ oraz bieżąca lokalizacja
navigateDodanie lub zastąpienie ścieżki albo przejście back / forward
read_frameKlatka jako tekst, z trasą, rozmiarem, fokusem i kursorem. styles: true dodaje kolory i atrybuty dla każdego spanu
pressKombinacje klawiszy: "down", "ctrl+k", "shift+tab", "tab tab enter", "down*3"
typeWpisywanie tekstu po jednym klawiszu na znak (do 2000; dla większej liczby użyj paste). submit: true naciska potem Enter
pasteJedno zdarzenie wklejania, jak ⌘V
scrollPrzewijanie kółkiem myszy o rows (i cols). Komponent <ScrollBox> przewija się kółkiem bez fokusu klawiatury
resizeUstawienie rozmiaru siatki w kolumnach i wierszach
inspect_treeDrzewo komponentów z granicami na ekranie oraz wszystkimi identyfikatorami elementów mogących otrzymać fokus
findGranice każdego dopasowania i komponent pod nim
wait_forOczekiwanie na pojawienie się lub zniknięcie tekstu albo na stan bezczynności aplikacji
logsPrzechwycone wyjście console.* i błędy React
fetchWywołanie handlera route.ts wewnątrz procesu. Treści są odczytywane do maxBytes; strumienie zdarzeń przez streamMs, po czym są anulowane
reloadPonowny 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

OpcjaOpis
--path <pathname>Pierwsza trasa (domyślnie /)
--cols / --rowsRozmiar siatki (domyślnie: viewport w text.config.ts, w przeciwnym razie 100×32)
--theme <name>Gotowy motyw
--no-configPominięcie text.config.ts
--verboseZapisywanie 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. window i document są niezdefiniowane, jak w text run.
  • Każdy serwer uruchamia jedną aplikację z jedną siatką. Każdy klient MCP uruchamia własny serwer.
  • text mcp uruchamia własną kopię aplikacji bez interfejsu graficznego. Nie może dołączyć do karty przeglądarki otwartej w text dev.
Edytuj tę stronę w serwisie GitHub