@ni-c/mcp-hub 0.6.3 → 0.7.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/CHANGELOG.md +154 -0
- package/README.md +34 -6
- package/dist/auth/headers.js +33 -0
- package/dist/auth/headers.js.map +1 -0
- package/dist/auth/provider.js +4 -0
- package/dist/auth/provider.js.map +1 -1
- package/dist/auth/routes.js +4 -1
- package/dist/auth/routes.js.map +1 -1
- package/dist/auth/store.js +152 -35
- package/dist/auth/store.js.map +1 -1
- package/dist/config.js +209 -27
- package/dist/config.js.map +1 -1
- package/dist/docker-proxy/index.js +106 -0
- package/dist/docker-proxy/index.js.map +1 -0
- package/dist/docker-proxy/policy.js +278 -0
- package/dist/docker-proxy/policy.js.map +1 -0
- package/dist/docker-proxy/secrets.js +111 -0
- package/dist/docker-proxy/secrets.js.map +1 -0
- package/dist/docker-proxy/server.js +265 -0
- package/dist/docker-proxy/server.js.map +1 -0
- package/dist/health.js +11 -1
- package/dist/health.js.map +1 -1
- package/dist/hub.js +3 -6
- package/dist/hub.js.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-limits.js +69 -0
- package/dist/mcp-limits.js.map +1 -0
- package/dist/proxy.js +4 -5
- package/dist/proxy.js.map +1 -1
- package/dist/sandbox/container-spec.js +115 -0
- package/dist/sandbox/container-spec.js.map +1 -0
- package/dist/sandbox/docker-client.js +291 -0
- package/dist/sandbox/docker-client.js.map +1 -0
- package/dist/sandbox/policy-protocol.js +11 -0
- package/dist/sandbox/policy-protocol.js.map +1 -0
- package/dist/supervisor.js +90 -17
- package/dist/supervisor.js.map +1 -1
- package/dist/transports/docker.js +163 -0
- package/dist/transports/docker.js.map +1 -0
- package/dist/transports/socket.js +59 -0
- package/dist/transports/socket.js.map +1 -0
- package/dist/transports/stream.js +102 -0
- package/dist/transports/stream.js.map +1 -0
- package/package.json +8 -4
package/dist/auth/store.js
CHANGED
|
@@ -8,6 +8,10 @@ import path from 'node:path';
|
|
|
8
8
|
* approved; approved ones are legitimate and never evicted.
|
|
9
9
|
*/
|
|
10
10
|
export const MAX_UNAPPROVED_CLIENTS = 100;
|
|
11
|
+
const LOCK_WAIT_MS = 10_000;
|
|
12
|
+
const STALE_LOCK_MS = 30_000;
|
|
13
|
+
const LOCK_POLL_MS = 10;
|
|
14
|
+
const lockSleep = new Int32Array(new SharedArrayBuffer(4));
|
|
11
15
|
/**
|
|
12
16
|
* All persistent auth state lives in two files under DATA_PATH:
|
|
13
17
|
* jwt-key.pem (Ed25519 private key) and state.json (clients, refresh tokens,
|
|
@@ -28,33 +32,117 @@ export class AuthStore {
|
|
|
28
32
|
publicKey;
|
|
29
33
|
state;
|
|
30
34
|
statePath;
|
|
35
|
+
lockPath;
|
|
31
36
|
/** Identity of the file contents this.state was loaded from; see fileSignature(). */
|
|
32
37
|
signature;
|
|
33
38
|
tmpCounter = 0;
|
|
34
39
|
constructor(dataDir) {
|
|
35
40
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
36
|
-
const keyPath = path.join(dataDir, 'jwt-key.pem');
|
|
37
|
-
if (!fs.existsSync(keyPath)) {
|
|
38
|
-
const { privateKey } = crypto.generateKeyPairSync('ed25519');
|
|
39
|
-
fs.writeFileSync(keyPath, privateKey.export({ type: 'pkcs8', format: 'pem' }), { mode: 0o600 });
|
|
40
|
-
}
|
|
41
|
-
this.privateKey = crypto.createPrivateKey(fs.readFileSync(keyPath, 'utf8'));
|
|
42
|
-
this.publicKey = crypto.createPublicKey(this.privateKey);
|
|
43
41
|
this.statePath = path.join(dataDir, 'state.json');
|
|
44
|
-
|
|
45
|
-
this.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.
|
|
56
|
-
|
|
57
|
-
|
|
42
|
+
this.lockPath = path.join(dataDir, '.auth-state.lock');
|
|
43
|
+
this.acquireLock();
|
|
44
|
+
try {
|
|
45
|
+
const keyPath = path.join(dataDir, 'jwt-key.pem');
|
|
46
|
+
if (!fs.existsSync(keyPath)) {
|
|
47
|
+
const { privateKey } = crypto.generateKeyPairSync('ed25519');
|
|
48
|
+
fs.writeFileSync(keyPath, privateKey.export({ type: 'pkcs8', format: 'pem' }), { mode: 0o600 });
|
|
49
|
+
}
|
|
50
|
+
this.privateKey = crypto.createPrivateKey(fs.readFileSync(keyPath, 'utf8'));
|
|
51
|
+
this.publicKey = crypto.createPublicKey(this.privateKey);
|
|
52
|
+
const restored = AuthStore.readState(this.statePath);
|
|
53
|
+
this.state = restored ?? {
|
|
54
|
+
cookieSecret: crypto.randomBytes(32).toString('base64url'),
|
|
55
|
+
clients: {},
|
|
56
|
+
refreshTokens: {},
|
|
57
|
+
approvals: {},
|
|
58
|
+
consumedRefreshTokens: {},
|
|
59
|
+
revokedBefore: {},
|
|
60
|
+
apiTokens: {}
|
|
61
|
+
};
|
|
62
|
+
if (restored)
|
|
63
|
+
this.signature = this.fileSignature();
|
|
64
|
+
else
|
|
65
|
+
this.persistUnlocked();
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
this.releaseLock();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Atomic directory creation is the portable cross-process mutex. */
|
|
72
|
+
acquireLock() {
|
|
73
|
+
const deadline = Date.now() + LOCK_WAIT_MS;
|
|
74
|
+
for (;;) {
|
|
75
|
+
try {
|
|
76
|
+
fs.mkdirSync(this.lockPath, { mode: 0o700 });
|
|
77
|
+
fs.writeFileSync(path.join(this.lockPath, 'owner'), `${process.pid}\n`, { mode: 0o600 });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (error.code !== 'EEXIST')
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
this.removeStaleLock();
|
|
85
|
+
if (Date.now() >= deadline)
|
|
86
|
+
throw new Error(`timed out waiting for auth state lock ${this.lockPath}`);
|
|
87
|
+
Atomics.wait(lockSleep, 0, 0, LOCK_POLL_MS);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Break a lock whose owner is gone.
|
|
92
|
+
*
|
|
93
|
+
* The owner's pid is the precise signal and is used whenever it can be read.
|
|
94
|
+
* Age is the fallback, and it has to be one: the directory is created before
|
|
95
|
+
* the owner file is written, so a process killed between the two leaves a
|
|
96
|
+
* lock nobody can attribute. Treating that as "held" would wedge every
|
|
97
|
+
* future AuthStore in the data directory until someone deleted it by hand.
|
|
98
|
+
*
|
|
99
|
+
* The pid also means nothing across a PID namespace — an admin CLI installed
|
|
100
|
+
* from npm on the host, against a /data volume the hub uses from inside a
|
|
101
|
+
* container. The documented invocation is `docker exec` into the hub, which
|
|
102
|
+
* shares the namespace; for the other case the age fallback is what applies.
|
|
103
|
+
*/
|
|
104
|
+
removeStaleLock() {
|
|
105
|
+
try {
|
|
106
|
+
const stat = fs.statSync(this.lockPath);
|
|
107
|
+
const pid = this.lockOwnerPid();
|
|
108
|
+
if (pid !== undefined) {
|
|
109
|
+
try {
|
|
110
|
+
process.kill(pid, 0);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
if (error.code !== 'ESRCH')
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else if (Date.now() - stat.mtimeMs <= STALE_LOCK_MS) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
fs.rmSync(this.lockPath, { recursive: true, force: true });
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// The owner may have released it between stat and read. Retry mkdir.
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/** undefined when the owner file is missing, unreadable or not a pid. */
|
|
128
|
+
lockOwnerPid() {
|
|
129
|
+
let raw;
|
|
130
|
+
try {
|
|
131
|
+
raw = fs.readFileSync(path.join(this.lockPath, 'owner'), 'utf8');
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
const pid = Number(raw.trim());
|
|
137
|
+
return Number.isSafeInteger(pid) && pid > 0 ? pid : undefined;
|
|
138
|
+
}
|
|
139
|
+
releaseLock() {
|
|
140
|
+
try {
|
|
141
|
+
fs.rmSync(this.lockPath, { recursive: true, force: true });
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.error(`mcp-hub: could not release auth state lock: ${error.message}`);
|
|
145
|
+
}
|
|
58
146
|
}
|
|
59
147
|
/**
|
|
60
148
|
* Inode, mtime and size of state.json, or undefined when it is gone. The
|
|
@@ -105,10 +193,43 @@ export class AuthStore {
|
|
|
105
193
|
* what stops persist() from writing a stale snapshot back over them.
|
|
106
194
|
*/
|
|
107
195
|
mutate(fn) {
|
|
108
|
-
this.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
196
|
+
this.acquireLock();
|
|
197
|
+
try {
|
|
198
|
+
this.reloadUnderLock();
|
|
199
|
+
const result = fn();
|
|
200
|
+
this.persistUnlocked();
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
this.releaseLock();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* A mutation must never proceed from stale memory, even if stat metadata is
|
|
209
|
+
* unchanged. A file that is *gone* is not stale memory, though: the
|
|
210
|
+
* constructor recreates it, and refusing here instead would turn a deleted
|
|
211
|
+
* state.json into a hub whose every refresh-token rotation fails until it is
|
|
212
|
+
* restarted. Unparseable content stays a hard error — that is a file with
|
|
213
|
+
* contents we cannot merge into, and overwriting it would drop grants.
|
|
214
|
+
*/
|
|
215
|
+
reloadUnderLock() {
|
|
216
|
+
let parsed;
|
|
217
|
+
try {
|
|
218
|
+
parsed = JSON.parse(fs.readFileSync(this.statePath, 'utf8'));
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
if (error.code === 'ENOENT') {
|
|
222
|
+
console.error('mcp-hub: auth state file is gone, writing the state in memory back to disk');
|
|
223
|
+
this.persistUnlocked();
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
throw new Error(`cannot reload auth state while holding the mutation lock: ${error.message}`);
|
|
227
|
+
}
|
|
228
|
+
const next = AuthStore.normalize(parsed);
|
|
229
|
+
if (!next)
|
|
230
|
+
throw new Error('cannot mutate unusable auth state');
|
|
231
|
+
this.state = next;
|
|
232
|
+
this.signature = this.fileSignature();
|
|
112
233
|
}
|
|
113
234
|
/**
|
|
114
235
|
* Shapes a parsed state file, or undefined when it is unusable. Fields added
|
|
@@ -153,12 +274,11 @@ export class AuthStore {
|
|
|
153
274
|
return undefined;
|
|
154
275
|
}
|
|
155
276
|
}
|
|
156
|
-
|
|
277
|
+
persistUnlocked() {
|
|
157
278
|
this.pruneExpired();
|
|
158
|
-
// Per-writer temporary name
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
// concurrent writers is a lost update, not a corrupt state.
|
|
279
|
+
// Per-writer temporary name plus atomic rename keeps readers from observing
|
|
280
|
+
// a half-written file. Mutations are serialized by the cross-process lock,
|
|
281
|
+
// so this write also cannot overwrite another process's newer state.
|
|
162
282
|
const tmp = `${this.statePath}.tmp-${process.pid}-${this.tmpCounter++}`;
|
|
163
283
|
try {
|
|
164
284
|
fs.writeFileSync(tmp, JSON.stringify(this.state, null, 2), { mode: 0o600 });
|
|
@@ -332,12 +452,9 @@ export class AuthStore {
|
|
|
332
452
|
}
|
|
333
453
|
/** Deleting the record is the revocation: verification refuses unknown ids. */
|
|
334
454
|
revokeApiToken(id) {
|
|
335
|
-
// reloadIfChanged() before the existence check, so revoking a token another
|
|
336
|
-
// process minted seconds ago reports true instead of "no such id".
|
|
337
|
-
this.reloadIfChanged();
|
|
338
|
-
if (!this.state.apiTokens[id])
|
|
339
|
-
return false;
|
|
340
455
|
return this.mutate(() => {
|
|
456
|
+
if (!this.state.apiTokens[id])
|
|
457
|
+
return false;
|
|
341
458
|
delete this.state.apiTokens[id];
|
|
342
459
|
return true;
|
|
343
460
|
});
|
package/dist/auth/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/auth/store.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/auth/store.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -4,6 +4,13 @@ import path from 'node:path';
|
|
|
4
4
|
const NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
5
5
|
const RESERVED_NAMES = new Set(['mcp', 'hub', 'authorize', 'token', 'register', 'login', 'consent', 'health', 'livez', 'revoke', '.well-known']);
|
|
6
6
|
const REMOTE_TYPES = new Set(['http', 'sse', 'streamable-http', 'streamable_http']);
|
|
7
|
+
const SECRETS_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
8
|
+
const VOLUME_SOURCE_PATTERN = /^(?:\/[^:]*|[a-zA-Z0-9][a-zA-Z0-9_.-]*)$/;
|
|
9
|
+
const PORT_PATTERN = /^(?:(\d{1,3}(?:\.\d{1,3}){3}):)?(\d{1,5}):(\d{1,5})(?:\/(tcp|udp))?$/;
|
|
10
|
+
const MEMORY_PATTERN = /^(\d+)([bkmg])?$/i;
|
|
11
|
+
export const DEFAULT_DOCKER_MEMORY = 512 * 1024 * 1024;
|
|
12
|
+
export const DEFAULT_DOCKER_PIDS_LIMIT = 256;
|
|
13
|
+
export const DEFAULT_DOCKER_CPUS = 1;
|
|
7
14
|
export class ConfigError extends Error {
|
|
8
15
|
}
|
|
9
16
|
/** Expand ${VAR} references from the process environment, like Claude Code does. */
|
|
@@ -16,10 +23,177 @@ export function expandEnvVars(value, env = process.env) {
|
|
|
16
23
|
return replacement;
|
|
17
24
|
});
|
|
18
25
|
}
|
|
19
|
-
function
|
|
20
|
-
|
|
26
|
+
function expanderFor(env, options) {
|
|
27
|
+
if (options?.expand === false)
|
|
28
|
+
return value => value;
|
|
29
|
+
return value => expandEnvVars(value, env);
|
|
21
30
|
}
|
|
22
|
-
function
|
|
31
|
+
function expandRecord(record, expand) {
|
|
32
|
+
return Object.fromEntries(Object.entries(record).map(([k, v]) => [k, expand(v)]));
|
|
33
|
+
}
|
|
34
|
+
function requireStringArray(name, field, value) {
|
|
35
|
+
if (!Array.isArray(value) || !value.every(v => typeof v === 'string')) {
|
|
36
|
+
throw new ConfigError(`Server "${name}": "${field}" must be an array of strings`);
|
|
37
|
+
}
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
function requireStringRecord(name, field, value) {
|
|
41
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value) || !Object.values(value).every(v => typeof v === 'string')) {
|
|
42
|
+
throw new ConfigError(`Server "${name}": "${field}" must be an object of string values`);
|
|
43
|
+
}
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
/** "512m" / "1g" / "1048576" -> bytes. */
|
|
47
|
+
export function parseMemory(name, value) {
|
|
48
|
+
if (typeof value === 'number') {
|
|
49
|
+
if (!Number.isSafeInteger(value) || value <= 0)
|
|
50
|
+
throw new ConfigError(`Server "${name}": "memory" must be a positive integer`);
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
if (typeof value !== 'string')
|
|
54
|
+
throw new ConfigError(`Server "${name}": "memory" must be a string like "512m" or a byte count`);
|
|
55
|
+
const match = MEMORY_PATTERN.exec(value.trim());
|
|
56
|
+
if (!match)
|
|
57
|
+
throw new ConfigError(`Server "${name}": "memory" must look like "512m", "1g" or a byte count`);
|
|
58
|
+
const factor = { b: 1, k: 1024, m: 1024 ** 2, g: 1024 ** 3 }[(match[2] ?? 'b').toLowerCase()];
|
|
59
|
+
const bytes = Number(match[1]) * factor;
|
|
60
|
+
if (bytes <= 0 || !Number.isSafeInteger(bytes))
|
|
61
|
+
throw new ConfigError(`Server "${name}": "memory" is out of range`);
|
|
62
|
+
return bytes;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Everything the docker proxy validates has to be spelled out literally.
|
|
66
|
+
*
|
|
67
|
+
* The proxy derives the container it will allow from this very config, but it
|
|
68
|
+
* deliberately does not hold the hub's environment — a `${VAR}` in the image
|
|
69
|
+
* name or a bind mount would be a field it could not check, which is exactly
|
|
70
|
+
* the field an attacker would choose. Only `env` values, which the proxy
|
|
71
|
+
* compares by key and never by value, may be substituted.
|
|
72
|
+
*/
|
|
73
|
+
function requireLiteral(name, field, value) {
|
|
74
|
+
if (value.includes('${')) {
|
|
75
|
+
throw new ConfigError(`Server "${name}": "${field}" must not use \${VAR} — only "env" values are substituted for docker servers`);
|
|
76
|
+
}
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
function parseDockerServer(name, entry, expand, hub) {
|
|
80
|
+
if (entry.command !== undefined && !Array.isArray(entry.command)) {
|
|
81
|
+
throw new ConfigError(`Server "${name}": for docker servers "command" is an array of strings (the container's Cmd)`);
|
|
82
|
+
}
|
|
83
|
+
if (typeof entry.image !== 'string' || entry.image.length === 0) {
|
|
84
|
+
throw new ConfigError(`Server "${name}": docker servers need an "image" string`);
|
|
85
|
+
}
|
|
86
|
+
const pull = entry.pull ?? 'never';
|
|
87
|
+
if (pull !== 'never' && pull !== 'missing') {
|
|
88
|
+
throw new ConfigError(`Server "${name}": "pull" must be "never" or "missing"`);
|
|
89
|
+
}
|
|
90
|
+
const secretsFrom = entry.secretsFrom;
|
|
91
|
+
if (secretsFrom !== undefined && (typeof secretsFrom !== 'string' || !SECRETS_NAME_PATTERN.test(secretsFrom))) {
|
|
92
|
+
throw new ConfigError(`Server "${name}": "secretsFrom" must be a name matching ${SECRETS_NAME_PATTERN}`);
|
|
93
|
+
}
|
|
94
|
+
const volumes = requireStringArray(name, 'volumes', entry.volumes ?? []).map(v => requireLiteral(name, 'volumes', v));
|
|
95
|
+
for (const volume of volumes) {
|
|
96
|
+
const parts = volume.split(':');
|
|
97
|
+
if (parts.length < 2 || parts.length > 3) {
|
|
98
|
+
throw new ConfigError(`Server "${name}": volume "${volume}" must look like "source:/target" or "source:/target:ro"`);
|
|
99
|
+
}
|
|
100
|
+
if (!VOLUME_SOURCE_PATTERN.test(parts[0]) || parts[0].includes('..')) {
|
|
101
|
+
throw new ConfigError(`Server "${name}": volume source "${parts[0]}" must be an absolute path without ".." or a named volume`);
|
|
102
|
+
}
|
|
103
|
+
if (!parts[1].startsWith('/'))
|
|
104
|
+
throw new ConfigError(`Server "${name}": volume target "${parts[1]}" must be an absolute path`);
|
|
105
|
+
if (parts[2] !== undefined && parts[2] !== 'ro' && parts[2] !== 'rw') {
|
|
106
|
+
throw new ConfigError(`Server "${name}": volume mode "${parts[2]}" must be "ro" or "rw"`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const ports = requireStringArray(name, 'ports', entry.ports ?? []).map(v => requireLiteral(name, 'ports', v));
|
|
110
|
+
for (const port of ports) {
|
|
111
|
+
const match = PORT_PATTERN.exec(port);
|
|
112
|
+
if (!match)
|
|
113
|
+
throw new ConfigError(`Server "${name}": port "${port}" must look like "127.0.0.1:8686:8000" or "8686:8000"`);
|
|
114
|
+
for (const value of [match[2], match[3]]) {
|
|
115
|
+
const number = Number(value);
|
|
116
|
+
if (number < 1 || number > 65535)
|
|
117
|
+
throw new ConfigError(`Server "${name}": port "${port}" is out of range`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const network = entry.network === undefined ? 'none' : entry.network;
|
|
121
|
+
if (typeof network !== 'string' || network.length === 0)
|
|
122
|
+
throw new ConfigError(`Server "${name}": "network" must be a string`);
|
|
123
|
+
if (ports.length > 0 && network === 'none') {
|
|
124
|
+
// Published ports on a container without a network silently do nothing;
|
|
125
|
+
// saying so here beats a sandbox that looks reachable and is not.
|
|
126
|
+
throw new ConfigError(`Server "${name}": "ports" need a network, but "network" is "none"`);
|
|
127
|
+
}
|
|
128
|
+
const tmpfs = requireStringArray(name, 'tmpfs', entry.tmpfs ?? ['/tmp']).map(v => requireLiteral(name, 'tmpfs', v));
|
|
129
|
+
for (const mount of tmpfs) {
|
|
130
|
+
if (!mount.startsWith('/'))
|
|
131
|
+
throw new ConfigError(`Server "${name}": tmpfs "${mount}" must be an absolute path`);
|
|
132
|
+
}
|
|
133
|
+
if (entry.readOnly !== undefined && typeof entry.readOnly !== 'boolean') {
|
|
134
|
+
throw new ConfigError(`Server "${name}": "readOnly" must be a boolean`);
|
|
135
|
+
}
|
|
136
|
+
if (entry.user !== undefined && typeof entry.user !== 'string') {
|
|
137
|
+
throw new ConfigError(`Server "${name}": "user" must be a string`);
|
|
138
|
+
}
|
|
139
|
+
if (entry.pidsLimit !== undefined && (!Number.isSafeInteger(entry.pidsLimit) || entry.pidsLimit < 1)) {
|
|
140
|
+
throw new ConfigError(`Server "${name}": "pidsLimit" must be a positive integer`);
|
|
141
|
+
}
|
|
142
|
+
if (entry.cpus !== undefined &&
|
|
143
|
+
(typeof entry.cpus !== 'number' ||
|
|
144
|
+
!Number.isFinite(entry.cpus) ||
|
|
145
|
+
entry.cpus <= 0 ||
|
|
146
|
+
!Number.isSafeInteger(Math.round(entry.cpus * 1_000_000_000)))) {
|
|
147
|
+
throw new ConfigError(`Server "${name}": "cpus" must be a positive number`);
|
|
148
|
+
}
|
|
149
|
+
for (const forbidden of ['privileged', 'capAdd', 'securityOpt', 'devices', 'restart']) {
|
|
150
|
+
if (entry[forbidden] !== undefined) {
|
|
151
|
+
throw new ConfigError(`Server "${name}": "${forbidden}" is not supported — sandboxes always run with all capabilities dropped, no-new-privileges and no restart policy`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
kind: 'docker',
|
|
156
|
+
image: requireLiteral(name, 'image', entry.image),
|
|
157
|
+
pull,
|
|
158
|
+
...(entry.command !== undefined ? { command: requireStringArray(name, 'command', entry.command).map(v => requireLiteral(name, 'command', v)) } : {}),
|
|
159
|
+
...(entry.entrypoint !== undefined
|
|
160
|
+
? { entrypoint: requireStringArray(name, 'entrypoint', entry.entrypoint).map(v => requireLiteral(name, 'entrypoint', v)) }
|
|
161
|
+
: {}),
|
|
162
|
+
env: expandRecord(requireStringRecord(name, 'env', entry.env ?? {}), expand),
|
|
163
|
+
...(secretsFrom !== undefined ? { secretsFrom } : {}),
|
|
164
|
+
volumes,
|
|
165
|
+
ports,
|
|
166
|
+
network: requireLiteral(name, 'network', network),
|
|
167
|
+
memory: entry.memory !== undefined ? parseMemory(name, entry.memory) : DEFAULT_DOCKER_MEMORY,
|
|
168
|
+
pidsLimit: entry.pidsLimit !== undefined ? entry.pidsLimit : DEFAULT_DOCKER_PIDS_LIMIT,
|
|
169
|
+
cpus: entry.cpus !== undefined ? entry.cpus : DEFAULT_DOCKER_CPUS,
|
|
170
|
+
readOnly: entry.readOnly !== false,
|
|
171
|
+
tmpfs,
|
|
172
|
+
...(entry.user !== undefined ? { user: requireLiteral(name, 'user', entry.user) } : {}),
|
|
173
|
+
hub
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function parseSocketServer(name, entry, type, expand, hub) {
|
|
177
|
+
if (entry.command !== undefined || entry.url !== undefined) {
|
|
178
|
+
throw new ConfigError(`Server "${name}": "${type}" servers take a socket address, not "command" or "url"`);
|
|
179
|
+
}
|
|
180
|
+
if (type === 'unix') {
|
|
181
|
+
if (typeof entry.socket !== 'string' || !entry.socket.startsWith('/')) {
|
|
182
|
+
throw new ConfigError(`Server "${name}": unix servers need a "socket" path starting with "/"`);
|
|
183
|
+
}
|
|
184
|
+
return { kind: 'socket', transport: 'unix', socketPath: expand(entry.socket), hub };
|
|
185
|
+
}
|
|
186
|
+
if (typeof entry.host !== 'string' || entry.host.length === 0) {
|
|
187
|
+
throw new ConfigError(`Server "${name}": tcp servers need a "host" string`);
|
|
188
|
+
}
|
|
189
|
+
const port = entry.port;
|
|
190
|
+
if (!Number.isSafeInteger(port) || port < 1 || port > 65535) {
|
|
191
|
+
throw new ConfigError(`Server "${name}": tcp servers need a "port" between 1 and 65535`);
|
|
192
|
+
}
|
|
193
|
+
return { kind: 'socket', transport: 'tcp', host: expand(entry.host), port: port, hub };
|
|
194
|
+
}
|
|
195
|
+
function parseServer(name, entry, env, options) {
|
|
196
|
+
const expand = expanderFor(env, options);
|
|
23
197
|
const hub = entry.hub !== false;
|
|
24
198
|
if (entry.hub !== undefined && typeof entry.hub !== 'boolean') {
|
|
25
199
|
throw new ConfigError(`Server "${name}": "hub" must be a boolean`);
|
|
@@ -28,10 +202,14 @@ function parseServer(name, entry, env) {
|
|
|
28
202
|
if (type !== undefined && typeof type !== 'string') {
|
|
29
203
|
throw new ConfigError(`Server "${name}": "type" must be a string`);
|
|
30
204
|
}
|
|
205
|
+
if (type === 'docker')
|
|
206
|
+
return parseDockerServer(name, entry, expand, hub);
|
|
207
|
+
if (type === 'unix' || type === 'tcp')
|
|
208
|
+
return parseSocketServer(name, entry, type, expand, hub);
|
|
31
209
|
const isRemote = (typeof type === 'string' && type !== 'stdio') || entry.url !== undefined;
|
|
32
210
|
if (isRemote) {
|
|
33
211
|
if (typeof type === 'string' && type !== 'stdio' && !REMOTE_TYPES.has(type)) {
|
|
34
|
-
throw new ConfigError(`Server "${name}": unknown type "${type}" (supported: stdio, http, sse)`);
|
|
212
|
+
throw new ConfigError(`Server "${name}": unknown type "${type}" (supported: stdio, http, sse, docker, unix, tcp)`);
|
|
35
213
|
}
|
|
36
214
|
if (typeof entry.url !== 'string' || entry.url.length === 0) {
|
|
37
215
|
throw new ConfigError(`Server "${name}": remote servers need a "url" string`);
|
|
@@ -39,11 +217,8 @@ function parseServer(name, entry, env) {
|
|
|
39
217
|
if (entry.command !== undefined) {
|
|
40
218
|
throw new ConfigError(`Server "${name}": "command" and "url" are mutually exclusive`);
|
|
41
219
|
}
|
|
42
|
-
const headers = entry.headers ?? {};
|
|
43
|
-
|
|
44
|
-
throw new ConfigError(`Server "${name}": "headers" must be an object of string values`);
|
|
45
|
-
}
|
|
46
|
-
const url = expandEnvVars(entry.url, env);
|
|
220
|
+
const headers = requireStringRecord(name, 'headers', entry.headers ?? {});
|
|
221
|
+
const url = expand(entry.url);
|
|
47
222
|
try {
|
|
48
223
|
new URL(url);
|
|
49
224
|
}
|
|
@@ -54,30 +229,24 @@ function parseServer(name, entry, env) {
|
|
|
54
229
|
kind: 'remote',
|
|
55
230
|
transport: type === 'sse' ? 'sse' : 'http',
|
|
56
231
|
url,
|
|
57
|
-
headers: expandRecord(headers,
|
|
232
|
+
headers: expandRecord(headers, expand),
|
|
58
233
|
hub
|
|
59
234
|
};
|
|
60
235
|
}
|
|
61
236
|
if (typeof entry.command !== 'string' || entry.command.length === 0) {
|
|
62
237
|
throw new ConfigError(`Server "${name}" is missing a "command" string`);
|
|
63
238
|
}
|
|
64
|
-
const args = entry.args ?? [];
|
|
65
|
-
|
|
66
|
-
throw new ConfigError(`Server "${name}": "args" must be an array of strings`);
|
|
67
|
-
}
|
|
68
|
-
const envEntry = entry.env ?? {};
|
|
69
|
-
if (typeof envEntry !== 'object' || envEntry === null || Array.isArray(envEntry) || !Object.values(envEntry).every(v => typeof v === 'string')) {
|
|
70
|
-
throw new ConfigError(`Server "${name}": "env" must be an object of string values`);
|
|
71
|
-
}
|
|
239
|
+
const args = requireStringArray(name, 'args', entry.args ?? []);
|
|
240
|
+
const envEntry = requireStringRecord(name, 'env', entry.env ?? {});
|
|
72
241
|
return {
|
|
73
242
|
kind: 'stdio',
|
|
74
|
-
command:
|
|
75
|
-
args: args.map(
|
|
76
|
-
env: expandRecord(envEntry,
|
|
243
|
+
command: expand(entry.command),
|
|
244
|
+
args: args.map(expand),
|
|
245
|
+
env: expandRecord(envEntry, expand),
|
|
77
246
|
hub
|
|
78
247
|
};
|
|
79
248
|
}
|
|
80
|
-
export function parseConfig(json, env = process.env) {
|
|
249
|
+
export function parseConfig(json, env = process.env, options) {
|
|
81
250
|
let raw;
|
|
82
251
|
try {
|
|
83
252
|
raw = JSON.parse(json);
|
|
@@ -100,12 +269,20 @@ export function parseConfig(json, env = process.env) {
|
|
|
100
269
|
if (typeof entry !== 'object' || entry === null) {
|
|
101
270
|
throw new ConfigError(`Server "${name}" must be an object`);
|
|
102
271
|
}
|
|
103
|
-
result.set(name, parseServer(name, entry, env));
|
|
272
|
+
result.set(name, parseServer(name, entry, env, options));
|
|
104
273
|
}
|
|
105
274
|
return result;
|
|
106
275
|
}
|
|
107
|
-
export function loadConfig(filePath, env = process.env) {
|
|
108
|
-
return parseConfig(fs.readFileSync(filePath, 'utf8'), env);
|
|
276
|
+
export function loadConfig(filePath, env = process.env, options) {
|
|
277
|
+
return parseConfig(fs.readFileSync(filePath, 'utf8'), env, options);
|
|
278
|
+
}
|
|
279
|
+
export function warnMutableDockerImages(config, component = 'mcp-hub') {
|
|
280
|
+
for (const [name, entry] of config) {
|
|
281
|
+
if (entry.kind !== 'docker' || entry.image.includes('@sha256:'))
|
|
282
|
+
continue;
|
|
283
|
+
console.warn(`${component}: docker server "${name}" uses mutable image reference "${entry.image}"; ` +
|
|
284
|
+
'this is supported for compatibility, but a sha256 digest is strongly recommended');
|
|
285
|
+
}
|
|
109
286
|
}
|
|
110
287
|
export function diffConfigs(before, after) {
|
|
111
288
|
const added = [...after.keys()].filter(name => !before.has(name));
|
|
@@ -126,14 +303,18 @@ export class ConfigWatcher extends EventEmitter {
|
|
|
126
303
|
current;
|
|
127
304
|
env;
|
|
128
305
|
pollIntervalMs;
|
|
306
|
+
parseOptions;
|
|
307
|
+
validate;
|
|
129
308
|
watcher;
|
|
130
309
|
debounce;
|
|
131
|
-
constructor(filePath, current, env = process.env, pollIntervalMs = 3_000) {
|
|
310
|
+
constructor(filePath, current, env = process.env, pollIntervalMs = 3_000, parseOptions, validate) {
|
|
132
311
|
super();
|
|
133
312
|
this.filePath = filePath;
|
|
134
313
|
this.current = current;
|
|
135
314
|
this.env = env;
|
|
136
315
|
this.pollIntervalMs = pollIntervalMs;
|
|
316
|
+
this.parseOptions = parseOptions;
|
|
317
|
+
this.validate = validate;
|
|
137
318
|
}
|
|
138
319
|
start() {
|
|
139
320
|
const dir = path.dirname(this.filePath);
|
|
@@ -159,7 +340,8 @@ export class ConfigWatcher extends EventEmitter {
|
|
|
159
340
|
reload() {
|
|
160
341
|
let next;
|
|
161
342
|
try {
|
|
162
|
-
next = loadConfig(this.filePath, this.env);
|
|
343
|
+
next = loadConfig(this.filePath, this.env, this.parseOptions);
|
|
344
|
+
this.validate?.(next);
|
|
163
345
|
}
|
|
164
346
|
catch (error) {
|
|
165
347
|
// Keep running with the previous config; a broken edit must not take the hub down.
|