framework-compliance-t…
Make a cloud account compliant with a security or industry framework using Prowler Cloud.
Testing patterns for the Prowler MCP Server: in-memory FastMCP clients, the ProwlerAPIClient singleton, JSON:API model builders and mocked httpx transports. Trigger: When writing tests under mcp_server/tests/ (tools, models, api_client, auth, sub-servers).
Claude Code
$ npx -y skills add prowler-cloud/prowler --skill prowler-test-mcp --agent claude-code
Codex
$ npx skills add prowler-cloud/prowler --skill prowler-test-mcp -a codex -y
Cursor
$ npx skills add prowler-cloud/prowler --skill prowler-test-mcp -a cursor -y
Gemini CLI
$ npx skills add prowler-cloud/prowler --skill prowler-test-mcp -a gemini-cli -y
GitHub Copilot
$ npx skills add prowler-cloud/prowler --skill prowler-test-mcp -a github-copilot -y
OpenCode
$ npx skills add prowler-cloud/prowler --skill prowler-test-mcp -a opencode -y
Windsurf
$ npx skills add prowler-cloud/prowler --skill prowler-test-mcp -a windsurf -y
name: prowler-test-mcp
description: >
Testing patterns for the Prowler MCP Server: in-memory FastMCP clients, the
ProwlerAPIClient singleton, JSON:API model builders and mocked httpx transports.
Trigger: When writing tests under mcp_server/tests/ (tools, models, api_client, auth, sub-servers).
license: Apache-2.0
metadata:
author: prowler-cloud
version: "1.1.0"
scope: [root, mcp_server]
auto_invoke:
- "Writing Prowler MCP server tests"
- "Testing MCP tools or models"
allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, TaskTool parameters use pydantic `Field(default=...)`, and only FastMCP's wrapper resolves those defaults. Calling a tool method directly with an argument omitted leaves it as a raw `FieldInfo` — which is truthy, so `if email:` silently builds a filter out of the `FieldInfo` repr. Direct calls MUST pass every argument.
hard-to-diagnose event-loop issues; open it inline in the test.
Tool instances captured the singleton by reference at import time, so only an in-place patch of `.client` reaches them.
instance holding a real `httpx.AsyncClient`. Use `isolated_api_client` if you genuinely need a fresh instance.
failure is swallowed, so the whole `prowler_*` namespace silently drops to zero tools. It is pinned in `[tool.pytest_env]`.
default arguments, evaluated once at module import, so `monkeypatch.setenv` has no effect on them.
repo-root `tests/`), or same-named modules collide under pytest's import mode.
deprecation warning fails the suite. Fix the cause; do not add a blanket filter.
---
Mirror the source tree *below the package root* — drop the `prowler_mcp_server/` level, exactly as the SDK maps `prowler/providers/...` to `tests/providers/...`. So `prowler_mcp_server/prowler_app/tools/` is tested in `tests/prowler_app/tools/`.
mcp_server/tests/
├── conftest.py # all shared fixtures
├── helpers/ # jsonapi.py, http.py, assertions.py, tokens.py
├── test_server.py # mounted-server contract
├── test_health.py
├── prowler_app/{models,tools,utils}/
├── prowler_hub/
└── prowler_documentation/---
| Fixture | Autouse | What it gives you | |---------|---------|-------------------| | `_pinned_environment` | yes | Deterministic env; blocks a developer's `.env` from leaking | | `_no_real_network` | yes | Any real socket connect raises `RuntimeError` | | `_singleton_registry_guard` | yes | Snapshots/restores `SingletonMeta._instances` | | `mock_router` | no | Route registry + request recorder | | `api_client` | no | The live `ProwlerAPIClient` singleton | | `mock_api_client` | no | **The workhorse** — singleton with a mocked transport | | `isolated_api_client` | no | Evicts the singleton, for construction/identity tests | | `mcp_root_server` | no | The mounted root server (session-scoped) | | `health_client` | no | Starlette `TestClient` for `/health` | | `http_request_headers` | no | Injects headers for HTTP-mode auth | | `hub_router` | no | Mocks the Hub sub-server's two sync clients | | `docs_router` | no | Mocks the docs search engine's two sync clients |
mock_router.add("GET", "/api/v1/users", json=jsonapi_collection([...]))
mock_router.add("GET", "/api/v1/tasks/t1", json=task_document("t1", "completed"))
mock_router.request_for("GET", "/api/v1/users") # last request, for header asserts
mock_router.query_params("GET", "/api/v1/users") # decoded query string
mock_router.paths() # everything requested so farRegister a route more than once to return a sequence — the last response repeats. That is how you drive `poll_task_until_complete` (`executing`, `executing`, `completed`). An unregistered request raises, listing what *was* registered.
---
**Tool test** — see `assets/mcp_tool_test.py`. Register routes, call through the in-memory client, assert on `result.data` *and* on the recorded request. When a tool chooses between endpoints, assert `mock_router.paths()` — a wrong choice is invisible in the response body.
**Model test** — see `assets/mcp_model_test.py`. Build the document with the `jsonapi` helpers, run `from_api_response()`, assert on both the model and `model_dump()`. `MinimalSerializerMixin` makes those differ, and an absent relationship (`None`) must never be conflated with an empty one (`[]`).
**Contract test** — see `assets/mcp_contract_test.py`. Namespacing and description coverage across every registered tool.
The worked example in the repo is `findings`, covered across both layers in `tests/prowler_app/{models,tools}/test_findings.py`. Read those first — they exercise every foundation capability in one feature.
Coverage has a meanin
Prowler is the world’s most widely used Open-Source Cloud Security Platform that automates security and compliance across any cloud environment.
Make a cloud account compliant with a security or industry framework using Prowler Cloud.
Vercel AI SDK patterns for the installed major (ui/package.json: `ai` 6.x, `@ai-sdk/react` 3.x). The skill name is historical;…
Django REST Framework patterns. Trigger: When implementing generic DRF APIs (ViewSets, serializers, routers, permissions,…
Reviews Django migration files for PostgreSQL best practices specific to Prowler. Trigger: When creating migrations, running…
Create and maintain GitHub Agentic Workflows (gh-aw) for Prowler. Trigger: When creating agentic workflows, modifying gh-aw…
Strict JSON:API v1.1 specification compliance. Trigger: When creating or modifying API endpoints, reviewing API responses, or…
Use for authorized security assessment of REST, GraphQL, WebSocket, or SOAP APIs, including discovery, authentication,…
Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys)…
Clean and finalize authorized natural-language text intended for readers by auditing suspicious invisible Unicode and rewriting…