@nimblebrain/mpak-sdk 0.1.2 → 0.2.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/LICENSE +13 -0
- package/README.md +241 -115
- package/dist/index.cjs +867 -176
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +484 -159
- package/dist/index.d.ts +484 -159
- package/dist/index.js +857 -164
- package/dist/index.js.map +1 -1
- package/package.json +16 -15
package/dist/index.d.ts
CHANGED
|
@@ -1,53 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { BundleSearchParamsInput, BundleSearchResponse, BundleDetail, VersionsResponse, VersionDetail, PlatformInfo, DownloadInfo, SkillSearchParamsInput, SkillSearchResponse, SkillDetail, SkillDownloadInfo, CacheMetadata, McpbManifest, CachedBundleInfo } from '@nimblebrain/mpak-schemas';
|
|
2
|
+
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* SDK-specific type definitions for mpak SDK
|
|
6
6
|
*
|
|
7
|
-
* API response types
|
|
8
|
-
* This file contains SDK-specific types (client config
|
|
7
|
+
* API response types should be imported directly from @nimblebrain/mpak-schemas.
|
|
8
|
+
* This file contains only SDK-specific types (client config).
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
/** Version in versions listing */
|
|
12
|
-
type BundleVersion = VersionsResponse['versions'][number];
|
|
13
|
-
/** Artifact in version detail */
|
|
14
|
-
type BundleArtifact = VersionDetail['artifacts'][number];
|
|
15
|
-
/** Download info alias */
|
|
16
|
-
type BundleDownloadInfo = DownloadInfo;
|
|
17
|
-
/** Skill summary in search results */
|
|
18
|
-
type Skill = SkillSummary;
|
|
19
|
-
|
|
20
|
-
/** Skill version in detail */
|
|
21
|
-
type SkillVersion = SkillDetail['versions'][number];
|
|
22
|
-
/** Platform identifier (os + arch) */
|
|
23
|
-
type Platform = PlatformInfo;
|
|
24
|
-
|
|
25
|
-
/** Provenance information for verified packages */
|
|
26
|
-
type Provenance = FullProvenance;
|
|
27
|
-
/** Author information */
|
|
28
|
-
interface Author {
|
|
29
|
-
name: string;
|
|
30
|
-
url?: string;
|
|
31
|
-
email?: string;
|
|
32
|
-
}
|
|
33
|
-
/** Query parameters for bundle search */
|
|
34
|
-
interface BundleSearchParams {
|
|
35
|
-
q?: string;
|
|
36
|
-
type?: string;
|
|
37
|
-
sort?: 'downloads' | 'recent' | 'name';
|
|
38
|
-
limit?: number;
|
|
39
|
-
offset?: number;
|
|
40
|
-
}
|
|
41
|
-
/** Query parameters for skill search */
|
|
42
|
-
interface SkillSearchParams {
|
|
43
|
-
q?: string;
|
|
44
|
-
tags?: string;
|
|
45
|
-
category?: string;
|
|
46
|
-
surface?: string;
|
|
47
|
-
sort?: 'downloads' | 'recent' | 'name';
|
|
48
|
-
limit?: number;
|
|
49
|
-
offset?: number;
|
|
50
|
-
}
|
|
51
11
|
/**
|
|
52
12
|
* Configuration options for MpakClient
|
|
53
13
|
*/
|
|
@@ -68,64 +28,11 @@ interface MpakClientConfig {
|
|
|
68
28
|
*/
|
|
69
29
|
userAgent?: string;
|
|
70
30
|
}
|
|
71
|
-
/**
|
|
72
|
-
* Base fields shared by all skill reference types
|
|
73
|
-
*/
|
|
74
|
-
interface SkillReferenceBase {
|
|
75
|
-
/** Skill artifact identifier (e.g., '@nimbletools/folk-crm') */
|
|
76
|
-
name: string;
|
|
77
|
-
/** Semver version (e.g., '1.0.0') or 'latest' */
|
|
78
|
-
version: string;
|
|
79
|
-
/** SHA256 integrity hash (format: 'sha256-hexdigest') */
|
|
80
|
-
integrity?: string;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Skill reference from mpak registry
|
|
84
|
-
*/
|
|
85
|
-
interface MpakSkillReference extends SkillReferenceBase {
|
|
86
|
-
source: 'mpak';
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Skill reference from GitHub repository
|
|
90
|
-
*/
|
|
91
|
-
interface GithubSkillReference extends SkillReferenceBase {
|
|
92
|
-
source: 'github';
|
|
93
|
-
/** GitHub repository (owner/repo) */
|
|
94
|
-
repo: string;
|
|
95
|
-
/** Path to skill file in repo */
|
|
96
|
-
path: string;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Skill reference from direct URL
|
|
100
|
-
*/
|
|
101
|
-
interface UrlSkillReference extends SkillReferenceBase {
|
|
102
|
-
source: 'url';
|
|
103
|
-
/** Direct download URL */
|
|
104
|
-
url: string;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Discriminated union of skill reference types
|
|
108
|
-
*/
|
|
109
|
-
type SkillReference = MpakSkillReference | GithubSkillReference | UrlSkillReference;
|
|
110
|
-
/**
|
|
111
|
-
* Result of resolving a skill reference
|
|
112
|
-
*/
|
|
113
|
-
interface ResolvedSkill {
|
|
114
|
-
/** The markdown content of the skill */
|
|
115
|
-
content: string;
|
|
116
|
-
/** Version that was resolved */
|
|
117
|
-
version: string;
|
|
118
|
-
/** Source the skill was fetched from */
|
|
119
|
-
source: 'mpak' | 'github' | 'url';
|
|
120
|
-
/** Whether integrity was verified */
|
|
121
|
-
verified: boolean;
|
|
122
|
-
}
|
|
123
31
|
|
|
124
32
|
/**
|
|
125
33
|
* Client for interacting with the mpak registry
|
|
126
34
|
*
|
|
127
35
|
* Requires Node.js 18+ for native fetch support.
|
|
128
|
-
* Uses jszip for skill bundle extraction.
|
|
129
36
|
*/
|
|
130
37
|
declare class MpakClient {
|
|
131
38
|
private readonly registryUrl;
|
|
@@ -135,7 +42,7 @@ declare class MpakClient {
|
|
|
135
42
|
/**
|
|
136
43
|
* Search for bundles
|
|
137
44
|
*/
|
|
138
|
-
searchBundles(params?:
|
|
45
|
+
searchBundles(params?: BundleSearchParamsInput): Promise<BundleSearchResponse>;
|
|
139
46
|
/**
|
|
140
47
|
* Get bundle details
|
|
141
48
|
*/
|
|
@@ -151,11 +58,11 @@ declare class MpakClient {
|
|
|
151
58
|
/**
|
|
152
59
|
* Get download info for a bundle
|
|
153
60
|
*/
|
|
154
|
-
getBundleDownload(name: string, version: string, platform?:
|
|
61
|
+
getBundleDownload(name: string, version: string, platform?: PlatformInfo): Promise<DownloadInfo>;
|
|
155
62
|
/**
|
|
156
63
|
* Search for skills
|
|
157
64
|
*/
|
|
158
|
-
searchSkills(params?:
|
|
65
|
+
searchSkills(params?: SkillSearchParamsInput): Promise<SkillSearchResponse>;
|
|
159
66
|
/**
|
|
160
67
|
* Get skill details
|
|
161
68
|
*/
|
|
@@ -169,96 +76,456 @@ declare class MpakClient {
|
|
|
169
76
|
*/
|
|
170
77
|
getSkillVersionDownload(name: string, version: string): Promise<SkillDownloadInfo>;
|
|
171
78
|
/**
|
|
172
|
-
* Download
|
|
79
|
+
* Download content from a URL and verify its SHA-256 integrity.
|
|
173
80
|
*
|
|
174
|
-
* @throws {MpakIntegrityError} If
|
|
81
|
+
* @throws {MpakIntegrityError} If SHA-256 doesn't match
|
|
82
|
+
* @throws {MpakNetworkError} For network failures
|
|
175
83
|
*/
|
|
176
|
-
|
|
177
|
-
content: string;
|
|
178
|
-
verified: boolean;
|
|
179
|
-
}>;
|
|
84
|
+
downloadContent(url: string, sha256: string): Promise<Uint8Array>;
|
|
180
85
|
/**
|
|
181
|
-
*
|
|
86
|
+
* Download a bundle by name, with optional version and platform.
|
|
87
|
+
* Defaults to latest version and auto-detected platform.
|
|
182
88
|
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
89
|
+
* @throws {MpakNotFoundError} If bundle not found
|
|
90
|
+
* @throws {MpakIntegrityError} If SHA-256 doesn't match
|
|
91
|
+
* @throws {MpakNetworkError} For network failures
|
|
92
|
+
*/
|
|
93
|
+
downloadBundle(name: string, version?: string, platform?: PlatformInfo): Promise<{
|
|
94
|
+
data: Uint8Array;
|
|
95
|
+
metadata: DownloadInfo['bundle'];
|
|
96
|
+
}>;
|
|
97
|
+
/**
|
|
98
|
+
* Download a skill bundle by name, with optional version.
|
|
99
|
+
* Defaults to latest version.
|
|
185
100
|
*
|
|
186
101
|
* @throws {MpakNotFoundError} If skill not found
|
|
187
|
-
* @throws {MpakIntegrityError} If
|
|
102
|
+
* @throws {MpakIntegrityError} If SHA-256 doesn't match
|
|
188
103
|
* @throws {MpakNetworkError} For network failures
|
|
104
|
+
*/
|
|
105
|
+
downloadSkillBundle(name: string, version?: string): Promise<{
|
|
106
|
+
data: Uint8Array;
|
|
107
|
+
metadata: SkillDownloadInfo['skill'];
|
|
108
|
+
}>;
|
|
109
|
+
/**
|
|
110
|
+
* Detect the current platform
|
|
111
|
+
*/
|
|
112
|
+
static detectPlatform(): PlatformInfo;
|
|
113
|
+
/**
|
|
114
|
+
* Compute SHA256 hash of content
|
|
115
|
+
*/
|
|
116
|
+
private computeSha256;
|
|
117
|
+
/**
|
|
118
|
+
* Validate that a name is scoped (@scope/name)
|
|
119
|
+
*/
|
|
120
|
+
private validateScopedName;
|
|
121
|
+
/**
|
|
122
|
+
* Fetch with timeout support
|
|
123
|
+
*/
|
|
124
|
+
private fetchWithTimeout;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
interface MpakBundleCacheOptions {
|
|
128
|
+
mpakHome?: string;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Manages the local bundle cache (`~/.mpak/cache/`).
|
|
132
|
+
*
|
|
133
|
+
* Handles downloading, extracting, and tracking cached bundles.
|
|
134
|
+
* The cache directory is derived from `mpakHome` — the root directory
|
|
135
|
+
* for all mpak state. Consumers can wire this to `MpakConfigManager.mpakHome`
|
|
136
|
+
* for a shared base, or pass any directory.
|
|
137
|
+
*
|
|
138
|
+
* Requires an `MpakClient` for registry operations (download, update checks).
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* // Via MpakSDK facade (recommended)
|
|
143
|
+
* const mpak = new MpakSDK();
|
|
144
|
+
* await mpak.cache.loadBundle('@scope/name');
|
|
145
|
+
*
|
|
146
|
+
* // Standalone
|
|
147
|
+
* const client = new MpakClient();
|
|
148
|
+
* const cache = new MpakBundleCache(client, { mpakHome: '/path/to/.mpak' });
|
|
149
|
+
* await cache.loadBundle('@scope/name');
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
declare class MpakBundleCache {
|
|
153
|
+
readonly cacheHome: string;
|
|
154
|
+
private readonly mpakClient;
|
|
155
|
+
constructor(client: MpakClient, options?: MpakBundleCacheOptions);
|
|
156
|
+
/**
|
|
157
|
+
* Compute the cache path for a package. Does not create the directory.
|
|
158
|
+
* @example getPackageCachePath('@scope/name') => '<cacheBase>/scope-name'
|
|
159
|
+
*/
|
|
160
|
+
getBundleCacheDirName(packageName: string): string;
|
|
161
|
+
/**
|
|
162
|
+
* Read and validate cache metadata for a package.
|
|
163
|
+
* Returns `null` if the package does not exist in the cache.
|
|
164
|
+
* throws Error if metadata is corrupt
|
|
165
|
+
*/
|
|
166
|
+
getBundleMetadata(packageName: string): CacheMetadata | null;
|
|
167
|
+
/**
|
|
168
|
+
* Read and validate the MCPB manifest from a cached package.
|
|
169
|
+
* Returns `null` if the package is not cached (directory doesn't exist).
|
|
170
|
+
*
|
|
171
|
+
* @throws {MpakCacheCorruptedError} If the cache directory exists but
|
|
172
|
+
* `manifest.json` is missing, contains invalid JSON, or fails schema validation.
|
|
173
|
+
*/
|
|
174
|
+
getBundleManifest(packageName: string): McpbManifest | null;
|
|
175
|
+
/**
|
|
176
|
+
* Scan the cache directory and return metadata for every cached registry bundle.
|
|
177
|
+
* Skips the `_local/` directory (local dev bundles) and entries with
|
|
178
|
+
* missing/corrupt metadata or manifests.
|
|
179
|
+
*/
|
|
180
|
+
listCachedBundles(): CachedBundleInfo[];
|
|
181
|
+
/**
|
|
182
|
+
* Remove a cached bundle from disk.
|
|
183
|
+
* @returns `true` if the bundle was cached and removed, `false` if it wasn't cached.
|
|
184
|
+
*/
|
|
185
|
+
removeCachedBundle(packageName: string): boolean;
|
|
186
|
+
/**
|
|
187
|
+
* Load a bundle into the local cache, downloading from the registry only
|
|
188
|
+
* if the cache is missing or stale. Returns the cache directory and version.
|
|
189
189
|
*
|
|
190
|
-
*
|
|
191
|
-
* ```typescript
|
|
192
|
-
* // Resolve from mpak registry
|
|
193
|
-
* const skill = await client.resolveSkillRef({
|
|
194
|
-
* source: 'mpak',
|
|
195
|
-
* name: '@nimblebraininc/folk-crm',
|
|
196
|
-
* version: '1.3.0',
|
|
197
|
-
* });
|
|
190
|
+
* Requires an `MpakClient` to be provided at construction time.
|
|
198
191
|
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
* name: '@example/my-skill',
|
|
203
|
-
* version: 'v1.0.0',
|
|
204
|
-
* repo: 'owner/repo',
|
|
205
|
-
* path: 'skills/my-skill/SKILL.md',
|
|
206
|
-
* });
|
|
192
|
+
* @param name - Scoped package name (e.g. `@scope/bundle`)
|
|
193
|
+
* @param options.version - Specific version to load. Omit for "latest".
|
|
194
|
+
* @param options.force - Skip cache checks and always re-download.
|
|
207
195
|
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
* name: '@example/custom',
|
|
212
|
-
* version: '1.0.0',
|
|
213
|
-
* url: 'https://example.com/skill.md',
|
|
214
|
-
* });
|
|
215
|
-
* ```
|
|
216
|
-
*/
|
|
217
|
-
resolveSkillRef(ref: SkillReference): Promise<ResolvedSkill>;
|
|
218
|
-
/**
|
|
219
|
-
* Resolve a skill from mpak registry
|
|
196
|
+
* @returns `cacheDir` — path to the extracted bundle on disk,
|
|
197
|
+
* `version` — the resolved version string,
|
|
198
|
+
* `pulled` — whether a download actually occurred.
|
|
220
199
|
*
|
|
221
|
-
*
|
|
200
|
+
* @throws If no `MpakClient` was provided at construction time.
|
|
222
201
|
*/
|
|
223
|
-
|
|
202
|
+
loadBundle(name: string, options?: {
|
|
203
|
+
version?: string;
|
|
204
|
+
force?: boolean;
|
|
205
|
+
}): Promise<{
|
|
206
|
+
cacheDir: string;
|
|
207
|
+
version: string;
|
|
208
|
+
pulled: boolean;
|
|
209
|
+
}>;
|
|
224
210
|
/**
|
|
225
|
-
*
|
|
211
|
+
* Fire-and-forget background check for bundle updates.
|
|
212
|
+
* Return the latest version string if an update is available, null otherwise (not cached, skipped, up-to-date, or error).
|
|
213
|
+
* The caller can just check `if (result) { console.log("update available: " + result) }`
|
|
214
|
+
* @param packageName - Scoped package name (e.g. `@scope/bundle`)
|
|
226
215
|
*/
|
|
227
|
-
|
|
216
|
+
checkForUpdate(packageName: string, options?: {
|
|
217
|
+
force?: boolean;
|
|
218
|
+
}): Promise<string | null>;
|
|
228
219
|
/**
|
|
229
|
-
*
|
|
220
|
+
* Write cache metadata for a package.
|
|
221
|
+
* @throws If the metadata fails schema validation.
|
|
230
222
|
*/
|
|
231
|
-
private
|
|
223
|
+
private writeCacheMetadata;
|
|
232
224
|
/**
|
|
233
|
-
*
|
|
225
|
+
* Download a bundle using pre-resolved download info, extract it into
|
|
226
|
+
* the cache, and write metadata.
|
|
234
227
|
*/
|
|
235
|
-
private
|
|
228
|
+
private downloadAndExtract;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Zod schema for per-package user configuration.
|
|
233
|
+
* Each key-value pair represents a user-supplied config value
|
|
234
|
+
* (e.g. API keys, workspace IDs) referenced via `${user_config.*}` in manifests.
|
|
235
|
+
*/
|
|
236
|
+
declare const PackageConfigSchema: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
237
|
+
/**
|
|
238
|
+
* Per-package user configuration — a string-to-string map of values
|
|
239
|
+
* that bundles reference via `${user_config.*}` placeholders.
|
|
240
|
+
*/
|
|
241
|
+
type PackageConfig = z.infer<typeof PackageConfigSchema>;
|
|
242
|
+
/**
|
|
243
|
+
* Manages the mpak user configuration file (`config.json`).
|
|
244
|
+
*
|
|
245
|
+
* Handles:
|
|
246
|
+
* - **Registry URL** — custom registry endpoint with hardcoded default fallback
|
|
247
|
+
* - **Per-package config** — key-value pairs for `${user_config.*}` substitution
|
|
248
|
+
*
|
|
249
|
+
* The config is lazy-loaded on first access and cached in memory.
|
|
250
|
+
* The config directory is created lazily on first write — read-only usage
|
|
251
|
+
* never touches the filesystem.
|
|
252
|
+
* All writes are validated against the schema before flushing to disk
|
|
253
|
+
* with `0o600` permissions (owner read/write only).
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```ts
|
|
257
|
+
* // Default: ~/.mpak/config.json
|
|
258
|
+
* const config = new MpakConfigManager();
|
|
259
|
+
*
|
|
260
|
+
* // Custom home and registry URL
|
|
261
|
+
* const config = new MpakConfigManager({ mpakHome: '/tmp/test-mpak', registryUrl: 'https://custom.registry.dev' });
|
|
262
|
+
*
|
|
263
|
+
* // Registry URL (config > default)
|
|
264
|
+
* config.getRegistryUrl();
|
|
265
|
+
*
|
|
266
|
+
* // Per-package user config for ${user_config.*} substitution
|
|
267
|
+
* config.setPackageConfigValue('@scope/bundle', 'api_key', 'sk-...');
|
|
268
|
+
* config.getPackageConfig('@scope/bundle'); // { api_key: 'sk-...' }
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
271
|
+
interface MpakConfigManagerOptions {
|
|
272
|
+
mpakHome?: string;
|
|
273
|
+
registryUrl?: string;
|
|
274
|
+
}
|
|
275
|
+
declare class MpakConfigManager {
|
|
276
|
+
readonly mpakHome: string;
|
|
277
|
+
private configFile;
|
|
278
|
+
private config;
|
|
279
|
+
constructor(options?: MpakConfigManagerOptions);
|
|
236
280
|
/**
|
|
237
|
-
*
|
|
281
|
+
* Resolve the registry URL with a 2-tier fallback:
|
|
282
|
+
* 1. Saved value in config file
|
|
283
|
+
* 2. Default: `https://registry.mpak.dev`
|
|
284
|
+
*
|
|
285
|
+
* @returns The resolved registry URL
|
|
238
286
|
*/
|
|
239
|
-
|
|
287
|
+
getRegistryUrl(): string;
|
|
240
288
|
/**
|
|
241
|
-
*
|
|
289
|
+
* Get all stored user config values for a package.
|
|
290
|
+
*
|
|
291
|
+
* @param packageName - Scoped package name (e.g. `@scope/bundle`)
|
|
292
|
+
* @returns The key-value map, or `undefined` if the package has no stored config
|
|
242
293
|
*/
|
|
243
|
-
|
|
294
|
+
getPackageConfig(packageName: string): PackageConfig | undefined;
|
|
244
295
|
/**
|
|
245
|
-
*
|
|
296
|
+
* Store a user config value for a package. Creates the package entry if needed.
|
|
297
|
+
*
|
|
298
|
+
* @param packageName - Scoped package name (e.g. `@scope/bundle`)
|
|
299
|
+
* @param key - The config key (e.g. `api_key`)
|
|
300
|
+
* @param value - The value to store
|
|
246
301
|
*/
|
|
247
|
-
|
|
302
|
+
setPackageConfigValue(packageName: string, key: string, value: string): void;
|
|
248
303
|
/**
|
|
249
|
-
*
|
|
304
|
+
* Remove all stored config for a package.
|
|
305
|
+
*
|
|
306
|
+
* @param packageName - Scoped package name (e.g. `@scope/bundle`)
|
|
307
|
+
* @returns `true` if the package had config that was removed, `false` if it didn't exist
|
|
250
308
|
*/
|
|
251
|
-
|
|
309
|
+
clearPackageConfig(packageName: string): boolean;
|
|
252
310
|
/**
|
|
253
|
-
*
|
|
311
|
+
* Remove a single config value for a package. If this was the last key,
|
|
312
|
+
* the package entry is cleaned up entirely.
|
|
313
|
+
*
|
|
314
|
+
* @param packageName - Scoped package name (e.g. `@scope/bundle`)
|
|
315
|
+
* @param key - The config key to remove
|
|
316
|
+
* @returns `true` if the key existed and was removed, `false` otherwise
|
|
254
317
|
*/
|
|
255
|
-
|
|
318
|
+
clearPackageConfigValue(packageName: string, key: string): boolean;
|
|
256
319
|
/**
|
|
257
|
-
*
|
|
320
|
+
* List all package names that have stored user config.
|
|
321
|
+
*
|
|
322
|
+
* @returns Array of scoped package names (e.g. `['@scope/pkg1', '@scope/pkg2']`)
|
|
258
323
|
*/
|
|
259
|
-
|
|
324
|
+
getPackageNames(): string[];
|
|
325
|
+
/**
|
|
326
|
+
* Load the config from disk, or create a fresh one if the file doesn't exist yet.
|
|
327
|
+
* The result is cached — subsequent calls return the in-memory copy without
|
|
328
|
+
* re-reading the file.
|
|
329
|
+
*
|
|
330
|
+
* @returns The validated config object
|
|
331
|
+
* @throws {MpakConfigCorruptedError} If the file exists but contains invalid JSON or fails schema validation
|
|
332
|
+
*/
|
|
333
|
+
private loadConfig;
|
|
334
|
+
/**
|
|
335
|
+
* Read the config file from disk, parse JSON, and validate against the schema.
|
|
336
|
+
*
|
|
337
|
+
* @returns The validated config object
|
|
338
|
+
* @throws {MpakConfigCorruptedError} If the file can't be read, contains invalid JSON,
|
|
339
|
+
* or doesn't match the expected schema
|
|
340
|
+
*/
|
|
341
|
+
private readAndValidateConfig;
|
|
342
|
+
/**
|
|
343
|
+
* Flush the in-memory config to disk. Creates the config directory if needed,
|
|
344
|
+
* validates against the schema, updates `lastUpdated`, and writes
|
|
345
|
+
* with mode `0o600` (owner read/write only — config may contain secrets).
|
|
346
|
+
*
|
|
347
|
+
* @throws {MpakConfigCorruptedError} If the in-memory config fails schema validation
|
|
348
|
+
*/
|
|
349
|
+
private saveConfig;
|
|
350
|
+
/**
|
|
351
|
+
* Persist a custom registry URL to the config file.
|
|
352
|
+
*
|
|
353
|
+
* @param url - The registry URL to save (e.g. `https://registry.example.com`)
|
|
354
|
+
*/
|
|
355
|
+
private setRegistryUrl;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Options for the {@link Mpak} facade.
|
|
360
|
+
*
|
|
361
|
+
* All fields are optional — sensible defaults are derived from
|
|
362
|
+
* `MpakConfigManager` (registry URL, mpakHome) when omitted.
|
|
363
|
+
*/
|
|
364
|
+
interface MpakOptions {
|
|
365
|
+
/** Root directory for mpak state. Defaults to `~/.mpak`. */
|
|
366
|
+
mpakHome?: string;
|
|
367
|
+
/** Registry URL override. Defaults to `MpakConfigManager.getRegistryUrl()`. */
|
|
368
|
+
registryUrl?: string;
|
|
369
|
+
/** Request timeout in milliseconds for the client. */
|
|
370
|
+
timeout?: number;
|
|
371
|
+
/** User-Agent string sent with every request. */
|
|
372
|
+
userAgent?: string;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Specifies which bundle to prepare.
|
|
376
|
+
*
|
|
377
|
+
* - `{ name, version? }` — registry bundle. Omit `version` for "latest".
|
|
378
|
+
* - `{ local }` — a local `.mcpb` file on disk. The caller is responsible for
|
|
379
|
+
* validating that the path exists and has a `.mcpb` extension before calling.
|
|
380
|
+
*/
|
|
381
|
+
type PrepareServerSpec = {
|
|
382
|
+
name: string;
|
|
383
|
+
version?: string;
|
|
384
|
+
} | {
|
|
385
|
+
local: string;
|
|
386
|
+
};
|
|
387
|
+
/**
|
|
388
|
+
* Options for {@link Mpak.prepareServer}.
|
|
389
|
+
*/
|
|
390
|
+
interface PrepareServerOptions {
|
|
391
|
+
/** Skip cache and re-download/re-extract. */
|
|
392
|
+
force?: boolean;
|
|
393
|
+
/** Extra environment variables merged on top of the manifest env. */
|
|
394
|
+
env?: Record<string, string>;
|
|
395
|
+
/**
|
|
396
|
+
* Directory for `MPAK_WORKSPACE` — where stateful bundles write
|
|
397
|
+
* project-local data (databases, logs, etc.). Defaults to `process.cwd()/.mpak`.
|
|
398
|
+
*/
|
|
399
|
+
workspaceDir?: string;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Fully resolved server configuration, ready to spawn.
|
|
403
|
+
*/
|
|
404
|
+
interface ServerCommand {
|
|
405
|
+
/** The executable command (e.g. `"node"`, `"python3"`, or an absolute binary path). */
|
|
406
|
+
command: string;
|
|
407
|
+
/** Arguments to pass to the command. */
|
|
408
|
+
args: string[];
|
|
409
|
+
/** Environment variables (manifest env + user config substitutions + caller overrides). */
|
|
410
|
+
env: Record<string, string>;
|
|
411
|
+
/** Working directory for the spawned process — the extracted bundle's cache directory. */
|
|
412
|
+
cwd: string;
|
|
413
|
+
/** The resolved package name. */
|
|
414
|
+
name: string;
|
|
415
|
+
/** The resolved version string. */
|
|
416
|
+
version: string;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Top-level facade that wires together the SDK's core components:
|
|
420
|
+
* `MpakConfigManager`, `MpakClient`, and `BundleCache`.
|
|
421
|
+
*
|
|
422
|
+
* Provides a single entry point for the common setup pattern,
|
|
423
|
+
* while still exposing each component for direct use.
|
|
424
|
+
*
|
|
425
|
+
* @example
|
|
426
|
+
* ```ts
|
|
427
|
+
* import { MpakSDK } from '@nimblebrain/mpak-sdk';
|
|
428
|
+
*
|
|
429
|
+
* const mpak = new MpakSDK();
|
|
430
|
+
*
|
|
431
|
+
* // Prepare a server for spawning
|
|
432
|
+
* const server = await mpak.prepareServer('@scope/pkg');
|
|
433
|
+
* const child = spawn(server.command, server.args, {
|
|
434
|
+
* env: { ...server.env, ...process.env },
|
|
435
|
+
* cwd: server.cwd,
|
|
436
|
+
* stdio: 'inherit',
|
|
437
|
+
* });
|
|
438
|
+
*
|
|
439
|
+
* // Access components directly
|
|
440
|
+
* mpak.config.setPackageConfigValue('@scope/pkg', 'api_key', 'sk-...');
|
|
441
|
+
* const bundles = await mpak.client.searchBundles({ q: 'mcp' });
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
444
|
+
declare class Mpak {
|
|
445
|
+
/** User configuration manager (`config.json`). */
|
|
446
|
+
readonly configManager: MpakConfigManager;
|
|
447
|
+
/** Registry API client. */
|
|
448
|
+
readonly client: MpakClient;
|
|
449
|
+
/** Local bundle cache. */
|
|
450
|
+
readonly bundleCache: MpakBundleCache;
|
|
451
|
+
constructor(options?: MpakOptions);
|
|
452
|
+
/**
|
|
453
|
+
* Prepare a bundle for execution.
|
|
454
|
+
*
|
|
455
|
+
* Accepts either a registry spec (`{ name, version? }`) or a local bundle
|
|
456
|
+
* spec (`{ local }`). Downloads/extracts as needed, reads the manifest,
|
|
457
|
+
* validates user config, and resolves the command, args, and env needed
|
|
458
|
+
* to spawn the MCP server process.
|
|
459
|
+
*
|
|
460
|
+
* @param spec - Which bundle to prepare. See {@link PrepareServerSpec}.
|
|
461
|
+
* @param options - Force re-download/re-extract, extra env, and workspace dir.
|
|
462
|
+
*
|
|
463
|
+
* @throws {MpakConfigError} If required user config values are missing.
|
|
464
|
+
* @throws {MpakCacheCorruptedError} If the manifest is missing or corrupt after download.
|
|
465
|
+
*/
|
|
466
|
+
prepareServer(spec: PrepareServerSpec, options?: PrepareServerOptions): Promise<ServerCommand>;
|
|
467
|
+
/**
|
|
468
|
+
* Load a registry bundle into cache and read its manifest.
|
|
469
|
+
*/
|
|
470
|
+
private prepareRegistryBundle;
|
|
471
|
+
/**
|
|
472
|
+
* Extract a local `.mcpb` bundle (if stale) and read its manifest.
|
|
473
|
+
* Local bundles are cached under `<cacheHome>/_local/<hash>`.
|
|
474
|
+
*
|
|
475
|
+
* The caller is responsible for validating that `bundlePath` exists
|
|
476
|
+
* and has a `.mcpb` extension before calling this method.
|
|
477
|
+
*/
|
|
478
|
+
private prepareLocalBundle;
|
|
479
|
+
/**
|
|
480
|
+
* Gather stored user config values and validate that all required fields are present.
|
|
481
|
+
* @throws If required config values are missing.
|
|
482
|
+
*/
|
|
483
|
+
private gatherUserConfig;
|
|
484
|
+
/**
|
|
485
|
+
* Resolve the manifest's `server` block into a spawnable command, args, and env.
|
|
486
|
+
*
|
|
487
|
+
* Handles three server types:
|
|
488
|
+
* - **binary** — runs the compiled executable at `entry_point`, chmod'd +x.
|
|
489
|
+
* - **node** — runs `mcp_config.command` (default `"node"`) with `mcp_config.args`,
|
|
490
|
+
* or falls back to `node <entry_point>` when args are empty.
|
|
491
|
+
* - **python** — like node, but resolves `python3`/`python` at runtime and
|
|
492
|
+
* prepends `<cacheDir>/deps` to `PYTHONPATH` for bundled dependencies.
|
|
493
|
+
*
|
|
494
|
+
* All `${__dirname}` placeholders in args are replaced with `cacheDir`.
|
|
495
|
+
* All `${user_config.*}` placeholders in env are replaced with gathered user values.
|
|
496
|
+
*
|
|
497
|
+
* @throws For unsupported server types.
|
|
498
|
+
*/
|
|
499
|
+
private resolveCommand;
|
|
500
|
+
/**
|
|
501
|
+
* Substitute `${__dirname}` placeholders in args.
|
|
502
|
+
*/
|
|
503
|
+
private static resolveArgs;
|
|
504
|
+
/**
|
|
505
|
+
* Substitute `${user_config.*}` placeholders in env vars.
|
|
506
|
+
*/
|
|
507
|
+
private static substituteEnvVars;
|
|
508
|
+
/**
|
|
509
|
+
* Find a working Python executable. Tries `python3` first, falls back to `python`.
|
|
510
|
+
*/
|
|
511
|
+
private static findPythonCommand;
|
|
260
512
|
}
|
|
261
513
|
|
|
514
|
+
/**
|
|
515
|
+
* Parse a scoped package spec (`@scope/name` or `@scope/name@version`)
|
|
516
|
+
* into its name and optional version components.
|
|
517
|
+
*
|
|
518
|
+
* @throws {MpakError} If the spec is not a valid scoped package name.
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* parsePackageSpec('@scope/name') // { name: '@scope/name' }
|
|
522
|
+
* parsePackageSpec('@scope/name@1.0.0') // { name: '@scope/name', version: '1.0.0' }
|
|
523
|
+
*/
|
|
524
|
+
declare function parsePackageSpec(spec: string): {
|
|
525
|
+
name: string;
|
|
526
|
+
version?: string;
|
|
527
|
+
};
|
|
528
|
+
|
|
262
529
|
/**
|
|
263
530
|
* Base error class for mpak SDK errors
|
|
264
531
|
*/
|
|
@@ -288,5 +555,63 @@ declare class MpakIntegrityError extends MpakError {
|
|
|
288
555
|
declare class MpakNetworkError extends MpakError {
|
|
289
556
|
constructor(message: string);
|
|
290
557
|
}
|
|
558
|
+
/**
|
|
559
|
+
* Thrown when the config file cannot be read, parsed, or validated.
|
|
560
|
+
*
|
|
561
|
+
* @param message - Human-readable description of what went wrong
|
|
562
|
+
* @param configPath - Absolute path to the config file that failed
|
|
563
|
+
* @param cause - The underlying error (parse failure, read error, etc.)
|
|
564
|
+
*/
|
|
565
|
+
declare class MpakConfigCorruptedError extends MpakError {
|
|
566
|
+
readonly configPath: string;
|
|
567
|
+
readonly cause?: Error | undefined;
|
|
568
|
+
constructor(message: string, configPath: string, cause?: Error | undefined);
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Thrown when required user config fields are missing for a package.
|
|
572
|
+
*
|
|
573
|
+
* @param packageName - The package that requires config
|
|
574
|
+
* @param missingFields - Structured list of missing fields
|
|
575
|
+
*/
|
|
576
|
+
/**
|
|
577
|
+
* Thrown when cache metadata or manifest is missing, corrupt, or fails validation.
|
|
578
|
+
*
|
|
579
|
+
* @param message - Human-readable description of what went wrong
|
|
580
|
+
* @param filePath - Absolute path to the file that failed
|
|
581
|
+
* @param cause - The underlying error (parse failure, validation error, etc.)
|
|
582
|
+
*/
|
|
583
|
+
declare class MpakCacheCorruptedError extends MpakError {
|
|
584
|
+
readonly filePath: string;
|
|
585
|
+
readonly cause?: Error | undefined;
|
|
586
|
+
constructor(message: string, filePath: string, cause?: Error | undefined);
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Thrown when a local `.mcpb` bundle is invalid — e.g. manifest is missing,
|
|
590
|
+
* contains invalid JSON, or fails schema validation.
|
|
591
|
+
*
|
|
592
|
+
* @param message - Human-readable description of what went wrong
|
|
593
|
+
* @param bundlePath - Absolute path to the `.mcpb` file
|
|
594
|
+
* @param cause - The underlying error
|
|
595
|
+
*/
|
|
596
|
+
declare class MpakInvalidBundleError extends MpakError {
|
|
597
|
+
readonly bundlePath: string;
|
|
598
|
+
readonly cause?: Error | undefined;
|
|
599
|
+
constructor(message: string, bundlePath: string, cause?: Error | undefined);
|
|
600
|
+
}
|
|
601
|
+
declare class MpakConfigError extends MpakError {
|
|
602
|
+
readonly packageName: string;
|
|
603
|
+
readonly missingFields: Array<{
|
|
604
|
+
key: string;
|
|
605
|
+
title: string;
|
|
606
|
+
description?: string;
|
|
607
|
+
sensitive: boolean;
|
|
608
|
+
}>;
|
|
609
|
+
constructor(packageName: string, missingFields: Array<{
|
|
610
|
+
key: string;
|
|
611
|
+
title: string;
|
|
612
|
+
description?: string;
|
|
613
|
+
sensitive: boolean;
|
|
614
|
+
}>);
|
|
615
|
+
}
|
|
291
616
|
|
|
292
|
-
export {
|
|
617
|
+
export { Mpak, MpakBundleCache, type MpakBundleCacheOptions, MpakCacheCorruptedError, MpakClient, type MpakClientConfig, MpakConfigCorruptedError, MpakConfigError, MpakConfigManager, type MpakConfigManagerOptions, MpakError, MpakIntegrityError, MpakInvalidBundleError, MpakNetworkError, MpakNotFoundError, type MpakOptions, type PackageConfig, type PrepareServerOptions, type PrepareServerSpec, type ServerCommand, parsePackageSpec };
|