portveil-mcp 0.4.1 → 0.4.2
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/README.md +16 -0
- package/dist/index.js +3 -3
- package/dist/portveil.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,6 +34,8 @@ Devices can be named loosely ("scraper" finds "Scraper box"); an ambiguous name
|
|
|
34
34
|
|
|
35
35
|
## Setup
|
|
36
36
|
|
|
37
|
+
No account yet? [Start free](https://portveil.com/free/) with just an email, no card.
|
|
38
|
+
|
|
37
39
|
1. In the [Portveil dashboard](https://portveil.com/dashboard/), create an **API token**. Choose **control** scope to let the assistant move devices, or **read** to let it only look. Don't give it your account key.
|
|
38
40
|
2. Note your account ID (`acct_…`).
|
|
39
41
|
3. Add the server to your assistant:
|
|
@@ -56,6 +58,20 @@ claude mcp add portveil -e PORTVEIL_ACCOUNT_ID=acct_… -e PORTVEIL_TOKEN=clt_
|
|
|
56
58
|
}
|
|
57
59
|
```
|
|
58
60
|
|
|
61
|
+
**Hermes Agent**: Hermes only installs npm packages older than 14 days, so install into its own folder and run it with node:
|
|
62
|
+
```bash
|
|
63
|
+
cd ~ && npm install --prefix ~/.hermes/mcp-servers/portveil portveil-mcp@latest
|
|
64
|
+
echo 'PORTVEIL_TOKEN=clt_…' >> ~/.hermes/.env
|
|
65
|
+
hermes mcp add portveil --command node \
|
|
66
|
+
--env PORTVEIL_ACCOUNT_ID=acct_… 'PORTVEIL_TOKEN=${PORTVEIL_TOKEN}' \
|
|
67
|
+
--args ~/.hermes/mcp-servers/portveil/node_modules/portveil-mcp/dist/index.js
|
|
68
|
+
```
|
|
69
|
+
For Hermes to use it well (when to act, what to confirm first, how to add devices), also install the Portveil skill from [ClawHub](https://clawhub.ai/roybogs/portveil):
|
|
70
|
+
```bash
|
|
71
|
+
hermes skills install roybogs/portveil
|
|
72
|
+
```
|
|
73
|
+
(Source: [`skills/portveil/SKILL.md`](skills/portveil/SKILL.md).)
|
|
74
|
+
|
|
59
75
|
Devices must be running the Portveil app or the Portveil agent with remote control on. Devices using the plain WireGuard app are shown but can't be moved.
|
|
60
76
|
|
|
61
77
|
## Security
|
package/dist/index.js
CHANGED
|
@@ -172,7 +172,7 @@ server.registerTool("add_device", {
|
|
|
172
172
|
kind: z.enum(["phone_or_computer", "linux_machine"]).describe("phone_or_computer: WireGuard app on a phone or laptop. linux_machine: a Linux server or agent machine running the Portveil agent"),
|
|
173
173
|
temporary_minutes: z.number().int().min(5).max(43200).optional().describe("phone_or_computer only: delete the device automatically after this many minutes (5 to 43200, i.e. 30 days). Omit for a permanent device"),
|
|
174
174
|
folder: z.string().min(1).optional().describe("phone_or_computer only: folder to save the tunnel files in. Default ~/Portveil/<name>"),
|
|
175
|
-
split_tunnel: z.boolean().optional().describe("linux_machine only: default
|
|
175
|
+
split_tunnel: z.boolean().optional().describe("linux_machine only, advanced: default false (full tunnel), which sends everything the machine connects to through Portveil and keeps SSH and other incoming connections on their normal route, so remote servers stay reachable. true only reaches Portveil's own network: the machine's internet traffic would NOT go through Portveil"),
|
|
176
176
|
},
|
|
177
177
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
178
178
|
}, ({ name, kind, temporary_minutes, folder, split_tunnel }) => run(async () => {
|
|
@@ -183,8 +183,8 @@ server.registerTool("add_device", {
|
|
|
183
183
|
}
|
|
184
184
|
if (kind === "linux_machine") {
|
|
185
185
|
return `Run these as root on the machine you're adding. It makes its own VPN key, so this can't be done from here. The token prompt doesn't echo; use an admin-scope API token or the account key, and never paste it into a chat.\n\n` +
|
|
186
|
-
agentSetup(apiBase, accountId, name, split_tunnel ??
|
|
187
|
-
`\n\
|
|
186
|
+
agentSetup(apiBase, accountId, name, split_tunnel ?? false) +
|
|
187
|
+
`\n\nIts own traffic then goes through Portveil, while SSH and other incoming connections keep their normal route, so a remote session stays up. The daemon keeps running; install it as a service to survive reboots. "${name}" then appears in list_devices, and can be moved once its exit confirms it${slots}.`;
|
|
188
188
|
}
|
|
189
189
|
const dir = resolve(folder?.replace(/^~(?=$|\/)/, homedir()) ?? join(homedir(), "Portveil", name.replace(/[^\w .-]+/g, "_")));
|
|
190
190
|
const k = wgKeypair();
|
package/dist/portveil.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Portveil API client and the logic behind the MCP tools. No MCP types here,
|
|
2
2
|
// so it can be tested against a fake API.
|
|
3
3
|
import { generateKeyPairSync } from "node:crypto";
|
|
4
|
-
export const VERSION = "0.4.
|
|
4
|
+
export const VERSION = "0.4.2";
|
|
5
5
|
/** "↓ 42.3 Mbps ↑ 6.1 Mbps", or "idle" when nothing is moving. */
|
|
6
6
|
export function describeSpeed(speed) {
|
|
7
7
|
if (speed.down_mbps < 0.1 && speed.up_mbps < 0.1)
|
|
@@ -24,7 +24,7 @@ export function wgConfig(priv, address, s) {
|
|
|
24
24
|
export function agentSetup(apiBase, accountId, name, splitTunnel) {
|
|
25
25
|
const q = (v) => `'${v.replace(/'/g, `'\\''`)}'`;
|
|
26
26
|
return [
|
|
27
|
-
"apt install -y wireguard-tools curl",
|
|
27
|
+
"apt install -y wireguard-tools curl nftables",
|
|
28
28
|
"curl -fsSLO https://portveil.com/downloads/portveil-agent",
|
|
29
29
|
"curl -fsSL https://portveil.com/downloads/portveil-agent.sha256 | sha256sum -c -",
|
|
30
30
|
"chmod +x portveil-agent",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "portveil-mcp",
|
|
3
3
|
"mcpName": "io.github.roybogs/portveil-mcp",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.2",
|
|
5
5
|
"description": "MCP server for Portveil: let AI assistants see your devices and move them between VPN locations.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|