crewly 1.20.246 → 1.20.248

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.
Files changed (72) hide show
  1. package/dist/backend/backend/src/constants.d.ts +31 -0
  2. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  3. package/dist/backend/backend/src/constants.js +31 -0
  4. package/dist/backend/backend/src/constants.js.map +1 -1
  5. package/dist/backend/backend/src/controllers/connector/connector.controller.d.ts +1 -0
  6. package/dist/backend/backend/src/controllers/connector/connector.controller.d.ts.map +1 -1
  7. package/dist/backend/backend/src/controllers/connector/connector.controller.js +7 -0
  8. package/dist/backend/backend/src/controllers/connector/connector.controller.js.map +1 -1
  9. package/dist/backend/backend/src/controllers/connector/connector.routes.d.ts +1 -0
  10. package/dist/backend/backend/src/controllers/connector/connector.routes.d.ts.map +1 -1
  11. package/dist/backend/backend/src/controllers/connector/connector.routes.js +7 -0
  12. package/dist/backend/backend/src/controllers/connector/connector.routes.js.map +1 -1
  13. package/dist/backend/backend/src/controllers/connector/remote-mcp.controller.d.ts +55 -0
  14. package/dist/backend/backend/src/controllers/connector/remote-mcp.controller.d.ts.map +1 -0
  15. package/dist/backend/backend/src/controllers/connector/remote-mcp.controller.js +148 -0
  16. package/dist/backend/backend/src/controllers/connector/remote-mcp.controller.js.map +1 -0
  17. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  18. package/dist/backend/backend/src/services/agent/agent-registration.service.js +5 -0
  19. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  20. package/dist/backend/backend/src/services/connector/connector-access.service.d.ts +8 -0
  21. package/dist/backend/backend/src/services/connector/connector-access.service.d.ts.map +1 -1
  22. package/dist/backend/backend/src/services/connector/connector-access.service.js +17 -0
  23. package/dist/backend/backend/src/services/connector/connector-access.service.js.map +1 -1
  24. package/dist/backend/backend/src/services/connector/remote-mcp-launch.service.d.ts +77 -0
  25. package/dist/backend/backend/src/services/connector/remote-mcp-launch.service.d.ts.map +1 -0
  26. package/dist/backend/backend/src/services/connector/remote-mcp-launch.service.js +132 -0
  27. package/dist/backend/backend/src/services/connector/remote-mcp-launch.service.js.map +1 -0
  28. package/dist/backend/backend/src/services/connector/remote-mcp-probe.service.d.ts +75 -0
  29. package/dist/backend/backend/src/services/connector/remote-mcp-probe.service.d.ts.map +1 -0
  30. package/dist/backend/backend/src/services/connector/remote-mcp-probe.service.js +155 -0
  31. package/dist/backend/backend/src/services/connector/remote-mcp-probe.service.js.map +1 -0
  32. package/dist/backend/backend/src/services/connector/remote-mcp.service.d.ts +192 -0
  33. package/dist/backend/backend/src/services/connector/remote-mcp.service.d.ts.map +1 -0
  34. package/dist/backend/backend/src/services/connector/remote-mcp.service.js +334 -0
  35. package/dist/backend/backend/src/services/connector/remote-mcp.service.js.map +1 -0
  36. package/dist/backend/backend/src/services/core/credential-files.d.ts.map +1 -1
  37. package/dist/backend/backend/src/services/core/credential-files.js +4 -1
  38. package/dist/backend/backend/src/services/core/credential-files.js.map +1 -1
  39. package/dist/backend/backend/src/services/worktree/docker-reclaim.d.ts +54 -0
  40. package/dist/backend/backend/src/services/worktree/docker-reclaim.d.ts.map +1 -0
  41. package/dist/backend/backend/src/services/worktree/docker-reclaim.js +102 -0
  42. package/dist/backend/backend/src/services/worktree/docker-reclaim.js.map +1 -0
  43. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.d.ts +8 -0
  44. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.d.ts.map +1 -1
  45. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.js +23 -0
  46. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.js.map +1 -1
  47. package/dist/backend/build-info.json +2 -2
  48. package/dist/cli/backend/src/constants.d.ts +31 -0
  49. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  50. package/dist/cli/backend/src/constants.js +31 -0
  51. package/dist/cli/backend/src/constants.js.map +1 -1
  52. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  53. package/dist/cli/backend/src/services/agent/agent-registration.service.js +5 -0
  54. package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
  55. package/dist/cli/backend/src/services/connector/connector-access.service.d.ts +85 -0
  56. package/dist/cli/backend/src/services/connector/connector-access.service.d.ts.map +1 -0
  57. package/dist/cli/backend/src/services/connector/connector-access.service.js +130 -0
  58. package/dist/cli/backend/src/services/connector/connector-access.service.js.map +1 -0
  59. package/dist/cli/backend/src/services/connector/remote-mcp-launch.service.d.ts +77 -0
  60. package/dist/cli/backend/src/services/connector/remote-mcp-launch.service.d.ts.map +1 -0
  61. package/dist/cli/backend/src/services/connector/remote-mcp-launch.service.js +132 -0
  62. package/dist/cli/backend/src/services/connector/remote-mcp-launch.service.js.map +1 -0
  63. package/dist/cli/backend/src/services/connector/remote-mcp.service.d.ts +192 -0
  64. package/dist/cli/backend/src/services/connector/remote-mcp.service.d.ts.map +1 -0
  65. package/dist/cli/backend/src/services/connector/remote-mcp.service.js +334 -0
  66. package/dist/cli/backend/src/services/connector/remote-mcp.service.js.map +1 -0
  67. package/dist/cli/backend/src/services/core/credential-files.d.ts.map +1 -1
  68. package/dist/cli/backend/src/services/core/credential-files.js +4 -1
  69. package/dist/cli/backend/src/services/core/credential-files.js.map +1 -1
  70. package/frontend/dist/assets/{index-c9630c55.js → index-8f4d482e.js} +277 -277
  71. package/frontend/dist/index.html +1 -1
  72. package/package.json +1 -1
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Remote MCP servers — streamable-HTTP MCP servers the owner connects once
3
+ * (Zoho MCP first, any other server the same way) and Crewly hands to every
4
+ * agent whose role may use them.
5
+ *
6
+ * Stored at `<CREWLY_HOME>/remote-mcp-servers.json` with mode 0600. The URL
7
+ * (Zoho's carries the server's API key) and any headers are secrets: they
8
+ * are never logged, never returned in full by {@link toView}, and never
9
+ * written into a project directory (a project `.mcp.json` would be
10
+ * committed). Agents get them through per-session files under CREWLY_HOME
11
+ * (see remote-mcp-launch.service).
12
+ *
13
+ * Each server is a gated connector `mcp:<id>` in
14
+ * {@link ConnectorAccessService}: open to every agent until the owner picks
15
+ * roles.
16
+ *
17
+ * @module services/connector/remote-mcp.service
18
+ */
19
+ import { ConnectorAccessService } from './connector-access.service.js';
20
+ /** Catalog preset a server was added from. */
21
+ export type RemoteMcpProvider = 'zoho' | 'custom';
22
+ /** One stored server (secrets included — never send this to a client). */
23
+ export interface RemoteMcpServer {
24
+ /** Stable id; also the MCP server name agents see and the `mcp:<id>` access key. */
25
+ id: string;
26
+ /** Owner-facing name. */
27
+ label: string;
28
+ /** Streamable-HTTP endpoint (secret). */
29
+ url: string;
30
+ /** Extra request headers (secret values). */
31
+ headers?: Record<string, string>;
32
+ /** Catalog preset. */
33
+ provider?: RemoteMcpProvider;
34
+ /** ISO time it was added. */
35
+ createdAt: string;
36
+ }
37
+ /** What the API returns: no secrets. */
38
+ export interface RemoteMcpServerView {
39
+ id: string;
40
+ label: string;
41
+ provider: RemoteMcpProvider;
42
+ /** Scheme + host only, e.g. `https://crm-123.zohomcp.com/…`. */
43
+ urlMasked: string;
44
+ /** Header names (values withheld). */
45
+ headerNames: string[];
46
+ createdAt: string;
47
+ /** Key of its role allowlist in connector access. */
48
+ connectorId: string;
49
+ }
50
+ /** Input for {@link RemoteMcpService.add}. */
51
+ export interface AddRemoteMcpInput {
52
+ label: string;
53
+ url: string;
54
+ headers?: Record<string, string>;
55
+ provider?: string;
56
+ }
57
+ /** A validation failure the API turns into a 400. */
58
+ export declare class RemoteMcpValidationError extends Error {
59
+ constructor(message: string);
60
+ }
61
+ /**
62
+ * The connector-access id of a server.
63
+ *
64
+ * @param id - Server id
65
+ * @returns `mcp:<id>`
66
+ */
67
+ export declare function remoteMcpConnectorId(id: string): string;
68
+ /**
69
+ * Show a URL without its secret parts: scheme and host only.
70
+ *
71
+ * @param url - Stored URL
72
+ * @returns e.g. `https://crm-123.zohomcp.com/…`, or `(hidden)` when it does not parse
73
+ */
74
+ export declare function maskRemoteMcpUrl(url: string): string;
75
+ /**
76
+ * Validate a server URL: https (http only for localhost), no whitespace,
77
+ * quotes or backslashes (it is embedded in launch files), bounded length.
78
+ *
79
+ * @param raw - Pasted URL
80
+ * @returns The trimmed URL
81
+ * @throws RemoteMcpValidationError when it is not usable (message never echoes the URL)
82
+ */
83
+ export declare function validateRemoteMcpUrl(raw: unknown): string;
84
+ /**
85
+ * Validate optional headers: token-shaped names, single-line values.
86
+ *
87
+ * @param raw - Headers object or undefined
88
+ * @returns Clean headers, or undefined when none
89
+ * @throws RemoteMcpValidationError on a bad name or value
90
+ */
91
+ export declare function validateRemoteMcpHeaders(raw: unknown): Record<string, string> | undefined;
92
+ /**
93
+ * Clean a label.
94
+ *
95
+ * @param raw - Label input
96
+ * @returns Trimmed label
97
+ * @throws RemoteMcpValidationError when empty
98
+ */
99
+ export declare function normalizeRemoteMcpLabel(raw: unknown): string;
100
+ /**
101
+ * Derive an id (MCP server name) from a label: lowercase slug, unique.
102
+ *
103
+ * @param label - Label
104
+ * @param taken - Ids already in use
105
+ * @returns e.g. `zoho`, `zoho-2`
106
+ */
107
+ export declare function deriveRemoteMcpId(label: string, taken: Set<string>): string;
108
+ /**
109
+ * Turn a stored server into its API shape.
110
+ *
111
+ * @param server - Stored server
112
+ * @returns The view (no URL, no header values)
113
+ */
114
+ export declare function toView(server: RemoteMcpServer): RemoteMcpServerView;
115
+ /**
116
+ * Reads and writes the remote MCP server store.
117
+ */
118
+ export declare class RemoteMcpService {
119
+ private static instance;
120
+ private readonly logger;
121
+ private readonly filePath;
122
+ private readonly access;
123
+ private writeChain;
124
+ /**
125
+ * @param crewlyHome - Override the home directory (tests)
126
+ * @param access - Connector access service (tests)
127
+ */
128
+ constructor(crewlyHome?: string, access?: ConnectorAccessService);
129
+ static getInstance(): RemoteMcpService;
130
+ /** Reset the singleton (tests). */
131
+ static resetInstance(): void;
132
+ /** Absolute path of the store file. */
133
+ getFilePath(): string;
134
+ /**
135
+ * Every stored server, with secrets. Unreadable entries are dropped.
136
+ *
137
+ * @returns Servers in the order they were added
138
+ */
139
+ list(): Promise<RemoteMcpServer[]>;
140
+ /**
141
+ * One server, with secrets.
142
+ *
143
+ * @param id - Server id
144
+ * @returns The server or undefined
145
+ */
146
+ get(id: string): Promise<RemoteMcpServer | undefined>;
147
+ /**
148
+ * Add a server.
149
+ *
150
+ * @param input - Label, URL, optional headers and provider
151
+ * @returns The stored server
152
+ * @throws RemoteMcpValidationError on bad input or a full store
153
+ */
154
+ add(input: AddRemoteMcpInput): Promise<RemoteMcpServer>;
155
+ /**
156
+ * Rename a server (its id, and so its MCP name and allowlist, stay).
157
+ *
158
+ * @param id - Server id
159
+ * @param label - New label
160
+ * @returns The updated server, or undefined when there is none
161
+ */
162
+ rename(id: string, label: string): Promise<RemoteMcpServer | undefined>;
163
+ /**
164
+ * Remove a server and its allowlist.
165
+ *
166
+ * @param id - Server id
167
+ * @returns True when it existed
168
+ */
169
+ remove(id: string): Promise<boolean>;
170
+ /**
171
+ * Servers an agent role may use (its `mcp:<id>` allowlist passes).
172
+ *
173
+ * @param role - Agent role
174
+ * @returns Allowed servers, with secrets
175
+ */
176
+ serversForRole(role: string): Promise<RemoteMcpServer[]>;
177
+ /**
178
+ * Serialised read-modify-write; the file is written 0600.
179
+ *
180
+ * @param fn - Change to apply
181
+ * @returns The change's result
182
+ */
183
+ private mutate;
184
+ }
185
+ /**
186
+ * Write JSON readable only by the owner (0600), atomically.
187
+ *
188
+ * @param filePath - Destination
189
+ * @param data - JSON value
190
+ */
191
+ export declare function writeSecretJson(filePath: string, data: unknown): Promise<void>;
192
+ //# sourceMappingURL=remote-mcp.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-mcp.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/connector/remote-mcp.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,334 @@
1
+ /**
2
+ * Remote MCP servers — streamable-HTTP MCP servers the owner connects once
3
+ * (Zoho MCP first, any other server the same way) and Crewly hands to every
4
+ * agent whose role may use them.
5
+ *
6
+ * Stored at `<CREWLY_HOME>/remote-mcp-servers.json` with mode 0600. The URL
7
+ * (Zoho's carries the server's API key) and any headers are secrets: they
8
+ * are never logged, never returned in full by {@link toView}, and never
9
+ * written into a project directory (a project `.mcp.json` would be
10
+ * committed). Agents get them through per-session files under CREWLY_HOME
11
+ * (see remote-mcp-launch.service).
12
+ *
13
+ * Each server is a gated connector `mcp:<id>` in
14
+ * {@link ConnectorAccessService}: open to every agent until the owner picks
15
+ * roles.
16
+ *
17
+ * @module services/connector/remote-mcp.service
18
+ */
19
+ import * as fs from 'fs/promises';
20
+ import * as path from 'path';
21
+ import { getCrewlyHomePath } from '../core/crewly-home.utils.js';
22
+ import { LoggerService } from '../core/logger.service.js';
23
+ import { REMOTE_MCP_CONSTANTS } from '../../constants.js';
24
+ import { ConnectorAccessService } from './connector-access.service.js';
25
+ const C = REMOTE_MCP_CONSTANTS;
26
+ /** A validation failure the API turns into a 400. */
27
+ export class RemoteMcpValidationError extends Error {
28
+ constructor(message) {
29
+ super(message);
30
+ this.name = 'RemoteMcpValidationError';
31
+ }
32
+ }
33
+ /**
34
+ * The connector-access id of a server.
35
+ *
36
+ * @param id - Server id
37
+ * @returns `mcp:<id>`
38
+ */
39
+ export function remoteMcpConnectorId(id) {
40
+ return `${C.CONNECTOR_PREFIX}${id}`;
41
+ }
42
+ /**
43
+ * Show a URL without its secret parts: scheme and host only.
44
+ *
45
+ * @param url - Stored URL
46
+ * @returns e.g. `https://crm-123.zohomcp.com/…`, or `(hidden)` when it does not parse
47
+ */
48
+ export function maskRemoteMcpUrl(url) {
49
+ try {
50
+ const u = new URL(url);
51
+ return `${u.protocol}//${u.host}/…`;
52
+ }
53
+ catch {
54
+ return '(hidden)';
55
+ }
56
+ }
57
+ /**
58
+ * Validate a server URL: https (http only for localhost), no whitespace,
59
+ * quotes or backslashes (it is embedded in launch files), bounded length.
60
+ *
61
+ * @param raw - Pasted URL
62
+ * @returns The trimmed URL
63
+ * @throws RemoteMcpValidationError when it is not usable (message never echoes the URL)
64
+ */
65
+ export function validateRemoteMcpUrl(raw) {
66
+ const url = typeof raw === 'string' ? raw.trim() : '';
67
+ if (!url)
68
+ throw new RemoteMcpValidationError('Paste the server URL.');
69
+ if (url.length > C.MAX_URL_LENGTH)
70
+ throw new RemoteMcpValidationError('That URL is too long.');
71
+ if (/[\s"'`\\<>]/.test(url) || /[\u0000-\u001f\u007f]/.test(url)) {
72
+ throw new RemoteMcpValidationError('That URL contains spaces or quotes — paste only the URL.');
73
+ }
74
+ let parsed;
75
+ try {
76
+ parsed = new URL(url);
77
+ }
78
+ catch {
79
+ throw new RemoteMcpValidationError('That is not a valid URL.');
80
+ }
81
+ const local = ['localhost', '127.0.0.1', '[::1]'].includes(parsed.hostname);
82
+ if (parsed.protocol !== 'https:' && !(parsed.protocol === 'http:' && local)) {
83
+ throw new RemoteMcpValidationError('The URL must start with https://');
84
+ }
85
+ return url;
86
+ }
87
+ /**
88
+ * Validate optional headers: token-shaped names, single-line values.
89
+ *
90
+ * @param raw - Headers object or undefined
91
+ * @returns Clean headers, or undefined when none
92
+ * @throws RemoteMcpValidationError on a bad name or value
93
+ */
94
+ export function validateRemoteMcpHeaders(raw) {
95
+ if (raw === undefined || raw === null)
96
+ return undefined;
97
+ if (typeof raw !== 'object' || Array.isArray(raw))
98
+ throw new RemoteMcpValidationError('headers must be an object of name → value.');
99
+ const out = {};
100
+ for (const [name, value] of Object.entries(raw)) {
101
+ if (!/^[A-Za-z0-9!#$%&'*+.^_`|~-]{1,64}$/.test(name))
102
+ throw new RemoteMcpValidationError(`Header name "${name.slice(0, 64)}" is not valid.`);
103
+ if (typeof value !== 'string' || /[\r\n\u0000]/.test(value) || value.length > 4096) {
104
+ throw new RemoteMcpValidationError(`Header "${name}" needs a single-line text value.`);
105
+ }
106
+ out[name] = value;
107
+ }
108
+ return Object.keys(out).length > 0 ? out : undefined;
109
+ }
110
+ /**
111
+ * Clean a label.
112
+ *
113
+ * @param raw - Label input
114
+ * @returns Trimmed label
115
+ * @throws RemoteMcpValidationError when empty
116
+ */
117
+ export function normalizeRemoteMcpLabel(raw) {
118
+ const label = (typeof raw === 'string' ? raw : '').replace(/\s+/g, ' ').trim().slice(0, C.MAX_LABEL_LENGTH);
119
+ if (!label)
120
+ throw new RemoteMcpValidationError('Give the server a name.');
121
+ return label;
122
+ }
123
+ /**
124
+ * Derive an id (MCP server name) from a label: lowercase slug, unique.
125
+ *
126
+ * @param label - Label
127
+ * @param taken - Ids already in use
128
+ * @returns e.g. `zoho`, `zoho-2`
129
+ */
130
+ export function deriveRemoteMcpId(label, taken) {
131
+ let base = label.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 32);
132
+ if (!base || !/^[a-z0-9]/.test(base))
133
+ base = 'mcp';
134
+ let id = base;
135
+ for (let n = 2; taken.has(id); n++)
136
+ id = `${base}-${n}`;
137
+ return id;
138
+ }
139
+ /**
140
+ * Turn a stored server into its API shape.
141
+ *
142
+ * @param server - Stored server
143
+ * @returns The view (no URL, no header values)
144
+ */
145
+ export function toView(server) {
146
+ return {
147
+ id: server.id,
148
+ label: server.label,
149
+ provider: server.provider ?? 'custom',
150
+ urlMasked: maskRemoteMcpUrl(server.url),
151
+ headerNames: Object.keys(server.headers ?? {}),
152
+ createdAt: server.createdAt,
153
+ connectorId: remoteMcpConnectorId(server.id),
154
+ };
155
+ }
156
+ /**
157
+ * Reads and writes the remote MCP server store.
158
+ */
159
+ export class RemoteMcpService {
160
+ static instance = null;
161
+ logger;
162
+ filePath;
163
+ access;
164
+ writeChain = Promise.resolve();
165
+ /**
166
+ * @param crewlyHome - Override the home directory (tests)
167
+ * @param access - Connector access service (tests)
168
+ */
169
+ constructor(crewlyHome, access) {
170
+ this.logger = LoggerService.getInstance().createComponentLogger('RemoteMcp');
171
+ this.filePath = path.join(crewlyHome || getCrewlyHomePath(), C.STORE_FILE);
172
+ this.access = () => access ?? ConnectorAccessService.getInstance();
173
+ }
174
+ static getInstance() {
175
+ if (!RemoteMcpService.instance)
176
+ RemoteMcpService.instance = new RemoteMcpService();
177
+ return RemoteMcpService.instance;
178
+ }
179
+ /** Reset the singleton (tests). */
180
+ static resetInstance() {
181
+ RemoteMcpService.instance = null;
182
+ }
183
+ /** Absolute path of the store file. */
184
+ getFilePath() {
185
+ return this.filePath;
186
+ }
187
+ /**
188
+ * Every stored server, with secrets. Unreadable entries are dropped.
189
+ *
190
+ * @returns Servers in the order they were added
191
+ */
192
+ async list() {
193
+ let raw;
194
+ try {
195
+ raw = await fs.readFile(this.filePath, 'utf8');
196
+ }
197
+ catch (err) {
198
+ if (err.code === 'ENOENT')
199
+ return [];
200
+ throw err;
201
+ }
202
+ let parsed;
203
+ try {
204
+ parsed = JSON.parse(raw);
205
+ }
206
+ catch {
207
+ this.logger.error('Remote MCP store is not valid JSON — treating it as empty', { file: this.filePath });
208
+ return [];
209
+ }
210
+ const servers = parsed?.servers;
211
+ if (!Array.isArray(servers))
212
+ return [];
213
+ return servers.filter((s) => !!s && typeof s.id === 'string' && C.ID_PATTERN.test(s.id) && typeof s.url === 'string' && typeof s.label === 'string');
214
+ }
215
+ /**
216
+ * One server, with secrets.
217
+ *
218
+ * @param id - Server id
219
+ * @returns The server or undefined
220
+ */
221
+ async get(id) {
222
+ return (await this.list()).find((s) => s.id === id);
223
+ }
224
+ /**
225
+ * Add a server.
226
+ *
227
+ * @param input - Label, URL, optional headers and provider
228
+ * @returns The stored server
229
+ * @throws RemoteMcpValidationError on bad input or a full store
230
+ */
231
+ async add(input) {
232
+ const label = normalizeRemoteMcpLabel(input.label);
233
+ const url = validateRemoteMcpUrl(input.url);
234
+ const headers = validateRemoteMcpHeaders(input.headers);
235
+ const provider = input.provider === 'zoho' ? 'zoho' : 'custom';
236
+ return this.mutate(async (servers) => {
237
+ if (servers.length >= C.MAX_SERVERS)
238
+ throw new RemoteMcpValidationError(`At most ${C.MAX_SERVERS} servers.`);
239
+ if (servers.some((s) => s.url === url))
240
+ throw new RemoteMcpValidationError('That server is already connected.');
241
+ const id = deriveRemoteMcpId(label, new Set(servers.map((s) => s.id)));
242
+ const server = { id, label, url, ...(headers ? { headers } : {}), provider, createdAt: new Date().toISOString() };
243
+ this.logger.info('Remote MCP server added', { id, provider, host: maskRemoteMcpUrl(url) });
244
+ return { servers: [...servers, server], result: server };
245
+ });
246
+ }
247
+ /**
248
+ * Rename a server (its id, and so its MCP name and allowlist, stay).
249
+ *
250
+ * @param id - Server id
251
+ * @param label - New label
252
+ * @returns The updated server, or undefined when there is none
253
+ */
254
+ async rename(id, label) {
255
+ const clean = normalizeRemoteMcpLabel(label);
256
+ return this.mutate(async (servers) => {
257
+ const idx = servers.findIndex((s) => s.id === id);
258
+ if (idx < 0)
259
+ return { servers, result: undefined };
260
+ const next = [...servers];
261
+ next[idx] = { ...next[idx], label: clean };
262
+ this.logger.info('Remote MCP server renamed', { id });
263
+ return { servers: next, result: next[idx] };
264
+ });
265
+ }
266
+ /**
267
+ * Remove a server and its allowlist.
268
+ *
269
+ * @param id - Server id
270
+ * @returns True when it existed
271
+ */
272
+ async remove(id) {
273
+ const removed = await this.mutate(async (servers) => {
274
+ const next = servers.filter((s) => s.id !== id);
275
+ return { servers: next, result: next.length !== servers.length };
276
+ });
277
+ if (removed) {
278
+ await this.access().removeRule(remoteMcpConnectorId(id));
279
+ this.logger.info('Remote MCP server removed', { id });
280
+ }
281
+ return removed;
282
+ }
283
+ /**
284
+ * Servers an agent role may use (its `mcp:<id>` allowlist passes).
285
+ *
286
+ * @param role - Agent role
287
+ * @returns Allowed servers, with secrets
288
+ */
289
+ async serversForRole(role) {
290
+ const servers = await this.list();
291
+ const out = [];
292
+ for (const s of servers) {
293
+ // An empty role must not read as "the owner" here: launch always has one.
294
+ if (await this.access().isAllowed(remoteMcpConnectorId(s.id), role || 'unknown'))
295
+ out.push(s);
296
+ }
297
+ return out;
298
+ }
299
+ /**
300
+ * Serialised read-modify-write; the file is written 0600.
301
+ *
302
+ * @param fn - Change to apply
303
+ * @returns The change's result
304
+ */
305
+ async mutate(fn) {
306
+ const run = this.writeChain.then(async () => {
307
+ const { servers, result } = await fn(await this.list());
308
+ await writeSecretJson(this.filePath, { servers });
309
+ return result;
310
+ });
311
+ this.writeChain = run.catch(() => undefined);
312
+ return run;
313
+ }
314
+ }
315
+ /**
316
+ * Write JSON readable only by the owner (0600), atomically.
317
+ *
318
+ * @param filePath - Destination
319
+ * @param data - JSON value
320
+ */
321
+ export async function writeSecretJson(filePath, data) {
322
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
323
+ const tmp = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
324
+ try {
325
+ await fs.writeFile(tmp, `${JSON.stringify(data, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
326
+ await fs.chmod(tmp, 0o600);
327
+ await fs.rename(tmp, filePath);
328
+ }
329
+ catch (err) {
330
+ await fs.rm(tmp, { force: true }).catch(() => undefined);
331
+ throw err;
332
+ }
333
+ }
334
+ //# sourceMappingURL=remote-mcp.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-mcp.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/connector/remote-mcp.service.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"credential-files.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/core/credential-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC3B,iDAAiD;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,WAAW,EAAE,OAAO,CAAC;CACrB;AAaD;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,WAAW,EAAE,CA0BzD"}
1
+ {"version":3,"file":"credential-files.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/core/credential-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC3B,iDAAiD;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,WAAW,EAAE,OAAO,CAAC;CACrB;AAaD;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,WAAW,EAAE,CA6BzD"}
@@ -12,7 +12,7 @@ import * as os from 'os';
12
12
  import * as path from 'path';
13
13
  import { getCrewlyHomePath } from './crewly-home.utils.js';
14
14
  import { getApiTokenFilePath } from './api-token.service.js';
15
- import { HARNESS_CONSTANTS, SLACK_AGENT_IDENTITY_CONSTANTS, SLACK_CLOUD_CONSTANTS, TELEGRAM_CONSTANTS, WHATSAPP_CONSTANTS } from '../../constants.js';
15
+ import { HARNESS_CONSTANTS, REMOTE_MCP_CONSTANTS, SLACK_AGENT_IDENTITY_CONSTANTS, SLACK_CLOUD_CONSTANTS, TELEGRAM_CONSTANTS, WHATSAPP_CONSTANTS } from '../../constants.js';
16
16
  import { CREWLY_CONSTANTS } from '../../../../config/constants.js';
17
17
  /**
18
18
  * `~/.crewly` as the modules that ignore CREWLY_HOME build it (Slack and
@@ -55,6 +55,9 @@ export function getGuardedCredentialPaths() {
55
55
  add('credential-store', path.join(home, 'credentials'), true);
56
56
  add('whatsapp-session', path.join(home, WHATSAPP_CONSTANTS.AUTH_DIR), true);
57
57
  add('claude-accounts', path.join(home, HARNESS_CONSTANTS.CLAUDE.ACCOUNTS.DIR), true);
58
+ // Remote MCP server URLs carry their key (Zoho MCP); runtimes read the launch files themselves.
59
+ add('remote-mcp-servers', path.join(home, REMOTE_MCP_CONSTANTS.STORE_FILE), false);
60
+ add('remote-mcp-launch-files', path.join(home, REMOTE_MCP_CONSTANTS.RUNTIME_DIR), true);
58
61
  return out;
59
62
  }
60
63
  //# sourceMappingURL=credential-files.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"credential-files.js","sourceRoot":"","sources":["../../../../../../backend/src/services/core/credential-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,8BAA8B,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtJ,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAYnE;;;;;;GAMG;AACH,SAAS,aAAa;IACrB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;AACxF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB;IACxC,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;IACjC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAG,CAAC,EAAU,EAAE,CAAS,EAAE,WAAoB,EAAQ,EAAE;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC;IACF,GAAG,CAAC,WAAW,EAAE,mBAAmB,EAAE,EAAE,KAAK,CAAC,CAAC;IAC/C,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;IACpD,GAAG,CAAC,qBAAqB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,KAAK,CAAC,CAAC;IACvF,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,KAAK,CAAC,CAAC;IAClE,GAAG,CAAC,wBAAwB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,8BAA8B,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,CAAC;IACrG,GAAG,CAAC,oBAAoB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,qBAAqB,CAAC,qBAAqB,CAAC,EAAE,KAAK,CAAC,CAAC;IAC/F,GAAG,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,EAAE,KAAK,CAAC,CAAC;IAC/F,KAAK,MAAM,QAAQ,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,CAAC,EAAE,CAAC;QACxE,GAAG,CAAC,GAAG,QAAQ,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,QAAQ,mBAAmB,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9F,CAAC;IACD,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC;IACpE,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9D,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5E,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IACrF,OAAO,GAAG,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"credential-files.js","sourceRoot":"","sources":["../../../../../../backend/src/services/core/credential-files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Docker reclaim for the low-disk pass.
3
+ *
4
+ * Agents that deploy build images on this machine all day; Docker Desktop's
5
+ * disk grew 23 GB in one night (2026-10-07) and took the Mac to 2.3 GB free
6
+ * while the worktree janitor found "nothing safe to delete". Only things that
7
+ * can be rebuilt or pulled again are removed:
8
+ *
9
+ * - older tags of registry images (`host/repo:tag`) — the newest tag of
10
+ * each repository stays, so the next build still has its layers; an image
11
+ * a container uses cannot be removed (docker refuses, we move on)
12
+ * - dangling images
13
+ * - build cache beyond a few GB, for the default builder and every
14
+ * docker-container (buildx) builder
15
+ *
16
+ * Never volumes, never containers. Skipped when the docker CLI or daemon is
17
+ * not there. Never throws.
18
+ *
19
+ * @module services/worktree/docker-reclaim
20
+ */
21
+ /** Runs a docker command; resolves stdout, rejects on failure. */
22
+ export type DockerExec = (args: string[], timeoutMs: number) => Promise<string>;
23
+ /** What a reclaim did. */
24
+ export interface DockerReclaimResult {
25
+ /** Docker was reachable */
26
+ ran: boolean;
27
+ /** Image tags removed */
28
+ removedImages: string[];
29
+ }
30
+ /** Build cache kept per builder. */
31
+ export declare const DOCKER_RECLAIM_KEEP_STORAGE = "3gb";
32
+ /**
33
+ * Older tags of each registry repository, newest first in `docker images`
34
+ * output (which lists newest first).
35
+ *
36
+ * @param listing - `docker images --format '{{.Repository}} {{.Tag}}'` output
37
+ * @returns `repo:tag` names to remove
38
+ */
39
+ export declare function olderRegistryTags(listing: string): string[];
40
+ /**
41
+ * Names of docker-container (buildx) builders.
42
+ *
43
+ * @param listing - `docker buildx ls` output
44
+ * @returns Builder names
45
+ */
46
+ export declare function containerBuilders(listing: string): string[];
47
+ /**
48
+ * Free what Docker holds that can be rebuilt or pulled again.
49
+ *
50
+ * @param exec - docker runner (tests)
51
+ * @returns What was done
52
+ */
53
+ export declare function reclaimDocker(exec?: DockerExec): Promise<DockerReclaimResult>;
54
+ //# sourceMappingURL=docker-reclaim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-reclaim.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/worktree/docker-reclaim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,kEAAkE;AAClE,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEhF,0BAA0B;AAC1B,MAAM,WAAW,mBAAmB;IACnC,2BAA2B;IAC3B,GAAG,EAAE,OAAO,CAAC;IACb,yBAAyB;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,oCAAoC;AACpC,eAAO,MAAM,2BAA2B,QAAQ,CAAC;AAUjD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAY3D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ3D;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,IAAI,GAAE,UAAwB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAoBhG"}