Metadata-Version: 2.4
Name: vfa-mcp
Version: 1.0.4
Summary: VFA — Visual & Functional Auditor: auditoria web autonoma (visual + funcional) expuesta como servidor MCP, con Playwright local y motor universal LiteLLM.
Author-email: AIDevTeam <red.line.v.o.s@outlook.com>
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://vaillan.github.io/vfa-docs
Project-URL: Documentation, https://vaillan.github.io/vfa-docs
Project-URL: Buy License, https://www.creem.io/payment/prod_6qWpfXtntbKRUvBifbObZj
Keywords: mcp,mcp-server,qa-automation,visual-regression,playwright,litellm,accessibility,llm-agents
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcp<2.0.0,>=1.2.0
Requires-Dist: litellm==1.106.3
Requires-Dist: playwright>=1.40.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: truststore>=0.9.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Dynamic: license-file

# VFA — Visual & Functional Web Auditor (MCP Server)

Autonomous black-box web QA agent exposed as an MCP server over `stdio`.
Pure hexagonal architecture (Ports & Adapters), one unified inference engine
powered by **LiteLLM**, and a local-first **Playwright** Chromium sandbox —
no Docker, no sidecars, no infrastructure to maintain.

## Why VFA

| Pillar                       | What it means                                                                                                                                                                                                                       |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Native Zero-Docker**       | Playwright downloads and manages Chromium on the host itself. A built-in ephemeral `BrowserContext` sandbox plus an Anti-SSRF firewall ship by default, and local development is first-class (`localhost`, `127.0.0.1`, `*.local`). |
| **Universal LiteLLM Engine** | A single adapter drives DeepSeek, OpenAI, Anthropic, Gemini, xAI/Grok, OpenRouter and Ollama. Switching providers is a two-variable change.                                                                                         |
| **Active Visual Grounding**  | Multimodal vision inspects real UIs, reads raster image CAPTCHAs and clicks by visual coordinates whenever the accessibility tree is not enough.                                                                                    |
| **1-Click Execution**        | Plug-and-play: `uvx vfa-mcp` starts the server with no permanent install, `pip install vfa-mcp` if you prefer an isolated virtualenv.                                                                                               |

```bash
uvx vfa-mcp
```

## Quickstart

### ⚠️ License Key (Required)

