# Connect to Vamo

You are an AI agent, and the person you are working with wants to use Vamo
from their AI tool. Vamo finds software engineers by what they have built on
GitHub. There is more than one way to connect, and the right one depends on
where you are running. Work through the steps in order.

Until the person has chosen a way in (step 2), run no command, edit no file and
send nothing to Vamo. Some ways change files on their machine, and they should
know what will happen before it does.

Some fetch tools summarize or reword a page,
and that changes the blocks. If yours does, or a block looks cut off, read the
raw text first with `curl -fsSL https://vamotalent.ai/agents/connect.md` (`curl.exe`
in PowerShell) and work from that. In a chat app with no terminal, there are no
blocks for you to run, so a summary is fine.

## 1. Know where you are

Work this out from your own tools. Run nothing to find out.

- **A chat app or web agent with no terminal on the person's machine.**
  ChatGPT, Claude on the web, or an agent hosted in the cloud.
- **A desktop chat app.** Claude Desktop, for example. It can add connectors,
  and you usually cannot run commands on the machine.
- **A coding agent with a terminal on the person's machine.** Claude Code,
  Cursor, Codex, Gemini CLI and others like them.

If you cannot tell, ask the person this one question and wait for the answer:

> Which app are you talking to me in right now (for example ChatGPT, Claude,
> Claude Desktop, Claude Code, Cursor or Codex), and is it running on your own
> computer?

## 2. Offer the ways in, and let the person choose

Explain the choice in a few short lines, recommend one, and ask. A short
version is enough:

> There are two ways to connect Vamo here.
>
> 1. **Sign in from your tool (recommended).** You add Vamo's MCP server in
>    your tool's connector or MCP settings, then approve access on a Vamo page
>    in your browser. Nothing is stored on your machine by me, and there is no
>    key to handle.
> 2. **Save an API key on this machine.** I run one request that trades your
>    one-time setup code for a Vamo API key, then save the key in a private file
>    so later sessions, scripts and the Vamo skills can use it. I will tell you
>    exactly what I touch and wait for your yes first.
>
> Or, if you would rather ask questions before setting anything up, ask away.
>
> Which would you like?

Offer only what fits where you are:

- **Chat app or web agent:** only the sign-in way. You walk the person through
  the clicks in step 4. You run nothing yourself.
- **Desktop chat app:** the sign-in way. Offer the key way only when the person
  asks for it and you can run commands on their machine.
- **Claude Code, or another coding agent on the person's own machine:** both,
  and recommend the key way. The Vamo skills install there and call the Vamo
  API directly, so a stored key is what makes them work in every later
  session. Signing in as well is fine: it adds the Vamo tools to this
  conversation.
- **Coding agent with a terminal elsewhere** (hosted or in the cloud): both.
  Recommend signing in when your tool supports it (step 4 lists the ones that
  do). Recommend the key when the person wants Vamo from code or scripts, when
  your tool cannot sign in, or when they simply prefer it.

The difference, in plain words: the MCP server gives you Vamo tools to call
inside this conversation, and the person signs in once. An API key is a
credential on this machine for code and scripts, including the Vamo skills,
which call the Vamo API directly. The two can sit side by side.

If the person wants to ask questions first, answer them from
https://vamotalent.ai/learn/support/mcp-skills-and-the-api and the pages it
links to. Set nothing up until they choose a way.

If another Vamo page sent you here for an API key (the skills install page
does), the person has already chosen the key way. Say so in one line, then go
to step 5, which still asks for their yes.

## 3. The setup code

The message that sent you here may carry a setup code: one token that starts
with `vamo_xc_…`. It may read "use code …" or, in older lines, "follow the
instructions with code …" or "Setup code: …". All of them work. Take the token
wherever it sits.

- **On the sign-in way you do not need the code.** Say so plainly, and leave it
  unused. It runs out on its own.
