@cmdforge/gen-apic-mp 0.0.1 → 0.0.2

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/.editorconfig ADDED
@@ -0,0 +1,11 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 2
6
+ end_of_line = lf
7
+ charset = utf-8
8
+ trim_trailing_whitespace = true
9
+
10
+ [*.md]
11
+ trim_trailing_whitespace = false
@@ -0,0 +1,26 @@
1
+ name: Publish Package
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ id-token: write # Required for OIDC
10
+ contents: read
11
+
12
+ jobs:
13
+ publish:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v6
17
+
18
+ - uses: actions/setup-node@v6
19
+ with:
20
+ node-version: '24'
21
+ registry-url: 'https://registry.npmjs.org'
22
+ package-manager-cache: false # never use caching in release builds
23
+ - run: npm ci
24
+ - run: npm run build --if-present
25
+ - run: npm test
26
+ - run: npm publish # Or: npm stage publish
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 cmdforge
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,45 +1,121 @@
1
- # @cmdforge/gen-apic-mp
1
+ # gen-apic-mp
2
2
 
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
3
+ Generate marketplace repository contents from an Azure API Center workspace.
4
4
 
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
5
+ This tool reads plugin and MCP assets from API Center, translates legacy `v0/servers/{name}` data into MCP server entries, and emits the repository structure expected by marketplace-style plugin catalogs.
6
6
 
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
7
+ ## What it generates
8
8
 
