oxylabs/web-api-mcp

GitHub ↗ · How this check works

Per-setup public labels: Linux / Haiku: Not tested · Linux / Luna: Not tested

Static status badge · SVG · read-only JSON. Embed with ![Coldpass status](https://coldpass.dev/badge/oxylabs--web-api-mcp.svg).

mcp-server

Not tested

The saved checks do not establish a current product result.

Answers apply to each recorded setup, revision and operation. Earlier observations remain in Run details.

Tested on Linux
PlatformHaikuLuna
Linuxnot testednot tested

Linux / Haiku 5.5: not tested · Oct 23, 2026 · 895116f090cc · claude-code / 2.1.300 (Claude Code)
Recorded operation: <guest-path> · local stdio MCP start + initialize + tools/list

Linux / Luna: not tested · Oct 23, 2026 · 895116f090cc · codex / codex-cli 0.163.0
Recorded operation: /tmp/oxylabs-venv/bin/oxylabs-web-api-mcp · local stdio MCP start + initialize + tools/list

Does what it says
0 of 1 claims checked out
  • Web API tools require an API key to call the service.: Real input did not produce the expected result: No Oxylabs Web API key

    Source: An Oxylabs Web API key — in the [Oxylabs dashboard](https://dashboard.oxylabs.io), create

    Input: {"tool": "list_scrapers", "arguments": {}}

    Expected: No Oxylabs Web API key

    Command: /tmp/oxylabs-venv/bin/oxylabs-web-api-mcp tools/call {"tool": "list_scrapers", "arguments": {}}

    Observed: No Oxylabs Web API key. Send it as an 'Authorization: <secret><key>' header, or set OXYLABS_WEB_API_KEY in the server environment (see .env.example) and restart the MCP server.", "type": "text"}], "isError": true}

MCP
Yes, observed
Local or hosted
local
Local: runs on your machine
Maintained
Maintained
actively maintained: last commit 8 days ago; 42 commits and 10 merged PRs in 90 days; 1 open issues, 1 open PRs; 0 of 4 recent threads got a maintainer reply; no releases

Last commit Oct 15, 2026

Issue
not tested
Examples
1 of 1 ran as expected
  • README development test suite: command completed successfully

    Source: README.md, Development

    Input: offline pytest suite

    Expected: tests pass

    Command: /tmp/oxylabs-venv/bin/python -m pytest

    Observed: ============================= test session starts ============================== platform linux -- Python 3.12.3, pytest-9.1.1, pluggy-1.7.0 rootdir: <guest-path> configfile: pyproject.toml testpaths: tests plugins: anyio-4.15.1, platformdirs-4.13.5 collected 75 items tests/test_server.py ................................................... [ 68%] ........................ [100%] ============================== 75 passed in 3.93s ==============================

Evidence
some README behavior checked
Agent interfaces
MCP
MCP

Observed interfaces were exercised by the checker. Documentation alone does not confirm compatibility.

MCP context
6 tools · about 2,884 tokens
6 tools · about 2,884 tokens

Largest returned tools/list page in these observations. Compact UTF-8 definition bytes ÷ 4, rounded up; approximate, excluding client framing and tool results. This is context size, not proof that every tool works.

Measured on linux with Luna · Oct 23, 2026 on 895116f090cc

Tested with
Codex / Luna
  • Linux: Codex / Luna · agent codex-cli 0.163.0 · Not tested · Oct 23, 2026 on 895116f090cc

Each entry describes its recorded operation and source revision. Other agent clients were not tested.

Safety
No unexpected network or file activity found in these checks

No problems traced to this repository code in these checks; a short run cannot prove safety.

Full event, path and process lists for each observed setup:

Run details

Haiku 5.5

Native agent · Not tested

Operation / attempted scope <guest-path> · local stdio MCP start + initialize + tools/list

Agent-reported scope: Run the Oxylabs Web API MCP server over stdio and call its tools (search, scrape) against the live Oxylabs API

MCP server returned: oxylabs-web-api · version 0.1.0.

MCP tools returned: search, scrape, check_scrape, read_scraped, list_scrapers, scrape_target. Tool listing does not establish authenticated tool-call success.

Run details
run
oxylabs--web-api-mcp-claude-haiku-5-5-1792777780162059126
date
Oct 23, 2026
time to working
not recorded
product hosting / execution
Local stdio MCP server in the guest
recorded operation scope
product operation
model
claude-haiku-5-5
agent / version
claude-code / 2.1.300 (Claude Code)
platform
linux
reported cost
$0.021856
Recorded source
https://github.com/oxylabs/web-api-mcp
Backend
hyperv
Tool transport
mcp-assigned-vm
Requested source pin (not an observed revision)
{"commit": "895116f090cc83258a5a7b1079aaca5e9207d7ee", "url": "https://github.com/oxylabs/web-api-mcp"}
Test version
readme-bdc1b9b3c0d2673aef87e076d14084a8123ddcf09d520c1ee2e364a37c3f4bb9
revision
895116f090cc83258a5a7b1079aaca5e9207d7ee
Whose fault: prerequisite · diagnosed

No Oxylabs Web API key in the guest

Recorded blocker / warning

Step: Calling the search or scrape tool, which needs OXYLABS_WEB_API_KEY

No Oxylabs Web API key in the guest

Safety: No problems traced to this repository code in these checks.

No problems traced to this repository code in these checks.

OSV scanned supported lockfiles; unpinned dependencies and unsupported formats are outside this check.

A short run cannot establish that code is safe.

Connections show IP addresses; proxies can hide the final hostname.

Tracing covers dispatched commands and their children, not the whole OS; guest root can interfere with tracing.

Full safety evidence →

Answers recorded for this run
  • read_scraped reads an offloaded page in chunks: Real input produced the expected result: Chunk two of the off

    Source: Read a large page that was offloaded to disk, in chunks

    Input: {"tool": "read_scraped", "arguments": {"path": "<guest-path>", "offset": 26, "length": 20}}

    Expected: returns the chunk starting at offset 26

    Command: <guest-path> tools/call {"tool": "read_scraped", "arguments": {"path": "<guest-path>", "offset": 26, "length": 20}}

    Observed: Chunk two of the off\"}", "type": "text"}], "isError": false, "structuredContent": {"path": "<guest-path>", "offset": 26, "returned_chars": 20, "total_chars": 59, "next_offset": 46, "eof": false, "text": "Chunk two of the off"}}

  • search needs a live Oxylabs key and returns ranked results: Needs a real OXYLABS_WEB_API_KEY and live API access; none is available in this guest. A no-key call returned isError 'No Oxylabs Web API key'.

    Source: Search the live web, returns ranked organic results (title, description, URL)

    Observed: Needs a real OXYLABS_WEB_API_KEY and live API access; none is available in this guest. A no-key call returned isError 'No Oxylabs Web API key'.

  • the key is required on stdio: Needs a real Oxylabs key to show a working call; the no-key error path was observed (search returned isError: No Oxylabs Web API key) but no key was supplied.

    Source: *(required on stdio)*

    Observed: Needs a real Oxylabs key to show a working call; the no-key error path was observed (search returned isError: No Oxylabs Web API key) but no key was supplied.