VFA is a commercial tool. An active **VFA Pro License** is required to execute audits and user flows.
* **Get your license:** [Purchase on Creem](https://www.creem.io/payment/prod_6qWpfXtntbKRUvBifbObZj)
* **Configuration:** Set the `VFA_LICENSE_KEY` environment variable in your MCP client or `.env`.

### 1. Install

One command, permanent install in your own virtualenv:

```bash
pip install vfa-mcp && playwright install chromium
```

Zero-install alternative (recommended for MCP clients):

```bash
uvx vfa-mcp
playwright install chromium   # first run only
```

### 2. Pick a provider

VFA resolves the API key from `VFA_LLM_API_KEY` first, then from the standard
variable of the selected provider (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`,
`GEMINI_API_KEY`, `DEEPSEEK_API_KEY`, `XAI_API_KEY`, `OPENROUTER_API_KEY`).

| Provider | `VFA_LLM_PROVIDER` | Example `VFA_LLM_MODEL` | API key variable | Base URL / Endpoint variable |
| :--- | :--- | :--- | :--- | :--- |
| OpenAI | `openai` | `gpt-4o` | `OPENAI_API_KEY` | — *(Default)* |
| Anthropic | `anthropic` | `claude-3-5-sonnet-20241022` | `ANTHROPIC_API_KEY` | — *(Default)* |
| Google Gemini | `gemini` | `gemini/gemini-2.0-flash` | `GEMINI_API_KEY` | — *(Default)* |
| DeepSeek (Direct) | `deepseek` | `deepseek/deepseek-chat` | `DEEPSEEK_API_KEY` | — *(Default)* |
| DeepSeek Vision | `deepseek` | `deepseek/deepseek-flash` | `DEEPSEEK_API_KEY` | — *(Default)* |
| **DeepSeek (OpenAI-compat)** | `openai` | `openai/deepseek-chat` *(o `deepseek-flash`)* | `DEEPSEEK_API_KEY` / `OPENAI_API_KEY` | `OPENAI_API_BASE="https://api.deepseek.com"` |
| **DeepSeek (Anthropic-compat)** | `anthropic` | `claude-3-5-sonnet` *(alias)* | `DEEPSEEK_API_KEY` / `ANTHROPIC_API_KEY` | `ANTHROPIC_BASE_URL="https://api.deepseek.com/anthropic"` |
| xAI / Grok | `xai` | `xai/grok-2-vision-1212` | `XAI_API_KEY` | — *(Default)* |
| OpenRouter | `openrouter` | `openrouter/anthropic/claude-3.5-sonnet` | `OPENROUTER_API_KEY` | — *(Default)* |
| Ollama (local) | `ollama` | `ollama/llama3.2-vision` | — *(Placeholder)* | `OLLAMA_API_BASE="http://localhost:11434"` |

Aliases accepted by the provider resolver: `google` (Gemini) and `grok` (xAI).
Vision falls back to the reasoning model when `VFA_VISION_PROVIDER` /
`VFA_VISION_MODEL` are left empty.

### 3. Wire it into your client

#### Zoo Code / Roo Code (`mcpSettings.json`)

Click the **MCP Servers** plug icon ⚙️ → **Edit MCP Settings**, then add:

```json
{
  "mcpServers": {
    "vfa": {
      "command": "uvx",
      "args": ["vfa-mcp"],
      "env": {
        "VFA_LICENSE_KEY": "PRO-XXXX-XXXX",
        "OPENAI_API_KEY": "sk-...",
        "HEADLESS": "true",
        "VFA_ALLOW_LOCAL_HOST": "true",
        "LITELLM_LOG": "ERROR"
      }
    }
  }
}
```

---

#### Claude Desktop (`claude_desktop_config.json`)

* **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
* **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "vfa": {
      "command": "uvx",
      "args": ["vfa-mcp"],
      "env": {
        "OPENAI_API_KEY": "sk-...",
        "HEADLESS": "true",
        "VFA_ALLOW_LOCAL_HOST": "true",
        "LITELLM_LOG": "ERROR"
      }
    }
  }
}
```

---

#### Cursor (`.cursor/mcp.json` or `Settings → Features → MCP`)

```json
{
  "mcpServers": {
    "vfa": {
      "command": "uvx",
      "args": ["vfa-mcp"],
      "env": {
        "OPENAI_API_KEY": "sk-...",
        "HEADLESS": "true",
        "VFA_ALLOW_LOCAL_HOST": "true",
        "LITELLM_LOG": "ERROR"
      }
    }
  }
}
```

---

### Provider Drop-in Presets (Replace the `"env"` block)

Simply swap the `"env"` object in any configuration above with your preferred model:

#### ⚡ DeepSeek (Reasoning + Fast Vision)
```json
"env": {
  "VFA_LLM_PROVIDER": "deepseek",
  "VFA_LLM_MODEL": "deepseek-chat",
  "VFA_VISION_PROVIDER": "deepseek",
  "VFA_VISION_MODEL": "deepseek-flash",
  "DEEPSEEK_API_KEY": "sk-...",
  "HEADLESS": "true",
  "VFA_ALLOW_LOCAL_HOST": "true",
  "LITELLM_LOG": "ERROR"
}
```

#### 🧠 Anthropic Claude 3.5 Sonnet
```json
"env": {
  "VFA_LLM_PROVIDER": "anthropic",
  "VFA_LLM_MODEL": "claude-3-5-sonnet-20241022",
  "ANTHROPIC_API_KEY": "sk-ant-...",
  "HEADLESS": "true",
  "VFA_ALLOW_LOCAL_HOST": "true",
  "LITELLM_LOG": "ERROR"
}
```

#### 🚀 Google Gemini 2.0 Flash (Multimodal)
```json
"env": {
  "VFA_LLM_PROVIDER": "gemini",
  "VFA_LLM_MODEL": "gemini/gemini-2.0-flash",
  "GEMINI_API_KEY": "AIzaSy...",
  "HEADLESS": "true",
  "VFA_ALLOW_LOCAL_HOST": "true",
  "LITELLM_LOG": "ERROR"
}
```

#### 🌐 OpenRouter (Universal Gateway)
```json
"env": {
  "VFA_LLM_PROVIDER": "openrouter",
  "VFA_LLM_MODEL": "openrouter/anthropic/claude-3.5-sonnet",
  "VFA_VISION_MODEL": "openrouter/google/gemini-2.0-flash-001",
  "OPENROUTER_API_KEY": "sk-or-v1-...",
  "HEADLESS": "true",
  "VFA_ALLOW_LOCAL_HOST": "true",
  "LITELLM_LOG": "ERROR"
}
```

#### 🏠 Ollama (100% Local / Offline)
```json
"env": {
  "VFA_LLM_PROVIDER": "ollama",
  "VFA_LLM_MODEL": "ollama/llama3.2-vision",
  "OLLAMA_API_BASE": "http://localhost:11434",
  "HEADLESS": "true",
  "VFA_ALLOW_LOCAL_HOST": "true",
  "LITELLM_LOG": "ERROR"
}
```

#### ⚙️ OpenAI-compatible:
```json
"env": {
  "VFA_LLM_PROVIDER": "openai",
  "VFA_LLM_MODEL": "openai/deepseek-v4-pro",
  "VFA_VISION_PROVIDER": "openai",
  "VFA_VISION_MODEL": "openai/deepseek-flash",
  "OPENAI_API_BASE": "https://api.deepseek.com",
  "OPENAI_API_KEY": "sk-...",
  "HEADLESS": "true",
  "VFA_ALLOW_LOCAL_HOST": "true",
  "LITELLM_LOG": "ERROR"
}
```

#### ⚙️ Anthropic-compatible:
```json
"env": {
  "VFA_LLM_PROVIDER": "anthropic",
  "VFA_LLM_MODEL": "claude-3-5-sonnet",
  "ANTHROPIC_BASE_URL": "https://api.deepseek.com/anthropic",
  "ANTHROPIC_API_KEY": "sk-...",
  "HEADLESS": "true",
  "VFA_ALLOW_LOCAL_HOST": "true",
  "LITELLM_LOG": "ERROR"
}
```

> Agent-facing usage guide (when to invoke each tool, report template, security
> rules): [`SKILL.md`](SKILL.md). Marketplace manifest: [`skill.json`](skill.json).

## Tool reference

### `qa_audit_url(url)`

Full-page screenshot, vision analysis and runtime error collection in a single call.

| Parameter | Type   | Required | Description                                                                                             |
| --------- | ------ | -------- | ------------------------------------------------------------------------------------------------------- |
| `url`     | string | yes      | Reachable URL to audit. Private/loopback targets are rejected unless `VFA_ALLOW_LOCAL_HOST` is enabled. |

Returns `url`, `ok` (`true` only when the audit passed and no runtime event was
captured), `summary`, `screenshot_base64` (PNG), `issues[]` (visual,
accessibility and layout findings) and `errors[]`.

### `qa_execute_user_flow(url, steps)`

Replays a user journey described in plain language (English or Spanish).

| Parameter | Type     | Required | Description                                                               |
| --------- | -------- | -------- | ------------------------------------------------------------------------- |
| `url`     | string   | yes      | Starting URL of the flow.                                                 |
| `steps`   | string[] | yes      | Ordered natural-language steps, e.g. `["Click 'Sign in'", "Verify ..."]`. |

Returns `url`, `success`, `ok`, `steps[{step, ok, detail}]`, `screenshots[]`
(base64 PNG milestones) and `errors[]`.

### `qa_get_runtime_errors()`

Drains the browser error buffer: `console.error`, uncaught exceptions
(`pageerror`) and HTTP responses with status `>= 400`.

| Parameter | Type | Required | Description   |
| --------- | ---- | -------- | ------------- |
| —         | —    | —        | No arguments. |

Returns `count` and `errors[{kind, message, url, status}]`, where `kind` is one
of `console`, `pageerror` or `http`. The call is read-destructive: it empties
the buffer, so invoke it once at the end of a sequence.

## Configuration reference

VFA is configured **exclusively through environment variables** — there are no
config files, no database and no flags to pass. Variables are grouped in three
independent layers:

| Layer                    | Variables                                                                  | Consumed by                                    |
| ------------------------ | -------------------------------------------------------------------------- | ---------------------------------------------- |
| **Reasoning engine**     | `VFA_LLM_PROVIDER`, `VFA_LLM_MODEL`, `VFA_LLM_API_KEY`, `VFA_LLM_BASE_URL` | The **Deep Agent** (LiteLLM tool-calling loop) |
| **Vision engine**        | `VFA_VISION_PROVIDER`, `VFA_VISION_MODEL`, `VFA_VISION_API_KEY`            | Visual grounding / CAPTCHA fallback            |
| **Browser & runtime**    | `HEADLESS`, `VFA_ALLOW_LOCAL_HOST`, `BROWSER_CDP_*`, `VFA_SESSION_*`, …    | Playwright adapter, session pool, Anti-SSRF    |

### Is anything mandatory?

Only **two things** are strictly mandatory:
1. `VFA_LICENSE_KEY`: Your commercial license key purchased from [Creem](https://www.creem.io/payment/prod_6qWpfXtntbKRUvBifbObZj).
2. An inference API key for your chosen provider (e.g. `OPENAI_API_KEY`, `DEEPSEEK_API_KEY`, etc.).

```bash
# Minimal production setup — works because the defaults are openai/gpt-4o
export OPENAI_API_KEY="sk-..."
```

### Does `VFA_LLM_MODEL` drive the Deep Agent?

**Yes.** `VFA_LLM_MODEL` is the model used by the Deep Agent — the component that
executes `qa_execute_user_flow` and performs the reasoning step of
`qa_audit_url`. Both tools go through LiteLLM with
`VFA_LLM_PROVIDER` + `VFA_LLM_MODEL`, so:

- **You may omit them** when you use OpenAI `gpt-4o` and export
  `OPENAI_API_KEY` (defaults: `openai` / `gpt-4o`).
- **You must set them** when you use any other provider, any other model, or an
  OpenAI-compatible gateway (DeepSeek, OpenRouter, Ollama, vLLM, Azure proxy…).
- The model **must support tool calling** (native function calling), because the
  ReAct loop sends a JSON action schema on every iteration.

For OpenAI-compatible endpoints, pair the model with a base URL:

```bash
export VFA_LLM_PROVIDER="openai"          # protocol, not the vendor
export VFA_LLM_MODEL="openai/deepseek-chat"
export OPENAI_API_KEY="sk-..."            # or VFA_LLM_API_KEY
export OPENAI_BASE_URL="https://api.deepseek.com"
```

### Credential and endpoint precedence

| What                | Resolution order                                                                                                                          |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| Reasoning API key   | `VFA_LLM_API_KEY` → provider standard variable (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, `DEEPSEEK_API_KEY`, `XAI_API_KEY`, `OPENROUTER_API_KEY`) → `OPENAI_API_KEY` |
| Reasoning base URL  | `VFA_LLM_BASE_URL` → `OPENAI_BASE_URL` → `OLLAMA_API_BASE` (only when the provider is `ollama`)                                            |
| Vision provider     | `VFA_VISION_PROVIDER` → `VFA_LLM_PROVIDER` → `openai`                                                                                    |
| Vision model        | `VFA_VISION_MODEL` → `VFA_LLM_MODEL` → `gpt-4o`                                                                                            |
| Vision API key      | `VFA_VISION_API_KEY` → `VFA_LLM_API_KEY` → provider standard variable → `OPENAI_API_KEY`                                                   |

`VFA_VISION_*` is therefore **optional by design**: if the reasoning model is
multimodal (`gpt-4o`, `claude-3-5-sonnet`, `gemini/gemini-2.0-flash`,
`xai/grok-2-vision-1212`), leave it empty and one model does everything. Set it
only when you want a **cheaper/faster model for screenshots** or when your
reasoning model is text-only.

### Full variable list

| Variable | Default | Required when | Purpose |
| :--- | :--- | :--- | :--- |
| `VFA_LICENSE_KEY` | _(empty)_ | Mandatory for all tool executions | Commercial Pro license key from [Creem](https://www.creem.io/payment/prod_6qWpfXtntbKRUvBifbObZj) |
| `VFA_LLM_PROVIDER` | `openai` | Using a non-OpenAI provider | SDK protocol/routing for the Deep Agent (`openai`, `anthropic`, `gemini`, `deepseek`, `xai`, `openrouter`, `ollama`; aliases `google`, `grok`) |
| `VFA_LLM_MODEL` | `gpt-4o` | Using a model other than `gpt-4o` | Reasoning model (must support tool calling) |
| `VFA_LLM_API_KEY` | _(empty)_ | Sharing one credential across providers | Generic key that overrides the provider standard variable |
| `VFA_LLM_BASE_URL` | _(empty)_ | OpenAI-compatible gateways, self-hosted or proxied endpoints | Base URL override (`OPENAI_BASE_URL` also honoured) |
| `VFA_VISION_PROVIDER` | inherits | Vision served by a different vendor | Routing for multimodal calls |
| `VFA_VISION_MODEL` | inherits | Reasoning model lacks image input, or cost split desired | Model used for screenshots and visual grounding |
| `VFA_VISION_API_KEY` | inherits | Vision served by a different vendor | Credential for multimodal calls |
| `OLLAMA_API_BASE` | _(empty)_ | `VFA_LLM_PROVIDER=ollama` | Local endpoint, e.g. `http://localhost:11434` (no key needed, a placeholder is used) |
| `VFA_AGENT_MAX_ITERATIONS` | `12` | Long flows that exceed the ReAct budget | Iteration ceiling of the Deep Agent loop |
| `VFA_LLM_TEMPERATURE` | `0.0` | Never (deterministic QA by default) | Sampling temperature |
| `VFA_LLM_TIMEOUT` | `60` | Slow/self-hosted models | Per-call timeout in seconds |
| `VFA_LLM_REQUESTS_PER_SECOND` | `0` | Free tiers or strict quotas | Token-bucket rate limiter; `0` disables it |
| `VFA_LLM_CHECKS_PER_SECOND` | `10.0` | Never | Rate limiter polling frequency |
| `HEADLESS` | `true` | Local debugging of the flow step by step | Run Chromium without a window |
| `VFA_ALLOW_LOCAL_HOST` | `true` | Must be `false` for internet-facing production deployments | Allow `localhost`, `127.0.0.1`, `0.0.0.0`, `*.local`; `false` restores strict Anti-SSRF blocking of loopback, private ranges and cloud metadata |
| `BROWSER_CDP_URL` | _(empty)_ | Attaching to an already running Chromium | Optional custom CDP endpoint; empty uses the managed local browser |
| `BROWSER_CDP_TIMEOUT_MS` | `2000` | Remote CDP endpoint slower than 2s | Timeout of the CDP connection attempt |
| `VFA_ACTION_TIMEOUT_MS` | `10000` | Heavy SPAs with slow first paint | Timeout of every individual Playwright action |
| `VFA_SCREENSHOT_FULL_PAGE` | `true` | Never (viewport-only reports needed) | Full-page screenshots instead of viewport only |
| `VFA_SESSION_POOL_ENABLED` | `true` | Stateless/multi-tenant deployments may disable it | Reuse browser sessions between tool calls |
| `VFA_SESSION_POOL_TTL` | `300` | Never | Idle seconds before a pooled session is closed |
| `VFA_SESSION_POOL_MAX_SIZE` | `5` | High-concurrency hosts | Maximum concurrent pooled sessions (LRU eviction) |
| `VFA_SESSION_STORAGE_STATE` | _(empty)_ | Replaying an authenticated journey | Imported Playwright `storageState`; empty keeps cookies in memory only |
| `SSL_VERIFY` | `true` | Self-signed certificates in local/staging | TLS verification switch (leave empty to skip verification; any non-empty value keeps it on) |

A copy-ready template with the same defaults lives in [`.env.example`](.env.example).

### Production checklist

1. **One credential per deployment**, injected by your secret manager — never
   committed and never placed in the MCP client JSON for shared machines.
2. **Keep `VFA_ALLOW_LOCAL_HOST=false`** on any host that can reach an internal
   network; it is the only guard against SSRF from an LLM-driven navigation.
3. **Pin `VFA_LLM_MODEL`** explicitly instead of relying on `gpt-4o`; upstream
   providers rotate model names and a silent change alters QA verdicts.
4. **Set `VFA_LLM_REQUESTS_PER_SECOND`** when you run parallel audits against a
   rate-limited provider, and raise `VFA_LLM_TIMEOUT` for slow self-hosted models.
5. **Keep `HEADLESS=true`** on servers (no X server is available) and keep
   `SSL_VERIFY` enabled outside staging.
6. **Do not mount `VFA_SESSION_STORAGE_STATE`** unless the flow needs a reused
   login: it writes real session cookies to the host filesystem.

## Architecture

```
app/
  domain/                  # Pure domain (no I/O, no frameworks)
    models.py              # AuditReport, StepResult, RuntimeErrorEvent, VFAContext
    parser.py              # Deterministic NLP parser (ES/EN)
    semantic.py            # Cascade: regex -> a11y snapshot -> LLM fallback
    vision.py              # Visual primitives and grounding contracts
  ports/                   # Abstract contracts
    browser.py             # BrowserSessionPort / BrowserGatewayPort
    llm.py                 # LLMPort / UsageLimiterPort
  adapters/
    browser/
      playwright_adapter.py  # Local sandboxed Chromium + ephemeral context
      network_guard.py       # Anti-SSRF firewall (private ranges / loopback)
      session_pool.py        # TTL + LRU pool, cookies in memory only
      capture.py             # console.error, pageerror, HTTP >= 400
      visual_primitives.py   # Screenshot and coordinate helpers
    llm/
      litellm_adapter.py     # Multi-provider acompletion + base64 vision
      deep_agent.py          # ReAct loop with native tool calling
      agent_tools.py         # Agent tool JSON schemas
      vision_grounding.py    # Visual grounding adapter
      rate_limiter.py        # Async token bucket
      visual_fallback.py     # Heuristic fallback chain
  tools/qa_tools.py        # The three QA tools
  config.py                # Single source of truth for configuration
server_mcp.py              # FastMCP entrypoint (stdio)
```

## Security model

- Chromium starts with strict isolation flags (`--disable-background-networking`,
  `--disable-default-apps`, `--disable-sync`, `--no-first-run`, `--hide-scrollbars`).
- Every session uses an ephemeral in-memory `BrowserContext`, destroyed on close:
  no cache, cookies or storage are persisted to the host disk.
- A context-level Anti-SSRF firewall aborts (`accessdenied`) requests to loopback,
  private ranges (`10/8`, `172.16/12`, `192.168/16`) and cloud metadata
  (`169.254.169.254`). Local development targets are allowed only while
  `VFA_ALLOW_LOCAL_HOST` is `true`; set it to `false` for strict production mode.
- The LLM credential never reaches the audited page: only the server process
  talks to the inference provider.

## Development

```bash
pip install -e ".[dev]"
playwright install chromium
pytest
```

Tests run without a real browser or network: every adapter is replaced by an
in-memory double (`tests/conftest.py`, `tests/visual_fakes.py`).

## License

Commercial, single-seat Pro license. Distributed on PyPI as `vfa-mcp`.  
Acquire your permanent license key at [Creem Checkout](https://www.creem.io/payment/prod_6qWpfXtntbKRUvBifbObZj).