- **On the key way it is what buys the key.** A code works once and lasts ten
  minutes. If it ran out, or there is none, the person copies a fresh setup
  prompt from Home in the Vamo dashboard at https://app.vamotalent.ai/setup/get-started and pastes it
  here.

Never ask the person for an API key, on either way.

## 4. Way A: sign in from your tool

The server address is:

```text
https://mcp.vamotalent.ai/mcp/search
```

If another Vamo setup prompt sent you here with an endpoint of its own, use that
address instead. It is on `mcp.vamotalent.ai` too.

The person adds it in their tool with no key and no header. Their browser then
opens a Vamo page, they sign in if asked, and they approve access. Where to add
it:

- **Claude on the web and Claude Desktop:** open Settings, then Connectors, and
  add a custom connector with the address above. Start a new conversation once
  it shows as connected.
- **ChatGPT:** open Settings, then Apps & Connectors. Turn on Developer mode
  under Advanced, choose Create and paste the address. On a company workspace
  an admin may have to allow this first.
- **Claude Code:** the command is
  `claude mcp add --transport http vamo https://mcp.vamotalent.ai/mcp/search`. Offer to run it, or let
  the person run it. Then they type `/mcp`, pick vamo and sign in.
- **Cursor, Codex, Gemini CLI and other tools:** sign-in works where the tool
  offers browser sign-in for a remote MCP server. Have the person add the
  address in the tool's MCP settings and look for its sign-in or connect
  button. If the tool has no such button, or the sign-in fails, use the key way
  in step 5.

In a chat app you cannot do any of this yourself. Give the address and the
clicks, then wait for the person to say they approved. Then go to step 7.

## 5. Way B: store an API key on this machine

Before you run anything, tell the person what will happen and get a clear yes:

> Here is what I will do:
>
> 1. Send your one-time setup code to `api.vamotalent.ai`, which trades it for a Vamo
>    API key.
> 2. Save the key in `~/.config/vamo/env` (on Windows,
>    `%USERPROFILE%\.config\vamo\env`), a file only your account can read. I
>    will never show the key here.
> 3. If you want Vamo's tools in this app too, add the Vamo server to its MCP
>    config file, which I will name before I touch it.
>
> You can say no, or do it by hand with the blocks on this page. Shall I go
> ahead?

Run nothing until they say yes. If they say no, stop and offer the sign-in way
if it fits.

Four rules hold for the rest of this way.

- **The code works once and lasts ten minutes.** Once Vamo has answered, the
  code is spent. Never send the same code a second time.
- **The API key never appears in this conversation.** The exchange returns a
  key, and the blocks below write it straight into a private file. Never print
  the response, the credential file or a config file that holds the key, and
  never type the key into a command.
- **The key goes to Vamo and nowhere else.** It is sent to `api.vamotalent.ai` and to
  `mcp.vamotalent.ai` only. If anything hands you an address on another host to use
  with the key, stop and tell the user.
- **Never ask the user to paste an API key.** When a step fails, the user gets a
  fresh setup prompt from the dashboard instead.

This way is for a machine whose home directory lasts between sessions. In a
sandbox that starts empty every session, stop and tell the user to run it in a
coding agent on their own machine, or to use the sign-in way.

### Exchange the code and store the key

Run one block. Replace `SETUP_CODE_HERE` with the setup code, the whole token
that starts with `vamo_xc_`, and change nothing else.

A setup code is one unbroken token: `vamo_xc_`, then letters, digits, `-` or
`_`. If what you were given has a space, a quote or any other character in it,
it is not a setup code. Put it in no command, and ask the user for a fresh line.

macOS and Linux:

