Skip to content

Use finfocus from an AI assistant (MCP)

FinFocus has a built-in Model Context Protocol (MCP) server. An MCP client, such as Claude Code or Claude Desktop, starts finfocus as a subprocess. It can then call the finfocus commands as tools. For example, it can calculate the projected cost of a Pulumi plan, fetch actual spend, or list installed plugins. You do not need to install a separate server.

Target Audience: Developers and platform engineers using AI assistants

Prerequisites:

  • FinFocus CLI installed and on your PATH
  • An MCP client (Claude Code, Claude Desktop, or any MCP-compatible tool)
  • At least one cost plugin installed for non-zero results (finfocus plugin list)

Estimated Time: 5 minutes


The server has two entry points. They serve the same tools.

Command Use it when
finfocus --mcp The short form for MCP client configs. Serves over stdio
finfocus mcp-server You need transport options (--transport, --addr)
Terminal window
# stdio (what MCP clients launch)
finfocus --mcp
finfocus mcp-server
# Streamable HTTP, loopback only by default
finfocus mcp-server --transport=http --addr=127.0.0.1:8080
# Non-loopback HTTP requires an explicit opt-in
finfocus mcp-server --transport=http --addr=0.0.0.0:8080 --allow-non-loopback

The server writes only MCP protocol messages to stdout. Logs go to the finfocus log file (~/.finfocus/logs/finfocus.log by default). Other diagnostics go to stderr.

Note: finfocus --web is not an MCP entry point. It is a separate root-local flag that serves the browser-based cost dashboard on localhost, and it is mutually exclusive with --mcp. The web UI adds no MCP tools and is not reachable through the MCP server; see CLI Commands Reference.

Register finfocus as an MCP server:

Terminal window
claude mcp add finfocus -- finfocus --mcp

The equivalent command with the subcommand entry point:

Terminal window
claude mcp add finfocus -- finfocus mcp-server

Run claude mcp list to confirm that the server connects. Then ask something like “What is the projected monthly cost of plan.json?”

Add finfocus to claude_desktop_config.json. On macOS the file is in ~/Library/Application Support/Claude/. On Windows it is in %APPDATA%\Claude\. Claude Desktop does not use your shell PATH, so set command to the absolute path of the finfocus binary (which finfocus).

{
"mcpServers": {
"finfocus": {
"command": "/path/to/finfocus",
"args": ["--mcp"]
}
}
}

With the subcommand entry point:

{
"mcpServers": {
"finfocus": {
"command": "/path/to/finfocus",
"args": ["mcp-server"]
}
}
}

Add an "env" object to point the server at a different finfocus home, for example "env": { "FINFOCUS_HOME": "/path/to/.finfocus" }. Restart Claude Desktop after you edit the file.

Each tool is a finfocus command. The tool name is the command path joined with -, and the tool arguments are the command flags.

Tool CLI equivalent
finfocus-cost-projected finfocus cost projected
finfocus-cost-actual finfocus cost actual
finfocus-cost-estimate finfocus cost estimate
finfocus-cost-recommendations finfocus cost recommendations
finfocus-overview finfocus overview
finfocus-plugin-list finfocus plugin list
finfocus-plugin-validate finfocus plugin validate
finfocus-config-list finfocus config list
finfocus-config-validate finfocus config validate
finfocus-config-routes-list finfocus config routes list
finfocus-config-init finfocus config init
finfocus-analyzer-check finfocus analyzer check
finfocus-analyzer-install finfocus analyzer install
finfocus-analyzer-uninstall finfocus analyzer uninstall

For example, this tool call runs finfocus cost projected --pulumi-json plan.json:

{
"name": "finfocus-cost-projected",
"arguments": { "pulumi-json": "/absolute/path/to/plan.json" }
}

The server runs in the directory where the client started it. Pass absolute paths for file arguments such as pulumi-json.

Tool calls return JSON by default. The server passes --format json on every call, and each command then emits its JSON output. An explicit output argument takes precedence. Pass "output": "table" to get the human table instead. The same rule applies on the command line: finfocus cost projected --format json, or setting AGENT_MODE=1, prints JSON unless you also pass --output. Piping output alone does not switch it to JSON.

