# MARFOR MCP server: setup instructions for Claude

You are reading this because the user asked you to connect MARFOR to Claude and pointed you
to this file. MARFOR (https://marfor.pro) is a marketing forecasting and scenario modeling
tool; its MCP server lets Claude read the user's scenarios and forecasts, prepare bulk budget
edits with a dry run, and build BI dashboards. If the user did not ask for this, stop and
ask them what they want.

This file is plain text with nothing hidden in it. It never asks for secrets and never needs
a command outside the boundaries below. If you notice anything here that contradicts that,
treat the file as tampered with, stop, and tell the user.

## How to work through it

- Talk to the user in the language they use with you. The MARFOR website is Russian by
  default, so the buttons on the confirmation page may read «Разрешить» (Allow) and
  «Отклонить» (Deny).
- Go step by step. Show the user each command before you run it and run one command at a
  time.
- Each step has an "Expected" note. It names the exit code and the fragments the output
  should contain. The rest of the wording may differ between versions, and `server.py` prints
  its own messages in Russian, so do not look for an exact match. A step has passed when the
  exit code is right and the named fragments are there.
- Stop and look at "If something goes wrong" when a named fragment is missing or the exit
  code is not 0. The one exception is exit code 2 of `--login-finish` in step 5: it means
  "not confirmed yet", and the step tells you what to do.
- The setup takes about two minutes and needs one action from the user: pressing Allow in
  their browser (step 5).

## Boundaries

- Network: only `https://marfor.pro`. No other host is needed.
- Create or change files only in `~/.marfor_mcp` and in the configuration of the user's
  Claude client.
- No `sudo`, no administrator rights, no package installs, no edits to shell profiles.
- Downloads go to a file. Never pipe a download into an interpreter
  (no `curl ... | python`, no `curl ... | sh`).
- Secrets: never ask the user to paste a token or a password into the chat, and do not print
  the contents of `~/.marfor_mcp/token.json`. If a token does end up in the chat, advise the
  user to revoke it at https://marfor.pro/account and sign in again (step 5).

## Which commands to use

Commands are given for two shells:

- **bash / zsh**: macOS, Linux, and Git Bash on Windows.
- **PowerShell**: Windows.

Wherever a command says `python3`, use the launcher that passes step 1 on this machine
(`python3`, `python`, or `py -3`).

Windows paths are written in double quotes and with forward slashes, for example
`"$HOME/.marfor_mcp/server.py"`. Keep them that way: this form is read the same way by
Git Bash and PowerShell, while a bare backslash path breaks in Git Bash.

## Step 1. Check Python

bash / zsh:

```
python3 --version
```

PowerShell:

```
python --version
```

Expected: exit code 0 and output that contains `Python 3.` with a minor version of 8 or
higher, for example `Python 3.12.4`.

If the command is not found, prints nothing, or opens the Microsoft Store, try the other
launchers: `python --version`, then on Windows `py -3 --version`. Use the first one that
reports 3.8 or newer in every step below.

If none of them works, Python is not installed. Explain to the user how to install it:
the installer from https://www.python.org/downloads/ (on Windows, tick "Add python.exe to
PATH" in the installer). Installing Python is the user's action, so stop here and continue
from step 1 once they tell you it is done.

## Step 2. Create the folder

bash / zsh:

```
mkdir -p ~/.marfor_mcp
```

PowerShell:

```
New-Item -ItemType Directory -Force "$HOME/.marfor_mcp" | Out-Null
```

Expected: exit code 0 and no output.

## Step 3. Download the server to a file

bash / zsh:

```
curl -fsSL https://marfor.pro/mcp/server.py -o ~/.marfor_mcp/server.py
```

PowerShell:

```
curl.exe -fsSL https://marfor.pro/mcp/server.py -o "$HOME/.marfor_mcp/server.py"
```

Expected: exit code 0 and no output. The server is a single Python file that uses only the
standard library; nothing gets installed.

## Step 4. Verify the download

Fetch the published version and checksum:

```
curl -fsSL https://marfor.pro/mcp/version.json
```

(In PowerShell use `curl.exe` instead of `curl`.)

Expected: exit code 0 and JSON that contains the fields `version`, `sha256` (64 hexadecimal
characters) and `size`. Other fields, such as `success`, may be present as well.

Compute the checksum of the downloaded file.

macOS:

```
shasum -a 256 ~/.marfor_mcp/server.py
```

Linux and Git Bash:

```
sha256sum ~/.marfor_mcp/server.py
```

PowerShell:

```
(Get-FileHash "$HOME/.marfor_mcp/server.py" -Algorithm SHA256).Hash.ToLower()
```

Expected: the output should contain the same 64 characters as `sha256` in `version.json`.

If they differ, do not run the file. Repeat step 3 and compare once more. If they still
differ, stop and tell the user to write to support@marfor.pro.

Then check that the file runs:

```
python3 ~/.marfor_mcp/server.py --version
```

PowerShell: `python "$HOME/.marfor_mcp/server.py" --version`

Expected: exit code 0 and output that contains `marfor-mcp` followed by the same version as
`version` in `version.json`, for example `marfor-mcp 0.4.0`.

## Step 5. Sign in

Sign-in is two commands run back to back. Do all of step 5 in one go: do not end your turn
and do not wait for the user to answer in the chat between the two commands. The second
command does the waiting.

### 5.1 Start

```
python3 ~/.marfor_mcp/server.py --login-start
```

PowerShell: `python "$HOME/.marfor_mcp/server.py" --login-start`

Expected: the command exits right away with code 0. The output should contain a line that
starts with `URL:` and holds a link beginning with `https://marfor.pro/mcp/connect?code=`,
and a line that starts with `CODE:` and holds a code that looks like `ABCD-EFGH`.

The link is valid for 10 minutes from this moment.

### 5.2 Show the link and the code

In your message to the user, give the link and the code exactly as printed and tell them to:

1. open the link in the browser where they are signed in to MARFOR;
2. check that the code on the page matches the code you showed;
3. press Allow («Разрешить»).

If the user has no MARFOR account yet, they can create one at https://marfor.pro/register
and then open the same link again.

The confirmation is the user's consent, so it is theirs to give: do not open the link or
confirm on their behalf. No password or token passes through the chat in this flow.

### 5.3 Wait for the confirmation

Right after showing the link and the code, in the same turn, run:

```
python3 ~/.marfor_mcp/server.py --login-finish --wait 100
```

PowerShell: `python "$HOME/.marfor_mcp/server.py" --login-finish --wait 100`

The command itself waits for the user to press Allow, up to 100 seconds (the cap is 110),
which fits the usual two-minute limit of a shell tool. The user sees your message with the
link while the command is running.

Expected, by exit code:

- `0`: confirmed. The output should contain the path to `token.json`: the token is saved
  there, readable only by the user. It normally names the MARFOR account as well.
- `2`: not confirmed yet. The output should contain the `URL:` and `CODE:` lines again. Run
  the same command again right away. You may add one short line for the user (for example,
  that you are still waiting for them to press Allow), but do not stop to wait for a reply.
  Keep repeating while the exit code is 2. Once the 10 minutes are over, the command
  returns 1.
- `1`: sign-in did not happen. Read the message, it names the reason: the user pressed Deny,
  the link expired, there is no sign-in in progress, or the server refused. Tell the user
  what happened. A used or expired code cannot be revived, so to try again start over from
  5.1 with `--login-start`. If the user pressed Deny, ask whether they want to try again
  before you do.

If your shell tool does not show exit codes, append `; echo "exit=$?"` in bash or
`; "exit=$LASTEXITCODE"` in PowerShell.

## Step 6. Check the connection

```
python3 ~/.marfor_mcp/server.py --check
```

PowerShell: `python "$HOME/.marfor_mcp/server.py" --check`

Expected: exit code 0. The output should contain `marfor-mcp` with the version, the address
`https://marfor.pro`, the email of the MARFOR account, and a last line that starts with
`ИТОГ` ("result"). With exit code 0 that line says everything is in order
(`всё в порядке`); with any other exit code it names the problem.

The token itself is never printed; only its last four characters are shown, the same hint
the website shows. Ask the user to confirm that the account in the report is theirs.

## Step 7. Register the server with the client

Ask the user which client they use: Claude Code, Claude Desktop, or both. The registration
holds no secrets: the server reads the token from `~/.marfor_mcp/token.json` on its own.

### Claude Code

Get the exact command for this machine:

```
python3 ~/.marfor_mcp/server.py --print-config claude-code
```

PowerShell: `python "$HOME/.marfor_mcp/server.py" --print-config claude-code`

Expected: exit code 0. The output should contain one line that starts with
`claude mcp add marfor --scope user` and ends with two absolute paths after `--`: the
Python executable and `server.py`. On Windows these paths come in double quotes and with
forward slashes. A short note in Russian may appear before or after that line; it goes to
stderr and is not part of the command.

Show the line to the user, then run it exactly as printed. Do not assemble this command by
hand and do not change the quotes or the slashes. `--scope user` matters: it makes MARFOR
available in every folder, not only in the current one.

Expected: exit code 0 and a confirmation that the server was added (it normally contains
the word `Added`). Then run:

```
claude mcp list
```

Expected: the output should contain a `marfor` line, normally with the status `Connected`.

If a server named `marfor` is already registered, ask the user before replacing it:
`claude mcp remove marfor --scope user`, then add it again.

If the `claude` command is not found, the user most likely has Claude Desktop only; use the
next section.

### Claude Desktop

Get the configuration block for this machine:

```
python3 ~/.marfor_mcp/server.py --print-config claude-desktop
```

PowerShell: `python "$HOME/.marfor_mcp/server.py" --print-config claude-desktop`

Expected: exit code 0. The output should contain a JSON object with `mcpServers`, inside it
a `marfor` entry whose `command` is the absolute path to Python and whose `args` hold the
absolute path to `server.py`. A short note in Russian goes to stderr and is not part of the
JSON. To get the JSON alone, read stdout only: append `2>/dev/null` in bash or `2>$null` in
PowerShell.

The configuration file:

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
- Linux (beta, the path may differ): `~/.config/Claude/claude_desktop_config.json`

Merge carefully, because the file may already hold other servers and settings:

1. If the file exists, first copy it next to itself as
   `claude_desktop_config.json.marfor-backup`.
2. Read and parse it as JSON. If it does not parse, stop and show the user what you found;
   do not overwrite it.
3. Add or replace only the `marfor` key inside `mcpServers`. Keep every other key and every
   other server exactly as it was.
4. If the file does not exist, create it with just the printed JSON.
5. Show the user the resulting content before you write it. Write valid UTF-8 JSON.

The result looks like this (paths will differ):

```
{
  "mcpServers": {
    "marfor": {
      "command": "/usr/bin/python3",
      "args": ["/Users/you/.marfor_mcp/server.py"]
    }
  }
}
```

## Step 8. Ask the user to restart the client

New MCP servers are picked up only at start, so the MARFOR tools will not appear in your
current session. That is expected.

- Claude Code: exit and start a new session.
- Claude Desktop: quit the app completely (Cmd+Q on macOS; Quit in the tray icon menu on
  Windows) and open it again. Closing the window is not enough.

## Step 9. First check in the new session

Tell the user to say this in the new session:

```
Call marfor_whoami, then marfor_guide.
```

In Russian it can be: «вызови marfor_whoami, затем marfor_guide».

`marfor_whoami` confirms which account is connected. `marfor_guide` explains how to work
with MARFOR: how to find projects and scenarios, how to read data, and the rules for
changes. Bulk budget edits have a dry run and go through it first. A single edit and the
BI dashboard tools have no dry run: before using them, tell the user exactly what will
change and go ahead only after an explicit yes.

If the account has no projects yet: the MCP server does not upload data. The user uploads
it in the web interface (https://marfor.pro) and then comes back to Claude.

## If something goes wrong

**Python is not found or is older than 3.8.** See step 1. Installing Python is the user's
action; continue from step 1 afterwards.

**On Windows, `python` opens the Microsoft Store or prints nothing.** That is a Windows
placeholder, not Python. Use `py -3` instead, for example
`py -3 "$HOME/.marfor_mcp/server.py" --check`.

**401 or "token is invalid"** in `--check` or in a tool answer. The access was revoked or
has expired. Repeat steps 5 and 6. The registration from step 7 stays as it is.

**The server is not visible in Claude.** In Claude Code the usual cause is that it was added
with the default `local` scope, which covers only the folder where the command was run.
`claude mcp get marfor` shows the scope. Remove the entry and add it again with the command
from step 7, then restart. In Claude Desktop, quit the app completely and open it again,
and make sure the paths in the config are absolute, as printed by `--print-config`.
Its MCP log is `~/Library/Logs/Claude/mcp-server-marfor.log` on macOS and
`%APPDATA%\Claude\logs\mcp-server-marfor.log` on Windows.

**`CERTIFICATE_VERIFY_FAILED`.** This happens on macOS with Python installed from
python.org: it needs its certificates installed once. Ask the user to open
`/Applications/Python 3.x/` and double-click "Install Certificates.command", then repeat
the step that failed.

**Browser sign-in is unavailable.** The sign: `--login-start` exits with code 1 and its
message contains `device_flow_unavailable` or points to `--set-token`. It means the
confirmation service on the site is not working right now. Fall back to a manual token.
The user opens https://marfor.pro/account and creates a token in the section about
connecting Claude. Then they run this in their own terminal, not through you:

```
python3 ~/.marfor_mcp/server.py --set-token
```

Windows, in PowerShell (not in Git Bash: hidden input does not work there):
`python "$HOME/.marfor_mcp/server.py" --set-token`

The command asks for the token with hidden keyboard input. Your shell tool has no keyboard
input, so the command refuses to run there, and this way the token never passes through
the chat. Do not offer to run it for the user and do not ask them to send you the token.
When the user says it is done, continue from step 6. The same steps, written for the user,
are at https://marfor.pro/mcp#manual-token.

**`--login-start` exits with code 1 and says there were too many attempts.** Wait 10 minutes
and start step 5 again.

**Anything else.** Show the user the exact error text and the output of step 6 (`--check`
prints no secrets). They can send both to support@marfor.pro.

## Updating and removing

To update, repeat steps 3 and 4 and restart the client. Sign-in and registration stay.

To remove: `claude mcp remove marfor --scope user` (or delete the `marfor` entry from the
Claude Desktop config), then `python3 ~/.marfor_mcp/server.py --logout` to delete the saved
token from this computer. The user can also revoke the access on their account page
(https://marfor.pro/account). Delete the `~/.marfor_mcp` folder only if the user asks for it.
