@pascalcouturier/skill-builder-mcp 2.1.0 → 2.1.1
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/CHANGELOG.md +13 -0
- package/SECURITY.md +11 -11
- package/dist/cli.js +25 -17
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,19 @@ The install line names the major version (`@2`), so restarting your AI tool or i
|
|
|
9
9
|
fetches the newest release of that major (see **Updating** in the
|
|
10
10
|
[README](./README.md#updating)).
|
|
11
11
|
|
|
12
|
+
## 2.1.1
|
|
13
|
+
|
|
14
|
+
Hardening.
|
|
15
|
+
|
|
16
|
+
- **At most four connections are held open at once.** A local program can fake the `Origin`
|
|
17
|
+
header and open sockets, so the connector now refuses new ones (HTTP 503) while four are
|
|
18
|
+
open. One Skill Builder tab needs one; the rest cover a reload or stale tabs. A turned-away
|
|
19
|
+
socket that stays silent is closed after 10 seconds, so idle ones can not block the real tab. Programs still
|
|
20
|
+
can not pair without the code only you see.
|
|
21
|
+
- No protocol change, so every 1.x and 2.x release keeps working with the current site.
|
|
22
|
+
- No new permissions: the connector still reads no files and no environment variables beyond
|
|
23
|
+
the allowlist, and makes no outbound connections.
|
|
24
|
+
|
|
12
25
|
## 2.1.0
|
|
13
26
|
|
|
14
27
|
Easier updates.
|
package/SECURITY.md
CHANGED
|
@@ -32,13 +32,13 @@ name, program start, file write or runtime code generation.
|
|
|
32
32
|
|
|
33
33
|
## Who can talk to it
|
|
34
34
|
|
|
35
|
-
| Who | What happens
|
|
36
|
-
| --------------------------------------------------------- |
|
|
37
|
-
| Another website in your browser | Refused: only `https://skill-builder.pascalcouturier.com` is accepted (exact match; `--dev` adds `http://localhost:5173` and `:4173`), and the `Host` header must be `127.0.0.1:<port>` or `localhost:<port>`, which stops DNS-rebinding attacks.
|
|
38
|
-
| Other devices on your network | Can not connect: it only listens on 127.0.0.1.
|
|
39
|
-
| A program on your computer pretending to be Skill Builder | Can connect (programs can fake the `Origin` header), but can not pair: the connector makes a random 60-bit pairing code and shows it only to you, through your AI tool and its log. The tab must prove it knows the code (HMAC bound to this connection's ECDH key). Three wrong codes close the connection; ten in one run turn pairing off until the AI tool restarts. Until paired, it receives nothing and can send nothing to your AI tool. |
|
|
40
|
-
| A program pretending to be this connector | Can not pair with Skill Builder: after you type the code, Skill Builder also asks the connector to prove it knows it. Only the connector that showed the code in your AI tool can, so an imitation is refused and the user is told. The code itself never crosses the connection.
|
|
41
|
-
| Your approved Skill Builder tab | Can answer the tool calls your AI tool makes. Every message is signed (HMAC-SHA256) and numbered, so it can not be forged, replayed or reordered. Messages are limited to 1 MB.
|
|
35
|
+
| Who | What happens |
|
|
36
|
+
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| Another website in your browser | Refused: only `https://skill-builder.pascalcouturier.com` is accepted (exact match; `--dev` adds `http://localhost:5173` and `:4173`), and the `Host` header must be `127.0.0.1:<port>` or `localhost:<port>`, which stops DNS-rebinding attacks. |
|
|
38
|
+
| Other devices on your network | Can not connect: it only listens on 127.0.0.1. |
|
|
39
|
+
| A program on your computer pretending to be Skill Builder | Can connect (programs can fake the `Origin` header), but can not pair: the connector makes a random 60-bit pairing code and shows it only to you, through your AI tool and its log. The tab must prove it knows the code (HMAC bound to this connection's ECDH key). At most four connections are held open at once, and a refused socket that stays silent is closed after 10 seconds. Three wrong codes close the connection; ten in one run turn pairing off until the AI tool restarts. Until paired, it receives nothing and can send nothing to your AI tool. |
|
|
40
|
+
| A program pretending to be this connector | Can not pair with Skill Builder: after you type the code, Skill Builder also asks the connector to prove it knows it. Only the connector that showed the code in your AI tool can, so an imitation is refused and the user is told. The code itself never crosses the connection. |
|
|
41
|
+
| Your approved Skill Builder tab | Can answer the tool calls your AI tool makes. Every message is signed (HMAC-SHA256) and numbered, so it can not be forged, replayed or reordered. Messages are limited to 1 MB. |
|
|
42
42
|
|
|
43
43
|
## Data and privacy
|
|
44
44
|
|
|
@@ -122,9 +122,9 @@ commands, edit files). Treat any tool's output as untrusted, including this one'
|
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
124
|
# What it contains, and its checksum
|
|
125
|
-
npm pack @pascalcouturier/skill-builder-mcp@2.1.
|
|
126
|
-
tar -tzf pascalcouturier-skill-builder-mcp-2.1.
|
|
127
|
-
npm view @pascalcouturier/skill-builder-mcp@2.1.
|
|
125
|
+
npm pack @pascalcouturier/skill-builder-mcp@2.1.1
|
|
126
|
+
tar -tzf pascalcouturier-skill-builder-mcp-2.1.1.tgz
|
|
127
|
+
npm view @pascalcouturier/skill-builder-mcp@2.1.1 dist.integrity
|
|
128
128
|
|
|
129
129
|
# That the registry signed it (in a project that installs it)
|
|
130
130
|
npm audit signatures
|
|
@@ -146,7 +146,7 @@ the approved GitHub Actions workflow (no npm token exists).
|
|
|
146
146
|
|
|
147
147
|
This means a release reaches you without you reviewing it first. If you want to review each one
|
|
148
148
|
(for example in a company), put an exact version after the `@` in your AI tool's settings, such as
|
|
149
|
-
`@2.1.
|
|
149
|
+
`@2.1.1`, and update it yourself; Skill Builder still shows when your connector is out of date.
|
|
150
150
|
Use the commands above to look at any release before you run it.
|
|
151
151
|
|
|
152
152
|
## Reporting a problem
|
package/dist/cli.js
CHANGED
|
@@ -7845,7 +7845,7 @@ var StdioServerTransport = class {
|
|
|
7845
7845
|
};
|
|
7846
7846
|
var package_default = {
|
|
7847
7847
|
name: "@pascalcouturier/skill-builder-mcp",
|
|
7848
|
-
version: "2.1.
|
|
7848
|
+
version: "2.1.1",
|
|
7849
7849
|
description: "Connect AI tools (GitHub Copilot, Claude Code, Codex, Cursor, Claude Desktop) to Skill Builder open in your browser, over MCP.",
|
|
7850
7850
|
license: "MIT",
|
|
7851
7851
|
author: "Pascal Couturier (https://pascalcouturier.com)",
|
|
@@ -11556,6 +11556,8 @@ var BRIDGE_LIMITS = {
|
|
|
11556
11556
|
pairingAttempts: 3,
|
|
11557
11557
|
/** Wrong pairing codes allowed per connector run; then it stops pairing until restarted. */
|
|
11558
11558
|
pairingFailuresPerRun: 10,
|
|
11559
|
+
/** Sockets the connector keeps open at once. One tab is expected; the rest cover stale tabs. */
|
|
11560
|
+
maxConnections: 4,
|
|
11559
11561
|
/** Calls per minute the tab accepts from one AI tool. */
|
|
11560
11562
|
callsPerMinute: 120
|
|
11561
11563
|
};
|
|
@@ -13088,6 +13090,10 @@ var Bridge = class {
|
|
|
13088
13090
|
this.options.log?.("Refused a connection with an unexpected Host header.");
|
|
13089
13091
|
return done(false, 403, "Host not allowed");
|
|
13090
13092
|
}
|
|
13093
|
+
if (server.clients.size >= BRIDGE_LIMITS.maxConnections) {
|
|
13094
|
+
this.options.log?.("Refused a connection: too many are open.");
|
|
13095
|
+
return done(false, 503, "Too many connections");
|
|
13096
|
+
}
|
|
13091
13097
|
done(true);
|
|
13092
13098
|
}
|
|
13093
13099
|
});
|
|
@@ -13102,25 +13108,11 @@ var Bridge = class {
|
|
|
13102
13108
|
}
|
|
13103
13109
|
accept(socket) {
|
|
13104
13110
|
if (this.locked) {
|
|
13105
|
-
|
|
13106
|
-
socket.send(JSON.stringify({
|
|
13107
|
-
type: "reject",
|
|
13108
|
-
code: "locked",
|
|
13109
|
-
message: "Too many wrong pairing codes. Restart the AI tool to try again."
|
|
13110
|
-
}));
|
|
13111
|
-
socket.close(1008);
|
|
13112
|
-
});
|
|
13111
|
+
this.turnAway(socket, "locked", "Too many wrong pairing codes. Restart the AI tool to try again.");
|
|
13113
13112
|
return;
|
|
13114
13113
|
}
|
|
13115
13114
|
if (this.link?.state === "paired") {
|
|
13116
|
-
|
|
13117
|
-
socket.send(JSON.stringify({
|
|
13118
|
-
type: "reject",
|
|
13119
|
-
code: "busy",
|
|
13120
|
-
message: "Another Skill Builder tab is already connected to this AI tool."
|
|
13121
|
-
}));
|
|
13122
|
-
socket.close(1008);
|
|
13123
|
-
});
|
|
13115
|
+
this.turnAway(socket, "busy", "Another Skill Builder tab is already connected to this AI tool.");
|
|
13124
13116
|
return;
|
|
13125
13117
|
}
|
|
13126
13118
|
this.link?.close(1e3);
|
|
@@ -13147,6 +13139,22 @@ var Bridge = class {
|
|
|
13147
13139
|
});
|
|
13148
13140
|
this.link = link;
|
|
13149
13141
|
}
|
|
13142
|
+
/**
|
|
13143
|
+
* Answers a socket's first message with a refusal and closes it. A socket that stays silent is
|
|
13144
|
+
* closed too, so idle ones can not use up the connection limit and block the real tab.
|
|
13145
|
+
*/
|
|
13146
|
+
turnAway(socket, code, message) {
|
|
13147
|
+
const timer = setTimeout(() => socket.close(1008), this.options.idleTimeoutMs ?? BRIDGE_LIMITS.handshakeTimeoutMs);
|
|
13148
|
+
socket.once("close", () => clearTimeout(timer));
|
|
13149
|
+
socket.once("message", () => {
|
|
13150
|
+
socket.send(JSON.stringify({
|
|
13151
|
+
type: "reject",
|
|
13152
|
+
code,
|
|
13153
|
+
message
|
|
13154
|
+
}));
|
|
13155
|
+
socket.close(1008);
|
|
13156
|
+
});
|
|
13157
|
+
}
|
|
13150
13158
|
setManifest(tools) {
|
|
13151
13159
|
const changed = JSON.stringify(tools) !== JSON.stringify(this.manifest);
|
|
13152
13160
|
this.manifest = tools;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pascalcouturier/skill-builder-mcp",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Connect AI tools (GitHub Copilot, Claude Code, Codex, Cursor, Claude Desktop) to Skill Builder open in your browser, over MCP.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Pascal Couturier (https://pascalcouturier.com)",
|