> ## Documentation Index
> Fetch the complete documentation index at: https://fastmcp-ts.docs.prefect.io/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI

> Run, inspect, call, and install MCP servers from the command line

Installing `@prefecthq/fastmcp-ts` gives you the `fastmcp` CLI as a self-contained binary. Every dependency is bundled, including the MCP SDK, so it runs wherever the package is installed with nothing else to install:

```bash theme={null}
npx fastmcp --help
```

Two global flags apply to every command. `--quiet` suppresses the human-readable output — tables, spinners, status lines — leaving only the data. `--json` switches that data to machine-readable JSON. Together they make the CLI scriptable, a property the rest of this page leans on.

## Run a server

`fastmcp run` starts a server file as a real process, the way it would run in production. TypeScript files run through `tsx` with no build step, so this is the command for serving a file locally or in a container.

```bash theme={null}
fastmcp run server.ts
fastmcp run server.ts --transport http --host 0.0.0.0 --port 3000 --path /mcp
fastmcp run server.ts --reload          # restart on file change
```

Reach for `--reload` during development: it watches the file and respawns the server on every change, so edits take effect without a manual restart. `--transport`, `--host`, `--port`, and `--path` set the same [`MCP_TRANSPORT`/`MCP_HOST`/`MCP_PORT`/`MCP_PATH` environment variables](/servers/running#configuration) `server.run()` already reads, so they're interchangeable with exporting those variables directly — useful when a deployment platform wants to pass configuration as flags.

## Entrypoint exports

Every example so far runs a file that starts itself — `server.ts` ends in a top-level `await server.run()`, the way the [running your server](/servers/running) guide teaches it. Point the CLI at a file that only *exports* a server instead, and it starts the server for you: `fastmcp run server.ts:app` imports `server.ts`, resolves the export named `app`, and calls `.run()` on it. This is the shape a platform wants when it deploys your server — it can bind the transport and port through `MCP_TRANSPORT` and `MCP_PORT` without your file needing to know it's being deployed at all.

Drop the `:app` and the CLI looks for a `default`, `mcp`, `server`, or `app` export, in that order, so a plain `export const server = new FastMCP(...)` is found with no export name given at all. This is the same convention Python FastMCP uses, which keeps a project's entrypoint recognizable regardless of which language wrote it.

```bash theme={null}
fastmcp run server.ts:app
fastmcp run server.ts          # auto-detects default/mcp/server/app
```

A named export can also be a factory — a function, sync or async, that takes no arguments and returns a `FastMCP` server when called. Reach for this when building the server needs work that only makes sense at start time, like reading a config file or opening a database connection before registering tools. Factories are only resolved when you name the export explicitly, since calling an arbitrary exported function as a side effect of guessing a name would be surprising — auto-detection only ever matches an export that's already a `FastMCP` instance.

```typescript server.ts theme={null}
import { FastMCP } from '@prefecthq/fastmcp-ts/server'

export async function createServer() {
  const config = await loadConfig()
  const server = new FastMCP({ name: config.name })
  // register tools, resources, prompts…
  return server
}
```

```bash theme={null}
fastmcp run server.ts:createServer
```

`run`, `inspect --file`, `list --file`, `call --file`, and `dev inspector` all resolve entrypoints the same way, so `file:export` works identically everywhere. `inspect`, `list`, and `call` also accept an explicit `--export <name>` flag, which takes precedence over the colon syntax when both are given:

```bash theme={null}
fastmcp inspect --file server.ts --export app
```

An export name that doesn't exist, or that resolves to something other than a `FastMCP` server or a factory returning one, is a hard error naming the file and export so a typo is easy to spot. A file with no `default`/`mcp`/`server`/`app` export and no `--export` flag is assumed to be the self-running kind — the CLI imports it, lets its top-level code start the server, and does nothing further.

## Inspect a server

`fastmcp inspect` lists a server's tools, resources, and prompts and renders them as tables. Point it at a file to start the server in-process and inspect it, or at a running URL to inspect a live server. This is the command for a quick read of what a server exposes — the fastest way to confirm a registration landed or remember a tool's arguments.

```bash theme={null}
fastmcp inspect --file server.ts
fastmcp inspect --url http://localhost:3000
fastmcp inspect --file server.ts --json
```

`fastmcp list` covers the same ground for a server already running, connecting over a URL or a `--command`. Use `inspect --file` when you have the source and want it spun up for you; use `list` when the server is already up and you are talking to it over the wire. When you pass `--command`, give the binary and its arguments separately rather than one string — `--command npx --args tsx,server.ts`, not a single `"npx tsx server.ts"` — so the binary resolves correctly.

```bash theme={null}
fastmcp list --url http://localhost:3000
fastmcp list --url http://localhost:3000 --resources --prompts --json
```

## Call tools and read resources

`fastmcp call` invokes a tool by name or reads a resource by URI. Arguments are `key=value` pairs, and values that parse as JSON are passed as their parsed type rather than strings:

```bash theme={null}
fastmcp call add --file server.ts a=1 b=2
fastmcp call config://settings --url http://localhost:3000
```

For nested or complex inputs, pass `--input-json` with a JSON object instead of `key=value` pairs — it is unambiguous where positional parsing is fragile. When a tool name doesn't match, the CLI suggests the closest registered name by fuzzy match, so a typo points you at what you meant.

```bash theme={null}
fastmcp call analyze --file server.ts --input-json '{"filters": {"status": "open"}}'
```

## Protocol era

`inspect`, `list`, and `call` connect to a server as a client, so they choose a [protocol era](/concepts/protocol-eras) the way the library client does. Each picks a default per transport: an HTTP URL negotiates automatically — it uses the modern (2026-07-28) era when the server supports it and falls back to legacy — while a stdio or in-process server the CLI spawns stays legacy. Two flags override the default. `--modern` opts a stdio or in-process connection into the same automatic negotiation. `--pin <revision>` requires one exact revision on any transport; it is the stronger request, so it wins even alongside `--modern`.

```bash theme={null}
fastmcp list --url http://localhost:3000                              # auto-negotiates
fastmcp inspect --file server.ts --modern                             # negotiate a spawned server
fastmcp call add --url http://localhost:3000 --pin 2026-07-28 a=1 b=2
```

A `--file` server is spawned as a subprocess and connected over real stdio, so `--modern` reaches the modern era through it. This differs from the library's [in-process transport](/clients/transports#in-process-connections), where an in-memory `FastMCP` connection stays legacy under `'auto'` and needs a pinned era to go modern.

`run` takes no era flag. It starts a server, and a fastmcp server serves both eras at once with no configuration.

When a `--pin` revision the server cannot speak reaches the wire, the CLI maps the `-32022 UnsupportedProtocolVersion` protocol error to a plain-English message: it names the versions the server does support and tells you to change or drop `--pin`. Two neighboring modern-era protocol errors get the same treatment: `-32021` when the server needs a client capability this CLI did not declare, and `-32020` when a request's protocol-version header does not match its body.

## Dev inspector

`fastmcp dev inspector` opens the [MCP Inspector](https://github.com/modelcontextprotocol/inspector) — a browser UI for poking at a server interactively — against a server file, with file-watch reload. Use it when you want to explore a server by hand: call tools through a form, read resources, watch notifications. It is the interactive counterpart to `inspect`, which prints a static snapshot to the terminal.

```bash theme={null}
fastmcp dev inspector server.ts
```

The Inspector speaks the legacy (2025) protocol era only. A fastmcp server pins its era per connection. It still serves the Inspector correctly. The Inspector cannot exercise 2026-07-28 (modern) era behavior. To check the modern era, run `fastmcp inspect --file server.ts --modern` instead.

## Install into editors and clients

`fastmcp install` writes a server into a client's MCP configuration so that editor or app launches it automatically. This is how you hand a finished server to the tools that consume it — Claude Code, Claude Desktop, Cursor, Gemini, Goose, or a project-local `mcp.json`.

```bash theme={null}
fastmcp install claude-code server.ts
fastmcp install claude-desktop server.ts
fastmcp install cursor server.ts
fastmcp install gemini server.ts
fastmcp install goose server.ts
fastmcp install mcp-json server.ts      # project-local mcp.json
```

Pass `--args` (comma-separated) and `--env` (comma-separated `KEY=VALUE`) to configure the entry that gets written. When a target already has an entry for the server, the CLI confirms before overwriting it.

## Discover configured servers

`fastmcp discover` scans every known client configuration on the machine and lists the MCP servers already configured across all of them. Use it to see what a machine is set up to run before installing or to audit existing configuration.

```bash theme={null}
fastmcp discover
```

## Authentication

Commands that connect to a remote server accept `--auth <token>`, which is sent as a bearer token on the connection:

```bash theme={null}
fastmcp list --url https://mcp.example.com --auth $TOKEN
```

## Pipelines and exit codes

The CLI keeps stdout reserved for machine-readable data and sends everything human-readable — tables, spinners, status messages — to stderr. That separation is what makes it composable: pipe the data into `jq` and the formatting never contaminates it.

```bash theme={null}
fastmcp call add --file server.ts a=1 b=2 | jq
fastmcp inspect --file server.ts --json | jq '.tools[].name'
```

The exit code reports the outcome for scripts: `0` on success, `1` for a user error, `2` for a connection failure, `3` for a server error.
