Your first server

Add a server, connect, and make your first call

Add a server

Click Add server in the sidebar. Two transports:

Remote (streamable HTTP) — paste the endpoint URL. Before you connect, the built-in endpoint check can diagnose it: whether it speaks MCP at all, which auth model it advertises, and — if you pasted a documentation page instead of the endpoint — which URLs in that page look like the real one.

Local (stdio) — a command plus its arguments, one argument per line (so a path with a space stays one argument). Environment variables go in as KEY=value lines. Paste straight out of a JSON config file; the textareas take it intact.

Connect

Connecting does three things in one action: dials the server, snapshots its contract, and records the snapshot in the local store. The record is what turns "connected" into "connected — and here is what changed since last time."

If the server wants OAuth, mcpi sends the first request unauthenticated; a server that needs sign-in answers with a challenge, and you get a Sign in button instead of an error. Your browser opens, you authorize, and the token lands in the macOS Keychain — reconnecting never means re-authenticating.

If the server needs an API key, add it as a header when saving (Authorization: Bearer …).

If the connection fails, the error names the actual cause. One worth knowing: servers still speaking the deprecated 2024-11-05 HTTP+SSE transport cannot connect over streamable HTTP — mcpi says so explicitly rather than showing a generic failure.

Browse and call

The middle pane lists what the server advertises — tools, resources, prompts — with a filter box for servers that advertise ninety tools. Select one and the detail pane shows a form generated from its input schema.

The form handles what real schema generators emit: pydantic's nullable idioms, schemars $refs, zod literal unions, documented enums. Anything it genuinely cannot represent falls back to a raw JSON editor for that field alone, with a visible raw badge — a form that silently mangles a payload is worse than one that admits the limit.

Run the call; the response lands below the form, and the call lands in history. Open any history entry to load its exact arguments back into the form and fire it again.

Navigation