A terminal UI for exploring and testing Model Context Protocol (MCP) servers. Connect to any MCP server, over streamable HTTP or stdio, then browse its tools, prompts and resources and call them from generated forms. See the results rendered or as raw JSON-RPC. OAuth login is built in and works over SSH and in devcontainers.
mcptui is for people building or debugging MCP servers, or checking what a server exposes before wiring it into an agent. It's a protocol explorer, not an agent: there's no LLM in the loop. You make the calls and see exactly what goes over the wire. It's a single Go binary with no browser, proxy or Node runtime, and doesn't assume anything about the server.
Tools tab: a form generated from the tool's input schema, and the result.
mcptui β everything dev β mcp-servers/everything 2.0.0 (2025-11-25) β connected
1 Tools (13) 2 Prompts (4) 3 Resources (9) 4 Chat (3) 5 Log
/ filter β get-sum Get Sum Tool [read-only] [idempotent]
echo ro β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
get-annotated-message ro β Returns the sum of two numbers
get-env ro β
get-resource-links ro β a * 3
get-resource-reference ro β First number
get-structured-content ro β b * 4
βΈ get-sum ro β Second number
get-tiny-image ro β
gzip-file-as-resource β
toggle-simulated-logging β [ Call β ] [ Edit JSON e ] [ Copy cmd c ] [ Docs d ]
toggle-subscriber-updates βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
trigger-long-running-operatβ¦β Result get-sum β 3ms (p)retty (m)arkdown (r)aw [ Copy y ] [ Savβ¦
simulate-research-query β The sum of 3 and 4 is 7.
β
β
p/m/r view y copy s save c/C copy cmd e json tab list esc form
Chat tab: every request, server notification and log message in the session, with a message box to send new calls (get-sum a=3 b=4, read <uri>) and a browsable list of everything the server offers.
mcptui β everything dev β mcp-servers/everything 2.0.0 (2025-11-25) β connected
1 Tools (13) 2 Prompts (4) 3 Resources (9) 4 Chat (5) 5 Log
β β€ demo://resource/static/document/features.md resources/rβ¦
β 2026-09-17 07:20:30 Β· 2ms Β· ok
β [ Rerun ctrl+r ] [ Edit e ] [ Copy cmd c ] [ curl C ]
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Connected to Everything Reference β¦ β Result demo://resource/static/document/features.md β 2msβ¦
Everything Server β Server Instructβ¦β β€ demo://resource/static/document/features.md text/markdβ¦
Audience: These instructions are wrβ¦β Everything Server - Features
β
β notifications/tools/list_changed β Architecture /architecture.md | Project Structure
list changed Β· refreshed β /structure.md | Startup Process /startup.md | Server
β Features | Extension Points /extension.md | How It
β get-sum {"a":3,"b":4} β Works /how-it-works.md
The sum of 3 and 4 is 7. β
β ## Tools
β echo {"message":"hello from mcptuiβ¦ β
Echo: hello from mcptui β β’ Β echoΒ (tools/echo.ts): Echoes the provided
β Β message: stringΒ . Uses Zod to validate inputs.
β β€ demo://resource/static/document/feβ¦ β β’ Β get-annotated-messageΒ (tools/get-annotated-
ββ move Β· tab/β pick Β· esc back
β get-sum Returns the sum of two numbers
β get-structured-content Returns structured content along with an output schema for client data vβ¦
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βΊ get-s
β send tab complete β previous shift+tab transcript esc tabs
- Connects to any MCP server: streamable HTTP (JSON or SSE responses, sessions, transparent re-initialize when a session expires) or a local stdio command. Saved profiles hold URLs, commands, headers and auth settings; a picker lets you switch between them.
- Handles authorization for you: the full MCP OAuth 2.1 flow (protected resource and authorization server discovery, dynamic client registration, PKCE, token refresh with rotation, revocation), plus a paste-the-redirect-URL fallback for headless machines. Bearer tokens and custom headers work too.
- Lets you browse everything the server exposes: tools (with annotations such as read-only or destructive), prompts, resources and resource templates, with docs, schemas and filtering.
- Makes calling things easy: forms generated from JSON Schema, a JSON editor or
$EDITOR, argument completion, live progress and cancellation. Destructive tools, and anything not read-only on a production profile, ask for confirmation first. - Shows results readably: pretty JSON, rendered markdown,
structuredContentchecked againstoutputSchema, images and binary resources you can save, and the raw JSON-RPC for every exchange. - Keeps a session transcript: the Chat tab records the connection, every call, server notifications and log messages. You can rerun or edit any entry, or copy it as a
curlormcptuicommand. - Works in scripts:
mcptui call|prompt|read|ls|infoprint JSON and share profiles and credentials with the TUI, andmcptui auth tokenfeedscurl.
Prebuilt binaries for macOS, Linux and Windows are attached to each release. The commands below download the latest release with curl; gh release download -R ideonate/mcptui -p '<pattern>' -O - works too.
# Apple Silicon; use darwin_amd64 on an Intel Mac
curl -fsSL https://github.com/ideonate/mcptui/releases/latest/download/mcptui_darwin_arm64.tar.gz | tar -xzf - mcptui
# /usr/local/bin is owned by root on macOS, so this needs sudo
sudo mkdir -p /usr/local/bin
sudo mv mcptui /usr/local/bin/
mcptui --versionNo sudo? Put it in your home directory instead:
mkdir -p ~/.local/bin && mv mcptui ~/.local/bin/
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrcThe binaries aren't notarized. Files fetched with curl or gh run as-is, but if you downloaded the archive in a browser and macOS refuses to open mcptui, clear the quarantine flag:
xattr -d com.apple.quarantine "$(command -v mcptui)"# x86_64; use linux_arm64 on ARM machines
curl -fsSL https://github.com/ideonate/mcptui/releases/latest/download/mcptui_linux_amd64.tar.gz | tar -xzf - mcptui
sudo install -m 0755 mcptui /usr/local/bin/mcptui
mcptui --versionOr without sudo: install -D -m 0755 mcptui ~/.local/bin/mcptui (~/.local/bin is on the PATH by default on Ubuntu; open a new shell if it didn't exist before).
Download mcptui_windows_amd64.zip and put mcptui.exe somewhere on your PATH.
Run the same commands again: they download the latest release, and the copy step replaces the old binary.
go install github.com/ideonate/mcptui@latest# A stdio server (temporary profile)
mcptui -- npx -y @modelcontextprotocol/server-everything
# A streamable HTTP server; logs in through the browser if the server returns 401
mcptui https://mcp.example.com/mcp
# Pick, create, edit or delete saved profiles in the TUI
mcptui
# Open a saved profile directly
mcptui example
# ...or save one from the command line
mcptui profiles add example https://mcp.example.com/mcp --env prodA bare mcptui opens the profile picker (the default profile is preselected, so β connects). With no profiles yet, it goes straight to the new-profile form: a name, a URL or stdio command, and optional badge, auth, token, scope and client id. Press ctrl+p in the app to switch profiles, or to save a temporary mcptui <url> connection as a profile.
The mouse works like in Textual apps: click tabs, list rows, form fields, [ buttons ] and the key hints in the footer; double-click a list item to open it (or a profile to connect); use the wheel to move through lists and scroll results. Hold shift (option on some macOS terminals) to select text, or run with --no-mouse.
Keyboard: esc steps back out (result β form β list β tab bar); in the tab bar β/β switch tabs and β/β go back in. tab / shift+tab cycle focus (tabs β list β form fields β result), β runs, and 1β5 jump straight to a tab. Press ? for everything.
| Where | Keys |
|---|---|
| Anywhere | 1β5 tabs Β· ctrl+p profiles Β· R refresh (or reconnect) Β· L / O log in / out Β· P ping Β· i server info & instructions Β· ? help Β· ctrl+c cancel a running request, or quit |
| Lists | j/k move Β· / filter Β· β open form (runs it directly if it has no arguments) Β· e / E arguments as JSON / in $EDITOR Β· d full docs & schemas Β· S subscribe to resource |
| Form | tab / shift+tab fields Β· β or ctrl+s call Β· space β β toggle/cycle Β· ctrl+n / ctrl+d add/remove array item Β· ctrl+t multi-line Β· ctrl+e JSON Β· ctrl+o $EDITOR Β· ctrl+space complete Β· esc back |
| Result | p / m / r pretty / markdown / raw JSON-RPC Β· y copy (OSC 52) Β· s save to file Β· c / C copy as mcptui command / curl |
| Chat | type add(1, 2), add {"a":1}, add a=1, greet name=Ada, read <uri> or ping and press β Β· tab completes a suggested name, β opens its form Β· β browse bar, β again recalls commands Β· shift+tab into the transcript, then r rerun, e edit, a show list/initialize requests too |
| Log | t show raw traffic Β· G follow Β· c clear |
Chat (tab 4) is a running transcript of the session: the connection (server info and instructions), every request including calls made from the other tabs, server notifications and log messages, requests the server sends to mcptui, disconnects and logins. Each entry has a short preview on the left and the full detail on the right. The message box runs along the bottom. With it empty, a Tools / Prompts / Resources & templates / Ping bar lets you browse everything the server offers (β then β/β, or click; β again recalls earlier commands); picking a category lists all of its items, and typing narrows the list; each tool and prompt shows its parameters, like (project, limit?). Picking an item opens its form on the right, even if it takes no arguments, and nothing is sent until you press β or Call (esc cancels). Or just type a command and it is sent straight away: a tool, prompt or resource name with arguments as JSON, key=value pairs, or in parentheses, where values fill the parameters in the order shown (required ones first) and can also be named: list_items(42, limit=10). If something needs arguments you didn't give, its form opens instead. Select any entry to see the full request and response on the right, and rerun or edit it from there.
Forms are generated from each tool's JSON Schema: strings, numbers, booleans, enums, arrays of scalars, and optional (anyOf [X, null]) fields. Anything more complex (nested objects, unions, $ref) becomes an inline JSON field, pre-filled with a skeleton. Arguments are validated before sending, and unset optional fields are left out.
Safety: tools annotated destructiveHint: true always ask for confirmation. In profiles with env_badge = "prod", every tool not marked readOnlyHint: true asks too. Override this with confirm = "never" | "writes" | "all".
$XDG_CONFIG_HOME/mcptui/config.toml (usually ~/.config/mcptui/config.toml):
default_profile = "local"
# history = false # don't write ~/.local/state/mcptui/history.jsonl
[profiles.local]
url = "http://127.0.0.1:8001/mcp"
# auth = "oauth" # default for http; only used if the server returns 401
env_badge = "dev" # dev | staging | prod: header colour and safety defaults
[profiles.some-remote]
url = "https://mcp.example.com/mcp"
client_id = "abc123" # only when dynamic registration isn't available
# client_secret = "env:SECRET"
scope = "read write" # optional
callback_port = 33418 # optional; 33418-33420 are registered
env_badge = "prod"
timeout = "2m" # optional request timeout; default none
[profiles.api-key]
url = "https://api.example.com/mcp"
auth = "bearer"
token = "env:MY_MCP_TOKEN"
headers = { "X-Org" = "env:MY_ORG" }
[profiles.local-stdio]
transport = "stdio"
command = ["python", "-m", "my_server"]
cwd = "/path/to/project"
env = { LOG_LEVEL = "debug" }Values of the form env:NAME are read from the environment.
mcptui implements MCP authorization (OAuth 2.1) itself:
- Discovery: protected resource metadata (RFC 9728), then authorization server metadata (RFC 8414, with OpenID Connect fallbacks and tolerance for trailing slashes).
- Client identity: a pre-registered
client_id, else a cached dynamic registration (RFC 7591, registered once per authorization server), else a new dynamic registration. - Flow: PKCE (S256),
state, and the RFC 8707resourceparameter. - Refresh: proactive and on
401, with refresh-token rotation saved atomically and a lock file so several mcptui processes can refresh safely.
The login URL is always shown: press c to copy it (native clipboard tool if available, plus OSC 52), o to open a browser, or cat ~/.local/state/mcptui/login-url.txt for an unbroken copy; in terminals with OSC 8 support the wrapped URL is also ctrl/cmd-clickable. If the browser runs on another machine (devcontainer, SSH) and can't reach the loopback callback, paste the URL from the browser's address bar into mcptui (press p, or just paste). Use --no-browser to skip opening a browser, and --callback-host to change the bind address.
Credentials are stored in $XDG_CONFIG_HOME/mcptui/credentials.json (mode 0600). Tokens are never logged.
mcptui auth login <profile> # force a new login
mcptui auth status [profile] # scope, expiry, authorization server, client id
mcptui auth token <profile> # print a valid access token (refreshes if needed)
mcptui auth logout <profile> # revoke (if supported) and delete
mcptui auth reset-client <profile> # forget the dynamic registration and register againFor example: curl -H "Authorization: Bearer $(mcptui auth token prod)" β¦.
These commands share the TUI's profiles and credentials, so they work in scripts and for coding agents:
mcptui call <profile> <tool> ['{json}' | @args.json | -] # result JSON; exit 1 on isError
mcptui prompt <profile> <name> [key=value ...]
mcptui read <profile> <uri> [-o file]
mcptui ls <profile> tools|prompts|resources|templates [--json]
mcptui info <profile> [--json]--rawprints the whole JSON-RPC response.--profile-url <url>or--stdio '<command>'replaces the profile argument with a temporary connection.-vlogs transport and auth events to stderr.- When no valid token exists and stdin isn't a terminal, commands fail with a hint to run
mcptui auth loginrather than waiting for a browser.
- Transports: streamable HTTP (JSON and SSE bodies,
Mcp-Session-Id,MCP-Protocol-Version, transparent re-initialize after a404,DELETEon exit, and the optional GET stream) and stdio (stderr in the Log tab; a crash is reported with the last stderr lines). - Tools:
tools/*, includingstructuredContentvalidated againstoutputSchema, and annotations. - Prompts and resources:
prompts/*;resources/*including templates and subscribe. - Also supported:
- Automatic pagination.
- Live progress and cancellation (
notifications/cancelled). notifications/messagelog messages.- Refresh on
list_changednotifications. - Argument completion (
completion/complete) andping.
- Server-to-client requests (sampling, elicitation, roots) are logged and answered with a JSON-RPC error.
- An OS keyring backend (
--keyring). - Saved argument presets.
- JSON folding and JSON path filtering in results.
- The device authorization grant and client ID metadata documents.
- The legacy HTTP+SSE transport.
- Answering sampling and elicitation requests.
See SPEC.md for the design and later ideas.
go test -race ./...
go test ./internal/tui -update # refresh TUI snapshotsinternal/testserver is an in-process MCP server (HTTP and stdio) used as a test fixture. The OAuth tests run against an in-process mock authorization server.
MIT, see LICENSE.