virtualsms-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,140 @@
1
+ # VirtualSMS MCP Server — Architecture
2
+
3
+ ## Overview
4
+
5
+ The VirtualSMS MCP server is a **stdio-transport MCP server** written in TypeScript. It wraps the VirtualSMS REST API and WebSocket gateway, exposing them as 11 MCP tools that AI agents can call directly.
6
+
7
+ ---
8
+
9
+ ## How MCP stdio Transport Works
10
+
11
+ ```
12
+ Claude Desktop / Cursor
13
+
14
+ │ stdin/stdout (JSON-RPC 2.0)
15
+
16
+ virtualsms-mcp process (Node.js)
17
+
18
+ ├──► REST API calls (axios)
19
+ │ https://virtualsms.io/api/v1/
20
+
21
+ └──► WebSocket connection (ws)
22
+ wss://virtualsms.io/ws/orders
23
+ ```
24
+
25
+ The MCP client (Claude Desktop, Cursor) spawns `virtualsms-mcp` as a child process and communicates via stdin/stdout using JSON-RPC 2.0. The server is persistent — it stays alive for the lifetime of the AI session, which is why it can hold WebSocket connections.
26
+
27
+ **Important:** Never write to stdout except via the MCP SDK. Any `console.log()` would corrupt the JSON-RPC stream. Use `process.stderr` for debug output.
28
+
29
+ ---
30
+
31
+ ## Client → API Flow
32
+
33
+ All REST calls go through `VirtualSMSClient` (src/client.ts):
34
+
35
+ ```
36
+ Tool Handler → VirtualSMSClient → axios → https://virtualsms.io/api/v1/
37
+ ```
38
+
39
+ The client:
40
+ - Attaches `Authorization: Bearer {apiKey}` to all authenticated requests
41
+ - Normalizes errors into human-readable messages
42
+ - Handles 401/403 with clear "set VIRTUALSMS_API_KEY" guidance
43
+
44
+ ---
45
+
46
+ ## Auth Flow
47
+
48
+ 1. User sets `VIRTUALSMS_API_KEY=vms_xxxxx` in their MCP config
49
+ 2. On startup, the MCP server reads `process.env.VIRTUALSMS_API_KEY`
50
+ 3. Every API call includes `Authorization: Bearer vms_xxxxx`
51
+ 4. The backend validates the key by SHA-256 hash lookup in `api_keys` table
52
+ 5. For WebSocket, the key is passed as `?api_key=vms_xxxxx` query param
53
+
54
+ ---
55
+
56
+ ## WebSocket Connection Lifecycle (`wait_for_code`)
57
+
58
+ ```
59
+ 1. buy_number() → REST POST /api/v1/order → {order_id, phone_number}
60
+
61
+ 2. Connect WebSocket:
62
+ wss://virtualsms.io/ws/orders?order_id={id}&api_key={key}
63
+
64
+ 3. Server sends: {type: "connected", order_id: "...", phone_number: "...", status: "pending"}
65
+
66
+ 4. When SMS arrives, server pushes:
67
+ {type: "sms", code: "12345", full_text: "Your code is 12345", sender: "..."}
68
+
69
+ 5. MCP server resolves with the code, closes WebSocket.
70
+
71
+ 6. If WebSocket fails (network error, server unreachable):
72
+ → Fallback to polling GET /api/v1/order/{id} every 5s
73
+
74
+ 7. If timeout:
75
+ → Return {success: false, order_id: ...} so user can recover
76
+ → Do NOT cancel automatically (user may still want the code)
77
+ ```
78
+
79
+ **Reconnect logic:** If the WebSocket disconnects unexpectedly (not on error/timeout), the client reconnects once after 1 second before falling back to polling.
80
+
81
+ ---
82
+
83
+ ## Error Handling Strategy
84
+
85
+ All tool errors are wrapped as `McpError` to prevent server crashes:
86
+
87
+ | Error type | McpError code |
88
+ |------------|---------------|
89
+ | Zod validation | `InvalidParams` |
90
+ | Missing API key | `InvalidRequest` |
91
+ | Network/API errors | `InternalError` |
92
+ | Unknown tool name | `MethodNotFound` |
93
+
94
+ This means the AI agent always gets a structured error it can act on, rather than a crash.
95
+
96
+ ---
97
+
98
+ ## File Structure
99
+
100
+ ```
101
+ virtualsms-mcp/
102
+ ├── src/
103
+ │ ├── index.ts # MCP server setup, tool routing, startup
104
+ │ ├── client.ts # VirtualSMSClient — REST API wrapper
105
+ │ └── tools.ts # Tool definitions (schemas) + handlers
106
+ ├── dist/ # Compiled output (from tsc)
107
+ │ ├── index.js # Has #!/usr/bin/env node shebang
108
+ │ ├── client.js
109
+ │ └── tools.js
110
+ ├── package.json
111
+ ├── tsconfig.json
112
+ ├── README.md
113
+ ├── ROADMAP.md
114
+ └── ARCHITECTURE.md
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Adding a New Tool
120
+
121
+ 1. Add input schema (zod) to `src/tools.ts`
122
+ 2. Add tool definition to `TOOL_DEFINITIONS` array
123
+ 3. Add handler function `handleXxx()` to `src/tools.ts`
124
+ 4. Add case to switch in `src/index.ts`
125
+ 5. Export schema + handler from `src/tools.ts`
126
+ 6. `npm run build`
127
+
128
+ ---
129
+
130
+ ## Local Development
131
+
132
+ ```bash
133
+ npm install
134
+ npm run build # compile TypeScript
135
+ npm run dev # watch mode (tsc --watch)
136
+ node dist/index.js # test startup (exits immediately — needs MCP client)
137
+
138
+ # Test with MCP Inspector:
139
+ npx @modelcontextprotocol/inspector node dist/index.js
140
+ ```
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 VirtualSMS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,270 @@
1
+ # VirtualSMS MCP Server
2
+
3
+ Receive SMS verification codes directly inside your AI agent workflows. Supports Claude Desktop, Cursor, and any MCP-compatible client.
4
+
5
+ **Powered by [VirtualSMS.io](https://virtualsms.io)** — virtual phone numbers for SMS verification.
6
+
7
+ ---
8
+
9
+ ## Quick Start
10
+
11
+ ```bash
12
+ npx virtualsms-mcp
13
+ ```
14
+
15
+ Or install globally:
16
+
17
+ ```bash
18
+ npm install -g virtualsms-mcp
19
+ ```
20
+
21
+ Get your API key at [virtualsms.io](https://virtualsms.io).
22
+
23
+ ---
24
+
25
+ ## Configuration
26
+
27
+ ### Claude Desktop
28
+
29
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "virtualsms": {
35
+ "command": "npx",
36
+ "args": ["virtualsms-mcp"],
37
+ "env": {
38
+ "VIRTUALSMS_API_KEY": "vms_your_api_key_here"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ ### Cursor
46
+
47
+ Edit `~/.cursor/mcp.json`:
48
+
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "virtualsms": {
53
+ "command": "npx",
54
+ "args": ["virtualsms-mcp"],
55
+ "env": {
56
+ "VIRTUALSMS_API_KEY": "vms_your_api_key_here"
57
+ }
58
+ }
59
+ }
60
+ }
61
+ ```
62
+
63
+ ### Environment Variables
64
+
65
+ | Variable | Required | Default | Description |
66
+ |----------|----------|---------|-------------|
67
+ | `VIRTUALSMS_API_KEY` | Yes (for auth tools) | — | Your VirtualSMS API key |
68
+ | `VIRTUALSMS_BASE_URL` | No | `https://virtualsms.io` | API base URL |
69
+
70
+ ---
71
+
72
+ ## Tools (11 total)
73
+
74
+ ### Discovery Tools (no auth required)
75
+
76
+ #### `list_services`
77
+ Get all available SMS verification services.
78
+
79
+ ```
80
+ list_services()
81
+ → [{code: "telegram", name: "Telegram"}, ...]
82
+ ```
83
+
84
+ #### `list_countries`
85
+ Get all available countries for SMS verification.
86
+
87
+ ```
88
+ list_countries()
89
+ → [{iso: "US", name: "United States"}, ...]
90
+ ```
91
+
92
+ #### `check_price`
93
+ Check price and availability for a service + country combination.
94
+
95
+ ```
96
+ check_price(service: "telegram", country: "US")
97
+ → {price_usd: 0.15, available: true}
98
+ ```
99
+
100
+ #### `find_cheapest`
101
+ Find cheapest countries for a service, sorted by price.
102
+
103
+ ```
104
+ find_cheapest(service: "telegram", limit: 5)
105
+ → {cheapest_options: [{country: "PK", price_usd: 0.05, ...}], total_available_countries: 23}
106
+ ```
107
+
108
+ #### `search_service`
109
+ Find the right service code using natural language.
110
+
111
+ ```
112
+ search_service(query: "uber")
113
+ → {matches: [{code: "uber", name: "Uber", match_score: 1.0}]}
114
+ ```
115
+
116
+ ### Account Tools (API key required)
117
+
118
+ #### `get_balance`
119
+ Check your account balance.
120
+
121
+ ```
122
+ get_balance()
123
+ → {balance_usd: 5.00}
124
+ ```
125
+
126
+ #### `active_orders`
127
+ List your active orders. **Essential for crash recovery.**
128
+
129
+ ```
130
+ active_orders()
131
+ active_orders(status: "pending")
132
+ → {count: 2, orders: [{order_id: "abc123", phone_number: "+14155552671", status: "pending", ...}]}
133
+ ```
134
+
135
+ Optional `status` filter: `"pending"`, `"sms_received"`, `"cancelled"`, `"completed"`
136
+
137
+ ### Order Management Tools (API key required)
138
+
139
+ #### `buy_number`
140
+ Purchase a virtual phone number.
141
+
142
+ ```
143
+ buy_number(service: "telegram", country: "US")
144
+ → {order_id: "abc123", phone_number: "+14155552671", expires_at: "...", status: "pending"}
145
+ ```
146
+
147
+ #### `check_sms`
148
+ Check if an SMS code has arrived for an order.
149
+
150
+ ```
151
+ check_sms(order_id: "abc123")
152
+ → {status: "sms_received", phone_number: "+14155552671", sms_code: "12345", sms_text: "Your code is 12345"}
153
+ ```
154
+
155
+ #### `cancel_order`
156
+ Cancel an order and request a refund (only if no SMS received yet).
157
+
158
+ ```
159
+ cancel_order(order_id: "abc123")
160
+ → {success: true, refunded: true}
161
+ ```
162
+
163
+ #### `wait_for_code` ⭐ Recommended
164
+ One-step tool: buys a number AND waits for the SMS code. Uses WebSocket for instant delivery with automatic polling fallback.
165
+
166
+ ```
167
+ wait_for_code(service: "telegram", country: "US")
168
+ wait_for_code(service: "whatsapp", country: "PK", timeout_seconds: 180)
169
+ → {
170
+ success: true,
171
+ phone_number: "+14155552671",
172
+ sms_code: "12345",
173
+ sms_text: "Your Telegram code: 12345",
174
+ order_id: "abc123",
175
+ delivery_method: "websocket",
176
+ elapsed_seconds: 8
177
+ }
178
+ ```
179
+
180
+ On timeout, returns `order_id` for recovery:
181
+ ```
182
+ → {success: false, error: "timeout", order_id: "abc123", phone_number: "...", tip: "Use check_sms..."}
183
+ ```
184
+
185
+ ---
186
+
187
+ ## How It Works
188
+
189
+ ### WebSocket vs Polling
190
+
191
+ `wait_for_code` uses a two-tier delivery system:
192
+
193
+ 1. **WebSocket (instant)** — connects to `wss://virtualsms.io/ws/orders?order_id=xxx` immediately after buying the number. When the SMS arrives, the server pushes it in real-time. Typical delivery: 2-15 seconds.
194
+
195
+ 2. **Polling fallback** — if WebSocket fails to connect or disconnects, automatically falls back to polling `GET /api/v1/order/{id}` every 5 seconds. Same result, slightly slower.
196
+
197
+ The `delivery_method` field in the response tells you which was used.
198
+
199
+ ### Architecture
200
+
201
+ ```
202
+ AI Agent (Claude/Cursor)
203
+
204
+ ▼ MCP stdio protocol
205
+ VirtualSMS MCP Server (this package)
206
+
207
+ ├──► REST API: https://virtualsms.io/api/v1/
208
+ │ buy_number, check_sms, cancel_order, etc.
209
+
210
+ └──► WebSocket: wss://virtualsms.io/ws/orders
211
+ real-time SMS push delivery
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Typical Workflows
217
+
218
+ ### Simple: Get a Telegram code
219
+ ```
220
+ wait_for_code(service: "telegram", country: "US")
221
+ ```
222
+
223
+ ### Budget: Find cheapest option first
224
+ ```
225
+ find_cheapest(service: "telegram", limit: 3)
226
+ # → picks cheapest country
227
+ wait_for_code(service: "telegram", country: "PK")
228
+ ```
229
+
230
+ ### Manual: Step by step
231
+ ```
232
+ buy_number(service: "google", country: "GB")
233
+ # → order_id: "abc123", phone: "+447911123456"
234
+
235
+ # Use the phone number to trigger the SMS...
236
+
237
+ check_sms(order_id: "abc123")
238
+ # Poll until sms_code appears, or:
239
+ cancel_order(order_id: "abc123") # if taking too long
240
+ ```
241
+
242
+ ---
243
+
244
+ ## Crash Recovery
245
+
246
+ If your MCP server crashes or the AI session is interrupted mid-verification:
247
+
248
+ 1. **Restart the MCP server** (it reconnects automatically)
249
+ 2. **List active orders:**
250
+ ```
251
+ active_orders(status: "pending")
252
+ ```
253
+ 3. **Check for codes:**
254
+ ```
255
+ check_sms(order_id: "abc123")
256
+ ```
257
+ 4. **Cancel if no longer needed:**
258
+ ```
259
+ cancel_order(order_id: "abc123")
260
+ ```
261
+
262
+ The `wait_for_code` tool always returns `order_id` even on timeout — this is your recovery handle.
263
+
264
+ ---
265
+
266
+ ## License
267
+
268
+ MIT — See [LICENSE](./LICENSE)
269
+
270
+ Built with ❤️ by [VirtualSMS.io](https://virtualsms.io)
package/ROADMAP.md ADDED
@@ -0,0 +1,48 @@
1
+ # VirtualSMS MCP Server — Roadmap
2
+
3
+ Current version: **v1.0.0** — Core tools, WebSocket delivery, crash recovery.
4
+
5
+ ---
6
+
7
+ ## v1.1 — Smart Features
8
+
9
+ - **`smart_verify`** — Auto-retry with different countries on failure. Finds cheapest country, buys number, waits for SMS, and if it times out, cancels and tries next country automatically. (Held from v1.0 pending refund mechanics verification.)
10
+ - **`recommend_country`** — ML-based country recommendation based on historical success rate analytics per service.
11
+ - **`price_compare`** — Show VirtualSMS price vs competitors for a given service/country.
12
+
13
+ ---
14
+
15
+ ## v1.2 — Batch & Automation
16
+
17
+ - **`batch_verify`** — Buy multiple numbers in parallel for bulk verification workflows.
18
+ - **`webhook_mode`** — Register a callback URL to receive SMS codes instead of waiting synchronously.
19
+ - Notification preferences: get notified via email or Telegram when a code arrives.
20
+
21
+ ---
22
+
23
+ ## v1.3 — Multi-Provider Aggregation
24
+
25
+ - Aggregate numbers across multiple upstream SMS providers.
26
+ - Auto-route to cheapest/fastest provider based on real-time availability.
27
+ - Unified service code mapping across providers (different providers use different codes for the same service).
28
+ - Provider health monitoring — skip providers with high failure rates.
29
+
30
+ ---
31
+
32
+ ## v2.0 — Remote Transport
33
+
34
+ - **SSE/Streamable HTTP transport** — zero-install, just add a URL to your MCP config.
35
+ - Hosted at `https://mcp.virtualsms.io`.
36
+ - OAuth2 auth flow for MCP clients (no more copying API keys).
37
+ - Usage dashboard for MCP users — see spend, history, success rates.
38
+
39
+ ---
40
+
41
+ ## Future Ideas
42
+
43
+ - **Number reputation scoring** — flag numbers with low verification success rates.
44
+ - **Success rate analytics** — per-service, per-country historical success rates exposed via API.
45
+ - **Rate limiting per API key tier** — different quotas for free, pro, enterprise.
46
+ - **Rental numbers** — keep a number for days or weeks (not just one-time verification).
47
+ - **Number recycling preferences** — opt out of recycled numbers for higher success rates.
48
+ - **Operator filtering** — prefer specific carriers per country for higher deliverability.
@@ -0,0 +1,49 @@
1
+ export interface Service {
2
+ code: string;
3
+ name: string;
4
+ icon?: string;
5
+ }
6
+ export interface Country {
7
+ iso: string;
8
+ name: string;
9
+ flag?: string;
10
+ }
11
+ export interface Price {
12
+ price_usd: number;
13
+ currency: string;
14
+ available: boolean;
15
+ }
16
+ export interface Balance {
17
+ balance_usd: number;
18
+ }
19
+ export interface Order {
20
+ order_id: string;
21
+ phone_number: string;
22
+ expires_at?: string;
23
+ status: string;
24
+ sms_code?: string;
25
+ sms_text?: string;
26
+ }
27
+ export interface CancelResult {
28
+ success: boolean;
29
+ refunded: boolean;
30
+ }
31
+ export declare class VirtualSMSClient {
32
+ private http;
33
+ private apiKey?;
34
+ private baseUrl;
35
+ constructor(baseUrl: string, apiKey?: string);
36
+ requireApiKey(): void;
37
+ listServices(): Promise<Service[]>;
38
+ listCountries(): Promise<Country[]>;
39
+ checkPrice(service: string, country: string): Promise<Price>;
40
+ getBalance(): Promise<Balance>;
41
+ createOrder(service: string, country: string): Promise<Order>;
42
+ getOrder(orderId: string): Promise<Order>;
43
+ cancelOrder(orderId: string): Promise<CancelResult>;
44
+ completeOrder(orderId: string): Promise<Order>;
45
+ listOrders(status?: string): Promise<Order[]>;
46
+ getApiKey(): string | undefined;
47
+ getBaseUrl(): string;
48
+ }
49
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,KAAK;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,OAAO;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAAgB;IAC5B,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IA4C5C,aAAa,IAAI,IAAI;IASf,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAKlC,aAAa,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAKnC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAO5D,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAM9B,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAM7D,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAMzC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAQnD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAQ9C,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAOnD,SAAS,IAAI,MAAM,GAAG,SAAS;IAI/B,UAAU,IAAI,MAAM;CAGrB"}
package/dist/client.js ADDED
@@ -0,0 +1,109 @@
1
+ import axios from 'axios';
2
+ export class VirtualSMSClient {
3
+ http;
4
+ apiKey;
5
+ baseUrl;
6
+ constructor(baseUrl, apiKey) {
7
+ this.apiKey = apiKey;
8
+ this.baseUrl = baseUrl;
9
+ this.http = axios.create({
10
+ baseURL: baseUrl,
11
+ timeout: 30000,
12
+ headers: {
13
+ 'Content-Type': 'application/json',
14
+ 'Accept': 'application/json',
15
+ },
16
+ });
17
+ // Add auth header if API key is set
18
+ this.http.interceptors.request.use((config) => {
19
+ if (this.apiKey) {
20
+ config.headers['Authorization'] = `Bearer ${this.apiKey}`;
21
+ }
22
+ return config;
23
+ });
24
+ // Handle errors gracefully
25
+ this.http.interceptors.response.use((res) => res, (err) => {
26
+ const status = err.response?.status;
27
+ const data = err.response?.data;
28
+ const message = data?.message || data?.error || err.message;
29
+ if (status === 401) {
30
+ throw new Error('Invalid API key. Get one at https://virtualsms.io');
31
+ }
32
+ else if (status === 402) {
33
+ throw new Error('Insufficient balance. Top up at https://virtualsms.io');
34
+ }
35
+ else if (status === 404) {
36
+ throw new Error(`Not found: ${message}`);
37
+ }
38
+ else if (status === 429) {
39
+ throw new Error('Rate limit exceeded. Please slow down requests.');
40
+ }
41
+ else if (status && status >= 500) {
42
+ throw new Error(`VirtualSMS server error (${status}). Please try again.`);
43
+ }
44
+ throw new Error(`API error: ${message}`);
45
+ });
46
+ }
47
+ requireApiKey() {
48
+ if (!this.apiKey) {
49
+ throw new Error('VIRTUALSMS_API_KEY is required for this operation. ' +
50
+ 'Get your API key at https://virtualsms.io');
51
+ }
52
+ }
53
+ async listServices() {
54
+ const res = await this.http.get('/api/v1/services');
55
+ return res.data;
56
+ }
57
+ async listCountries() {
58
+ const res = await this.http.get('/api/v1/countries');
59
+ return res.data;
60
+ }
61
+ async checkPrice(service, country) {
62
+ const res = await this.http.get('/api/v1/price', {
63
+ params: { service, country },
64
+ });
65
+ return res.data;
66
+ }
67
+ async getBalance() {
68
+ this.requireApiKey();
69
+ const res = await this.http.get('/api/v1/balance');
70
+ return res.data;
71
+ }
72
+ async createOrder(service, country) {
73
+ this.requireApiKey();
74
+ const res = await this.http.post('/api/v1/order', { service, country });
75
+ return res.data;
76
+ }
77
+ async getOrder(orderId) {
78
+ this.requireApiKey();
79
+ const res = await this.http.get(`/api/v1/order/${orderId}`);
80
+ return res.data;
81
+ }
82
+ async cancelOrder(orderId) {
83
+ this.requireApiKey();
84
+ const res = await this.http.put(`/api/v1/order/${orderId}`, {
85
+ action: 'cancel',
86
+ });
87
+ return res.data;
88
+ }
89
+ async completeOrder(orderId) {
90
+ this.requireApiKey();
91
+ const res = await this.http.put(`/api/v1/order/${orderId}`, {
92
+ action: 'complete',
93
+ });
94
+ return res.data;
95
+ }
96
+ async listOrders(status) {
97
+ this.requireApiKey();
98
+ const params = status ? { status } : {};
99
+ const res = await this.http.get('/api/v1/orders', { params });
100
+ return res.data;
101
+ }
102
+ getApiKey() {
103
+ return this.apiKey;
104
+ }
105
+ getBaseUrl() {
106
+ return this.baseUrl;
107
+ }
108
+ }
109
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * VirtualSMS MCP Server
4
+ * Receive SMS verification codes with AI agents
5
+ * https://virtualsms.io
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;GAIG"}