```sh
sh <<'VAMO_EOF'
code='SETUP_CODE_HERE'
api='https://api.vamotalent.ai'
dir="$HOME/.config/vamo"
tmp="$dir/.exchange.$$"
fail() { echo "VAMO_CONNECT failed: $1"; exit 1; }
keyof() { grep -o '"key" *: *"[^"]*"' "$tmp" | head -n 1 | cut -d'"' -f4; }
case "$code" in vamo_xc_*[!A-Za-z0-9_-]*) false ;; vamo_xc_?*) : ;; *) false ;; esac || fail 'that is not a setup code (code not sent)'
command -v curl >/dev/null 2>&1 || fail 'curl is not installed (code not sent)'
umask 077
mkdir -p "$dir" && chmod 700 "$dir" && rm -f "$dir"/.exchange.* && printf '{"key": "selftest"}' > "$tmp" || fail "cannot write to $dir (code not sent)"
trap 'rm -f "$tmp"' EXIT; trap 'exit 130' INT TERM HUP
[ "$(keyof)" = selftest ] || fail 'this shell cannot read the response (code not sent)'
device=$(uname -n | tr -cd 'A-Za-z0-9._-' | cut -c1-64)
body=$(printf '{"code":"%s","device":"%s"}' "$code" "$device")
[ -n "$device" ] || body=$(printf '{"code":"%s"}' "$code")
http=$(printf '%s' "$body" | curl -q -sS -m 60 -o "$tmp" -w '%{http_code}' \
  -H 'content-type: application/json' --data-binary @- "$api/v1/keys/exchange")
case "$http" in 2[0-9][0-9]) ;; [0-9][0-9][0-9]) fail "status $http" ;; *) fail 'curl gave no status' ;; esac
key=$(keyof)
printf '%s' "$key" | grep -Eq '^vamo_sk_[A-Za-z0-9_]+$' || fail 'the response had no key'
printf 'VAMO_API_KEY=%s\n' "$key" > "$dir/env" && chmod 600 "$dir/env" || fail "cannot write $dir/env"
echo 'VAMO_CONNECT ok'
grep -Eo '"(label|apiBaseUrl|mcpUrl)" *: *"[^"]*"' "$tmp"
grep -o '"permissions" *: *\[[^]]*]' "$tmp"
VAMO_EOF
```

Windows, in PowerShell. Use this block even when a bash shell is available,
because only it can limit the file to the user's account. If your shell tool
only runs bash, save the block as a `.ps1` file in the temp folder, run
`powershell -NoProfile -ExecutionPolicy Bypass -File <that file>`, then delete
the file.

