@dominusnode/mcp-server 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.
- package/LICENSE +21 -0
- package/README.md +303 -0
- package/dist/src/config.d.ts +15 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +111 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/http-client.d.ts +23 -0
- package/dist/src/http-client.d.ts.map +1 -0
- package/dist/src/http-client.js +241 -0
- package/dist/src/http-client.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +160 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/proxy-fetch.d.ts +23 -0
- package/dist/src/proxy-fetch.d.ts.map +1 -0
- package/dist/src/proxy-fetch.js +549 -0
- package/dist/src/proxy-fetch.js.map +1 -0
- package/dist/src/token-manager.d.ts +18 -0
- package/dist/src/token-manager.d.ts.map +1 -0
- package/dist/src/token-manager.js +192 -0
- package/dist/src/token-manager.js.map +1 -0
- package/dist/src/tools/account.d.ts +6 -0
- package/dist/src/tools/account.d.ts.map +1 -0
- package/dist/src/tools/account.js +329 -0
- package/dist/src/tools/account.js.map +1 -0
- package/dist/src/tools/agent-wallet.d.ts +5 -0
- package/dist/src/tools/agent-wallet.d.ts.map +1 -0
- package/dist/src/tools/agent-wallet.js +355 -0
- package/dist/src/tools/agent-wallet.js.map +1 -0
- package/dist/src/tools/crypto.d.ts +4 -0
- package/dist/src/tools/crypto.d.ts.map +1 -0
- package/dist/src/tools/crypto.js +102 -0
- package/dist/src/tools/crypto.js.map +1 -0
- package/dist/src/tools/fetch.d.ts +4 -0
- package/dist/src/tools/fetch.d.ts.map +1 -0
- package/dist/src/tools/fetch.js +73 -0
- package/dist/src/tools/fetch.js.map +1 -0
- package/dist/src/tools/keys.d.ts +4 -0
- package/dist/src/tools/keys.d.ts.map +1 -0
- package/dist/src/tools/keys.js +88 -0
- package/dist/src/tools/keys.js.map +1 -0
- package/dist/src/tools/paypal.d.ts +4 -0
- package/dist/src/tools/paypal.d.ts.map +1 -0
- package/dist/src/tools/paypal.js +50 -0
- package/dist/src/tools/paypal.js.map +1 -0
- package/dist/src/tools/plans.d.ts +4 -0
- package/dist/src/tools/plans.d.ts.map +1 -0
- package/dist/src/tools/plans.js +48 -0
- package/dist/src/tools/plans.js.map +1 -0
- package/dist/src/tools/proxy.d.ts +4 -0
- package/dist/src/tools/proxy.d.ts.map +1 -0
- package/dist/src/tools/proxy.js +51 -0
- package/dist/src/tools/proxy.js.map +1 -0
- package/dist/src/tools/sessions.d.ts +4 -0
- package/dist/src/tools/sessions.d.ts.map +1 -0
- package/dist/src/tools/sessions.js +21 -0
- package/dist/src/tools/sessions.js.map +1 -0
- package/dist/src/tools/slots.d.ts +4 -0
- package/dist/src/tools/slots.d.ts.map +1 -0
- package/dist/src/tools/slots.js +61 -0
- package/dist/src/tools/slots.js.map +1 -0
- package/dist/src/tools/teams.d.ts +4 -0
- package/dist/src/tools/teams.d.ts.map +1 -0
- package/dist/src/tools/teams.js +520 -0
- package/dist/src/tools/teams.js.map +1 -0
- package/dist/src/tools/usage.d.ts +4 -0
- package/dist/src/tools/usage.d.ts.map +1 -0
- package/dist/src/tools/usage.js +79 -0
- package/dist/src/tools/usage.js.map +1 -0
- package/dist/src/tools/wallet-auth.d.ts +6 -0
- package/dist/src/tools/wallet-auth.d.ts.map +1 -0
- package/dist/src/tools/wallet-auth.js +158 -0
- package/dist/src/tools/wallet-auth.js.map +1 -0
- package/dist/src/tools/wallet.d.ts +4 -0
- package/dist/src/tools/wallet.d.ts.map +1 -0
- package/dist/src/tools/wallet.js +57 -0
- package/dist/src/tools/wallet.js.map +1 -0
- package/dist/src/types.d.ts +142 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +33 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dominus Node
|
|
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,303 @@
|
|
|
1
|
+
# @dominusnode/mcp-server
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for Dominus Node — rotating proxy tools for AI agents.
|
|
4
|
+
|
|
5
|
+
**One server, every AI platform:** Claude Desktop, Claude Code, Gemini CLI, Codex CLI, Cursor, VS Code, Jan AI, Docker AI, elizaOS, LangChain, and any MCP-compatible client.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **24 tools** for proxy access, account management, billing, crypto payments, and usage monitoring
|
|
10
|
+
- **dominusnode_fetch** — fetch any URL through rotating residential/datacenter proxies
|
|
11
|
+
- **Geo-targeting** — route requests through specific countries, states, or cities
|
|
12
|
+
- **Bootstrap mode** — start with no API key, let the agent create its own account
|
|
13
|
+
- **Crypto payments** — pay with BTC, ETH, LTC, XMR, ZEC, USDC, SOL, USDT, DAI, BNB, LINK — or card/PayPal via Stripe
|
|
14
|
+
- **x402 ready** — machine-to-machine USDC micropayments (Coinbase Agentic Wallets)
|
|
15
|
+
- **Free tier** — 1GB bandwidth, 10 connections, no payment required
|
|
16
|
+
|
|
17
|
+
## Quick Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx @dominusnode/mcp-server
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
No API key? No problem — the server starts in **bootstrap mode** with tools to create an account and start using proxies immediately.
|
|
24
|
+
|
|
25
|
+
## Setup by Platform
|
|
26
|
+
|
|
27
|
+
### Claude Desktop
|
|
28
|
+
|
|
29
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"mcpServers": {
|
|
34
|
+
"dominusnode": {
|
|
35
|
+
"command": "npx",
|
|
36
|
+
"args": ["-y", "@dominusnode/mcp-server"],
|
|
37
|
+
"env": {
|
|
38
|
+
"DOMINUSNODE_API_KEY": "dn_live_your_key_here"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Claude Code
|
|
46
|
+
|
|
47
|
+
Add to `.mcp.json` in your project root:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcpServers": {
|
|
52
|
+
"dominusnode": {
|
|
53
|
+
"command": "npx",
|
|
54
|
+
"args": ["-y", "@dominusnode/mcp-server"],
|
|
55
|
+
"env": {
|
|
56
|
+
"DOMINUSNODE_API_KEY": "dn_live_your_key_here"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Gemini CLI
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"mcpServers": {
|
|
68
|
+
"dominusnode": {
|
|
69
|
+
"command": "npx",
|
|
70
|
+
"args": ["-y", "@dominusnode/mcp-server"],
|
|
71
|
+
"env": {
|
|
72
|
+
"DOMINUSNODE_API_KEY": "dn_live_your_key_here"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Codex CLI
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"mcpServers": {
|
|
84
|
+
"dominusnode": {
|
|
85
|
+
"command": "npx",
|
|
86
|
+
"args": ["-y", "@dominusnode/mcp-server"],
|
|
87
|
+
"env": {
|
|
88
|
+
"DOMINUSNODE_API_KEY": "dn_live_your_key_here"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Cursor / VS Code
|
|
96
|
+
|
|
97
|
+
Add to MCP server settings:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"dominusnode": {
|
|
102
|
+
"command": "npx",
|
|
103
|
+
"args": ["-y", "@dominusnode/mcp-server"],
|
|
104
|
+
"env": {
|
|
105
|
+
"DOMINUSNODE_API_KEY": "dn_live_your_key_here"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### elizaOS
|
|
112
|
+
|
|
113
|
+
Add to your agent's `character.json`:
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"mcpServers": {
|
|
118
|
+
"dominusnode": {
|
|
119
|
+
"command": "npx",
|
|
120
|
+
"args": ["-y", "@dominusnode/mcp-server"],
|
|
121
|
+
"env": {
|
|
122
|
+
"DOMINUSNODE_API_KEY": "dn_live_your_key_here"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### LangChain / LangGraph
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from langchain_mcp_adapters.client import MultiServerMCPClient
|
|
133
|
+
|
|
134
|
+
async with MultiServerMCPClient({
|
|
135
|
+
"dominusnode": {
|
|
136
|
+
"command": "npx",
|
|
137
|
+
"args": ["-y", "@dominusnode/mcp-server"],
|
|
138
|
+
"env": {"DOMINUSNODE_API_KEY": "dn_live_your_key_here"}
|
|
139
|
+
}
|
|
140
|
+
}) as client:
|
|
141
|
+
tools = client.get_tools()
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Jan AI / Docker AI
|
|
145
|
+
|
|
146
|
+
Same MCP config pattern — any client that speaks MCP over stdio works.
|
|
147
|
+
|
|
148
|
+
## Bootstrap Mode (No API Key)
|
|
149
|
+
|
|
150
|
+
Start without any configuration — the agent creates its own account:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"mcpServers": {
|
|
155
|
+
"dominusnode": {
|
|
156
|
+
"command": "npx",
|
|
157
|
+
"args": ["-y", "@dominusnode/mcp-server"]
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Available bootstrap tools:
|
|
164
|
+
- `dominusnode_setup` — one-shot account creation
|
|
165
|
+
- `dominusnode_register` / `dominusnode_login` — step-by-step
|
|
166
|
+
- `dominusnode_pay_crypto` — fund with crypto
|
|
167
|
+
- `dominusnode_x402_info` — machine-to-machine payment info
|
|
168
|
+
- `dominusnode_agent_wallet_create` / `dominusnode_agent_wallet_balance` — Coinbase Agentic Wallet
|
|
169
|
+
|
|
170
|
+
## Tools Reference (24 total)
|
|
171
|
+
|
|
172
|
+
### Proxy
|
|
173
|
+
|
|
174
|
+
| Tool | Description |
|
|
175
|
+
|------|-------------|
|
|
176
|
+
| `dominusnode_fetch` | Fetch URL through rotating proxy (HTTP/HTTPS, geo-targeting) |
|
|
177
|
+
| `dominusnode_get_proxy_config` | Proxy endpoints and geo options |
|
|
178
|
+
| `dominusnode_get_proxy_status` | Live status, latency, providers |
|
|
179
|
+
|
|
180
|
+
### Account (Self-Service)
|
|
181
|
+
|
|
182
|
+
| Tool | Description |
|
|
183
|
+
|------|-------------|
|
|
184
|
+
| `dominusnode_register` | Create a new account (free tier, no payment needed) |
|
|
185
|
+
| `dominusnode_login` | Login with email/password |
|
|
186
|
+
| `dominusnode_setup` | One-shot: register + create API key + get proxy config |
|
|
187
|
+
| `dominusnode_get_account_info` | Account email, status, MFA |
|
|
188
|
+
|
|
189
|
+
### Billing
|
|
190
|
+
|
|
191
|
+
| Tool | Description |
|
|
192
|
+
|------|-------------|
|
|
193
|
+
| `dominusnode_get_balance` | Wallet balance in USD |
|
|
194
|
+
| `dominusnode_get_forecast` | Spending forecast, days remaining |
|
|
195
|
+
| `dominusnode_get_transactions` | Transaction history (paginated) |
|
|
196
|
+
|
|
197
|
+
### Crypto Payments
|
|
198
|
+
|
|
199
|
+
| Tool | Description |
|
|
200
|
+
|------|-------------|
|
|
201
|
+
| `dominusnode_pay_crypto` | Create crypto invoice (BTC/ETH/LTC/XMR/ZEC/USDC/SOL/USDT/DAI/BNB/LINK) |
|
|
202
|
+
| `dominusnode_check_payment` | Check crypto payment status |
|
|
203
|
+
|
|
204
|
+
### x402 & Agentic Wallets
|
|
205
|
+
|
|
206
|
+
| Tool | Description |
|
|
207
|
+
|------|-------------|
|
|
208
|
+
| `dominusnode_x402_info` | Get x402 micropayment protocol info |
|
|
209
|
+
| `dominusnode_agent_wallet_create` | Create Coinbase Agentic Wallet with spending limits |
|
|
210
|
+
| `dominusnode_agent_wallet_balance` | Check agentic wallet balance and budget |
|
|
211
|
+
|
|
212
|
+
### Usage
|
|
213
|
+
|
|
214
|
+
| Tool | Description |
|
|
215
|
+
|------|-------------|
|
|
216
|
+
| `dominusnode_get_usage` | Usage summary (bytes, cost, requests) |
|
|
217
|
+
| `dominusnode_get_daily_usage` | Daily bandwidth breakdown |
|
|
218
|
+
| `dominusnode_get_top_hosts` | Top target hosts by bandwidth |
|
|
219
|
+
|
|
220
|
+
### API Keys
|
|
221
|
+
|
|
222
|
+
| Tool | Description |
|
|
223
|
+
|------|-------------|
|
|
224
|
+
| `dominusnode_list_keys` | List API keys |
|
|
225
|
+
| `dominusnode_create_key` | Create new API key (shown once) |
|
|
226
|
+
| `dominusnode_revoke_key` | Revoke API key by ID |
|
|
227
|
+
|
|
228
|
+
### Plans & Sessions
|
|
229
|
+
|
|
230
|
+
| Tool | Description |
|
|
231
|
+
|------|-------------|
|
|
232
|
+
| `dominusnode_get_plan` | Current plan and monthly usage |
|
|
233
|
+
| `dominusnode_list_plans` | Available pricing plans |
|
|
234
|
+
| `dominusnode_get_active_sessions` | Active proxy sessions |
|
|
235
|
+
|
|
236
|
+
## Environment Variables
|
|
237
|
+
|
|
238
|
+
| Variable | Required | Default | Description |
|
|
239
|
+
|----------|----------|---------|-------------|
|
|
240
|
+
| `DOMINUSNODE_API_KEY` | No | — | API key (omit for bootstrap mode) |
|
|
241
|
+
| `DOMINUSNODE_API_URL` | No | `https://api.dominusnode.com` | REST API base URL |
|
|
242
|
+
| `DOMINUSNODE_PROXY_HOST` | No | `proxy.dominusnode.com` | Proxy gateway host |
|
|
243
|
+
| `DOMINUSNODE_HTTP_PROXY_PORT` | No | `8080` | HTTP proxy port |
|
|
244
|
+
| `DOMINUSNODE_SOCKS5_PROXY_PORT` | No | `1080` | SOCKS5 proxy port |
|
|
245
|
+
| `DOMINUSNODE_FETCH_TIMEOUT_MS` | No | `30000` | Proxy fetch timeout (max 120000) |
|
|
246
|
+
| `DOMINUSNODE_FETCH_MAX_RESPONSE_BYTES` | No | `5242880` | Max response body (5MB) |
|
|
247
|
+
|
|
248
|
+
## Pricing
|
|
249
|
+
|
|
250
|
+
| Tier | Price | Bandwidth |
|
|
251
|
+
|------|-------|-----------|
|
|
252
|
+
| Free | $0 | 1 GB/month, 10 connections |
|
|
253
|
+
| Pay-as-you-go | $5/GB | Unlimited |
|
|
254
|
+
| Volume 100GB | $4/GB | 100 GB/month |
|
|
255
|
+
| Volume 1TB | $3/GB | 1 TB/month |
|
|
256
|
+
|
|
257
|
+
Crypto payments: BTC, ETH, LTC, XMR, ZEC, USDC, SOL, USDT, DAI, BNB, LINK
|
|
258
|
+
|
|
259
|
+
## Example: AI Agent Workflow
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
Agent: "I need to scrape product prices from 3 countries"
|
|
263
|
+
|
|
264
|
+
1. dominusnode_setup(email, password) → account + API key (if bootstrap mode)
|
|
265
|
+
2. dominusnode_get_balance() → "$0.00 (free tier: 1GB available)"
|
|
266
|
+
3. dominusnode_fetch(url: "https://shop.example.com/prices", country: "US") → US prices
|
|
267
|
+
4. dominusnode_fetch(url: "https://shop.example.com/prices", country: "GB") → UK prices
|
|
268
|
+
5. dominusnode_fetch(url: "https://shop.example.com/prices", country: "DE") → DE prices
|
|
269
|
+
6. dominusnode_get_usage(days: 1) → "0.3 MB, $0.002"
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
Agent: "I need anonymous proxy access"
|
|
274
|
+
|
|
275
|
+
1. dominusnode_pay_crypto(amount_usd: 10, currency: "XMR") → Monero invoice
|
|
276
|
+
2. (agent pays invoice)
|
|
277
|
+
3. dominusnode_check_payment(invoice_id) → "confirmed, $10.00 credited"
|
|
278
|
+
4. dominusnode_fetch(url: "https://target.com", country: "JP") → response
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Integration Guides
|
|
282
|
+
|
|
283
|
+
- [elizaOS Integration](docs/eliza-integration.md)
|
|
284
|
+
- [LangChain Integration](docs/langchain-integration.md)
|
|
285
|
+
|
|
286
|
+
## Development
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
cd packages/mcp-server
|
|
290
|
+
npm install
|
|
291
|
+
npm run build
|
|
292
|
+
npm test
|
|
293
|
+
|
|
294
|
+
# Run locally
|
|
295
|
+
DOMINUSNODE_API_KEY=dn_live_xxx node dist/src/index.js
|
|
296
|
+
|
|
297
|
+
# Run in bootstrap mode (no key)
|
|
298
|
+
node dist/src/index.js
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## License
|
|
302
|
+
|
|
303
|
+
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface McpConfig {
|
|
2
|
+
apiKey: string | null;
|
|
3
|
+
apiUrl: string;
|
|
4
|
+
proxyHost: string;
|
|
5
|
+
httpProxyPort: number;
|
|
6
|
+
socks5ProxyPort: number;
|
|
7
|
+
fetchTimeoutMs: number;
|
|
8
|
+
fetchMaxResponseBytes: number;
|
|
9
|
+
mcpAgentSecret: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class ConfigError extends Error {
|
|
12
|
+
constructor(message: string);
|
|
13
|
+
}
|
|
14
|
+
export declare function parseConfig(env?: Record<string, string | undefined>): McpConfig;
|
|
15
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,WAAW,CAAC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,SAAS,CAsG5F"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
export class ConfigError extends Error {
|
|
2
|
+
constructor(message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = "ConfigError";
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export function parseConfig(env = process.env) {
|
|
8
|
+
const apiKey = env["DOMINUSNODE_API_KEY"] ?? null;
|
|
9
|
+
// Validate format if provided, but allow null for bootstrap mode
|
|
10
|
+
if (apiKey !== null && !apiKey.startsWith("dn_live_")) {
|
|
11
|
+
throw new ConfigError("DOMINUSNODE_API_KEY must start with 'dn_live_'");
|
|
12
|
+
}
|
|
13
|
+
const apiUrl = (env["DOMINUSNODE_API_URL"] ?? "https://api.dominusnode.com").replace(/\/+$/, "");
|
|
14
|
+
// Validate API URL protocol to prevent credential leakage to non-HTTPS endpoints
|
|
15
|
+
try {
|
|
16
|
+
const parsedApiUrl = new URL(apiUrl);
|
|
17
|
+
if (parsedApiUrl.protocol !== "https:" && parsedApiUrl.protocol !== "http:") {
|
|
18
|
+
throw new ConfigError("DOMINUSNODE_API_URL must use http: or https: protocol");
|
|
19
|
+
}
|
|
20
|
+
// Warn when http: is used for non-localhost (credentials sent in plaintext)
|
|
21
|
+
if (parsedApiUrl.protocol === "http:" && !["localhost", "127.0.0.1", "[::1]"].includes(parsedApiUrl.hostname)) {
|
|
22
|
+
process.stderr.write("WARNING: DOMINUSNODE_API_URL uses http: — credentials will be sent in plaintext. Use https: in production.\n");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
if (e instanceof ConfigError)
|
|
27
|
+
throw e;
|
|
28
|
+
throw new ConfigError("DOMINUSNODE_API_URL is not a valid URL");
|
|
29
|
+
}
|
|
30
|
+
const proxyHost = env["DOMINUSNODE_PROXY_HOST"] ?? "proxy.dominusnode.com";
|
|
31
|
+
// Validate proxyHost strictly to prevent SSRF via config injection
|
|
32
|
+
if (!/^[a-zA-Z0-9.\-]+$/.test(proxyHost)) {
|
|
33
|
+
throw new ConfigError("DOMINUSNODE_PROXY_HOST contains invalid characters (only alphanumeric, dots, hyphens allowed)");
|
|
34
|
+
}
|
|
35
|
+
if (proxyHost.length > 253) {
|
|
36
|
+
throw new ConfigError("DOMINUSNODE_PROXY_HOST exceeds maximum hostname length (253)");
|
|
37
|
+
}
|
|
38
|
+
// Block bare localhost and other loopback/private hostnames
|
|
39
|
+
const BLOCKED_PROXY_HOSTS = new Set([
|
|
40
|
+
"localhost", "localhost.localdomain", "ip6-localhost", "ip6-loopback",
|
|
41
|
+
"0.0.0.0", "127.0.0.1",
|
|
42
|
+
]);
|
|
43
|
+
const proxyHostLower = proxyHost.toLowerCase();
|
|
44
|
+
if (BLOCKED_PROXY_HOSTS.has(proxyHostLower) ||
|
|
45
|
+
proxyHostLower.endsWith(".internal") ||
|
|
46
|
+
proxyHostLower.endsWith(".local") ||
|
|
47
|
+
proxyHostLower.endsWith(".localhost")) {
|
|
48
|
+
throw new ConfigError("DOMINUSNODE_PROXY_HOST must not be a localhost/internal hostname");
|
|
49
|
+
}
|
|
50
|
+
// Block private IP ranges
|
|
51
|
+
const ipMatch = proxyHost.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
|
|
52
|
+
if (ipMatch) {
|
|
53
|
+
// Block octal notation IPs (e.g., 0177.0.0.1) to prevent private IP bypass
|
|
54
|
+
const octets = [ipMatch[1], ipMatch[2], ipMatch[3], ipMatch[4]];
|
|
55
|
+
if (octets.some(o => o.startsWith("0") && o.length > 1)) {
|
|
56
|
+
throw new ConfigError("DOMINUSNODE_PROXY_HOST must not use octal IP notation");
|
|
57
|
+
}
|
|
58
|
+
const a = parseInt(ipMatch[1], 10);
|
|
59
|
+
const b = parseInt(ipMatch[2], 10);
|
|
60
|
+
if (a === 127 || a === 10 || a === 0 || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168)) {
|
|
61
|
+
throw new ConfigError("DOMINUSNODE_PROXY_HOST must not be a private/loopback IP address");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const httpProxyPort = parsePort(env["DOMINUSNODE_HTTP_PROXY_PORT"], 8080, "DOMINUSNODE_HTTP_PROXY_PORT");
|
|
65
|
+
const socks5ProxyPort = parsePort(env["DOMINUSNODE_SOCKS5_PROXY_PORT"], 1080, "DOMINUSNODE_SOCKS5_PROXY_PORT");
|
|
66
|
+
const fetchTimeoutMs = parsePositiveInt(env["DOMINUSNODE_FETCH_TIMEOUT_MS"], 30_000, "DOMINUSNODE_FETCH_TIMEOUT_MS");
|
|
67
|
+
if (fetchTimeoutMs > 120_000) {
|
|
68
|
+
throw new ConfigError("DOMINUSNODE_FETCH_TIMEOUT_MS must not exceed 120000");
|
|
69
|
+
}
|
|
70
|
+
const fetchMaxResponseBytes = parsePositiveInt(env["DOMINUSNODE_FETCH_MAX_RESPONSE_BYTES"], 5 * 1024 * 1024, "DOMINUSNODE_FETCH_MAX_RESPONSE_BYTES");
|
|
71
|
+
// Enforce upper bound to prevent config-based OOM
|
|
72
|
+
const MAX_FETCH_RESPONSE_BYTES = 50 * 1024 * 1024; // 50MB hard cap
|
|
73
|
+
if (fetchMaxResponseBytes > MAX_FETCH_RESPONSE_BYTES) {
|
|
74
|
+
throw new ConfigError(`DOMINUSNODE_FETCH_MAX_RESPONSE_BYTES must not exceed ${MAX_FETCH_RESPONSE_BYTES}`);
|
|
75
|
+
}
|
|
76
|
+
// Shared secret for MCP agent auto-verification (prevents header spoofing)
|
|
77
|
+
const mcpAgentSecret = env["MCP_AGENT_SECRET"] ?? "";
|
|
78
|
+
// Enforce minimum strength when MCP_AGENT_SECRET is set
|
|
79
|
+
if (mcpAgentSecret && mcpAgentSecret.length < 32) {
|
|
80
|
+
throw new ConfigError("MCP_AGENT_SECRET must be at least 32 characters when set");
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
apiKey,
|
|
84
|
+
apiUrl,
|
|
85
|
+
proxyHost,
|
|
86
|
+
httpProxyPort,
|
|
87
|
+
socks5ProxyPort,
|
|
88
|
+
fetchTimeoutMs,
|
|
89
|
+
fetchMaxResponseBytes,
|
|
90
|
+
mcpAgentSecret,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function parsePort(value, defaultValue, name) {
|
|
94
|
+
if (value === undefined)
|
|
95
|
+
return defaultValue;
|
|
96
|
+
const n = parseInt(value, 10);
|
|
97
|
+
if (isNaN(n) || n < 1 || n > 65535) {
|
|
98
|
+
throw new ConfigError(`${name} must be a valid port number (1-65535)`);
|
|
99
|
+
}
|
|
100
|
+
return n;
|
|
101
|
+
}
|
|
102
|
+
function parsePositiveInt(value, defaultValue, name) {
|
|
103
|
+
if (value === undefined)
|
|
104
|
+
return defaultValue;
|
|
105
|
+
const n = parseInt(value, 10);
|
|
106
|
+
if (isNaN(n) || n <= 0) {
|
|
107
|
+
throw new ConfigError(`${name} must be a positive integer`);
|
|
108
|
+
}
|
|
109
|
+
return n;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { TokenManager } from "./token-manager.js";
|
|
2
|
+
export interface HttpRequestOptions {
|
|
3
|
+
method: string;
|
|
4
|
+
path: string;
|
|
5
|
+
body?: unknown;
|
|
6
|
+
headers?: Record<string, string>;
|
|
7
|
+
requiresAuth?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare class HttpClient {
|
|
10
|
+
private baseUrl;
|
|
11
|
+
private tokenManager;
|
|
12
|
+
private rateLimiter;
|
|
13
|
+
private mcpAgentSecret;
|
|
14
|
+
constructor(baseUrl: string, tokenManager: TokenManager, mcpAgentSecret?: string);
|
|
15
|
+
request<T>(opts: HttpRequestOptions): Promise<T>;
|
|
16
|
+
/** Store tokens from an external auth flow (e.g., registration in bootstrap mode) */
|
|
17
|
+
storeTokens(accessToken: string, refreshToken: string): void;
|
|
18
|
+
get<T>(path: string, requiresAuth?: boolean): Promise<T>;
|
|
19
|
+
post<T>(path: string, body?: unknown, requiresAuth?: boolean): Promise<T>;
|
|
20
|
+
patch<T>(path: string, body?: unknown): Promise<T>;
|
|
21
|
+
delete<T>(path: string): Promise<T>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=http-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../../src/http-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAwFvD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,qBAAa,UAAU;IAKnB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,YAAY;IALtB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,cAAc,CAAS;gBAGrB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,YAAY,EAClC,cAAc,SAAK;IASf,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC;IA+ItD,qFAAqF;IACrF,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAItD,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,UAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIrD,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,YAAY,UAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAItE,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIlD,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAG1C"}
|