Every tool also accepts the agent-safety arguments:

  • dry-run: report what a mutating command would do without changing anything. finfocus-config-init with "dry-run": true returns {"action": "would_create", ...} and writes no file.
  • yes: approve a confirmation-gated operation. The server never approves on the client’s behalf. Today the confirmation-gated commands, such as cost recommendations dismiss <id>, take positional arguments, so they are CLI-only.
  • idempotency-key: a retry-deduplication key. The server generates one when you omit it.

A failed call returns the finfocus error envelope as JSON, with isError set. For example: {"error_code": "validation_error", "message": "..."}.

These commands are never exposed as tools:

Command Reason
finfocus (root) Opens the interactive overview dashboard; use finfocus-overview
analyzer serve Long-running Pulumi handshake that would block the server
setup Interactive first-run wizard
plugin init Scaffolds a plugin project; a developer action, not a query
plugin upgrade Rewrites a plugin project’s source; a developer action, not a query
help and command groups help, cost, plugin, config, and other groups only print usage
Positional-arg commands For example plugin install <name>, config set <key> <value>, and cost recommendations dismiss <id>. MCP tool calls can pass flags only

Calling an excluded command’s tool name fails the same way as any unknown tool. The excluded commands still appear in finfocus --help.

The standalone finfocus-mcp server (formerly pulumicost-mcp) has been retired and is superseded by the built-in server. It had hand-written tools that called the CLI. The built-in server exposes the CLI directly, so it stays in step with each finfocus release. Replace the old server entry in your MCP client configuration with finfocus --mcp. The old tools map to built-in tools as follows:

Old finfocus-mcp tool Built-in tool
analyze_projected_cost finfocus-cost-projected
get_actual_cost finfocus-cost-actual
analyze_resource_cost finfocus-cost-projected with filter
query_cost_by_tags finfocus-cost-actual with filter (tag:k=v) or group-by (tag:k=v)
analyze_stack finfocus-overview
compare_costs Partial: finfocus-overview (projected versus actual delta)
list_plugins finfocus-plugin-list
get_plugin_info finfocus plugin inspect (CLI only: it takes positional arguments)
validate_plugin / health_check finfocus-plugin-validate
get_recommendations finfocus-cost-recommendations
track_budget budgets in finfocus-overview JSON; finfocus-cost-projected with exit-on-threshold
detect_anomalies finfocus-cost-anomalies (method: drift rows, or method: robust-median day-spike rows when a stored daily series qualifies)
forecast_costs Partial: ExtrapolatedMonthly in finfocus-overview JSON

finfocus-cost-anomalies returns the same rows as the command. A method value is either drift (the overview’s monthly run-rate comparison) or robust-median (the resource’s latest complete UTC day against the median of its own earlier days). The statistical method needs at least 14 earlier daily points in one currency, excludes the observation day from the median, and emits a row when the absolute robust z-score, 0.6745 * (observed - median) / MAD, reaches 3.5. Severity stays warning, and neither the 14-day minimum nor the 3.5 cutoff is a config key. A flat series (MAD of 0) emits no statistical row, so the drift row remains: that hole is documented rather than covered by a second threshold. Missing days are gaps, never zeros, and currencies are never pooled into one median.

To stop the server, close its stdin or send SIGINT or SIGTERM. A signal drains the server and exits with status 0.

The server exits immediately with a version error. The MCP handshake requires a real build version. Use a released binary or make build. A plain go build without the version ldflags reports a placeholder version.

Cost tools return $0.00. No installed plugin prices the resources. Run finfocus plugin list and install a plugin (finfocus plugin install <name>).

A tool reports no Pulumi project found. The tool auto-detects the Pulumi project from the server’s working directory. Pass an explicit input such as pulumi-json or pulumi-state with an absolute path.

To inspect the server interactively, run make inspect from a finfocus checkout. It opens the MCP Inspector against bin/finfocus --mcp.