9
- ## Purpose
9
+ For a workspace, `gen-apic-mp` produces:
10
10
 
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@cmdforge/gen-apic-mp`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
11
+ ```text
12
+ .github/plugin/marketplace.json
13
+ .claude-plugin/marketplace.json
14
+ plugins/{pluginName}/plugin.json
15
+ plugins/{pluginName}/.mcp.json
16
+ ```
15
17
 
16
- ## What is OIDC Trusted Publishing?
18
+ The generated `.mcp.json` only contains normal MCP server launch configuration:
17
19
 
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
20
+ - stdio servers: `transport`, `command`, `args`, `env`, `cwd`
21
+ - remote servers: `transport`, `url`, `headers`
19
22
 
20
- ## Setup Instructions
23
+ ## Install
21
24
 
22
- To properly configure OIDC trusted publishing for this package:
25
+ ```bash
26
+ npm install
27
+ npm run build
28
+ ```
23
29
 
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
30
+ To use the CLI directly from the repo during development:
28
31
 
29
- ## DO NOT USE THIS PACKAGE
32
+ ```bash
33
+ node dist/server/cli.js --help
34
+ ```
30
35
 
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
36
+ ## CLI
36
37
 
37
- ## More Information
38
+ ```bash
39
+ gen-apic-mp <serviceName> <region> <workspaceName> [--unpack [directory]]
40
+ ```
38
41
 
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
42
+ Arguments:
42
43
 
43
- ---
44
+ - `serviceName`: region-unique Azure API Center service name
45
+ - `region`: Azure region, like `eastus`
46
+ - `workspaceName`: API Center workspace to export
44
47
 
45
- **Maintained for OIDC setup purposes only**
48
+ Option:
49
+
50
+ - `--unpack [directory]`: write the generated marketplace tree directly into a directory instead of creating a zip
51
+
52
+ If `--unpack` is provided without a value, it defaults to the current working directory, but only if that directory contains a `package.json`.
53
+
54
+ ## Examples
55
+
56
+ Create a zip in the current directory:
57
+
58
+ ```bash
59
+ gen-apic-mp my-api-center eastus marketplace
60
+ ```
61
+
62
+ Unpack directly into the current repo:
63
+
64
+ ```bash
65
+ gen-apic-mp my-api-center eastus marketplace --unpack
66
+ ```
67
+
68
+ Unpack into a specific directory:
69
+
70
+ ```bash
71
+ gen-apic-mp my-api-center eastus marketplace --unpack /path/to/marketplace-repo
72
+ ```
73
+
74
+ ## Output behavior
75
+
76
+ Without `--unpack`, the CLI writes:
77
+
78
+ ```text
79
+ {workspaceName}-marketplace.zip
80
+ ```
81
+
82
+ With `--unpack`, the CLI does not create a zip. It syncs the generated tree directly into the target directory.
83
+
84
+ ## How MCP translation works
85
+
86
+ For each plugin resource with `kind: "mcp"`, the tool:
87
+
88
+ 1. Fetches the MCP asset using the plugin resource `resourceId`
89
+ 2. Fetches the legacy server entry from `workspaces/{workspaceName}/v0/servers/{mcp.name}`
90
+ 3. Uses the `server.name` from that payload as the key in `.mcp.json`
91
+ 4. Translates the server entry into a `types.McpServer`
92
+
93
+ The translator supports:
94
+
95
+ - direct stdio-style entries with `command`, `args`, and `env`
96
+ - direct remote-style entries with `url` and remote transport
97
+ - nested `server.remotes`
98
+ - nested `server.packages` as fallback when `remotes` is empty
99
+
100
+ ## Current limitations
101
+
102
+ - Skill directories are not generated yet, so `plugin.json` only includes `skills` when that support is added
103
+ - The tool expects the target API Center workspace to expose:
104
+ - portal config at `config.json`
105
+ - plugin assets in the workspace API listing
106
+ - MCP assets reachable from plugin resource IDs
107
+ - legacy server entries at `v0/servers/{name}`
108
+
109
+ ## Development
110
+
111
+ Build:
112
+
113
+ ```bash
114
+ npm run build
115
+ ```
116
+
117
+ Test:
118
+
119
+ ```bash
120
+ npm test
121
+ ```
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/server/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ import { Command, Option } from "commander";
3
+ import { generateMarketplaceGit, resolveUnpackDirectory } from "./marketplace.js";
4
+ const program = new Command();
5
+ const unpackPreset = "__CURRENT_WORKING_PACKAGE__";
6
+ const unpackOption = new Option("--unpack [directory]", "Also unpack the generated marketplace into a directory; defaults to the current directory").preset(unpackPreset);
7
+ program.configureHelp({
8
+ optionDescription(option) {
9
+ const description = option.description ?? "";
10
+ if (option.attributeName() === "unpack" && option.presetArg === unpackPreset)
11
+ return description;
12
+ return option.description;
13
+ },
14
+ });
15
+ program
16
+ .argument("<serviceName>", "Region-unique API Center service name")
17
+ .argument("<region>", "Region name")
18
+ .argument("<workspaceName>", "Workspace to convert into marketplace zip")
19
+ .addOption(unpackOption)
20
+ .action(async (serviceName, region, workspaceName, options) => {
21
+ const unpack = await resolveUnpackDirectory(options.unpack);
22
+ const result = await generateMarketplaceGit({ serviceName, region, workspaceName }, { unpack });
23
+ if (result.unpackPath) {
24
+ console.log(`Unpacked marketplace into ${result.unpackPath}`);
25
+ return;
26
+ }
27
+ console.log(`Wrote ${result.pluginCount} plugins to ${result.zipPath}`);
28
+ });
29
+ program.parse();
30
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/server/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAElF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,MAAM,YAAY,GAAG,6BAA6B,CAAC;AACnD,MAAM,YAAY,GAAG,IAAI,MAAM,CAC7B,sBAAsB,EACtB,2FAA2F,CAC5F,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAEvB,OAAO,CAAC,aAAa,CAAC;IACpB,iBAAiB,CAAC,MAAM;QACtB,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;QAC7C,IAAI,MAAM,CAAC,aAAa,EAAE,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,KAAK,YAAY;YAC1E,OAAO,WAAW,CAAC;QACrB,OAAO,MAAM,CAAC,WAAW,CAAC;IAC5B,CAAC;CACF,CAAC,CAAC;AAEH,OAAO;KACJ,QAAQ,CAAC,eAAe,EAAE,uCAAuC,CAAC;KAClE,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;KACnC,QAAQ,CAAC,iBAAiB,EAAE,2CAA2C,CAAC;KACxE,SAAS,CAAC,YAAY,CAAC;KACvB,MAAM,CAAC,KAAK,EACX,WAAmB,EACnB,MAAc,EACd,aAAqB,EACrB,OAA4B,EAC5B,EAAE;IACF,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAChG,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,6BAA6B,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,WAAW,eAAe,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;AAC1E,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./marketplace.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from "./marketplace.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { types } from "../shared/index.js";
2
+ export declare class ApiCenterClient {
3
+ readonly info: types.WorkspaceInfo;
4
+ get serviceName(): string;
5
+ get region(): string;
6
+ get workspaceName(): string;
7
+ constructor(info: types.WorkspaceInfo);
8
+ plane(plane: types.PlaneType): string;
9
+ path(plane: types.PlaneType, path: string): string;
10
+ url(plane: types.PlaneType, path: string, params?: Record<string, unknown>): string;
11
+ workspace(path: string, params?: Record<string, unknown>): string;
12
+ get<T>(url: string): Promise<T>;
13
+ paged<T>(url: string): AsyncGenerator<T[], void, unknown>;
14
+ config(): Promise<types.PortalConfig>;
15
+ apis($top?: number, $skip?: number): AsyncGenerator<types.ApiAssetItem[], void, unknown>;
16
+ plugin(name: string): Promise<types.PluginAsset>;
17
+ mcp(resourceId: string): Promise<types.McpAsset>;
18
+ v0Server(name: string): Promise<types.V0ServerJsonEntry>;
19
+ }
20
+ export declare function mcpServerNameFromV0Entry(entry: types.V0ServerJsonEntry): string;
21
+ export declare function mcpServerFromV0Entry(entry: types.V0ServerJsonEntry): types.McpServer;
22
+ export declare function mcpServersFromServerJson(serverJson: types.ServerJson): {
23
+ [k: string]: types.McpServer;
24
+ };
25
+ export type GenerateMarketplaceGitOptions = {
26
+ unpack?: string;
27
+ };
28
+ export declare function generateMarketplaceGit(info: types.WorkspaceInfo, options?: GenerateMarketplaceGitOptions): Promise<{
29
+ zipPath: string | undefined;
30
+ unpackPath: string | undefined;
31
+ pluginCount: number;
32
+ marketplaceJson: types.MarketplaceJson;
33
+ }>;
34
+ export declare function resolveUnpackDirectory(value: string | undefined): Promise<string | undefined>;
35
+ //# sourceMappingURL=marketplace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketplace.d.ts","sourceRoot":"","sources":["../../src/server/marketplace.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAI3C,qBAAa,eAAe;aAKE,IAAI,EAAE,KAAK,CAAC,aAAa;IAJrD,IAAI,WAAW,WAAoC;IACnD,IAAI,MAAM,WAA+B;IACzC,IAAI,aAAa,WAAsC;gBAE3B,IAAI,EAAE,KAAK,CAAC,aAAa;IAErD,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS;IAI5B,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM;IAIzC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAO9E,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAItD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM;IAWjB,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM;IAUrB,MAAM;IAIZ,IAAI,CAAC,IAAI,SAAK,EAAE,KAAK,CAAC,EAAE,MAAM;IAIxB,MAAM,CAAC,IAAI,EAAE,MAAM;IAInB,GAAG,CAAC,UAAU,EAAE,MAAM;IAItB,QAAQ,CAAC,IAAI,EAAE,MAAM;CAG5B;AAmMD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,KAAK,CAAC,iBAAiB,UAStE;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,KAAK,CAAC,iBAAiB,GAC7B,KAAK,CAAC,SAAS,CAqCjB;AAED,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU;;EAKpE;AAmED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,KAAK,CAAC,aAAa,EACzB,OAAO,GAAE,6BAAkC;;;;qBA4DY,KAAK,CAAC,eAAe;GAK7E;AAID,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,+BAerE"}