promenow-tools is the HTTP MCP server behind the Terminal Pro statusline installer. Instead of walking through the spec abstractly, this guide shows you the actual JSON-RPC transcripts from the live server — what Claude Code sends, what it gets back, and why the file-manifest model keeps your filesystem safe.
The initialize handshake
Every MCP session starts with an initialize call. Claude Code sends its protocol version and client info; the server confirms compatibility and introduces itself. Here is the real exchange with https://promenow.app/api/mcp:
Request:
POST https://promenow.app/api/mcp
Content-Type: application/json
Accept: application/json, text/event-stream
Authorization: Bearer pn_live_...
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": { "name": "demo", "version": "1" }
}
}Response:
{
"result": {
"protocolVersion": "2025-03-26",
"capabilities": { "tools": {} },
"serverInfo": { "name": "promenow-tools", "version": "0.2.0" },
"instructions": "ProMeNow Tools exposes scoped micro-tools. Returned file manifests must be applied locally only after normal user approval."
},
"jsonrpc": "2.0",
"id": 1
}Two things worth noting. First, the server echoes the same protocolVersion back — a requirement of the spec to confirm compatibility. Second, the instructionsfield carries a policy note to Claude: file manifests require user approval before being written. This is not enforced at the network level; it relies on Claude Code's standard approval flow.
tools/list: what the server exposes
After initialize, Claude Code calls tools/list to discover available tools. promenow-tools returns four:
| Tool | Purpose |
|---|---|
promenow_apps | List available Terminal Pro apps and their status. |
promenow_token_status | Inspect the authenticated token — scope, created date, last used. |
terminal_statusline_preview | Render a live statusline string with a given config and column count. Args: token?, config?, columns (40–240). |
terminal_statusline_pull | Return the full file manifest for your configured statusline — runtime script, config, settings patch, apply helper. |
tools/call: a real preview
Here is an actual terminal_statusline_preview call with columns: 88:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "terminal_statusline_preview",
"arguments": { "columns": 88 }
}
}Response:
{
"result": {
"content": [
{
"type": "text",
"text": "M Opus 4.8 | E high | ctx 26%/1M | 5h 42% 0m | 7d 36% 4d8h"
}
]
},
"jsonrpc": "2.0",
"id": 3
}That rendered string is exactly what would appear in your terminal statusline. The server computed it using your account's saved config — model, segments, theme — at the requested column width. No client-side rendering required.
The content format — an array of {type, text} objects — is the standard MCP tool result shape. Tools can return multiple content items; Claude Code assembles them in order.
The file-manifest model
terminal_statusline_pull does not write any files. It returns a manifest: a list of objects, each with a path and content field. Claude Code presents these to you as proposed file writes and waits for your approval before touching anything.
The manifest typically includes:
~/.claude/terminal-pro/terminal-pro-statusline.mjs— the runtime script that reads the JSON payload and renders your statusline.~/.claude/terminal-pro/statusline.config.json— your segment and theme configuration, mirroring what you set in the builder.~/.claude/terminal-pro/apply-claude-settings.cjs— a helper that patches your~/.claude/settings.jsonto wire the statusline command.- A settings patch snippet showing exactly what will change in settings.json.
The server never has network access to your filesystem. It can only return text. The approval step — Claude Code asking "write these files?" — is the same flow as any other file write in a Claude Code session. You can review the content before confirming.
This design means the server can be updated server-side (a new runtime version, a new default config) without any action on your part beyond re-running the pull.
How authentication flows through
Each JSON-RPC request carries your bearer token in the Authorization header. The server hashes it, looks up the matching account, and scopes the response to your configuration. An audit event is recorded: timestamp, tool name, token identity (not the raw token).
A request without a valid token gets a 401 at the HTTP layer before it reaches JSON-RPC routing. This means the error appears as a connection failure in Claude Code, not a JSON-RPC error response.
Reproducing any of this with curl
You can replay any of these calls manually. The only requirement beyond a valid token is the Accept header:
curl -s -X POST https://promenow.app/api/mcp \
-H "Authorization: Bearer pn_live_your_token" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'This is useful for debugging — if Claude Code is failing to call a tool, reproduce the raw HTTP call first to confirm whether the issue is authentication, the request shape, or Claude Code's handling of the response.
To install your statusline directly, use the Terminal Pro builder, which generates the claude mcp add command pre-filled with your token. Or see Build a statusline in 5 minutes for the manual route.