```powershell
& {
  $code = 'SETUP_CODE_HERE'
  $api = 'https://api.vamotalent.ai'
  $ErrorActionPreference = 'Stop'
  $dir = Join-Path $env:USERPROFILE '.config\vamo'
  $envFile = Join-Path $dir 'env'
  if ($code -cnotmatch '^vamo_xc_[A-Za-z0-9_-]+$') { 'VAMO_CONNECT failed: that is not a setup code (code not sent)'; return }
  try {
    $sid = [Security.Principal.WindowsIdentity]::GetCurrent().User.Value
    New-Item -ItemType Directory -Force -Path $dir | Out-Null
    icacls $dir /inheritance:r /grant:r "*${sid}:(OI)(CI)F" | Out-Null
    if ($LASTEXITCODE -ne 0) { throw 'icacls failed' }
  } catch { "VAMO_CONNECT failed: cannot prepare $dir (code not sent)"; return }
  [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
  $body = @{ code = $code; device = [Environment]::MachineName } | ConvertTo-Json -Compress
  try {
    $r = Invoke-RestMethod -Method Post -Uri "$api/v1/keys/exchange" -ContentType 'application/json' -Body $body -TimeoutSec 60
  } catch {
    $http = '000'
    if ($_.Exception.Response) { $http = [int]$_.Exception.Response.StatusCode }
    "VAMO_CONNECT failed: status $http"; return
  }
  if ("$($r.key)" -notmatch '^vamo_sk_[A-Za-z0-9_]+$') { 'VAMO_CONNECT failed: the response had no key'; return }
  try {
    [IO.File]::WriteAllText($envFile, "VAMO_API_KEY=$($r.key)`n")
    icacls $envFile /inheritance:r /grant:r "*${sid}:F" | Out-Null
  } catch { "VAMO_CONNECT failed: cannot write $envFile"; return }
  'VAMO_CONNECT ok'
  $r | Select-Object label, apiBaseUrl, mcpUrl, permissions | ConvertTo-Json -Compress
}
```

The key is now in `~/.config/vamo/env`, or `%USERPROFILE%\.config\vamo\env` on
Windows, as one line: `VAMO_API_KEY=...`. Only this user can read the file. That
is where the key lives on this machine. Never copy it into a project `.env`, a
shell profile or the repository.

Read what the block printed.

| It printed | What happened | Do this |
| --- | --- | --- |
| `VAMO_CONNECT ok` | The key is stored. The lines after it give `label`, `apiBaseUrl`, `mcpUrl` and `permissions` | Go to step 6, or to step 7 if the person wants no MCP server in this app |
| `failed: status 404` | The code was already used, has expired, or was replaced by a newer one | Tell the user: "That setup code is no longer valid. Copy a fresh setup prompt from Home in the Vamo dashboard at https://app.vamotalent.ai/setup/get-started and paste it here." Then stop |
| `failed: status 000` | The request never reached Vamo | Get outbound HTTPS to `api.vamotalent.ai` allowed, then run the block again |
| `failed: status 429` | Too many attempts came from this network | Wait a minute, then run the block again |
| `failed: ... (code not sent)` | Nothing was sent, so the code is still good | Fix what the line names and run the block again. Not a setup code: the placeholder is still there, or what replaced it has a character a code never has. Copy the code again from the user's message with nothing around it. No `curl`: install it with the system package manager, such as `sudo apt-get install -y curl`. Cannot write: your shell is sandboxed, so ask the user to approve running the block outside the sandbox. Cannot read the response: the block changed in copying, so fetch this page again as raw text and run it unchanged. If it fails the same way, stop and report it. Never store the key somewhere else instead, and never swap in a tool that prints the response |
| Anything else | The exchange did not finish | Report the exact line, then ask the user for a fresh setup prompt from Home at https://app.vamotalent.ai/setup/get-started |

## 6. Way B, continued: add the Vamo server with the stored key

Do this only if the person wants Vamo's tools in this app. Name the file or
command you will change before you change it. A person who only wants the key
for code, scripts or the skills can skip to step 7.


`label` reads like `Cursor on this-machine`. Its first words name the tool the
user picked in the dashboard. Set up that tool, with the `mcpUrl` the block
printed in place of `MCP_URL_HERE`. If no `mcpUrl` was printed, go to step 7.
When the label starts with `Other client`, the user did not pick a tool: set up
the tool you are running in. If you cannot tell which tool that is, or the label
names a tool you do not recognize, ask the user which tool to set up.

If another setup prompt gave you an endpoint of its own for this step, use that
endpoint as `mcpUrl`. When the key was already stored there is no label: set up
the tool you are running in.

Whichever it is, `mcpUrl` is on `mcp.vamotalent.ai`. Add no server on another host
with this key.

Each block reads the key from the credential file, so the key is never part of
a command you type. If a block fails because your shell is sandboxed, ask the
user to approve running it outside the sandbox.

### Claude Code

Claude Code only takes the header as a command argument, so the key is in that
one command's arguments while it runs. It keeps the header, as plain text, in
its own user config (`~/.claude.json`). The block discards the command's output
on purpose.

macOS and Linux:

```sh
sh <<'VAMO_EOF'
command -v claude >/dev/null 2>&1 || { echo 'VAMO_MCP failed: claude is not on PATH'; exit 1; }
. "$HOME/.config/vamo/env"
[ -n "$VAMO_API_KEY" ] || { echo 'VAMO_MCP failed: no stored key'; exit 1; }
claude mcp remove vamo --scope local >/dev/null 2>&1
claude mcp remove vamo --scope user >/dev/null 2>&1
claude mcp add --transport http --scope user vamo 'MCP_URL_HERE' \
  --header "Authorization: Bearer $VAMO_API_KEY" >/dev/null 2>&1 \
  && echo 'VAMO_MCP ok' || echo 'VAMO_MCP failed'
