@crewdhq/crewd-mcp 0.0.0-stage → 0.1.7

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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +176 -2
  3. package/dist-mcp/cli.d.ts +3 -0
  4. package/dist-mcp/cli.d.ts.map +1 -0
  5. package/dist-mcp/cli.js +9 -0
  6. package/dist-mcp/cli.js.map +1 -0
  7. package/dist-mcp/core/adapters.d.ts +29 -0
  8. package/dist-mcp/core/adapters.d.ts.map +1 -0
  9. package/dist-mcp/core/adapters.js +306 -0
  10. package/dist-mcp/core/adapters.js.map +1 -0
  11. package/dist-mcp/core/installer.d.ts +42 -0
  12. package/dist-mcp/core/installer.d.ts.map +1 -0
  13. package/dist-mcp/core/installer.js +236 -0
  14. package/dist-mcp/core/installer.js.map +1 -0
  15. package/dist-mcp/core/manifest.d.ts +17 -0
  16. package/dist-mcp/core/manifest.d.ts.map +1 -0
  17. package/dist-mcp/core/manifest.js +128 -0
  18. package/dist-mcp/core/manifest.js.map +1 -0
  19. package/dist-mcp/core/project.d.ts +11 -0
  20. package/dist-mcp/core/project.d.ts.map +1 -0
  21. package/dist-mcp/core/project.js +57 -0
  22. package/dist-mcp/core/project.js.map +1 -0
  23. package/dist-mcp/core/registry.d.ts +36 -0
  24. package/dist-mcp/core/registry.d.ts.map +1 -0
  25. package/dist-mcp/core/registry.js +224 -0
  26. package/dist-mcp/core/registry.js.map +1 -0
  27. package/dist-mcp/core/tar.d.ts +23 -0
  28. package/dist-mcp/core/tar.d.ts.map +1 -0
  29. package/dist-mcp/core/tar.js +145 -0
  30. package/dist-mcp/core/tar.js.map +1 -0
  31. package/dist-mcp/core/token.d.ts +23 -0
  32. package/dist-mcp/core/token.d.ts.map +1 -0
  33. package/dist-mcp/core/token.js +70 -0
  34. package/dist-mcp/core/token.js.map +1 -0
  35. package/dist-mcp/server.d.ts +14 -0
  36. package/dist-mcp/server.d.ts.map +1 -0
  37. package/dist-mcp/server.js +429 -0
  38. package/dist-mcp/server.js.map +1 -0
  39. package/dist-mcp/types.d.ts +141 -0
  40. package/dist-mcp/types.d.ts.map +1 -0
  41. package/dist-mcp/types.js +43 -0
  42. package/dist-mcp/types.js.map +1 -0
  43. package/package.json +52 -4
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RegistryClient = exports.DEFAULT_REGISTRY_URL = void 0;
7
+ exports.loadRegistryConfig = loadRegistryConfig;
8
+ exports.parsePackageRef = parsePackageRef;
9
+ exports.sanitizeUntrustedText = sanitizeUntrustedText;
10
+ const node_fs_1 = __importDefault(require("node:fs"));
11
+ const node_path_1 = __importDefault(require("node:path"));
12
+ const node_os_1 = __importDefault(require("node:os"));
13
+ const yaml_1 = __importDefault(require("yaml"));
14
+ exports.DEFAULT_REGISTRY_URL = "https://api.crewd.dev";
15
+ function loadRegistryConfig() {
16
+ let registryUrl = process.env.CREWD_REGISTRY || "";
17
+ let token = process.env.CREWD_TOKEN || "";
18
+ if (!registryUrl || !token) {
19
+ const configPath = node_path_1.default.join(node_os_1.default.homedir(), ".config", "crewd", "config.yaml");
20
+ if (node_fs_1.default.existsSync(configPath)) {
21
+ try {
22
+ const fileContent = node_fs_1.default.readFileSync(configPath, "utf-8");
23
+ const parsed = yaml_1.default.parse(fileContent);
24
+ if (parsed && typeof parsed === "object") {
25
+ if (!registryUrl && typeof parsed.registry === "string") {
26
+ registryUrl = parsed.registry;
27
+ }
28
+ if (!token && typeof parsed.token === "string") {
29
+ token = parsed.token;
30
+ }
31
+ }
32
+ }
33
+ catch {
34
+ // Ignore config reading errors
35
+ }
36
+ }
37
+ }
38
+ if (!registryUrl) {
39
+ registryUrl = exports.DEFAULT_REGISTRY_URL;
40
+ }
41
+ return {
42
+ registryUrl: registryUrl.replace(/\/+$/, ""),
43
+ token: token || undefined,
44
+ };
45
+ }
46
+ function parsePackageRef(ref) {
47
+ // Expected formats: @namespace/name, @namespace/name@version, @namespace/name@^1.0.0
48
+ const parts = ref.split("@");
49
+ if (parts.length < 2) {
50
+ throw new Error(`Invalid package reference "${ref}": expected @namespace/name[@version]`);
51
+ }
52
+ const namePart = parts[1]; // "namespace/name"
53
+ const subparts = namePart.split("/");
54
+ if (subparts.length !== 2 || !subparts[0] || !subparts[1]) {
55
+ throw new Error(`Invalid package reference "${ref}": expected @namespace/name[@version]`);
56
+ }
57
+ const namespace = subparts[0];
58
+ const name = subparts[1];
59
+ const fullName = `@${namespace}/${name}`;
60
+ const versionRange = parts.length >= 3 && parts[2] ? parts[2] : "*";
61
+ return { fullName, namespace, name, versionRange };
62
+ }
63
+ /**
64
+ * Sanitizes untrusted text from package manifests, readmes, and descriptions.
65
+ * Truncates overly long fields and strips control characters.
66
+ */
67
+ function sanitizeUntrustedText(text, maxLen = 500) {
68
+ if (!text)
69
+ return "";
70
+ // Strip null bytes and non-printable control characters except newline and tab
71
+ const cleaned = text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
72
+ if (cleaned.length <= maxLen) {
73
+ return cleaned;
74
+ }
75
+ return cleaned.substring(0, maxLen) + "... [truncated]";
76
+ }
77
+ class RegistryClient {
78
+ baseUrl;
79
+ token;
80
+ constructor(baseUrl, token) {
81
+ const cfg = loadRegistryConfig();
82
+ this.baseUrl = (baseUrl || cfg.registryUrl).replace(/\/+$/, "");
83
+ this.token = token || cfg.token;
84
+ }
85
+ getHeaders() {
86
+ const headers = {
87
+ "Accept": "application/json",
88
+ "User-Agent": "crewd-mcp/0.1.0",
89
+ };
90
+ if (this.token) {
91
+ headers["Authorization"] = `Bearer ${this.token}`;
92
+ }
93
+ return headers;
94
+ }
95
+ async searchPackages(query, kind, limit) {
96
+ const url = new URL(`${this.baseUrl}/v1/search`);
97
+ if (query)
98
+ url.searchParams.set("q", query);
99
+ if (kind)
100
+ url.searchParams.set("type", kind);
101
+ if (limit)
102
+ url.searchParams.set("limit", String(limit));
103
+ let res;
104
+ try {
105
+ res = await fetch(url.toString(), {
106
+ method: "GET",
107
+ headers: this.getHeaders(),
108
+ });
109
+ }
110
+ catch (err) {
111
+ throw new Error(`registry unreachable at ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`);
112
+ }
113
+ if (!res.ok) {
114
+ const errText = await res.text().catch(() => "");
115
+ throw new Error(`Registry search failed (HTTP ${res.status}): ${errText || res.statusText}`);
116
+ }
117
+ const data = await res.json();
118
+ return {
119
+ packages: (data.packages || []).map((p) => ({
120
+ ...p,
121
+ description: sanitizeUntrustedText(p.description, 500),
122
+ })),
123
+ total: data.total ?? (data.packages?.length || 0),
124
+ };
125
+ }
126
+ async getPackage(namespace, name) {
127
+ const url = `${this.baseUrl}/v1/packages/${encodeURIComponent(namespace)}/${encodeURIComponent(name)}`;
128
+ let res;
129
+ try {
130
+ res = await fetch(url, {
131
+ method: "GET",
132
+ headers: this.getHeaders(),
133
+ });
134
+ }
135
+ catch (err) {
136
+ throw new Error(`registry unreachable at ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`);
137
+ }
138
+ if (res.status === 404) {
139
+ throw new Error(`package not found: @${namespace}/${name}`);
140
+ }
141
+ if (!res.ok) {
142
+ const errText = await res.text().catch(() => "");
143
+ throw new Error(`Failed to fetch package @${namespace}/${name} (HTTP ${res.status}): ${errText}`);
144
+ }
145
+ const data = await res.json();
146
+ data.description = sanitizeUntrustedText(data.description, 500);
147
+ return data;
148
+ }
149
+ async getVersion(namespace, name, version) {
150
+ const url = `${this.baseUrl}/v1/packages/${encodeURIComponent(namespace)}/${encodeURIComponent(name)}/${encodeURIComponent(version)}`;
151
+ let res;
152
+ try {
153
+ res = await fetch(url, {
154
+ method: "GET",
155
+ headers: this.getHeaders(),
156
+ });
157
+ }
158
+ catch (err) {
159
+ throw new Error(`registry unreachable at ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`);
160
+ }
161
+ if (res.status === 404) {
162
+ throw new Error(`package version not found: @${namespace}/${name}@${version}`);
163
+ }
164
+ if (!res.ok) {
165
+ const errText = await res.text().catch(() => "");
166
+ throw new Error(`Failed to fetch version @${namespace}/${name}@${version} (HTTP ${res.status}): ${errText}`);
167
+ }
168
+ const data = await res.json();
169
+ if (data.readme) {
170
+ data.readme = sanitizeUntrustedText(data.readme, 2000);
171
+ }
172
+ return data;
173
+ }
174
+ async resolve(packages, hosts) {
175
+ const url = `${this.baseUrl}/v1/resolve`;
176
+ const payload = {
177
+ packages: packages.map((p) => ({
178
+ name: p.name,
179
+ range: p.range || "*",
180
+ isTeam: p.isTeam || false,
181
+ })),
182
+ hosts: hosts || ["claude-code"],
183
+ };
184
+ let res;
185
+ try {
186
+ res = await fetch(url, {
187
+ method: "POST",
188
+ headers: {
189
+ ...this.getHeaders(),
190
+ "Content-Type": "application/json",
191
+ },
192
+ body: JSON.stringify(payload),
193
+ });
194
+ }
195
+ catch (err) {
196
+ throw new Error(`registry unreachable at ${this.baseUrl}: ${err instanceof Error ? err.message : String(err)}`);
197
+ }
198
+ if (!res.ok) {
199
+ const errText = await res.text().catch(() => "");
200
+ throw new Error(`Dependency resolution failed (HTTP ${res.status}): ${errText || res.statusText}`);
201
+ }
202
+ return await res.json();
203
+ }
204
+ async downloadTarball(tarballUrl) {
205
+ const targetUrl = tarballUrl.startsWith("http") ? tarballUrl : `${this.baseUrl}${tarballUrl.startsWith("/") ? "" : "/"}${tarballUrl}`;
206
+ let res;
207
+ try {
208
+ res = await fetch(targetUrl, {
209
+ method: "GET",
210
+ headers: this.getHeaders(),
211
+ });
212
+ }
213
+ catch (err) {
214
+ throw new Error(`failed to download tarball from ${targetUrl}: ${err instanceof Error ? err.message : String(err)}`);
215
+ }
216
+ if (!res.ok) {
217
+ throw new Error(`Failed to download tarball from ${targetUrl}: HTTP ${res.status}`);
218
+ }
219
+ const arrayBuffer = await res.arrayBuffer();
220
+ return Buffer.from(arrayBuffer);
221
+ }
222
+ }
223
+ exports.RegistryClient = RegistryClient;
224
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/core/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export interface PackageFile {
2
+ path: string;
3
+ size: number;
4
+ content: Buffer;
5
+ type: string;
6
+ }
7
+ /**
8
+ * Validates integrity hash matching "sha256-<hex>".
9
+ */
10
+ export declare function verifyTarballIntegrity(tarballBuffer: Buffer, expectedIntegrity: string): void;
11
+ /**
12
+ * Validates that an archive file entry does not perform path traversal.
13
+ */
14
+ export declare function validateSafePath(entryPath: string, rootDir: string): string;
15
+ /**
16
+ * Parses and extracts all files from a tar.gz buffer in-memory with strict security validations.
17
+ */
18
+ export declare function unpackTarballInMemory(tarballBuffer: Buffer): Promise<Map<string, PackageFile>>;
19
+ /**
20
+ * Extracts a tar.gz buffer directly into a target directory with path safety enforcement.
21
+ */
22
+ export declare function extractTarballToDisk(tarballBuffer: Buffer, destDir: string): Promise<string[]>;
23
+ //# sourceMappingURL=tar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tar.d.ts","sourceRoot":"","sources":["../../src/core/tar.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAS7F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAyB3E;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAoDpG;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAYpG"}
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.verifyTarballIntegrity = verifyTarballIntegrity;
40
+ exports.validateSafePath = validateSafePath;
41
+ exports.unpackTarballInMemory = unpackTarballInMemory;
42
+ exports.extractTarballToDisk = extractTarballToDisk;
43
+ const node_crypto_1 = __importDefault(require("node:crypto"));
44
+ const node_path_1 = __importDefault(require("node:path"));
45
+ const node_fs_1 = __importDefault(require("node:fs"));
46
+ const node_stream_1 = require("node:stream");
47
+ const tar = __importStar(require("tar"));
48
+ /**
49
+ * Validates integrity hash matching "sha256-<hex>".
50
+ */
51
+ function verifyTarballIntegrity(tarballBuffer, expectedIntegrity) {
52
+ const hash = node_crypto_1.default.createHash("sha256").update(tarballBuffer).digest("hex");
53
+ const computed = `sha256-${hash}`;
54
+ if (expectedIntegrity && expectedIntegrity !== computed) {
55
+ throw new Error(`Package integrity mismatch: registry declared ${expectedIntegrity}, but received tarball produced ${computed}`);
56
+ }
57
+ }
58
+ /**
59
+ * Validates that an archive file entry does not perform path traversal.
60
+ */
61
+ function validateSafePath(entryPath, rootDir) {
62
+ // Reject absolute paths
63
+ if (node_path_1.default.isAbsolute(entryPath)) {
64
+ throw new Error(`Path traversal rejected: package entry "${entryPath}" is an absolute path`);
65
+ }
66
+ // Normalize path and check for traversal
67
+ const normalized = node_path_1.default.normalize(entryPath);
68
+ if (normalized === ".." ||
69
+ normalized.startsWith(".." + node_path_1.default.sep) ||
70
+ normalized.startsWith("../") ||
71
+ normalized.startsWith("..\\")) {
72
+ throw new Error(`Path traversal rejected: package entry "${entryPath}" navigates outside target directory`);
73
+ }
74
+ const resolved = node_path_1.default.resolve(rootDir, normalized);
75
+ const rootWithSep = rootDir.endsWith(node_path_1.default.sep) ? rootDir : rootDir + node_path_1.default.sep;
76
+ if (resolved !== rootDir && !resolved.startsWith(rootWithSep)) {
77
+ throw new Error(`Path traversal rejected: package entry "${entryPath}" escapes target root directory`);
78
+ }
79
+ return resolved;
80
+ }
81
+ /**
82
+ * Parses and extracts all files from a tar.gz buffer in-memory with strict security validations.
83
+ */
84
+ async function unpackTarballInMemory(tarballBuffer) {
85
+ const files = new Map();
86
+ const dummyRoot = "/package/root";
87
+ await new Promise((resolve, reject) => {
88
+ const parser = new tar.Parser({
89
+ onReadEntry(entry) {
90
+ const entryPath = entry.path;
91
+ // Path traversal defense
92
+ try {
93
+ validateSafePath(entryPath, dummyRoot);
94
+ }
95
+ catch (err) {
96
+ entry.resume();
97
+ reject(err);
98
+ return;
99
+ }
100
+ // Check symlinks
101
+ if (entry.type === "SymbolicLink") {
102
+ const linkTarget = entry.linkpath || "";
103
+ if (node_path_1.default.isAbsolute(linkTarget) || linkTarget.startsWith("..")) {
104
+ entry.resume();
105
+ reject(new Error(`Path traversal rejected: symlink "${entryPath}" targets external path "${linkTarget}"`));
106
+ return;
107
+ }
108
+ }
109
+ const chunks = [];
110
+ entry.on("data", (chunk) => chunks.push(chunk));
111
+ entry.on("end", () => {
112
+ if (entry.type === "File") {
113
+ files.set(entryPath, {
114
+ path: entryPath,
115
+ size: entry.size || 0,
116
+ content: Buffer.concat(chunks),
117
+ type: entry.type,
118
+ });
119
+ }
120
+ });
121
+ entry.on("error", (err) => reject(err));
122
+ },
123
+ });
124
+ parser.on("error", reject);
125
+ parser.on("finish", () => resolve());
126
+ const stream = node_stream_1.Readable.from(tarballBuffer);
127
+ stream.pipe(parser);
128
+ });
129
+ return files;
130
+ }
131
+ /**
132
+ * Extracts a tar.gz buffer directly into a target directory with path safety enforcement.
133
+ */
134
+ async function extractTarballToDisk(tarballBuffer, destDir) {
135
+ const files = await unpackTarballInMemory(tarballBuffer);
136
+ const writtenPaths = [];
137
+ for (const [relPath, file] of files.entries()) {
138
+ const fullPath = validateSafePath(relPath, destDir);
139
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(fullPath), { recursive: true });
140
+ node_fs_1.default.writeFileSync(fullPath, file.content);
141
+ writtenPaths.push(relPath);
142
+ }
143
+ return writtenPaths;
144
+ }
145
+ //# sourceMappingURL=tar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tar.js","sourceRoot":"","sources":["../../src/core/tar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export interface ConfirmTokenData {
2
+ token: string;
3
+ pkgName: string;
4
+ version: string;
5
+ plannedFiles: string[];
6
+ integrity: string;
7
+ createdAt: number;
8
+ expiresAt: number;
9
+ }
10
+ export declare const TOKEN_TTL_MS: number;
11
+ /**
12
+ * Creates and registers a single-use confirm token for a planned package hire.
13
+ */
14
+ export declare function createConfirmToken(pkgName: string, version: string, plannedFiles: string[], integrity: string, ttlMs?: number): ConfirmTokenData;
15
+ /**
16
+ * Validates and consumes a confirm token. The token is single-use and will be removed immediately.
17
+ */
18
+ export declare function consumeConfirmToken(token: string, pkgName: string, version?: string): ConfirmTokenData;
19
+ /**
20
+ * Clears all tokens (useful in test teardown).
21
+ */
22
+ export declare function clearTokenStore(): void;
23
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/core/token.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,eAAO,MAAM,YAAY,QAAgB,CAAC;AAE1C;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,SAAe,GACnB,gBAAgB,CAsBlB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAmCtG;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TOKEN_TTL_MS = void 0;
7
+ exports.createConfirmToken = createConfirmToken;
8
+ exports.consumeConfirmToken = consumeConfirmToken;
9
+ exports.clearTokenStore = clearTokenStore;
10
+ const node_crypto_1 = __importDefault(require("node:crypto"));
11
+ // In-memory store for short-lived confirmation tokens
12
+ const tokenStore = new Map();
13
+ // Token lifetime: 5 minutes
14
+ exports.TOKEN_TTL_MS = 5 * 60 * 1000;
15
+ /**
16
+ * Creates and registers a single-use confirm token for a planned package hire.
17
+ */
18
+ function createConfirmToken(pkgName, version, plannedFiles, integrity, ttlMs = exports.TOKEN_TTL_MS) {
19
+ // Clean up any expired tokens
20
+ const now = Date.now();
21
+ for (const [key, val] of tokenStore.entries()) {
22
+ if (val.expiresAt <= now) {
23
+ tokenStore.delete(key);
24
+ }
25
+ }
26
+ const token = `crewd_confirm_${node_crypto_1.default.randomBytes(24).toString("hex")}`;
27
+ const data = {
28
+ token,
29
+ pkgName,
30
+ version,
31
+ plannedFiles,
32
+ integrity,
33
+ createdAt: now,
34
+ expiresAt: now + ttlMs,
35
+ };
36
+ tokenStore.set(token, data);
37
+ return data;
38
+ }
39
+ /**
40
+ * Validates and consumes a confirm token. The token is single-use and will be removed immediately.
41
+ */
42
+ function consumeConfirmToken(token, pkgName, version) {
43
+ if (!token) {
44
+ throw new Error("Missing confirm_token. Run 'plan_hire' first and provide the resulting confirm_token.");
45
+ }
46
+ const data = tokenStore.get(token);
47
+ if (!data) {
48
+ throw new Error("Invalid or expired confirm_token. Tokens are single-use and expire after 5 minutes. Run 'plan_hire' to generate a fresh token.");
49
+ }
50
+ // Single-use: remove immediately
51
+ tokenStore.delete(token);
52
+ const now = Date.now();
53
+ if (data.expiresAt < now) {
54
+ throw new Error("confirm_token has expired (5-minute limit exceeded). Run 'plan_hire' to generate a fresh token.");
55
+ }
56
+ if (data.pkgName !== pkgName) {
57
+ throw new Error(`confirm_token mismatch: token was issued for "${data.pkgName}", but requested hire is for "${pkgName}".`);
58
+ }
59
+ if (version && version !== "*" && data.version !== version) {
60
+ throw new Error(`confirm_token version mismatch: token was issued for version "${data.version}", but requested hire is for "${version}".`);
61
+ }
62
+ return data;
63
+ }
64
+ /**
65
+ * Clears all tokens (useful in test teardown).
66
+ */
67
+ function clearTokenStore() {
68
+ tokenStore.clear();
69
+ }
70
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/core/token.ts"],"names":[],"mappings":";;;;;;AAqBA,gDA4BC;AAKD,kDAmCC;AAKD,0CAEC;AAhGD,8DAAiC;AAYjC,sDAAsD;AACtD,MAAM,UAAU,GAAG,IAAI,GAAG,EAA4B,CAAC;AAEvD,4BAA4B;AACf,QAAA,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE1C;;GAEG;AACH,SAAgB,kBAAkB,CAChC,OAAe,EACf,OAAe,EACf,YAAsB,EACtB,SAAiB,EACjB,KAAK,GAAG,oBAAY;IAEpB,8BAA8B;IAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;QAC9C,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;YACzB,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,iBAAiB,qBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;IACxE,MAAM,IAAI,GAAqB;QAC7B,KAAK;QACL,OAAO;QACP,OAAO;QACP,YAAY;QACZ,SAAS;QACT,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG,GAAG,KAAK;KACvB,CAAC;IAEF,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB,CAAC,KAAa,EAAE,OAAe,EAAE,OAAgB;IAClF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,uFAAuF,CAAC,CAAC;IAC3G,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,gIAAgI,CACjI,CAAC;IACJ,CAAC;IAED,iCAAiC;IACjC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEzB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,IAAI,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,iGAAiG,CAClG,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,iDAAiD,IAAI,CAAC,OAAO,iCAAiC,OAAO,IAAI,CAC1G,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,IAAI,OAAO,KAAK,GAAG,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CACb,iEAAiE,IAAI,CAAC,OAAO,iCAAiC,OAAO,IAAI,CAC1H,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe;IAC7B,UAAU,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { RegistryClient } from "./core/registry.js";
3
+ /**
4
+ * Creates and configures the Crewd MCP server with all 6 tools.
5
+ */
6
+ export declare function createCrewdMcpServer(options?: {
7
+ registryClient?: RegistryClient;
8
+ projectRoot?: string;
9
+ }): McpServer;
10
+ /**
11
+ * Starts the MCP server on stdio transport.
12
+ */
13
+ export declare function startStdioServer(): Promise<void>;
14
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,EAAE,cAAc,EAA0C,MAAM,oBAAoB,CAAC;AAQ5F;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE;IAC7C,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,SAAS,CAgeZ;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAItD"}