@happyvertical/smrt-app-cli 0.60.10 → 0.60.12

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/README.md CHANGED
@@ -243,3 +243,52 @@ credentials must match both server and issuer; environment credentials also
243
243
  require `${PREFIX}_TOKEN_ISSUER`. This does not replace the terminal device
244
244
  flow with browser OAuth. See the
245
245
  [remote authorization contract](../../docs/content/architecture/remote-mcp-authorization.md).
246
+
247
+ ### Generate local desktop plugin metadata
248
+
249
+ Use `generateDesktopPluginArtifacts` in the product's packaging step. Pass
250
+ public product metadata from the portable plugin manifest, such as the
251
+ [checked-in Kitchen manifest](../../plugins/smrt-kitchen/plugin.json). The
252
+ required fields are `name` (lowercase letters, digits and single hyphens),
253
+ `version` (SemVer), `description`, and `author.name`. The optional
254
+ `extensions["com.openai"].interface.displayName` defaults to `name`.
255
+
256
+ ```ts
257
+ import { generateDesktopPluginArtifacts } from '@happyvertical/smrt-app-cli';
258
+
259
+ const files = generateDesktopPluginArtifacts(productManifest, {
260
+ platform: 'darwin',
261
+ executable: 'server/smrt-mcp-launcher',
262
+ });
263
+ ```
264
+
265
+ The result maps distribution-root-relative paths to deterministic UTF-8 JSON.
266
+ Materialize the files in a fresh staging directory. Place the executable under
267
+ the same `server/` path in each plugin directory. Run the generator for the
268
+ target platform (`darwin`, `win32`, or `linux`), using an `.exe` launcher
269
+ filename for Windows. The launcher
270
+ must resolve the installed app's bundled runtime and obtain local authorization
271
+ at launch. The generator reads public metadata only and takes no environment,
272
+ MCP arguments, endpoint, or authentication configuration.
273
+
274
+ - `claude-desktop/<name>/manifest.json` is the binary extension manifest in
275
+ the staging directory for `mcpb pack`. Include the executable when packing.
276
+ The manifest declares the target platform and resolves the launcher from the
277
+ installed extension directory.
278
+ [Claude Desktop Extensions](https://www.anthropic.com/research/desktop-extensions) ·
279
+ [MCPB manifest format](https://github.com/modelcontextprotocol/mcpb/blob/main/MANIFEST.md)
280
+ - `plugins/<name>/plugin.json` and `mcp.json` are the portable ChatGPT
281
+ desktop plugin, listed in `.agents/plugins/marketplace.json`.
282
+ [OpenAI plugin packaging](https://developers.openai.com/plugins/build/plugins) ·
283
+ [Desktop-only plugins](https://developers.openai.com/plugins/deploy/desktop-only) ·
284
+ [Agent Plugins stdio path rules](https://agent-plugins.org/plugin-authors/mcp-servers#stdio-commands-and-paths)
285
+ - `plugins/<name>/.claude-plugin/plugin.json` and
286
+ `.claude-plugin/marketplace.json` provide Claude Code marketplace
287
+ compatibility. Claude Desktop installs the MCPB extension from the separate
288
+ staging directory.
289
+ [Claude Code marketplaces](https://code.claude.com/docs/en/plugin-marketplaces)
290
+
291
+ Each generated catalog contains one entry. For a shared catalog, merge the
292
+ entry into the catalog maintained by the packager. Live installation and
293
+ execution in Claude Desktop and ChatGPT desktop require the production
294
+ launcher and separate host verification.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as runAppCliExecutable } from "../src-DjwsOuHK.js";
2
+ import { i as runAppCliExecutable } from "../src-DjROuXuC.js";
3
3
  //#region src/bin/smrt-app.ts
4
4
  /**
5
5
  * `smrt-app` — configuration-driven executable for a published SMRT app CLI.
@@ -0,0 +1,13 @@
1
+ export interface DesktopPluginLauncher {
2
+ /** Platform of the packaged executable. */
3
+ readonly platform: 'darwin' | 'win32' | 'linux';
4
+ /** Executable the desktop packager supplies under server/ in each package. */
5
+ readonly executable: string;
6
+ }
7
+ /**
8
+ * Render manifest and marketplace files relative to a new distribution root.
9
+ * The input is public product metadata in the portable Agent Plugins shape.
10
+ * The packager supplies the launcher separately for its target platform.
11
+ */
12
+ export declare function generateDesktopPluginArtifacts(productManifest: unknown, launcher: DesktopPluginLauncher): Readonly<Record<string, string>>;
13
+ //# sourceMappingURL=desktop-plugins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"desktop-plugins.d.ts","sourceRoot":"","sources":["../src/desktop-plugins.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,qBAAqB;IACpC,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;IAChD,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAmDD;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,eAAe,EAAE,OAAO,EACxB,QAAQ,EAAE,qBAAqB,GAC9B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA2GlC"}
package/dist/index.d.ts CHANGED
@@ -18,6 +18,7 @@
18
18
  import { type CliConfig, type RequestJsonOptions } from './config.js';
19
19
  export { AppCliRequestError, type AppCliResultMetadata, assertSecureServerUrl, type CliConfig, type CliConfigContext, clearStoredToken, getServerUrl, getStoredToken, loadCliConfig, type RequestJsonOptions, type RequestJsonResult, redactTransportValue, requestJson, requestJsonResult, saveAuth, saveCliConfig, } from './config.js';
20
20
  import { type ResourceListResponse } from './discovery.js';
21
+ export { type DesktopPluginLauncher, generateDesktopPluginArtifacts, } from './desktop-plugins.js';
21
22
  export { type CliResource, type CommandDefinition, type CommandKind, type CommandScope, fetchResourceList, findCommand, findResourceBySlug, type ResourceListResponse, } from './discovery.js';
22
23
  export { buildUrl, invokeCommand } from './invoke.js';
23
24
  export { createMcpClientIdMetadataDocument, type McpClientIdMetadataDocument, type McpClientRegistration, type McpClientRegistrationOptions, type McpRegisteredClient, type OAuthApplicationType, type OAuthAuthorizationServerMetadata, registerMcpClient, resolveMcpClientRegistration, } from './mcp-oauth.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { a as getStoredToken, c as requestJson, d as saveAuth, f as saveCliConfig, h as runMcpStdioBridge, i as getServerUrl, l as requestJsonResult, n as assertSecureServerUrl, o as loadCliConfig, p as createMcpStdioBridge, r as clearStoredToken, s as redactTransportValue, t as AppCliRequestError } from "./config-B9dESami.js";
2
- import { a as buildFlagParser, c as createMcpClientIdMetadataDocument, d as buildUrl, f as invokeCommand, h as findResourceBySlug, i as runAppCliExecutable, l as registerMcpClient, m as findCommand, n as createAppCli, o as classifySchema, p as fetchResourceList, r as parseAppCliExecutableConfig, s as renderResponse, t as SMRT_MCP_RESULT_METADATA_KEY, u as resolveMcpClientRegistration } from "./src-DjwsOuHK.js";
3
- export { AppCliRequestError, SMRT_MCP_RESULT_METADATA_KEY, assertSecureServerUrl, buildFlagParser, buildUrl, classifySchema, clearStoredToken, createAppCli, createMcpClientIdMetadataDocument, createMcpStdioBridge, fetchResourceList, findCommand, findResourceBySlug, getServerUrl, getStoredToken, invokeCommand, loadCliConfig, parseAppCliExecutableConfig, redactTransportValue, registerMcpClient, renderResponse, requestJson, requestJsonResult, resolveMcpClientRegistration, runAppCliExecutable, runMcpStdioBridge, saveAuth, saveCliConfig };
2
+ import { a as buildFlagParser, c as createMcpClientIdMetadataDocument, d as buildUrl, f as invokeCommand, g as findResourceBySlug, h as findCommand, i as runAppCliExecutable, l as registerMcpClient, m as fetchResourceList, n as createAppCli, o as classifySchema, p as generateDesktopPluginArtifacts, r as parseAppCliExecutableConfig, s as renderResponse, t as SMRT_MCP_RESULT_METADATA_KEY, u as resolveMcpClientRegistration } from "./src-DjROuXuC.js";
3
+ export { AppCliRequestError, SMRT_MCP_RESULT_METADATA_KEY, assertSecureServerUrl, buildFlagParser, buildUrl, classifySchema, clearStoredToken, createAppCli, createMcpClientIdMetadataDocument, createMcpStdioBridge, fetchResourceList, findCommand, findResourceBySlug, generateDesktopPluginArtifacts, getServerUrl, getStoredToken, invokeCommand, loadCliConfig, parseAppCliExecutableConfig, redactTransportValue, registerMcpClient, renderResponse, requestJson, requestJsonResult, resolveMcpClientRegistration, runAppCliExecutable, runMcpStdioBridge, saveAuth, saveCliConfig };
@@ -57,6 +57,121 @@ function findCommand(resource, commandName) {
57
57
  return resource.commands.find((c) => c.commandName === commandName);
58
58
  }
59
59
  //#endregion
60
+ //#region src/desktop-plugins.ts
61
+ var AGENT_PLUGIN_SCHEMAS = "https://agent-plugins.org/schemas/1.0.0";
62
+ var PLUGIN_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
63
+ var SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?$/;
64
+ var PORTABLE_SEGMENT = /^[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*$/;
65
+ var WINDOWS_DEVICE = /^(?:con|prn|aux|nul|com[0-9]|lpt[0-9])(?:\.|$)/i;
66
+ function object(value, field) {
67
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(`Desktop plugin ${field} must be an object`);
68
+ return value;
69
+ }
70
+ function field(record, key) {
71
+ return Object.hasOwn(record, key) ? record[key] : void 0;
72
+ }
73
+ function optionalObject(record, key, label) {
74
+ const value = field(record, key);
75
+ return value === void 0 ? {} : object(value, label);
76
+ }
77
+ function publicText(value, label) {
78
+ if (typeof value !== "string" || value.trim().length === 0 || /\p{Cc}/u.test(value)) throw new Error(`Desktop plugin ${label} must be non-empty plain text`);
79
+ return value.trim();
80
+ }
81
+ function resolveLauncher(executable) {
82
+ if (typeof executable !== "string" || !executable.startsWith("server/") || executable.split("/").some((segment) => !PORTABLE_SEGMENT.test(segment) || WINDOWS_DEVICE.test(segment))) throw new Error("Desktop plugin launcher must be a portable path under server/");
83
+ return executable;
84
+ }
85
+ /**
86
+ * Render manifest and marketplace files relative to a new distribution root.
87
+ * The input is public product metadata in the portable Agent Plugins shape.
88
+ * The packager supplies the launcher separately for its target platform.
89
+ */
90
+ function generateDesktopPluginArtifacts(productManifest, launcher) {
91
+ const manifest = object(productManifest, "product manifest");
92
+ const name = publicText(field(manifest, "name"), "name");
93
+ if (name.length > 64 || !PLUGIN_NAME.test(name) || WINDOWS_DEVICE.test(name)) throw new Error("Desktop plugin name must be a portable lowercase slug");
94
+ const version = publicText(field(manifest, "version"), "version");
95
+ if (!SEMVER.test(version)) throw new Error("Desktop plugin version must be a semantic version");
96
+ const description = publicText(field(manifest, "description"), "description");
97
+ const author = { name: publicText(field(object(field(manifest, "author"), "author"), "name"), "author.name") };
98
+ const displayNameValue = field(optionalObject(optionalObject(optionalObject(manifest, "extensions", "extensions"), "com.openai", "extensions.com.openai"), "interface", "OpenAI interface"), "displayName");
99
+ const displayName = displayNameValue === void 0 ? name : publicText(displayNameValue, "OpenAI interface displayName");
100
+ const launcherConfig = object(launcher, "launcher");
101
+ const platform = field(launcherConfig, "platform");
102
+ if (platform !== "darwin" && platform !== "win32" && platform !== "linux") throw new Error("Desktop plugin launcher platform must be darwin, win32, or linux");
103
+ const executable = resolveLauncher(field(launcherConfig, "executable"));
104
+ const metadata = {
105
+ name,
106
+ version,
107
+ description,
108
+ author
109
+ };
110
+ const pluginDir = `plugins/${name}`;
111
+ const source = `./${pluginDir}`;
112
+ const files = {
113
+ [`claude-desktop/${name}/manifest.json`]: {
114
+ manifest_version: "0.3",
115
+ ...metadata,
116
+ display_name: displayName,
117
+ compatibility: { platforms: [platform] },
118
+ server: {
119
+ type: "binary",
120
+ entry_point: executable,
121
+ mcp_config: { command: `\${__dirname}/${executable}` }
122
+ }
123
+ },
124
+ [`${pluginDir}/plugin.json`]: {
125
+ $schema: `${AGENT_PLUGIN_SCHEMAS}/plugin.schema.json`,
126
+ ...metadata,
127
+ extensions: { "com.openai": { interface: {
128
+ displayName,
129
+ developerName: author.name
130
+ } } }
131
+ },
132
+ [`${pluginDir}/mcp.json`]: {
133
+ $schema: `${AGENT_PLUGIN_SCHEMAS}/mcp.schema.json`,
134
+ mcpServers: { [name]: {
135
+ type: "stdio",
136
+ command: `./${executable}`,
137
+ cwd: `\${PLUGIN_ROOT}`
138
+ } }
139
+ },
140
+ [`${pluginDir}/.claude-plugin/plugin.json`]: {
141
+ ...metadata,
142
+ mcpServers: { [name]: { command: `\${CLAUDE_PLUGIN_ROOT}/${executable}` } }
143
+ },
144
+ ".agents/plugins/marketplace.json": {
145
+ name,
146
+ interface: { displayName },
147
+ plugins: [{
148
+ name,
149
+ source: {
150
+ source: "local",
151
+ path: source
152
+ },
153
+ policy: {
154
+ installation: "AVAILABLE",
155
+ authentication: "ON_INSTALL"
156
+ },
157
+ category: "Productivity"
158
+ }]
159
+ },
160
+ ".claude-plugin/marketplace.json": {
161
+ name,
162
+ description,
163
+ owner: author,
164
+ plugins: [{
165
+ name,
166
+ source,
167
+ description,
168
+ category: "productivity"
169
+ }]
170
+ }
171
+ };
172
+ return Object.fromEntries(Object.entries(files).map(([path, value]) => [path, `${JSON.stringify(value, null, 2)}\n`]));
173
+ }
174
+ //#endregion
60
175
  //#region src/invoke.ts
61
176
  /**
62
177
  * Build the URL the CLI should hit for this command, plus the fetch init
@@ -1151,4 +1266,4 @@ function similar(a, b) {
1151
1266
  return true;
1152
1267
  }
1153
1268
  //#endregion
1154
- export { buildFlagParser as a, createMcpClientIdMetadataDocument as c, buildUrl as d, invokeCommand as f, findResourceBySlug as h, runAppCliExecutable as i, registerMcpClient as l, findCommand as m, createAppCli as n, classifySchema as o, fetchResourceList as p, parseAppCliExecutableConfig as r, renderResponse as s, SMRT_MCP_RESULT_METADATA_KEY$1 as t, resolveMcpClientRegistration as u };
1269
+ export { buildFlagParser as a, createMcpClientIdMetadataDocument as c, buildUrl as d, invokeCommand as f, findResourceBySlug as g, findCommand as h, runAppCliExecutable as i, registerMcpClient as l, fetchResourceList as m, createAppCli as n, classifySchema as o, generateDesktopPluginArtifacts as p, parseAppCliExecutableConfig as r, renderResponse as s, SMRT_MCP_RESULT_METADATA_KEY$1 as t, resolveMcpClientRegistration as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-app-cli",
3
- "version": "0.60.10",
3
+ "version": "0.60.12",
4
4
  "description": "Reusable CLI factory for SMRT apps — branded `<name> <resource> <command>` CLI + stdio MCP bridge with decorator-driven resource discovery",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -21,12 +21,12 @@
21
21
  "AGENTS.md"
22
22
  ],
23
23
  "dependencies": {
24
- "@happyvertical/smrt-users": "0.60.10",
24
+ "@happyvertical/smrt-users": "0.60.12",
25
25
  "@modelcontextprotocol/client": "2.3.1",
26
26
  "@modelcontextprotocol/server": "2.3.1"
27
27
  },
28
28
  "devDependencies": {
29
- "@happyvertical/smrt-core": "0.60.10",
29
+ "@happyvertical/smrt-core": "0.60.12",
30
30
  "@types/node": "24.13.6",
31
31
  "typescript": "6.0.3",
32
32
  "vite": "8.1.6",