VAMO_EOF
```

Windows:

```powershell
& {
  $ErrorActionPreference = 'Continue'
  if (-not (Get-Command claude -ErrorAction SilentlyContinue)) { 'VAMO_MCP failed: claude is not on PATH'; return }
  $line = Get-Content (Join-Path $env:USERPROFILE '.config\vamo\env') | Where-Object { $_ -like 'VAMO_API_KEY=*' } | Select-Object -First 1
  $key = "$line" -replace '^VAMO_API_KEY=', ''
  if (-not $key) { 'VAMO_MCP failed: no stored key'; return }
  claude mcp remove vamo --scope local *> $null
  claude mcp remove vamo --scope user *> $null
  $global:LASTEXITCODE = 1
  claude mcp add --transport http --scope user vamo 'MCP_URL_HERE' --header "Authorization: Bearer $key" *> $null
  if ($LASTEXITCODE -eq 0) { 'VAMO_MCP ok' } else { 'VAMO_MCP failed' }
}
```

- Never use `--scope project`. It writes the key into `.mcp.json` in the
  repository.
- Never run `claude mcp get vamo`. It prints the header. `claude mcp list` is
  safe, and shows whether the server connects.
- If the block prints `VAMO_MCP failed`, report it. Never run the `add` again
  with its output showing, because that output carries the header.
- The tools load in the next Claude Code session.

### Codex

Codex takes the key from an environment variable, so its config never holds
it. Codex loads `~/.codex/.env` when it starts. The block copies the key line
into that file, from one file to the other, then names the variable to Codex.

macOS and Linux:

```sh
sh <<'VAMO_EOF'
umask 077
new="$HOME/.codex/.env.vamo-tmp"
mkdir -p "$HOME/.codex" && touch "$HOME/.codex/.env" \
  && { grep -v '^VAMO_API_KEY=' "$HOME/.codex/.env"; grep '^VAMO_API_KEY=' "$HOME/.config/vamo/env"; } > "$new" \
  && mv "$new" "$HOME/.codex/.env" && echo 'VAMO_MCP ok' || { rm -f "$new"; echo 'VAMO_MCP failed'; }
