Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
An MCP (Model Context Protocol) server that wraps the VirtualSMS Consumer API, allowing AI assistants like Claude, Cursor, and Copilot to purchase virtual phone numbers, retrieve SMS verification codes, and manage activations — all through natural language.
VirtualSMS is a platform for renting virtual phone numbers for SMS verification. It supports 200+ services (Telegram, WhatsApp, Google, Instagram, etc.) across 100+ countries with multiple provider backends.
This MCP server exposes 19 tools that map 1:1 to the VirtualSMS Consumer API actions. It normalizes the API's mixed text/JSON responses into clean structured JSON that LLMs can reason about.
| Category | Tools | Purpose |
|---|---|---|
| Account | get_balance, get_rate_limit_info | Check account balance and rate limit status |
| Information & Pricing | get_numbers_status, get_countries, get_services_list, get_operators, get_prices, get_prices_extended, get_prices_verification, get_top_countries_by_service | Browse availability, services, and pricing |
| Ordering | order_number, order_number_v2 | Purchase virtual phone numbers |
| Activation Management | get_active_activations, check_extra_activation, get_extra_activation, set_activation_status, get_activation_status, get_activation_status_v2 | Manage ordered numbers and retrieve SMS codes |
| Notifications | get_notifications | View account alerts and penalties |
claude mcp add virtualsms --env VIRTUALSMS_API_KEY=your_api_key_here -- npx -y @virtualsmslabs/mcp"Check my VirtualSMS balance" "Get prices for Telegram in Brazil" "Order a number for WhatsApp in Argentina, then check for the SMS code"
All configuration is via environment variables:
| Variable | Required | Default | Description |
|---|---|---|---|
VIRTUALSMS_API_KEY | Yes | — | Your VirtualSMS API key |
VIRTUALSMS_API_URL | No | https://api.virtualsms.de | Base API URL (override for self-hosted or testing) |
VIRTUALSMS_POOL_PROVIDER | No | — | Default provider alias: alpha, prime, gamma, or zeta |
VirtualSMS supports multiple upstream providers behind aliases:
| Alias | Description |
|---|---|
alpha | Default provider |
prime | Alternate provider |
gamma | Alternate provider |
zeta | Alternate provider |
If VIRTUALSMS_POOL_PROVIDER is not set, the platform auto-routes to the best available provider. You can override it per-call using the poolProvider parameter on most tools.
#### get_balance Get current account balance.
{ balance: number }#### get_rate_limit_info Get rate limit information from the most recent API call.
{ rateLimit: { limit: number, remaining: number } | null }Returns null if no API call has been made yet or the API did not return rate limit headers. The limit is the maximum number of requests per window, and remaining is how many are left. This information is updated automatically after every other tool call.
#### get_numbers_status Get quantity of available numbers per service.
country?, operator?, poolProvider?{ "serviceCode_countryId": count, ... }#### get_countries Get list of all available countries.
poolProvider?countryId → { id, rus, eng, chn, visible, retry, rent, multiService }#### get_services_list Get available services for a country.
country?, poolProvider?{ status, services: [{ code, name }] }#### get_operators Get available mobile operators for a country.
country (required), poolProvider?{ status, countryOperators: ["any", "claro", "vivo", ...] }#### get_prices Get current prices for services.
service?, country?, poolProvider?{ countryId: { serviceCode: { cost, count } } }#### get_prices_extended Get prices with price tiers.
service?, country?, freePrice?, poolProvider?{ countryId: { serviceCode: { cnt, physicalCount, freePriceMap, cost } } }#### get_prices_verification Get prices organized by service then country.
service?, poolProvider?{ serviceCode: { countryId: { count, price } } }#### get_top_countries_by_service Get top 10 countries by purchase share and success rate.
service (required)[{ country, share, rate }]#### order_number Purchase a virtual phone number for SMS verification.
service (required), country (required), maxPrice?, operator?, phoneException?, forward?, activationType?, language?, useCashBack?, userId?, ref?, poolProvider?{ activationId, phoneNumber }#### order_number_v2 Purchase a virtual phone number with richer JSON response.
order_number + orderId?{ activationId, phoneNumber, activationCost, countryCode, canGetAnotherSms, activationTime }#### get_active_activations Get all current active activations.
{ status, activeActivations: [{ activationId, serviceCode, phoneNumber, activationCost, activationStatus, smsCode, smsText, ... }] }#### check_extra_activation Check if a number is available for extra activation.
id (required — original activation ID){ status, cost, service, phone, country }#### get_extra_activation Create an extra activation on a previously used number.
id (required){ activationId, phoneNumber }#### set_activation_status Change activation status.
id (required), status (required — "1" ready, "3" retry, "6" finish, "8" cancel){ success: boolean, action: string }#### get_activation_status Get activation status (text format).
id (required){ status, code? } — status is one of STATUS_WAIT_CODE, STATUS_WAIT_RETRY, STATUS_OK, STATUS_CANCEL#### get_activation_status_v2 Get activation status (JSON format, more detailed).
id (required){ status, code?, verificationType?, sms?, call? }#### get_notifications Get user notifications (penalties, low balance, admin messages).
{ status, notifications: [{ id, type, title, content, read, createdAt }], unreadCount }The VirtualSMS API uses text-based error codes. This MCP server normalizes them into structured JSON error objects:
{
"error": "NO_NUMBERS",
"message": "No phone numbers available for the requested service/country."
}Errors are returned as tool results (not thrown as exceptions), so the LLM can reason about them and take corrective action.
| Code | Meaning |
|---|---|
BAD_KEY | Invalid or missing API key |
NO_BALANCE | Insufficient account balance |
NO_NUMBERS | No phone numbers available |
WRONG_SERVICE | Invalid service code |
WRONG_COUNTRY | Invalid or missing country ID |
WRONG_ACTIVATION_ID | Invalid activation ID |
EARLY_CANCEL_DENIED | Cannot cancel within 5 minutes of ordering |
BANNED | Account is blocked or rate-limited (HTTP 429) |
CONCURRENT_LIMIT | Concurrent activation limit reached (HTTP 429) |
NO_ACTIVATION | No activation found with the given ID |
The API enforces rate limits and returns X-RateLimit-Limit and X-RateLimit-Remaining headers on every response. When the rate limit is exceeded (HTTP 429), the API returns a Retry-After header indicating how many seconds to wait before retrying.
The MCP server captures these headers automatically. Use the get_rate_limit_info tool to check your current rate limit status at any time. When a rate limit error occurs, the error response includes:
{
"error": "BANNED",
"message": "Account or IP has been banned",
"httpStatus": 429,
"retryAfter": 60,
"rateLimitLimit": 100,
"rateLimitRemaining": 0
}For step-by-step installation instructions for your specific IDE, see:
If you are an LLM looking to install this MCP server autonomously, see:
Here's a typical SMS verification workflow using the MCP tools:
1. get_balance → Check you have funds
2. get_prices(service="wa", country="73") → Check price and availability
3. order_number(service="wa", country="73") → Purchase a number → get activationId
4. set_activation_status(id, status="1") → Signal "ready to receive SMS"
5. get_activation_status(id) → Poll until STATUS_OK:{code}
6. set_activation_status(id, status="6") → Finish the activationgit clone https://github.com/VirtualSMSLabs/mcp.git
cd mcp
npm install
npm run build
npm startnpm run inspectorThis launches the MCP Inspector — a web UI for interactively testing MCP tools.
MIT — Copyright (c) 2026 VirtualSMS Labs
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.