See what's on your ports, the processes behind them, and diagnose conflicts and leaks.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent โ or use 1-click editor setup below.
๐ก Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
See what's on your ports, then act on it. So can your AI agent.
lsof -i is slow and cryptic. ss -tlnp is unreadable. netstat is deprecated. You just want to know what's on port 3000 and kill it.
One command. Every listening port, the process behind it, memory usage, uptime, and the full command โ in a colored table. Then inspect, kill, or watch it live.
It's also an MCP server โ one binary, no Node, no npx โ so Claude Code and Cursor can answer "what's on 3000?" without shelling out to lsof and misparsing the result.
~1 MB single binary. Zero runtime dependencies. Linux, macOS, and Windows.
Or grab a binary from Releases.
--all includes non-listening connections โ one row per connection, so a pile-up of TIME_WAIT or CLOSE_WAIT sockets is visible rather than collapsed. --wide shows full commands. --json for scripting.
Ports whose owner can't be resolved are still listed, with - in the columns that can't be filled. That happens for another user's process without sudo, and for sockets like TIME_WAIT that outlive the process that opened them.
The scan, doctor, and MCP examples below are real output, captured by
demo/record.shinside an isolated namespace โ which is why the user isrootand the paths are/opt/app. The Docker example is illustrative, since it needs a running daemon.
Give your coding agent eyes on your ports. portview mcp speaks the Model Context Protocol over stdio, so Claude Code, Cursor, and any other MCP client can query and act on ports directly instead of shelling out to lsof and guessing at the output.
Or configure it manually:
| Tool | What it does |
|---|---|
list_ports | Every listening port with process, user, uptime, memory, full command |
inspect_port | One port in detail: each process's working directory, plus its child processes โ so the agent knows what else stops when it stops your dev server |
find_process | Which ports a service is on, by name or command substring |
doctor | Conflicts, wildcard exposure, stale connections, resource hogs |
diff_ports | What opened, closed, or changed owner since a baseline โ "what did starting that actually do?" |
kill_port | Terminate what's on a port (marked destructive to the client). dry_run shows which PIDs it would signal, without signalling them |
No Node, no npx, no runtime. It's the same ~1 MB binary โ nothing extra to install. The MCP server added 29 KB, because it pulls in no new dependencies.
Pass --read-only to withhold kill_port entirely, so the agent can look but not touch:
Listed in the MCP Registry as
mcp-name: io.github.Mapika/portview.
| Key | Action |
|---|---|
j/k, โ/โ | Navigate rows |
Enter | Inspect port (full command, cwd, children, connections) |
d/D | Kill process or manage Docker container |
/ | Filter across all columns |
โ/โ, r | Cycle sort column, reverse direction |
t | Toggle process tree view |
a | Toggle all/listening-only |
q | Quit |
Tree view (t): Groups child processes under their parents with visual connectors. See which workers belong to which master process at a glance.
Detail view (Enter): Shows the full unwrapped command, working directory, child process list with ports, and open connections (in --all mode).
Diagnose common port problems in one command:
| Check | Flags |
|---|---|
| Port conflicts | Multiple PIDs bound to the same port |
| Wildcard exposure | Databases (postgres, redis, mysql, mongod, โฆ) listening on 0.0.0.0 |
| Docker-host conflicts | A container publishing a port the host already uses |
| Stale connections | TIME_WAIT or CLOSE_WAIT pileups on one port โ a connection leak |
| Resource hogs | Listeners holding more than 1 GB resident |
Docker is auto-detected. portview doctor --json for scripting (exit code 1 on errors).
There's a GitHub Action, so a workflow can fail when a service ends up exposed or a test run leaks connections:
It annotates each finding inline on the run, writes a summary table, and exposes
findings (JSON), count, errors, and warnings as step outputs:
Set install: false if portview is already on PATH. Linux and macOS runners.
Inspect ports on any machine you can SSH to:
Kill actions in the remote TUI are forwarded over SSH.
Nothing to install on the remote host. If portview isn't there, it falls back
automatically to collecting over the same SSH connection with ss and ps โ
present on essentially every Linux box:
Force it with --agentless to skip the remote portview entirely. You still get
the process, user, memory, uptime, and full command โ it resolves
/proc/<pid>/exe on the remote host, so a Node server reads as node rather
than the MainThread that ss reports.
doctor works agentless too โ the checks are pure functions over collected
data, so they run locally against whatever the probe brought back:
That produces the same findings as running portview doctor on the host
itself. The Docker check is reported as skipped rather than passed, since the
probe doesn't query Docker on the far end.
watch works agentless as well, including the interactive kill:
The probe loops on the far end and the TUI reads the records it sends back, so the whole session costs one SSH connection rather than one per refresh.
Agentless mode covers everything: scans, port inspection, process search,
diagnostics, and watch. On Linux it uses ss and ps; where ss does not
exist it falls back to lsof, which covers macOS and the BSDs.
Add --docker to any command. Docker-published ports appear as first-class rows:
Container-only rows have no host process, so PID, UPTIME, and MEM render as -.
Press d on a Docker row to Stop, Restart, or tail Logs.
Columns: port, proto, pid, user, process, uptime, mem, command. Use --no-color to disable.
All data is read directly from the OS โ no shelling out to lsof, ss, or netstat.
| Field | Linux | macOS | Windows |
|---|---|---|---|
| Ports | /proc/net/tcp{,6}, udp{,6} | proc_pidfdinfo | GetExtendedTcp/UdpTable |
| PID | inodeโpid via /proc/*/fd/ | proc_listpids | Included in socket table |
| Process | /proc/<pid>/exe | proc_pidpath | QueryFullProcessImageNameW |
| Memory | /proc/<pid>/status VmRSS | proc_pidinfo | K32GetProcessMemoryInfo |
| Uptime | /proc/<pid>/stat | proc_pidinfo | GetProcessTimes |
The process name comes from the executable, not /proc/<pid>/comm. comm is the thread name, and runtimes overwrite it โ Node.js renames its main thread to MainThread, which is why ps, ss, and lsof all report a Node dev server as MainThread. It is also truncated to 15 bytes.
Docker integration queries docker ps when --docker is passed. SSH mode runs portview --json on the remote host via the system ssh binary. MCP mode speaks newline-delimited JSON-RPC 2.0 on stdin/stdout, with a hand-rolled JSON reader โ no serde, no extra dependency.
| Tool | What's missing |
|---|---|
lsof -i :3000 | Different flags per OS, cryptic output, slow |
ss -tlnp | Unreadable, no uptime/memory/docker, no TUI |
netstat | Deprecated on modern Linux, limited info |
fkill-cli | Requires Node.js, kill-first not diagnostic-first |
procs | General process viewer, not port-centric |
None of them speak MCP, so none of them can be handed to an agent.
There's also a smaller thing they all get wrong. Start a Node dev server and ask what's on the port:
ps, ss, and lsof all read /proc/<pid>/comm, the thread name โ and Node renames its main thread to MainThread. portview reads the executable instead.
portview is diagnostic-first: understand what's on your ports, then act.
Requires Rust 1.85+ (edition 2024). Shell completions and man page are generated at build time.
There's also a Dockerfile. Note that a container has its own network and PID
namespaces, so portview inside one sees the container's ports โ share the
host's namespaces to inspect the host:
See CONTRIBUTING.md for development setup and guidelines, and demo/README.md for regenerating the recordings.
Changes should type-check on all three platforms, not just yours:
sudo (it reads /proc/<pid>/fd/). Rows you can't attribute show - for PID, user, process, and command rather than being hidden.sudo โ sockets are enumerated per process via proc_pidfdinfo, so a process that can't be opened contributes nothing to enumerate. For the same reason doctor cannot detect TIME_WAIT pileups there; CLOSE_WAIT is detected normally.- for name and user. Kill always force-terminates. Run as Administrator for full detail.docker CLI and daemon accessss + ps on Linux and lsof where ss does not exist. The remote needs one of those and a POSIX shell. Agentless collection cannot see Docker on the far end, so that check reports as skipped rather than passed.MIT
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/portview)<a href="https://allmcps.com/mcp/portview"><img src="https://allmcps.com/api/badge/portview?style=directory" alt="Portview on AllMCPs" /></a>