VAMO_EOF
codex mcp add vamo --url 'MCP_URL_HERE' --bearer-token-env-var VAMO_API_KEY
```

Windows:

```powershell
& {
  $ErrorActionPreference = 'Stop'
  $line = Get-Content (Join-Path $env:USERPROFILE '.config\vamo\env') | Where-Object { $_ -like 'VAMO_API_KEY=*' } | Select-Object -First 1
  if (-not $line) { 'VAMO_MCP failed: no stored key'; return }
  $dst = Join-Path $env:USERPROFILE '.codex\.env'
  New-Item -ItemType Directory -Force -Path (Split-Path $dst) | Out-Null
  $keep = @()
  if (Test-Path $dst) { $keep = @(Get-Content $dst | Where-Object { $_ -notlike 'VAMO_API_KEY=*' }) }
  [IO.File]::WriteAllText($dst, (($keep + $line) -join "`n") + "`n")
  'VAMO_MCP ok'
}
codex mcp add vamo --url 'MCP_URL_HERE' --bearer-token-env-var VAMO_API_KEY
```

The server loads the next time Codex starts.

### Cursor, Gemini CLI, Claude Desktop and other tools with a config file

These tools keep the header, as plain text, in their own config file. That file
may already hold a Vamo key from an earlier setup, so change it in three moves,
in this order.

1. **Before you open the file, run the first block.** It puts the placeholder
   `__VAMO_API_KEY__` where any Vamo key is. Open the file only after it prints
   `VAMO_MCP ready`.
2. **Add or correct the entry with your file tools.** Keep everything else the
   file holds, and write the placeholder where the key goes. If another entry
   shows the placeholder too, it held a Vamo key of its own and gets the same
   key in the next move. Name that entry in your report.
3. **Run the second block.** It puts the stored key in place of the
   placeholder. After it prints `VAMO_MCP ok`, never open, print or diff that
   file. To change the entry later, start again at 1.

Cursor, in `~/.cursor/mcp.json`. Use this file in the home directory, never
`.cursor/mcp.json` inside a project:

```json
{
  "mcpServers": {
    "vamo": {
      "url": "MCP_URL_HERE",
      "headers": { "Authorization": "Bearer __VAMO_API_KEY__" }
    }
  }
}
```

Gemini CLI, in `~/.gemini/settings.json`. Use this file in the home directory,
never `.gemini/settings.json` inside a project. Gemini CLI names the address of
a Streamable HTTP server `httpUrl`:

```json
{
  "mcpServers": {
    "vamo": {
      "httpUrl": "MCP_URL_HERE",
      "headers": { "Authorization": "Bearer __VAMO_API_KEY__" }
    }
  }
}
```

Claude Desktop, in `~/Library/Application Support/Claude/claude_desktop_config.json`
on macOS and `%APPDATA%\Claude\claude_desktop_config.json` on Windows. It
reaches a remote server through `mcp-remote`, which needs Node.js:

```json
{
  "mcpServers": {
    "vamo": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "MCP_URL_HERE", "--header", "Authorization:${AUTH_HEADER}"],
      "env": { "AUTH_HEADER": "Bearer __VAMO_API_KEY__" }
    }
  }
}
```

Any other tool: a remote MCP server over Streamable HTTP at `mcpUrl`, with the
header `Authorization: Bearer __VAMO_API_KEY__`, in that tool's own config for
this user.

The first block on macOS and Linux. Set `f` to the config file, the same in
both blocks:

```sh
sh <<'VAMO_EOF'
f="$HOME/.cursor/mcp.json"
# Gemini CLI: f="$HOME/.gemini/settings.json"
# Claude Desktop: f="$HOME/Library/Application Support/Claude/claude_desktop_config.json"
fail() { echo "VAMO_MCP failed: $1"; exit 1; }
grep -q '^VAMO_API_KEY=.' "$HOME/.config/vamo/env" 2>/dev/null || fail 'no stored key'
[ -L "$f" ] && fail 'that file is a symlink, so it may live in a shared folder. Ask the user first. If they agree, set f to the file it points to and run this again'
umask 077
if grep -q 'vamo_sk_' "$f" 2>/dev/null; then
  sed 's/vamo_sk_[A-Za-z0-9_]*/__VAMO_API_KEY__/g' "$f" > "$f.vamo-tmp" && mv "$f.vamo-tmp" "$f" || { rm -f "$f.vamo-tmp"; fail 'cannot rewrite that file'; }
