iterm-mcp

iterm-mcp

An MCP server that exposes iTerm2 tab control as native tools, designed for the conductor pattern where one Claude/Codex session drives sibling tabs.

Category
Visit Server

README

iterm-mcp

version node platform

An MCP server that exposes iTerm2 tab control as native tools — designed for the conductor pattern where one Claude/Codex session drives sibling tabs.

Tools

Tool What it does
iterm_ping Sanity check that the server is reachable
tabs_list Enumerate iTerm tabs with runtime detection (claude / codex / ssh / shell) and resume-UUID extraction
tabs_peek Read tab contents, optionally tail-limited to last N lines
tabs_search Search recent tab contents for substring or regex matches with line numbers
tabs_dispatch Write text into a tab with 3-tier submit escalation (CR+LF → keystroke → file-drop)
tabs_focus Bring a tab to the foreground
tabs_send_keystroke Send a raw return / tab / escape / backspace / space keystroke via Accessibility

Three-tier dispatch escalation

tabs_dispatch is the workhorse. Submitting text reliably across local-shell, claude, codex, and SSH-into-remote tabs needs different mechanisms, so the tool escalates:

  1. Tier 1 — crlf: AppleScript write text + CR + LF. Fast and quiet; works for short text into local claude tabs.
  2. Tier 2 — keystroke: Focus the tab, then have System Events deliver keystroke return. Required for codex tabs and remote ssh sessions where Tier 1 unreliably submits.
  3. Tier 3 — fallback: Write the intended dispatch to ~/.claude/plans/pending-dispatches/<ts>-w<W>t<T>.md. Operator-recoverable.

escalation: "auto" (default) tries Tier 1, falls through to Tier 2 on failure, drops to Tier 3 if both fail. You can also force a tier explicitly: crlf, keystroke, or fallback.

Refuse-self

tabs_dispatch reads ~/.claude/plans/inter-agent-sync/conductor-active.txt and refuses dispatch when:

  • target window/tab matches the conductor's own tab, or
  • target tab's resume UUID is in also_refuse_self_for_resume_uuids, or
  • target tab's resume UUID equals the conductor's session_id.

This prevents the conductor from ever dispatching into itself (which would cause a feedback loop).

Screenshot

(placeholder — drop a screenshot of tabs_list output in a claude session here)

Install

git clone https://github.com/CondorCommodore/iterm-mcp.git
cd iterm-mcp
npm install
npm run build
claude mcp add iterm-mcp -s user -- node $(pwd)/dist/server.js

On first dispatch, macOS will prompt to grant Accessibility permission to your terminal / Claude Code app so that System Events can deliver keystrokes. Grant it in System Settings → Privacy & Security → Accessibility.

Smoke test

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' | node dist/server.js

You should see a JSON-RPC initialize result on stdout and [iterm-mcp] server ready on stderr.

Test

npm test           # vitest run tests/unit
npm run test:watch # vitest watch

Unit tests mock osascript / ps invocation and verify both the AppleScript shape we send and our result parsing.

Troubleshooting

error TS2589: Type instantiation is excessively deep and possibly infinite

The MCP SDK's McpServer.registerTool uses extremely deep generic inference over Zod schemas. With zod ^3.25 and @modelcontextprotocol/sdk ^1.29 together, TypeScript hits its instantiation-depth ceiling and refuses to compile.

We work around it in src/server.ts with a thin wrapper that erases the SDK's generics:

const reg: (name: string, config: any, cb: any) => void = (n, c, h) => {
  (server as any).registerTool(n, c, h);
};

Runtime behavior is identical — only the compile-time type check is short-circuited. When the SDK ships a less-recursive overload, the wrapper can be retired.

osascript: command not found

iterm-mcp only runs on macOS. AppleScript and System Events are macOS-only.

Dispatch silently no-ops on a codex or ssh tab

That's Tier 1 (crlf) being unreliable on those runtimes. Either let escalation: "auto" fall through to Tier 2, or pin escalation: "keystroke" directly.

"Not authorized to send keystrokes"

System Events needs Accessibility permission for the parent process that spawns osascript (your terminal, or Claude Code itself). Grant it under System Settings → Privacy & Security → Accessibility.

Refuse-self firing on the wrong tab

Check that ~/.claude/plans/inter-agent-sync/conductor-active.txt reflects the conductor's actual window/tab. The file is key=value lines: conductor_window, conductor_tab, session_id, also_refuse_self_for_resume_uuids (comma-separated).

License

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured