@cmdforge/gen-apic-mp 0.0.1 → 0.0.3

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.
@@ -0,0 +1,139 @@
1
+ export type WorkspaceInfo = {
2
+ serviceName: string;
3
+ region: string;
4
+ workspaceName: string;
5
+ };
6
+ export type PortalConfig = {
7
+ dataApiHostName: string;
8
+ title: string;
9
+ capabilities: [];
10
+ };
11
+ export type JsonObject = Record<string, unknown>;
12
+ export type McpAssetItem = {
13
+ name: string;
14
+ title: string;
15
+ summary: string;
16
+ description: string;
17
+ kind: 'mcp';
18
+ lifecycleStage: string;
19
+ externalDocumentation: [];
20
+ contacts: [];
21
+ customProperties: JsonObject;
22
+ lastUpdated: string;
23
+ };
24
+ export type PluginAssetItem = {
25
+ name: string;
26
+ title: string;
27
+ description: string;
28
+ kind: 'plugin';
29
+ lifecycleStage: string;
30
+ externalDocumentation: [];
31
+ contacts: [];
32
+ customProperties: JsonObject;
33
+ lastUpdated: string;
34
+ };
35
+ export type ApiAssetItem = McpAssetItem | PluginAssetItem;
36
+ export type PluginMcpResource = {
37
+ resourceId: string;
38
+ title: string;
39
+ summary: string;
40
+ kind: 'mcp';
41
+ };
42
+ export type PluginResource = PluginMcpResource;
43
+ export type PluginAsset = {
44
+ name: string;
45
+ title: string;
46
+ summary: string;
47
+ description: string;
48
+ version: string;
49
+ resources: PluginResource[];
50
+ customProperties?: JsonObject;
51
+ };
52
+ export type PagedResponse<T> = {
53
+ value: T[];
54
+ nextLink?: string;
55
+ };
56
+ export type PlaneType = 'portal' | 'data';
57
+ export type V0HttpTransport = {
58
+ transport?: 'http' | 'https' | 'sse' | 'streamable-http';
59
+ type?: 'http' | 'https' | 'sse' | 'streamable-http';
60
+ url: string;
61
+ headers?: Record<string, string>;
62
+ };
63
+ export type V0StdioTransport = {
64
+ transport?: 'stdio';
65
+ type?: 'stdio';
66
+ command: string;
67
+ args?: string[];
68
+ env?: Record<string, string>;
69
+ cwd?: string;
70
+ };
71
+ export type V0ServerJsonEntry = V0HttpTransport | V0StdioTransport | JsonObject;
72
+ export type ServerJson = {
73
+ mcpServers?: Record<string, V0ServerJsonEntry>;
74
+ servers?: Record<string, V0ServerJsonEntry>;
75
+ };
76
+ export type V0ServerEntryResponse = V0ServerJsonEntry;
77
+ export type McpServerStdio = {
78
+ transport: 'stdio';
79
+ command: string;
80
+ args?: string[];
81
+ env?: Record<string, string>;
82
+ cwd?: string;
83
+ };
84
+ export type McpServerHttp = {
85
+ transport: 'http' | 'sse';
86
+ url: string;
87
+ headers?: Record<string, string>;
88
+ };
89
+ export type McpServer = (McpServerStdio | McpServerHttp) & JsonObject;
90
+ export type McpJson = {
91
+ mcpServers: Record<string, McpServer>;
92
+ };
93
+ export type GenerateMcpServerOptions = {
94
+ metaKeys?: string[];
95
+ };
96
+ export type PluginJson = {
97
+ name: string;
98
+ description: string;
99
+ version: string;
100
+ mcpServers?: string;
101
+ skills?: string[];
102
+ };
103
+ export type MarketplacePluginJson = {
104
+ name: string;
105
+ version: string;
106
+ description: string;
107
+ source: string | {
108
+ source: string;
109
+ repo: string;
110
+ path: string;
111
+ };
112
+ author?: {
113
+ name: string;
114
+ url: string;
115
+ };
116
+ homepage?: string;
117
+ keywords?: string[];
118
+ license?: string;
119
+ repository?: string;
120
+ skills: string[];
121
+ };
122
+ export type MarketplaceJson = {
123
+ name: string;
124
+ metadata: {
125
+ description: string;
126
+ version: string;
127
+ };
128
+ owner: {
129
+ name: string;
130
+ email?: string;
131
+ };
132
+ plugins: MarketplacePluginJson[];
133
+ };
134
+ export type McpAsset = McpAssetItem & {
135
+ version?: string;
136
+ serverJson?: ServerJson;
137
+ customProperties: JsonObject;
138
+ };
139
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,EAAE,CAAC;IAC1B,QAAQ,EAAE,EAAE,CAAC;IACb,gBAAgB,EAAE,UAAU,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,EAAE,CAAC;IAC1B,QAAQ,EAAE,EAAE,CAAC;IACb,gBAAgB,EAAE,UAAU,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB,YAAY,GACZ,eAAe,CAAC;AAEpB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,cAAc,GACtB,iBAAiB,CAAC;AAEtB,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,gBAAgB,CAAC,EAAE,UAAU,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAC7B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE1C,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,iBAAiB,CAAC;IACzD,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,iBAAiB,CAAC;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GACzB,eAAe,GACf,gBAAgB,GAChB,UAAU,CAAC;AAEf,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,CAAC;AAEtD,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,CAAC,cAAc,GAAG,aAAa,CAAC,GAAG,UAAU,CAAC;AAEtE,MAAM,MAAM,OAAO,GAAG;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG;QACf,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QACR,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,EAAE,qBAAqB,EAAE,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,gBAAgB,EAAE,UAAU,CAAC;CAC9B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,10 +1,44 @@
1
1
  {
2
2
  "name": "@cmdforge/gen-apic-mp",
3
- "version": "0.0.1",
4
- "description": "OIDC trusted publishing setup package for @cmdforge/gen-apic-mp",
5
- "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
9
- ]
3
+ "description": "Generate a marketplace.zip containing the contents of an expected marketplace.git repository for the given Azure API Center portal.",
4
+ "version": "0.0.3",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "author": {
8
+ "name": "Fluttershy",
9
+ "url": "https://github.com/Fluttershy"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/cmdforge/gen-apic-mp.git"
14
+ },
15
+ "bin": {
16
+ "gen-apic-mp": "./dist/server/cli.js"
17
+ },
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/shared/index.d.ts",
21
+ "import": "./dist/shared/index.js"
22
+ },
23
+ "./server": {
24
+ "types": "./dist/server/index.d.ts",
25
+ "import": "./dist/server/index.js"
26
+ }
27
+ },
28
+ "scripts": {
29
+ "build": "tsc",
30
+ "test": "node --test --import tsx src/**/*.test.ts"
31
+ },
32
+ "dependencies": {
33
+ "commander": "15.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "25.9.3",
37
+ "typescript": "^5.8.0",
38
+ "tsx": "4.22.4"
39
+ },
40
+ "allowScripts": {
41
+ "esbuild": true,
42
+ "fsevents": true
43
+ }
10
44
  }
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command, Option } from "commander";
4
+ import { generateMarketplaceGit, resolveUnpackDirectory } from "./marketplace.js";
5
+
6
+ const program = new Command();
7
+ const unpackPreset = "__CURRENT_WORKING_PACKAGE__";
8
+ const unpackOption = new Option(
9
+ "--unpack [directory]",
10
+ "Also unpack the generated marketplace into a directory; defaults to the current directory",
11
+ ).preset(unpackPreset);
12
+ const mcpMetaOption = new Option(
13
+ "--mcp-meta <key>",
14
+ "Include the specified _meta key in generated .mcp.json server entries",
15
+ ).argParser((value: string, previous: string[] = []) => [...previous, value]);
16
+
17
+ program.configureHelp({
18
+ optionDescription(option) {
19
+ const description = option.description ?? "";
20
+ if (option.attributeName() === "unpack" && option.presetArg === unpackPreset)
21
+ return description;
22
+ return option.description;
23
+ },
24
+ });
25
+
26
+ program
27
+ .argument("<serviceName>", "Region-unique API Center service name")
28
+ .argument("<region>", "Region name")
29
+ .argument("<workspaceName>", "Workspace to convert into marketplace zip")
30
+ .addOption(unpackOption)
31
+ .addOption(mcpMetaOption)
32
+ .action(async (
33
+ serviceName: string,
34
+ region: string,
35
+ workspaceName: string,
36
+ options: { unpack?: string; mcpMeta?: string[] },
37
+ ) => {
38
+ const unpack = await resolveUnpackDirectory(options.unpack);
39
+ const mcpMetaKeys = options.mcpMeta;
40
+
41
+ const result = await generateMarketplaceGit(
42
+ { serviceName, region, workspaceName },
43
+ { unpack, mcpMetaKeys },
44
+ );
45
+ if (result.unpackPath) {
46
+ console.log(`Unpacked marketplace into ${result.unpackPath}`);
47
+ return;
48
+ }
49
+
50
+ console.log(`Wrote ${result.pluginCount} plugins to ${result.zipPath}`);
51
+ });
52
+
53
+ program.parse();
@@ -0,0 +1 @@
1
+ export * from "./marketplace.js";
@@ -0,0 +1,169 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+
4
+ import {
5
+ mcpServerFromV0Entry,
6
+ mcpServerNameFromV0Entry,
7
+ mcpServersFromServerJson,
8
+ } from "./marketplace.js";
9
+
10
+ test("translates stdio-style v0 server.json entries", () => {
11
+ const server = mcpServerFromV0Entry({
12
+ command: "npx",
13
+ args: ["-y", "@example/server"],
14
+ env: {
15
+ API_KEY: "secret",
16
+ PORT: 3000,
17
+ },
18
+ });
19
+
20
+ assert.deepEqual(server, {
21
+ transport: "stdio",
22
+ command: "npx",
23
+ args: ["-y", "@example/server"],
24
+ env: {
25
+ API_KEY: "secret",
26
+ PORT: "3000",
27
+ },
28
+ });
29
+ });
30
+
31
+ test("translates HTTP-style v0 server.json entries", () => {
32
+ const server = mcpServerFromV0Entry({
33
+ type: "streamable-http",
34
+ url: "https://example.test/mcp",
35
+ headers: {
36
+ Authorization: "Bearer token",
37
+ },
38
+ });
39
+
40
+ assert.deepEqual(server, {
41
+ transport: "http",
42
+ url: "https://example.test/mcp",
43
+ headers: {
44
+ Authorization: "Bearer token",
45
+ },
46
+ });
47
+ });
48
+
49
+ test("reads both mcpServers and servers roots", () => {
50
+ assert.deepEqual(
51
+ mcpServersFromServerJson({
52
+ servers: {
53
+ sample: {
54
+ command: "node",
55
+ args: ["server.js"],
56
+ },
57
+ },
58
+ }),
59
+ {
60
+ sample: {
61
+ transport: "stdio",
62
+ command: "node",
63
+ args: ["server.js"],
64
+ },
65
+ },
66
+ );
67
+ });
68
+
69
+ test("translates nested server remotes and uses nested name", () => {
70
+ const entry = {
71
+ server: {
72
+ $schema: "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
73
+ name: "msdocs-mcp-server",
74
+ title: "Microsoft docs",
75
+ description: "AI assistant with real-time access to official Microsoft documentation.",
76
+ version: "Original",
77
+ remotes: [
78
+ {
79
+ type: "sse",
80
+ url: "https://learn.microsoft.com/api/mcp",
81
+ },
82
+ ],
83
+ _meta: {
84
+ "custom.auth": {
85
+ clientId: "client-id",
86
+ publicClient: true,
87
+ },
88
+ },
89
+ },
90
+ _meta: {
91
+ "registry.id": "placeholder-id",
92
+ "custom.auth": {
93
+ clientId: "wrong-level",
94
+ },
95
+ },
96
+ };
97
+
98
+ assert.equal(mcpServerNameFromV0Entry(entry), "msdocs-mcp-server");
99
+ assert.deepEqual(mcpServerFromV0Entry(entry), {
100
+ transport: "sse",
101
+ url: "https://learn.microsoft.com/api/mcp",
102
+ });
103
+ assert.deepEqual(mcpServerFromV0Entry(entry, {
104
+ metaKeys: ["custom.auth", "registry.id"],
105
+ }), {
106
+ transport: "sse",
107
+ url: "https://learn.microsoft.com/api/mcp",
108
+ clientId: "client-id",
109
+ publicClient: true,
110
+ });
111
+ });
112
+
113
+ test("falls back to first package when nested server has no remotes", () => {
114
+ const entry = {
115
+ server: {
116
+ name: "pkg-server",
117
+ packages: [
118
+ {
119
+ registryType: "npm",
120
+ identifier: "@example/pkg-server",
121
+ version: "1.2.3",
122
+ transport: {
123
+ type: "stdio",
124
+ },
125
+ environmentVariables: [
126
+ {
127
+ name: "API_KEY",
128
+ value: "secret",
129
+ },
130
+ ],
131
+ packageArguments: [
132
+ {
133
+ type: "named",
134
+ name: "--mode",
135
+ value: "test",
136
+ },
137
+ ],
138
+ },
139
+ ],
140
+ },
141
+ _meta: {
142
+ "oauth-client": {
143
+ client_name: "example",
144
+ },
145
+ ignored: true,
146
+ },
147
+ };
148
+
149
+ assert.equal(mcpServerNameFromV0Entry(entry), "pkg-server");
150
+ assert.deepEqual(mcpServerFromV0Entry(entry), {
151
+ transport: "stdio",
152
+ command: "npx",
153
+ args: ["-y", "@example/pkg-server@1.2.3", "--mode", "test"],
154
+ env: {
155
+ API_KEY: "secret",
156
+ },
157
+ });
158
+ assert.deepEqual(mcpServerFromV0Entry(entry, {
159
+ metaKeys: ["oauth-client"],
160
+ }), {
161
+ transport: "stdio",
162
+ command: "npx",
163
+ args: ["-y", "@example/pkg-server@1.2.3", "--mode", "test"],
164
+ env: {
165
+ API_KEY: "secret",
166
+ },
167
+ client_name: "example",
168
+ });
169
+ });