fi
echo 'VAMO_MCP ready'
VAMO_EOF
```

The first block on Windows:

```powershell
& {
  $ErrorActionPreference = 'Stop'
  $f = Join-Path $env:USERPROFILE '.cursor\mcp.json'
  # Gemini CLI: $f = Join-Path $env:USERPROFILE '.gemini\settings.json'
  # Claude Desktop: $f = Join-Path $env:APPDATA 'Claude\claude_desktop_config.json'
  $line = Get-Content (Join-Path $env:USERPROFILE '.config\vamo\env') | Where-Object { $_ -like 'VAMO_API_KEY=?*' } | Select-Object -First 1
  if (-not $line) { 'VAMO_MCP failed: no stored key'; return }
  if (Test-Path $f) {
    $text = [IO.File]::ReadAllText($f)
    if ($text -cmatch 'vamo_sk_') { [IO.File]::WriteAllText($f, ($text -creplace 'vamo_sk_[A-Za-z0-9_]*', '__VAMO_API_KEY__')) }
  }
  'VAMO_MCP ready'
}
```

The second block on macOS and Linux:

```sh
sh <<'VAMO_EOF'
f="$HOME/.cursor/mcp.json"
# Gemini CLI: f="$HOME/.gemini/settings.json"
# Claude Desktop: f="$HOME/Library/Application Support/Claude/claude_desktop_config.json"
fail() { echo "VAMO_MCP failed: $1"; exit 1; }
. "$HOME/.config/vamo/env"
[ -n "$VAMO_API_KEY" ] || fail 'no stored key'
[ -L "$f" ] && fail 'that file is a symlink, so it may live in a shared folder. Ask the user first. If they agree, set f to the file it points to and run this again'
grep -q '__VAMO_API_KEY__' "$f" || fail 'no __VAMO_API_KEY__ placeholder in that file'
umask 077
printf 's/__VAMO_API_KEY__/%s/g\n' "$VAMO_API_KEY" | sed -f /dev/stdin "$f" > "$f.vamo-tmp" && mv "$f.vamo-tmp" "$f" && chmod 600 "$f" || { rm -f "$f.vamo-tmp"; fail 'cannot rewrite that file'; }
echo 'VAMO_MCP ok'
VAMO_EOF
```

The second block on Windows:

```powershell
& {
  $ErrorActionPreference = 'Stop'
  $f = Join-Path $env:USERPROFILE '.cursor\mcp.json'
  # Gemini CLI: $f = Join-Path $env:USERPROFILE '.gemini\settings.json'
  # Claude Desktop: $f = Join-Path $env:APPDATA 'Claude\claude_desktop_config.json'
  $line = Get-Content (Join-Path $env:USERPROFILE '.config\vamo\env') | Where-Object { $_ -like 'VAMO_API_KEY=*' } | Select-Object -First 1
  $key = "$line" -replace '^VAMO_API_KEY=', ''
  $text = [IO.File]::ReadAllText($f)
  if (-not $key -or -not $text.Contains('__VAMO_API_KEY__')) { 'VAMO_MCP failed: no stored key, or no __VAMO_API_KEY__ placeholder in that file'; return }
  [IO.File]::WriteAllText($f, $text.Replace('__VAMO_API_KEY__', $key))
  'VAMO_MCP ok'
}
```

The server loads after the tool restarts. Claude Desktop has to be quit fully
and opened again.

## 7. Verify

One check, for the way the person chose.

**Sign-in way.** Reload your MCP servers or start a new conversation if the
Vamo tools are not there yet. You should see `search`, `similar`, `enrich` and
`deep_research`. Call `search` once with a tiny request, such as
`{"filters":["location_ids","ContainsAny",{"place":["Berlin"]}],"sort":"devrank","limit":1}`.
A good result is one line for one real person: their GitHub login, name, title
and company, location, devRank and why they matched.

**Key way.** One read of the account the key belongs to. It changes nothing.
Only the status is printed.

macOS and Linux:

```sh
sh <<'VAMO_EOF'
. "$HOME/.config/vamo/env"
printf 'header = "Authorization: Bearer %s"\n' "$VAMO_API_KEY" | curl -q -sS -m 60 -K - \
  -o /dev/null -w 'VAMO_VERIFY status %{http_code}\n' 'https://api.vamotalent.ai/v1/me'
