@portproof/mcp 0.0.0-stage → 0.2.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 +150 -2
- package/dist/index.js +1814 -0
- package/llms.txt +42 -0
- package/package.json +56 -4
package/llms.txt
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Portproof MCP server
|
|
2
|
+
|
|
3
|
+
> Proxy traffic by the GB: one prepaid GB balance per organisation, usable on two shared pools, mobile 4G/5G (carrier modems) and residential (opt-in peer devices). Pool, country, rotation and session are chosen in the proxy username, so one credential serves everything. The pools are shared: the traffic is never dedicated, private, static or unlimited, and a sticky session keeps the same device while the carrier may still change its IP. Countries online now come from list_countries; never state a country count from memory. Dedicated ports are coming soon and not on sale yet. Paid in cryptocurrency. This stdio MCP server (npm package @portproof/mcp) exposes the Portproof API (base `PORTPROOF_API_URL` + `/v1`, default https://api.portproof.org; key `PORTPROOF_API_KEY`) as nineteen tools.
|
|
4
|
+
|
|
5
|
+
## Traffic tools
|
|
6
|
+
|
|
7
|
+
- get_traffic {} -> GB total / used / left, expiry (validity_days 0 = GB never expire), limits, connection details with the password masked (null unless the key holds ports:write). Key scope ports:read.
|
|
8
|
+
- list_countries {} -> devices online now per pool and country, counts only (exit addresses are never listed). Public.
|
|
9
|
+
- build_proxy_url { pool, country, rotation, session?, protocol?, reveal_password? } -> username, URL and curl / Python / Node / Playwright snippets; password masked unless reveal_password is true. Key scope ports:write.
|
|
10
|
+
- test_connection { pool?, country?, rotation? } -> ok, exit IP, latency, error_code; exit_country is normally null (no country check); never report the requested country as the exit country. 6 per minute. Key scope ports:write.
|
|
11
|
+
- buy_traffic { gb | trial:true, accept_terms:true, confirm:true, idempotency_key } -> order with gb and cost_cents as the server recorded them. Charges the wallet. accept_terms records that the user accepts the terms, the acceptable-use policy and the immediate start of the service. Key scope ports:write.
|
|
12
|
+
|
|
13
|
+
## Port tools (dedicated ports: coming soon, not on sale yet)
|
|
14
|
+
|
|
15
|
+
- get_pricing {} -> field traffic (per-GB tier table, packages, trial, validity) and field skus (port price table; buy_via ports or cart; Partner network SKUs only while on sale for the caller's organisation). Public.
|
|
16
|
+
- search_inventory { country?, carrier? } -> available Own network ports per site/carrier with carrier_id. Public.
|
|
17
|
+
- quote { sku, term, quantity } -> unit_cents, discount_pct, total_cents, currency, charged:false; for a Partner network SKU price_cents and shop_url instead, or not_on_sale. Public.
|
|
18
|
+
- buy_port { sku, term, carrier_id?, auto_renew?, confirm:true, idempotency_key } -> port, proxy_urls, cost_cents, currency. Charges money. A Partner network SKU (buy_via "cart" in get_pricing) is bought in the web shop: the answer is purchased:false, charged:false, price_cents and shop_url, or not_on_sale.
|
|
19
|
+
- list_ports { limit?, cursor? } -> compact port summaries (label, network, no credentials), next_cursor. A Partner network port has no site_code.
|
|
20
|
+
- get_port { port_id } -> full Port with label, network, credentials (if owned; Partner network ports carry credentials.http and credentials.socks5, which may differ in every field), capabilities, renewal, rotation_url (the Portproof link that rotates the IP) and proxy_urls built from each protocol's own set.
|
|
21
|
+
- rotate { port_id, confirm:true, idempotency_key } -> rotated, reason, old_ip4, new_ip4, elapsed_ms and the signed rotation record. Waits up to 180 s in all, following the status link when the first answer is 202; status pending with rotation_id when still running. No charge.
|
|
22
|
+
- set_rotation_schedule { port_id, interval_s (0 = sticky, else 60..86400), confirm:true, idempotency_key } -> rotation_interval_s, sticky. No charge.
|
|
23
|
+
- renew_port { port_id, confirm:true, idempotency_key } -> renewed, ends_at, auto_renew, cost_cents, currency. One more term from the account balance. Charges money.
|
|
24
|
+
- set_auto_renew { port_id, enabled, confirm:true, idempotency_key } -> auto_renew, ends_at. Off: the port ends at the end of its term. No charge now.
|
|
25
|
+
- get_passport { port_id } -> port details (API object passport) with label and network. Never credentials.
|
|
26
|
+
- get_receipt { receipt_id } -> rotation record plus signature { verified, key_id, reason, keys_url } checked against <API origin>/.well-known/portproof-keys.json.
|
|
27
|
+
- get_usage { port_id, from?, to?, granularity? } -> buckets, totals, data[]. Default granularity hour.
|
|
28
|
+
- get_status {} -> platform, sites, carriers, public incidents, support. Public.
|
|
29
|
+
|
|
30
|
+
## Rules
|
|
31
|
+
|
|
32
|
+
- buy_traffic, buy_port, renew_port, rotate, set_rotation_schedule and set_auto_renew are refused (error code confirmation_required / idempotency_key_required, no API call made) unless confirm is exactly true and idempotency_key is a non-empty printable string; buy_traffic is also refused (terms_acceptance_required) without accept_terms: true. Ask the user before confirming. A refused purchase stays stored under its key for 24 h, so buy with a new key after fixing the cause. Reuse an idempotency_key only to retry the identical request; the API answers idempotency_conflict (409) when a key is reused for a different purchase.
|
|
33
|
+
- cost_cents is present whenever money moved (buy_traffic, buy_port, renew_port). quote never charges.
|
|
34
|
+
- Every response is compact JSON in one text block. Errors: {"error":{code,status,title,detail,retry_after?,errors?}} using API problem codes: insufficient_funds, kyb_required_for_volume, trial_already_used, traffic_not_purchased, kyb_required, no_inventory, use_cart, conflict, port_cooldown (retry_after seconds), rescore_quota, insufficient_scope, unauthorized, not_found, validation_failed, idempotency_conflict, rate_limited; local codes: confirmation_required, idempotency_key_required, terms_acceptance_required, not_on_sale, api_unreachable, timeout, http_error, config_missing (no PORTPROOF_API_KEY), unexpected_response.
|
|
35
|
+
- Ids are prefixed ULIDs: prt_ ports, rot_ rotations (rotation records), car_ carriers, ord_ orders.
|
|
36
|
+
- Money is integer cents in EUR (the us-4g port SKU is USD). Times are ISO 8601 UTC.
|
|
37
|
+
|
|
38
|
+
## Setup
|
|
39
|
+
|
|
40
|
+
- Run: npx -y @portproof/mcp (Node.js 20 or newer) with PORTPROOF_API_KEY in the environment. PORTPROOF_API_URL is optional and defaults to https://api.portproof.org.
|
|
41
|
+
- Client config: {"mcpServers":{"portproof":{"command":"npx","args":["-y","@portproof/mcp"],"env":{"PORTPROOF_API_KEY":"pk_live_..."}}}}. Claude Desktop, Claude Code and Cursor snippets are in README.md.
|
|
42
|
+
- API keys are created in the dashboard at https://portproof.org/app/keys; there is no sandbox, every key acts on the real balance.
|
package/package.json
CHANGED
|
@@ -1,6 +1,58 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portproof/mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "MCP server for Portproof: proxy traffic by the GB on shared mobile 4G/5G and residential pools, paid in crypto, as tools for AI agents",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"mcp",
|
|
8
|
+
"mcp-server",
|
|
9
|
+
"model-context-protocol",
|
|
10
|
+
"proxy",
|
|
11
|
+
"proxies",
|
|
12
|
+
"mobile-proxy",
|
|
13
|
+
"residential-proxy",
|
|
14
|
+
"4g",
|
|
15
|
+
"5g",
|
|
16
|
+
"ai-agents",
|
|
17
|
+
"claude",
|
|
18
|
+
"cursor",
|
|
19
|
+
"price-monitoring",
|
|
20
|
+
"geo-testing"
|
|
21
|
+
],
|
|
22
|
+
"homepage": "https://portproof.org",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"author": "Portproof",
|
|
25
|
+
"mcpName": "org.portproof/mcp",
|
|
26
|
+
"bin": {
|
|
27
|
+
"portproof-mcp": "dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist/index.js",
|
|
31
|
+
"llms.txt"
|
|
32
|
+
],
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=20"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"dev": "tsx src/index.ts",
|
|
41
|
+
"build": "tsc -p tsconfig.json --noEmit && node scripts/build.mjs",
|
|
42
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.scripts.json --noEmit",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"smoke": "tsx scripts/smoke.ts",
|
|
45
|
+
"smoke:stub": "tsx scripts/smoke.ts --stub",
|
|
46
|
+
"prepack": "npm run build",
|
|
47
|
+
"prepublishOnly": "npm run typecheck && npm run test"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
51
|
+
"ulid": "^3.0.0",
|
|
52
|
+
"zod": "^3.25.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@portproof/shared": "*",
|
|
56
|
+
"esbuild": "^0.25.12"
|
|
57
|
+
}
|
|
58
|
+
}
|