MCP cho tác nhân lập trình

text mcp: cho phép tác nhân lập trình điều hướng, nhấn phím và đọc frame qua Model Context Protocol.

text mcp chạy thư mục app/ không có giao diện, trong cùng tiến trình, và cung cấp ứng dụng qua Giao thức ngữ cảnh mô hình để các agent lập trình có thể dùng mà không cần DevTools. Agent điều hướng, nhấn phím, đọc frame dưới dạng văn bản thuần và gọi route handler.

bunx --bun text mcp              # serve ./app over stdiobunx --bun text mcp apps/console # another project

text mcp cần Bun. Khi khởi động bằng Node, nó tự chạy lại bằng Bun nếu có bun trong PATH, nếu không sẽ báo lỗi TX019. Các máy khách MCP khởi động nó cho bạn, nên bạn hiếm khi chạy thủ công.

Thiết lập

Mỗi máy khách khởi động text mcp từ thư mục dự án của bạn. Dùng bunx --bun để các tệp route chạy dưới dạng 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

Hoặc commit cấu hình cho cả nhóm:

.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"] }  }}

Với dự án trong thư mục con, nối thêm đường dẫn: ["--bun", "text", "mcp", "apps/console"].

Công cụ

Công cụMô tả
list_routesTrang và route handler trong app/, cùng vị trí hiện tại
navigateThêm hoặc thay thế đường dẫn, hoặc đi back / forward
read_frameFrame dưới dạng văn bản, kèm route, kích thước, tiêu điểm và con trỏ. styles: true thêm màu sắc và thuộc tính cho từng span
pressTổ hợp phím: "down", "ctrl+k", "shift+tab", "tab tab enter", "down*3"
typeGõ văn bản với mỗi ký tự là một lần nhấn phím (tối đa 2.000; dùng paste nếu dài hơn). submit: true nhấn Enter sau đó
pasteMột sự kiện dán, như ⌘V
scrollCuộn bằng con lăn chuột theo rows (và cols). <ScrollBox> cuộn theo con lăn mà không cần tiêu điểm bàn phím
resizeĐặt kích thước lưới theo cột và hàng
inspect_treeCây component kèm ranh giới trên màn hình và mọi id có thể nhận tiêu điểm
findRanh giới của từng kết quả khớp và component bên dưới
wait_forChờ văn bản xuất hiện hoặc biến mất, hoặc ứng dụng chuyển sang trạng thái nhàn rỗi
logsĐầu ra console.* và lỗi React đã thu thập
fetchGọi handler route.ts trong cùng tiến trình. Đọc phần thân tối đa maxBytes; đọc luồng sự kiện trong streamMs, rồi hủy
reloadImport lại ứng dụng sau khi bạn sửa tệp

Các công cụ nhập liệu trả về frame mới, nên agent không cần gọi riêng read_frame sau mỗi lần nhấn phím. Frame hiện tại và danh sách route cũng có sẵn dưới dạng tài nguyên text://frame và text://routes.

Một lượt trao đổi điển hình:

→ 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  …

Frame và trạng thái nhàn rỗi

Trước khi bất kỳ công cụ nào đọc frame, nó chờ ứng dụng chuyển sang trạng thái nhàn rỗi: không có frame được lên lịch, không có fetch đang chạy và không có commit hay frame trong 50 ms. Vì vậy agent thấy kết quả nhập liệu của mình, thay vì một frame đang cập nhật dở.

<Spinner> hoặc biểu đồ cập nhật mỗi giây một lần vẫn được coi là nhàn rỗi giữa các lần cập nhật, nên trang có hoạt ảnh vẫn đọc được. Ứng dụng render thường xuyên hơn mỗi 50 ms sẽ không bao giờ nhàn rỗi. Thao tác đọc dừng chờ sau 1,5 giây (settleMs thay đổi thời gian này), xuất frame mới nhất và đánh dấu là busy. wait_for không có văn bản sẽ chờ trạng thái nhàn rỗi, với quietMs riêng, và trả về lỗi nếu trạng thái nhàn rỗi không bao giờ xuất hiện.

Tọa độ tính theo ô, bắt đầu từ 0: x là cột, y là hàng. Ký tự rộng như CJK và emoji chiếm hai cột.

Lỗi và nhật ký

stdout truyền giao thức. Đầu ra console.* của ứng dụng, các lệnh gọi process.stdout.write ngoài luồng và lỗi React chuyển vào logs, có đánh số để agent có thể chỉ yêu cầu mục mới bằng since. Khi có lỗi được ghi kể từ lần đọc gần nhất, phần đầu frame tiếp theo sẽ thông báo.

Sự cố trả về dưới dạng lỗi công cụ, không bao giờ làm sập tiến trình. Công cụ hết thời gian chờ sẽ bị hủy trước khi lệnh gọi tiếp theo chạy, nên lệnh gọi chậm không bao giờ gõ vào frame của lệnh gọi tiếp theo. Lỗi có mã Text.js sẽ giữ nguyên mã, ví dụ TX007 cho phím không xác định. Nếu ứng dụng không tải được, mọi công cụ đều giải thích lý do. Sửa tệp và gọi reload.

Tùy chọn

Tùy chọnMô tả
--path <pathname>Route đầu tiên (mặc định /)
--cols / --rowsKích thước lưới (mặc định: viewport trong text.config.ts, nếu không có thì 100×32)
--theme <name>Theme định sẵn
--no-configBỏ qua text.config.ts
--verboseGhi cả nhật ký đã thu thập vào stderr

Cách hoạt động

text mcp chạy ứng dụng giống như text run: mọi mô-đun route đều được import từ đầu, App Router dùng lịch sử trong bộ nhớ, và các lệnh gọi fetch("/api/…") cùng nguồn chạy handler trong cùng tiến trình. Frame chuyển vào lưới ô ngoài màn hình thay vì terminal. Các trang được render phía máy chủ (export const runtime = "server") và component async function của chúng render trong cùng tiến trình, như trong text dev, và frame được đọc khi chúng hoàn tất.

reload unmount ứng dụng, xóa mọi mô-đun dự án khỏi bộ nhớ đệm mô-đun của Bun (kể cả tệp ngoài app/), quét lại app/ và mount lại tại vị trí hiện tại.

Để nhúng máy chủ vào tiến trình của bạn, hoặc dùng phương thức truyền tải khác:

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();

Giới hạn

  • Ứng dụng chạy trong Bun, không phải trình duyệt. window và document không được định nghĩa, như trong text run.
  • Mỗi máy chủ chạy một ứng dụng với một lưới. Mỗi máy khách MCP khởi động máy chủ riêng.
  • text mcp chạy bản sao không có giao diện riêng của ứng dụng. Nó không thể gắn vào tab trình duyệt đang mở bằng text dev.
Sửa trang này trên GitHub