Examples

  • lint passes: command completed successfully

    Source: README.md / ## Development

    Input: ruff check .

    Expected: All checks passed!

    Command: <guest-path> check .

    Observed: All checks passed!

  • formatting is clean: command completed successfully

    Source: README.md / ## Development

    Input: ruff format --check .

    Expected: already formatted

    Command: <guest-path> format --check .

    Observed: 5 files already formatted

  • offline test suite passes: command completed successfully

    Source: README.md / ## Development

    Input: pytest

    Expected: 75 passed

    Command: <guest-path> -q

    Observed: ........................................................................ [ 96%] ... [100%] 75 passed in 4.02s

Local or hosted: local

Suggested next step (agent-reported): Provide OXYLABS_WEB_API_KEY in the guest (or a per-request Bearer header) and rerun a search and a scrape call against the live API.

What the agent did

Run the Oxylabs Web API MCP server over stdio and call its tools (search, scrape) against the live Oxylabs API

cd <guest-path> && pwd && ls -la && id -u && python3 --version && cat /etc/os-release | head -3 && (git -C . rev-parse HEAD 2>&1 | head -1)
cd <guest-path> && cat README.md 2>/dev/null | head -300
cd <guest-path> && ls -la .coldpass scripts tests src; cat pyproject.toml; cat .env.example; which uv pipx pip3 git; python3 -m venv --help >/dev/null 2>&1 && echo venv_ok || echo venv_missing
cd <guest-path> && git init -q && git remote add origin https://github.com/oxylabs/web-api-mcp && timeout 120 git fetch --depth 1 origin 895116f090cc83258a5a7b1079aaca5e9207d7ee; echo "fetch rc=$?"; git reset --mixed FETCH_HEAD 2>&1; git log --oneline -1 2>&1; git status --short | head
cd /tmp && python3 -m venv <guest-path> && <guest-path> --version && cd <guest-path> && timeout 900 <guest-path> install -q -e '.[dev]' 2>&1 | tail -20; echo "rc=${PIPESTATUS[0]}"; ls <guest-path> | grep -E 'oxylabs|pytest|ruff'
rm -rf <guest-path>; sudo -n apt-get update -qq 2>&1 | tail -3; sudo -n DEBIAN_FRONTEND=noninteractive apt-get install -y -qq python3.12-venv 2>&1 | tail -3; echo "rc=${PIPESTATUS[0]}"; cd /tmp && python3 -m venv <guest-path> && <guest-path> --version
cd <guest-path> && timeout 900 <guest-path> install -q -e '.[dev]' 2>&1 | tail -20; echo "rc=${PIPESTATUS[0]}"; ls <guest-path> | grep -E 'oxylabs|pytest|ruff'
cd <guest-path> && V=<guest-path>; $V/ruff check . ; echo "ruff check rc=$?"; $V/ruff format --check . ; echo "ruff format rc=$?"; timeout 600 $V/pytest -q 2>&1 | tail -15; echo "pytest rc=${PIPESTATUS[0]}"
cd <guest-path> && ls -R src | head -30 && grep -n "def \<email>\<email>\|OXYLABS_WEB_API_KEY\|credentials" src/oxylabs_web_api_mcp/server.py | head -80
ls -la <guest-path> /inputs/ 2>&1 | head; cd <guest-path> && sed -n 217,237p src/oxylabs_web_api_mcp/server.py; env | grep -i -E 'proxy|oxylabs' | sed 's/=.*/=<set>/'; sed -n 1446,1470p src/oxylabs_web_api_mcp/server.py
cd <guest-path> && sed -n 522,550p src/oxylabs_web_api_mcp/server.py; sed -n 1212,1253p src/oxylabs_web_api_mcp/server.py
cd <guest-path> && grep -n "def \|mcp_http\|'mcp'\|\"mcp\"\|credentials_error\|env" check.py | head -150
cd <guest-path> && sed -n 350,362p check.py; sed -n 384,444p check.py; sed -n 788,856p check.py
cd <guest-path> && sed -n 1168,1204p check.py; sed -n 856,870p check.py; sed -n 935,960p check.py; sed -n 1273,1300p check.py
mkdir -p <guest-path> <guest-path> && cat > <guest-path> <<'EOF'
import json, subprocess, sys, os
argv = json.loads(sys.argv[1]); tool = sys.argv[2]; args = json.loads(sys.argv[3])
p = subprocess.Popen(argv, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
def send(d): p.stdin.write(json.dumps(d)+"\n"); p.stdin.flush()
def recv():
    while True:
        line = p.stdout.readline()
        if not line: return None
        try: d = json.loads(line)
        except ValueError: continue
        return d
send({"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"1"}}})
print("init:", json.dumps(recv().get("result",{}).get("serverInfo")))
send({"jsonrpc":"2.0","method":"notifications/initialized"})
send({"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}})
r = recv(); print("tools:", [t["name"] for t in r["result"]["tools"]])
send({"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":tool,"arguments":args}})
print("call:", json.dumps(recv(), ensure_ascii=False)[:1500])
p.stdin.close(); p.terminate()
EOF
cd <guest-path> && V=<guest-path>; 
echo "--- search without key (env key unset)"; env -u OXYLABS_WEB_API_KEY timeout 60 <guest-path> -I mcp_call.py '["<guest-path>"]' search '{"query":"oxylabs"}' 2>&1 | tail -5
echo "--- fixture + read_scraped"; printf 'Oxylabs fixture line one.\nChunk two of the offloaded page.\n' > <guest-path>
OXYLABS_SPILL_DIR=<guest-path> timeout 60 <guest-path> -I mcp_call.py '["<guest-path>"]' read_scraped '{"path":"<guest-path>","length":200}' 2>&1 | tail -5
cd <guest-path> && sed -i 's/        return d$/        if d.get("id") is None and "method" in d: continue\n        return d/' mcp_call.py && env -u OXYLABS_WEB_API_KEY timeout 60 <guest-path> -I mcp_call.py '["<guest-path>"]' search '{"query":"oxylabs"}' 2>&1 | tail -2 | cut -c1-900
cd <guest-path> && grep -n -i "cron\|schedule\|sleep\|--once\|--now\|webhook\|interval" src/oxylabs_web_api_mcp/server.py | head; echo ---; grep -n -F "Read a large page that was offloaded to disk, in chunks" README.md; grep -n -F "*(required on stdio)*" README.md | cut -c1-120; grep -n -F "## Development" README.md; grep -n -F "Read a single URL as" README.md | cut -c1-80
cd <guest-path> && V=<guest-path> && cat > probe.json <<EOF
{"kind":"mcp","argv":["$V"],"cwd":"<guest-path>","env":{"OXYLABS_SPILL_DIR":"<guest-path>"},"tool":"read_scraped","arguments":{"path":"<guest-path>","offset":0,"length":200},"expected_text":"Chunk two of the offloaded page."}
EOF
cat > claims.json <<EOF
[
 {"kind":"claim","claim":"read_scraped reads an offloaded page in chunks","source":"Read a large page that was offloaded to disk, in chunks","input":"fixture page in spill dir, offset 26, length 20","expected":"returns the chunk starting at offset 26","probe_kind":"mcp","argv":["$V"],"env":{"OXYLABS_SPILL_DIR":"<guest-path>"},"tool":"read_scraped","arguments":{"path":"<guest-path>","offset":26,"length":20},"expected_text":"Chunk two of the off","cwd":"<guest-path>"},
 {"kind":"claim","claim":"search needs a live Oxylabs key and returns ranked results","source":"Search the live web, returns ranked organic results (title, description, URL)","testable":false,"reason":"Needs a real OXYLABS_WEB_API_KEY and live API access; none is available in this guest. A no-key call returned isError 'No Oxylabs Web API key'."},
 {"kind":"claim","claim":"the key is required on stdio","source":"*(required on stdio)*","testable":false,"reason":"Needs a real Oxylabs key to show a working call; the no-key error path was observed (search returned isError: No Oxylabs Web API key) but no key was supplied."}
]
EOF
cat > examples.json <<'EOF'
[
 {"kind":"example","claim":"lint passes","source":"README.md / ## Development","input":"ruff check .","expected":"All checks passed!","argv":["<guest-path>","check","."],"cwd":"<guest-path>","expected_text":"All checks passed!"},
 {"kind":"example","claim":"formatting is clean","source":"README.md / ## Development","input":"ruff format --check .","expected":"already formatted","argv":["<guest-path>","format","--check","."],"cwd":"<guest-path>","expected_text":"already formatted"},
 {"kind":"example","claim":"offline test suite passes","source":"README.md / ## Development","input":"pytest","expected":"75 passed","argv":["<guest-path>","-q"],"cwd":"<guest-path>","expected_text":"75 passed"}
]
EOF
cat > cycles.json <<'EOF'
{"detected":false,"reason":"Entry points inspected: README.md and src/oxylabs_web_api_mcp/server.py (main runs mcp.run stdio or http once). No cron, scheduler, loop, --once/--now, or webhook in the product; the only sleep is retry backoff inside one HTTP request. CI schedules are not product cycles.","checks":[]}
EOF
cat > report.json <<'EOF'
{"outcome":"needs_credentials","fault_owner":"prerequisite","operation":"Run the Oxylabs Web API MCP server over stdio and call its tools (search, scrape) against the live Oxylabs API","operation_scope":"Verified offline: install, ruff lint/format, 75 offline pytest tests, and read_scraped on a local fixture file. Not verified: search and scrape, which need a real OXYLABS_WEB_API_KEY that this guest does not have. No key was requested or obtained.","steps":["git init; git remote add origin https://github.com/oxylabs/web-api-mcp; git fetch --depth 1 origin 895116f090cc83258a5a7b1079aaca5e9207d7ee; git reset --mixed FETCH_HEAD","python3 -m venv <guest-path> (Python 3.12.3, README requires 3.10+)","pip install -e '.[dev]' (README Development section)","ruff check . && ruff format --check .","pytest (75 passed)","oxylabs-web-api-mcp over stdio: tools/list shows search, scrape, check_scrape, read_scraped, list_scrapers, scrape_target","read_scraped on a fixture file in OXYLABS_SPILL_DIR returned the expected chunk","search with no key returned isError: 'No Oxylabs Web API key...'"],"deviations":["python3-venv was missing; installed with sudo apt-get install python3.12-venv","workspace was not a git checkout; applied the pin with git init + fetch + reset as instructed","read_scraped was checked against a fixture text file I wrote into <guest-path>, because the product only writes spill files during a live scrape","No Oxylabs API key was available, so search/scrape/check_scrape/list_scrapers/scrape_target were not run against the live API","checker expects a credentials_error via a missing-response path; the product instead returns isError result text, so that check was recorded as an observation, not a PASS"],"stuck_step":"Calling the search or scrape tool, which needs OXYLABS_WEB_API_KEY","main_blocker":"No Oxylabs Web API key in the guest","plain_failure":"The main web search and page-reading features cannot run here because they need a paid Oxylabs API key, which this sandbox does not have. The install, the offline tests, and reading saved pages work.","suggested_fix":"Provide OXYLABS_WEB_API_KEY in the guest (or a per-request Bearer header) and rerun a search and a scrape call against the live API."}
EOF
for f in probe claims examples cycles report; do python3 -I -m json.tool $f.json >/dev/null && echo "$f ok"; done; ls -la <guest-path>
cd <guest-path> && <env-var>=<guest-path> python3 -I <guest-path> --validate --replay; echo; echo "rc=$?"
pgrep -af "oxylabs-web-api-mcp|mcp_call" || echo "no servers running"; ls <guest-path>
Earlier attempts (1)

Luna

Native agent · Not tested

Operation / attempted scope /tmp/oxylabs-venv/bin/oxylabs-web-api-mcp · local stdio MCP start + initialize + tools/list

Agent-reported scope: MCP list_scrapers tool call

MCP server returned: oxylabs-web-api · version 0.1.0.

MCP tools returned: search, scrape, check_scrape, read_scraped, list_scrapers, scrape_target. Tool listing does not establish authenticated tool-call success.

Run details
run
oxylabs--web-api-mcp-gpt-6-luna-1792808173704411679
date
Oct 23, 2026
time to working
not recorded
product hosting / execution
Local stdio MCP server in the guest
recorded operation scope
Installed editable package with Python 3.12.3; live API request requires Oxylabs Web API key.
model
gpt-6-luna
agent / version
codex / codex-cli 0.163.0
platform
linux
reported cost
not reported (not assumed free)
Recorded source
https://github.com/oxylabs/web-api-mcp
Backend
hyperv
Tool transport
mcp-assigned-vm
Requested source pin (not an observed revision)
{"commit": "895116f090cc83258a5a7b1079aaca5e9207d7ee", "url": "https://github.com/oxylabs/web-api-mcp"}
Test version
readme-f72312298d35d84837d4fc5f6f22b138d54d456600b5ed431e36e8f5db931dbf
revision
895116f090cc83258a5a7b1079aaca5e9207d7ee
Whose fault: prerequisite · diagnosed

An Oxylabs Web API key is required and not available in this VM.

Fix: fix-4d91dce18b26eacf314a.

Recorded blocker / warning

Step: Calling upstream Web API via list_scrapers

An Oxylabs Web API key is required and not available in this VM.

Safety: No problems traced to this repository code in these checks.

No problems traced to this repository code in these checks.

OSV scanned supported lockfiles; unpinned dependencies and unsupported formats are outside this check.

A short run cannot establish that code is safe.

Connections show IP addresses; proxies can hide the final hostname.

Tracing covers dispatched commands and their children, not the whole OS; guest root can interfere with tracing.

Full safety evidence →

Answers recorded for this run
  • Web API tools require an API key to call the service.: Real input did not produce the expected result: No Oxylabs Web API key

    Source: An Oxylabs Web API key — in the [Oxylabs dashboard](https://dashboard.oxylabs.io), create

    Input: {"tool": "list_scrapers", "arguments": {}}

    Expected: No Oxylabs Web API key

    Command: /tmp/oxylabs-venv/bin/oxylabs-web-api-mcp tools/call {"tool": "list_scrapers", "arguments": {}}

    Observed: No Oxylabs Web API key. Send it as an 'Authorization: <secret><key>' header, or set OXYLABS_WEB_API_KEY in the server environment (see .env.example) and restart the MCP server.", "type": "text"}], "isError": true}

Examples

  • README development test suite: command completed successfully

    Source: README.md, Development

    Input: offline pytest suite

    Expected: tests pass

    Command: /tmp/oxylabs-venv/bin/python -m pytest

    Observed: ============================= test session starts ============================== platform linux -- Python 3.12.3, pytest-9.1.1, pluggy-1.7.0 rootdir: <guest-path> configfile: pyproject.toml testpaths: tests plugins: anyio-4.15.1, platformdirs-4.13.5 collected 75 items tests/test_server.py ................................................... [ 68%] ........................ [100%] ============================== 75 passed in 3.93s ==============================

Local or hosted: local

Suggested next step (agent-reported): Set OXYLABS_WEB_API_KEY to a valid Web API key and rerun the MCP tool call.

What the agent did

MCP list_scrapers tool call

cd <guest-path> && (vault-search 'web-api-mcp README setup MCP tools' || true) && ls -la && rg --files -g 'README*' -g 'AGENTS.md' -g 'package.json' -g 'pyproject.toml' -g 'requirements*.txt' -g '*lock*' -g '.github/workflows/*' | head -80 && cat README.md
cd <guest-path> && python3 --version && id -u && cat pyproject.toml && cat .env.example && find . -name AGENTS.md -o -path './.github/workflows/*' -type f; git rev-parse HEAD || true; ls -la .coldpass
cd <guest-path> && python3 -m venv /tmp/oxylabs-venv && /tmp/oxylabs-venv/bin/python -m pip install -e '.[dev]' && /tmp/oxylabs-venv/bin/oxylabs-web-api-mcp --help
sudo -n apt-get update && sudo -n apt-get install -y python3.12-venv
cd <guest-path> && python3 -m venv /tmp/oxylabs-venv && /tmp/oxylabs-venv/bin/python -m pip install -e '.[dev]' && /tmp/oxylabs-venv/bin/oxylabs-web-api-mcp --help && sed -n '1,240p' src/oxylabs_web_api_mcp/server.py
cd <guest-path> && python3 - <<'PY'
import json
from pathlib import Path
p=Path('.coldpass'); p.mkdir(exist_ok=True)
claims=[{"kind":"claim","claim":"The server exposes six read-only tools.","source":"All six are annotated `readOnlyHint` — nothing here writes anything — so clients can run","input":"list available MCP tools","expected":"search, scrape, check_scrape, read_scraped, list_scrapers, scrape_target","probe_kind":"mcp","argv":["/tmp/oxylabs-venv/bin/oxylabs-web-api-mcp"],"tool":"list_scrapers","arguments":{},"expected_text":"search","cwd":"<guest-path>"}]
probe={"kind":"mcp","argv":["/tmp/oxylabs-venv/bin/oxylabs-web-api-mcp"],"cwd":"<guest-path>","tool":"list_scrapers","arguments":{},"expected_text":"amazon"}
for name,obj in [('claims.json',claims),('probe.json',probe),('cycles.json',{'detected':False,'reason':'Inspected README entry points and source: this MCP server responds to client tool calls and contains no product scheduler or cycle trigger.','checks':[]}),('examples.json',[{'kind':'example','claim':'README development test suite','source':'README.md, Development','input':'offline pytest suite','expected':'tests pass','argv':['/tmp/oxylabs-venv/bin/python','-m','pytest'], 'cwd':'<guest-path>'}])]:
 (p/name).write_text(json.dumps(obj,indent=2)+'\n')
PY
/tmp/oxylabs-venv/bin/python -m pytest -q
cd <guest-path> && <env-var>=<guest-path> python3 -I <guest-path> --validate --replay
cd <guest-path> && python3 - <<'PY'
import json
from pathlib import Path
p=Path('.coldpass')
(p/'probe.json').write_text(json.dumps({'kind':'mcp','argv':['/tmp/oxylabs-venv/bin/oxylabs-web-api-mcp'],'cwd':'<guest-path>','tool':'list_scrapers','arguments':{},'expected_text':'No Oxylabs Web API key'},indent=2)+'\n')
(p/'claims.json').write_text(json.dumps([{'kind':'claim','claim':'Web API tools require an API key to call the service.','source':'An Oxylabs Web API key — in the [Oxylabs dashboard](https://dashboard.oxylabs.io), create','input':'call list_scrapers without configured key','expected':'No Oxylabs Web API key','probe_kind':'mcp','argv':['/tmp/oxylabs-venv/bin/oxylabs-web-api-mcp'],'tool':'list_scrapers','arguments':{},'expected_text':'No Oxylabs Web API key','cwd':'<guest-path>'}],indent=2)+'\n')
(p/'report.json').write_text(json.dumps({'outcome':'needs_credentials','fault_owner':'prerequisite','operation':'MCP list_scrapers tool call','operation_scope':'Installed editable package with Python 3.12.3; live API request requires Oxylabs Web API key.','steps':['Installed python3.12-venv with sudo apt-get.','Created /tmp/oxylabs-venv and ran pip install -e ".[dev]".','Ran documented offline pytest suite: 75 passed.','Invoked the documented stdio server and attempted list_scrapers.'],'deviations':['Initial venv creation failed: ensurepip unavailable; installed python3.12-venv with sudo -n apt-get update && sudo -n apt-get install -y python3.12-venv.','MCP call returned the server message: No Oxylabs Web API key.'],'stuck_step':'Calling upstream Web API via list_scrapers','main_blocker':'An Oxylabs Web API key is required and not available in this VM.','plain_failure':'The package installs and its offline tests pass, but the useful live scraper listing cannot run without an Oxylabs API key.','suggested_fix':'Set OXYLABS_WEB_API_KEY to a valid Web API key and rerun the MCP tool call.'},indent=2)+'\n')
PY
<env-var>=<guest-path> python3 -I <guest-path> --validate --replay