VAMO_EOF
```

Windows:

```powershell
& {
  $line = Get-Content (Join-Path $env:USERPROFILE '.config\vamo\env') | Where-Object { $_ -like 'VAMO_API_KEY=*' } | Select-Object -First 1
  $key = "$line" -replace '^VAMO_API_KEY=', ''
  [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
  $http = 200
  try { Invoke-RestMethod -Uri 'https://api.vamotalent.ai/v1/me' -Headers @{ Authorization = "Bearer $key" } -TimeoutSec 60 | Out-Null }
  catch { $http = '000'; if ($_.Exception.Response) { $http = [int]$_.Exception.Response.StatusCode } }
  "VAMO_VERIFY status $http"
}
```

`200` means the key works. `401` means the key did not reach Vamo or was
revoked: report it and ask the user for a fresh line. `000` means the network
blocked the request: get `api.vamotalent.ai` allowed and run the check again.

## 8. Done

When the check passes, tell the person, warmly and in a few lines:

> **You're connected to Vamo.**
>
> What to do next:
>
> - **Try a first search.** Ask me "Find the strongest engineers at
>   <company>" or "Rust developers in Berlin who build databases".
> - **Learn more** in the Vamo docs and tutorials: https://vamotalent.ai/learn

Then, if your tool can hold skills, install the Vamo skills. Say so in one line
first, and skip it only if the person says no. They teach you Vamo's search
methods, so results come out the same way every time. Use the way your tool
installs them:

- **Claude Code:** run, in your shell,
  `claude plugin marketplace add vamo-ai/vamo-skills && claude plugin install vamo@vamo-skills`.
  If `claude` has no `plugin` command, ask the person to type
  `/plugin marketplace add vamo-ai/vamo-skills`, then
  `/plugin install vamo@vamo-skills`.
- **Claude on the web or desktop:** the person opens **Customize**, then
  **Plugins**, **Add**, **Add marketplace**, enters `vamo-ai/vamo-skills` and
  installs **vamo**.
- **Codex, Cursor or Gemini CLI:** run
  `npx skills add vamo-ai/vamo-skills -g -a <codex|cursor|gemini-cli> -y`.
- **ChatGPT:** skills are for Business, Enterprise and Edu workspaces, and a
  workspace admin imports them. Mention it in one line and move on.
- **Any other tool that reads skills:** follow https://vamotalent.ai/skills/install.md.

If your tool cannot hold skills, skip this offer. Say that new skills and
connectors load in a new session or after a restart.

Add, on the key way, the key's `permissions` and that the key is stored on this
machine and was never shown. On the sign-in way, add that the person can see
and remove this tool on the API keys page in the Vamo dashboard. If you added
the server to a tool, say it loads after that tool restarts.

Never include the key, and never offer to show it.

## 9. If something goes wrong

- **The setup code expired or was already used** (`failed: status 404`). The
  person copies a fresh setup prompt from Home at https://app.vamotalent.ai/setup/get-started.
- **The sign-in page did not open.** Check that the address was pasted whole,
  then try the tool's connect or sign-in button again. Some company accounts
  block custom connectors: see https://vamotalent.ai/learn/support/cant-add-vamo.
- **The Vamo page says the plan or role does not include connecting tools.**
  An owner or admin of the Vamo account can change that. See
  https://vamotalent.ai/learn/support/sign-in-fails-or-plan-not-included.
- **`401` or `403` with a stored key.** The key was revoked, or lacks that
  access. Get a fresh setup prompt from Home and run step 5 again, or switch to
  the sign-in way.
- **The tool cannot reach the server.** Check the address for typos: it must be
  on `mcp.vamotalent.ai`. A company proxy or firewall may block it: get `mcp.vamotalent.ai`
  and `api.vamotalent.ai` allowed.
- **Deep research asks for GitHub.** It runs on the person's own GitHub
  connection. Open the link the error gives, or connect GitHub at
  https://app.vamotalent.ai/setup/connections, then run it again.
- **Something else.** Fetch https://vamotalent.ai/agent-setup/check.md and follow it. It
  checks the whole setup and names what to fix.
