apiblaze 0.21.54 → 0.21.56
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/dist/index.js +34 -19
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var __toESM = (mod, isNodeMode, target2) => (target2 = mod != null ? __create(__
|
|
|
34
34
|
var version;
|
|
35
35
|
var init_package = __esm({
|
|
36
36
|
"package.json"() {
|
|
37
|
-
version = "0.21.
|
|
37
|
+
version = "0.21.56";
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
|
|
@@ -1124,7 +1124,7 @@ async function resolveProject(teamId, nameOrId, version2) {
|
|
|
1124
1124
|
projectName: chosen.projectName,
|
|
1125
1125
|
apiVersion: chosen.apiVersion,
|
|
1126
1126
|
teamId,
|
|
1127
|
-
tenant: chosen.tenant
|
|
1127
|
+
tenant: chosen.tenant ?? void 0
|
|
1128
1128
|
};
|
|
1129
1129
|
}
|
|
1130
1130
|
var import_chalk6;
|
|
@@ -5309,8 +5309,8 @@ __export(directory_exports, {
|
|
|
5309
5309
|
fetchDirectoryReport: () => fetchDirectoryReport,
|
|
5310
5310
|
isApiError: () => isApiError,
|
|
5311
5311
|
isReady: () => isReady,
|
|
5312
|
+
parseCompliant: () => parseCompliant,
|
|
5312
5313
|
parsePlatforms: () => parsePlatforms,
|
|
5313
|
-
parsePolicy: () => parsePolicy,
|
|
5314
5314
|
printReport: () => printReport
|
|
5315
5315
|
});
|
|
5316
5316
|
function attestationId(flag) {
|
|
@@ -5343,7 +5343,7 @@ function directoryBodyFromFlags(f) {
|
|
|
5343
5343
|
}
|
|
5344
5344
|
return out;
|
|
5345
5345
|
}
|
|
5346
|
-
function
|
|
5346
|
+
function parseCompliant(policy, platform) {
|
|
5347
5347
|
if (platform && (policy === void 0 || policy === true)) return parsePlatforms(platform) ?? ["claude"];
|
|
5348
5348
|
if (policy === void 0 || policy === false || policy === true) return ["claude"];
|
|
5349
5349
|
const raw = (Array.isArray(policy) ? policy : [policy]).flatMap((s) => String(s).split(",")).map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
@@ -5354,7 +5354,7 @@ function parsePolicy(policy, platform) {
|
|
|
5354
5354
|
PLATFORMS.forEach((x) => out.add(x));
|
|
5355
5355
|
continue;
|
|
5356
5356
|
}
|
|
5357
|
-
if (!PLATFORMS.includes(p)) throw new Error(`Unknown
|
|
5357
|
+
if (!PLATFORMS.includes(p)) throw new Error(`Unknown directory "${p}" for --compliant. Use claude, chatgpt or all.`);
|
|
5358
5358
|
out.add(p);
|
|
5359
5359
|
}
|
|
5360
5360
|
return PLATFORMS.filter((p) => out.has(p));
|
|
@@ -10604,7 +10604,7 @@ async function runCheck(project, opts) {
|
|
|
10604
10604
|
}
|
|
10605
10605
|
const name = project;
|
|
10606
10606
|
if (!name) throw new Error(`Which ${B.thingShort}? ${B.cli} check --directory-ready <project>`);
|
|
10607
|
-
const platforms =
|
|
10607
|
+
const platforms = parseCompliant(opts.compliant ?? opts.policy, opts.platform);
|
|
10608
10608
|
const stage = opts.stage === "create" ? "create" : opts.stage === "ready" || !opts.stage ? "ready" : void 0;
|
|
10609
10609
|
if (!stage) throw new Error("--stage must be create or ready");
|
|
10610
10610
|
const caller = requireCaller();
|
|
@@ -11123,7 +11123,7 @@ function seedMessage(proj2) {
|
|
|
11123
11123
|
async function runConnector(target2, opts) {
|
|
11124
11124
|
const caller = requireCaller();
|
|
11125
11125
|
const { teamId } = await resolveActingTeam(caller, opts.team);
|
|
11126
|
-
const platforms =
|
|
11126
|
+
const platforms = parseCompliant(opts.compliant ?? opts.policy, opts.platform);
|
|
11127
11127
|
const json = !!opts.json;
|
|
11128
11128
|
const interactive2 = !!process.stdin.isTTY && !json && !opts.yes;
|
|
11129
11129
|
const say = (s) => {
|
|
@@ -11221,7 +11221,12 @@ async function runConnector(target2, opts) {
|
|
|
11221
11221
|
process.stdout.write(JSON.stringify({ ready: true, project: proj2.projectId, headline: r.rendered.headline, report: r.report, packet: { markdown: mdPath, json: jsonPath }, portals: PORTALS, ...reviewer ? { reviewer } : {} }) + "\n");
|
|
11222
11222
|
return;
|
|
11223
11223
|
}
|
|
11224
|
-
|
|
11224
|
+
if (r.rendered.compliance) {
|
|
11225
|
+
console.log();
|
|
11226
|
+
console.log(r.rendered.compliance.split("\n").map((l, i) => i === 0 ? import_chalk28.default.bold(l) : l.replace(/^(\s+)✓ /, (_m, sp2) => `${sp2}${import_chalk28.default.green("\u2713")} `).replace(/^(\s+)! /, (_m, sp2) => `${sp2}${import_chalk28.default.yellow("!")} `)).join("\n"));
|
|
11227
|
+
} else {
|
|
11228
|
+
printReport(r, false);
|
|
11229
|
+
}
|
|
11225
11230
|
console.log();
|
|
11226
11231
|
console.log(import_chalk28.default.green.bold(` ${r.rendered.headline}`));
|
|
11227
11232
|
console.log(` Submission packet: ${import_chalk28.default.cyan(mdPath)} and ${import_chalk28.default.cyan(jsonPath)}`);
|
|
@@ -12007,9 +12012,9 @@ the header are not owned by ana@example.com's key.
|
|
|
12007
12012
|
|
|
12008
12013
|
## Listing it in the Claude or ChatGPT directory
|
|
12009
12014
|
|
|
12010
|
-
\`npx ${cli} create --
|
|
12011
|
-
in one command, to the letter of the Claude directory's policies (\`--
|
|
12012
|
-
\`npx ${cli} connector <name> --
|
|
12015
|
+
\`npx ${cli} create --compliant --target https://yourdomain.com/openapi.yaml --domain mcp.yourdomain.com\` \u2014 directory-ready
|
|
12016
|
+
in one command, to the letter of the Claude directory's policies (\`--compliant chatgpt\` or \`--compliant all\` for OpenAI's too;
|
|
12017
|
+
\`npx ${cli} connector <name> --compliant \u2026\` runs the same flow on an existing ${B.thingShort}): it creates the ${B.thingShort} from the spec, checks what the
|
|
12013
12018
|
directories require, applies the safe fixes, registers the MCP hostname and waits for its ONE CNAME
|
|
12014
12019
|
(\u2192 proxy.abz.run), hides utility endpoints and fills thin tool descriptions, asks for the rest with
|
|
12015
12020
|
every answer pre-filled from the spec and cut to the portal's limits (Enter accepts), creates the reviewer account, and writes the
|
|
@@ -12752,6 +12757,9 @@ async function runAuthz(projectArg, apiVersionArg) {
|
|
|
12752
12757
|
if (!match) {
|
|
12753
12758
|
throw new Error(`Project "${projectArg}" not found in your active team (${creds.teamName ?? teamId}). Run \`apiblaze projects\`.`);
|
|
12754
12759
|
}
|
|
12760
|
+
if (match.configMissing) {
|
|
12761
|
+
throw new Error(`Project "${projectArg}": its settings could not be loaded, so its tenant is unknown and no rule can be published to it. Open it in the dashboard (Refresh, or delete and re-create it) first.`);
|
|
12762
|
+
}
|
|
12755
12763
|
const projectId = match.projectId;
|
|
12756
12764
|
const apiVersion = apiVersionArg || match.apiVersion;
|
|
12757
12765
|
const tenant2 = match.tenant || projectId;
|
|
@@ -12813,6 +12821,9 @@ async function runRule(projectArg, ruleText, opts) {
|
|
|
12813
12821
|
if (!match) {
|
|
12814
12822
|
throw new Error(`Project "${projectArg}" not found in your active team (${creds.teamName ?? teamId}). Run \`${B.cli} projects\`.`);
|
|
12815
12823
|
}
|
|
12824
|
+
if (match.configMissing) {
|
|
12825
|
+
throw new Error(`Project "${projectArg}": its settings could not be loaded, so its tenant is unknown and no rule can be published to it. Open it in the dashboard (Refresh, or delete and re-create it) first.`);
|
|
12826
|
+
}
|
|
12816
12827
|
const projectId = match.projectId;
|
|
12817
12828
|
const apiVersion = opts.apiversion || match.apiVersion;
|
|
12818
12829
|
const tenant2 = match.tenant || projectId;
|
|
@@ -14068,7 +14079,10 @@ function declineAll(items) {
|
|
|
14068
14079
|
console.log(import_chalk48.default.yellow(` --yes: installing without ${skippable.length} setting${skippable.length === 1 ? "" : "s"} that need consent.`));
|
|
14069
14080
|
for (const i of skippable) console.log(import_chalk48.default.dim(` skipped ${i.kind} ${i.value}`));
|
|
14070
14081
|
}
|
|
14071
|
-
return new Set(skippable.map(
|
|
14082
|
+
return new Set(skippable.map(declineKey));
|
|
14083
|
+
}
|
|
14084
|
+
function declineKey(item) {
|
|
14085
|
+
return item.kind === "transform" ? `transform:${item.value}` : `kind:${item.kind}`;
|
|
14072
14086
|
}
|
|
14073
14087
|
async function confirmYesNo(message, interactive2) {
|
|
14074
14088
|
if (!interactive2) {
|
|
@@ -14101,7 +14115,7 @@ async function askConsent(items, interactive2, reinstalling) {
|
|
|
14101
14115
|
}
|
|
14102
14116
|
if (typed.toLowerCase() === "yes") return declined;
|
|
14103
14117
|
for (const item of items) {
|
|
14104
|
-
declined.add(item
|
|
14118
|
+
declined.add(declineKey(item));
|
|
14105
14119
|
}
|
|
14106
14120
|
console.log(import_chalk48.default.dim(` Installing without ${count} setting${count === 1 ? "" : "s"} \u2014 everything else is applied.`));
|
|
14107
14121
|
return declined;
|
|
@@ -20094,13 +20108,14 @@ program.command("login").description(`Authenticate with ${B.product}`).option("-
|
|
|
20094
20108
|
process.exit(1);
|
|
20095
20109
|
}
|
|
20096
20110
|
});
|
|
20097
|
-
program.command("create").description(`Put an app that is already DEPLOYED behind ${B.product}: a public URL and an MCP address for AI agents in front of your URL or OpenAPI spec. Included: API keys, sign-in, ownership rules, rate limits. No login needed. (App on this machine? Use \`dev\`.)`).option("--name <name>", B.cli === "mcpblaze" ? "MCP server name (becomes <name>-<tenant>.mcpblaze.com)" : "Proxy name (becomes <name>.abz.run)").option("--target <url|file>", "What to proxy \u2014 pass ANY of: a target server base URL (https://httpbin.org), a local OpenAPI file (./openapi.yaml), or a remote OpenAPI URL (https://acme.com/openapi.yaml). Spec inputs are detected automatically; routes, API version and environments then come from the spec").addOption(new import_commander.Option("--openapi <file|url>", "Deprecated alias \u2014 --target now detects spec files/URLs itself").hideHelp()).addOption(new import_commander.Option("--openapispec <file|url>", "Deprecated alias for --openapi").hideHelp()).option("--team <id|name>", "Team to create under (defaults to your active team)").option("--auth <type>", "Open ONE door only: api_key | oauth (sign in with GitHub, APIblaze-hosted) | none. Omitted = both doors.").option("--apikey", "API-key door only (no sign-in): the bootstrap keys are minted and printed; callers send X-API-Key, agents connect with a key.").option("--oauth [config]", `Sign-in door only (no API key). Bare = APIblaze-hosted GitHub sign-in. '{"iss","aud","jwks"}' = trust YOUR hosted login's JWTs. '{"provider","clientId","clientSecret"?}' = APIblaze-hosted login page with YOUR OAuth app (github \xB7 google \xB7 microsoft \xB7 facebook \xB7 auth0 \xB7 oidc); the secret is optional except for github and facebook. '{"provider":"oidc","issuer":"https://acme.okta.com/oauth2/default","clientId":"\u2026"}' = any OpenID Connect IdP by issuer (Okta \xB7 Entra \xB7 Keycloak \xB7 Cognito \xB7 \u2026).`).option("--identified", "Require every call to identify its end user (X-End-User-Id from a backend key, or a login token \u2014 a client key alone cannot); unattributed calls are rejected").option("--iam", `Turn IAM on for the ${B.thingShort}'s tenant so users & groups apply to identified calls`).option("--apiversion <version>", `API version to create (e.g. 2.0.0). Creating a new version of a ${B.thingShort} you own adds a version to the existing project.`).option("--tenant <slug>", `Tenant to attach the ${B.thingShort} to (created if new). Omitted \u2192 your team's most-recently-used tenant.`).option("--product <slug>", "Product tag to group this project under in the portal (team-scoped; anonymous create). Defaults to your team's existing/placeholder tag.").option("--display-name <name>", "Human-friendly display name").option("--subdomain <slug>", "Explicit subdomain (defaults to --name)").option("--config <file>", "JSON file with the full request body (anonymous create): requests_auth, login providers + client/server token types, scopes, callback URLs, etc. See apiblaze_anonymous.yaml. Flags override its fields.").option("-y, --yes", "Skip the confirmation prompt").option("--auto", `Zero prompts, start to finish: generates the ${B.thingShort} name when --name is omitted (from the target host, salted), takes every confirmation as yes, auto-picks the tenant. Implies --yes.`).option("--new-session", "Start a fresh anonymous session (do not group with prior anonymous creates)").option("--json", "Output machine-readable JSON (non-interactive)").option("--
|
|
20111
|
+
program.command("create").description(`Put an app that is already DEPLOYED behind ${B.product}: a public URL and an MCP address for AI agents in front of your URL or OpenAPI spec. Included: API keys, sign-in, ownership rules, rate limits. No login needed. (App on this machine? Use \`dev\`.)`).option("--name <name>", B.cli === "mcpblaze" ? "MCP server name (becomes <name>-<tenant>.mcpblaze.com)" : "Proxy name (becomes <name>.abz.run)").option("--target <url|file>", "What to proxy \u2014 pass ANY of: a target server base URL (https://httpbin.org), a local OpenAPI file (./openapi.yaml), or a remote OpenAPI URL (https://acme.com/openapi.yaml). Spec inputs are detected automatically; routes, API version and environments then come from the spec").addOption(new import_commander.Option("--openapi <file|url>", "Deprecated alias \u2014 --target now detects spec files/URLs itself").hideHelp()).addOption(new import_commander.Option("--openapispec <file|url>", "Deprecated alias for --openapi").hideHelp()).option("--team <id|name>", "Team to create under (defaults to your active team)").option("--auth <type>", "Open ONE door only: api_key | oauth (sign in with GitHub, APIblaze-hosted) | none. Omitted = both doors.").option("--apikey", "API-key door only (no sign-in): the bootstrap keys are minted and printed; callers send X-API-Key, agents connect with a key.").option("--oauth [config]", `Sign-in door only (no API key). Bare = APIblaze-hosted GitHub sign-in. '{"iss","aud","jwks"}' = trust YOUR hosted login's JWTs. '{"provider","clientId","clientSecret"?}' = APIblaze-hosted login page with YOUR OAuth app (github \xB7 google \xB7 microsoft \xB7 facebook \xB7 auth0 \xB7 oidc); the secret is optional except for github and facebook. '{"provider":"oidc","issuer":"https://acme.okta.com/oauth2/default","clientId":"\u2026"}' = any OpenID Connect IdP by issuer (Okta \xB7 Entra \xB7 Keycloak \xB7 Cognito \xB7 \u2026).`).option("--identified", "Require every call to identify its end user (X-End-User-Id from a backend key, or a login token \u2014 a client key alone cannot); unattributed calls are rejected").option("--iam", `Turn IAM on for the ${B.thingShort}'s tenant so users & groups apply to identified calls`).option("--apiversion <version>", `API version to create (e.g. 2.0.0). Creating a new version of a ${B.thingShort} you own adds a version to the existing project.`).option("--tenant <slug>", `Tenant to attach the ${B.thingShort} to (created if new). Omitted \u2192 your team's most-recently-used tenant.`).option("--product <slug>", "Product tag to group this project under in the portal (team-scoped; anonymous create). Defaults to your team's existing/placeholder tag.").option("--display-name <name>", "Human-friendly display name").option("--subdomain <slug>", "Explicit subdomain (defaults to --name)").option("--config <file>", "JSON file with the full request body (anonymous create): requests_auth, login providers + client/server token types, scopes, callback URLs, etc. See apiblaze_anonymous.yaml. Flags override its fields.").option("-y, --yes", "Skip the confirmation prompt").option("--auto", `Zero prompts, start to finish: generates the ${B.thingShort} name when --name is omitted (from the target host, salted), takes every confirmation as yes, auto-picks the tenant. Implies --yes.`).option("--new-session", "Start a fresh anonymous session (do not group with prior anonymous creates)").option("--json", "Output machine-readable JSON (non-interactive)").option("--compliant [directories...]", `Directory-ready in one command, to the letter of that directory's policies: create the ${B.thingShort} from --target (an OpenAPI URL/file), apply the safe fixes, set up the custom MCP domain (--domain, one CNAME), ask for every listing answer with the spec's proposal pre-filled (cut to the portal's limits), create the reviewer account, write the submission packet. Bare = claude; or claude \xB7 chatgpt \xB7 all. Ends with the compliance table: every rule the listing satisfies and the policy page it comes from. Same as \`${B.cli} connector <spec> --compliant \u2026\`.`).addOption(new import_commander.Option("--policy [directories...]", "Older spelling of --compliant").hideHelp()).option("--domain <host>", "With --compliant: the MCP server's custom hostname (mcp.<your domain>); asked for when missing, suggested from the spec").option("--wait <minutes>", "With --compliant: how long to wait for the custom domain to activate once its CNAME is in place (default 15; 0 = do not wait)").option("--directory-ready", "Make it directory-ready for the Claude and ChatGPT directories: OAuth door, custom-domain checks, listing fields; the readiness report runs after the create and a blocker exits 1").option("--privacy-url <url>", "Directory listing: public https privacy policy").option("--support <email|url>", "Directory listing: support contact").option("--docs-url <url>", "Directory listing: public documentation URL (the developer portal by default)").option("--prompt <text>", "Directory listing: an example prompt (repeat the flag; three are needed)", collect, []).option("--server-name <name>", 'Directory listing: the name (2\u201340 chars, no "MCP"/"Plugin" suffix)').option("--tagline <text>", "Directory listing: one-line tagline").option("--description <text>", "Directory listing: description").option("--icon-url <url>", "Directory listing: square icon (https)").option("--vuln-contact <email|url>", "Directory listing: vulnerability-disclosure contact").option("--attest <id>", "Attest (repeatable): guidelines \xB7 own-backend \xB7 no-financial \xB7 no-genai-media \xB7 no-prompt-injection \xB7 no-conversation-data \xB7 public-docs (Claude's seven) \xB7 no-digital-goods \xB7 content-13-no-ads \xB7 no-restricted-data (ChatGPT)", collect, []).option("--allowed-origin <origin>", "Directory mode: an extra browser origin allowed on the MCP host (repeatable)", collect, []).option("--openai-challenge <token>", "ChatGPT: the domain-verification token the OpenAI portal shows under Plugins \u2192 Connect MCP server").action(async (opts) => {
|
|
20098
20112
|
try {
|
|
20099
|
-
|
|
20113
|
+
const compliant = opts.compliant ?? opts.policy;
|
|
20114
|
+
if (compliant !== void 0 && compliant !== false) {
|
|
20100
20115
|
const spec2 = opts.target ?? opts.openapi ?? opts.openapispec;
|
|
20101
|
-
if (!spec2) throw new Error(`--
|
|
20116
|
+
if (!spec2) throw new Error(`--compliant needs the OpenAPI document: ${B.cli} create --compliant --target https://yourdomain.com/openapi.yaml --domain mcp.yourdomain.com`);
|
|
20102
20117
|
const { auth: _auth, target: _target, openapi: _openapi, openapispec: _spec, directoryReady: _dr, ...rest } = opts;
|
|
20103
|
-
await runConnector(spec2, { ...rest, full: true });
|
|
20118
|
+
await runConnector(spec2, { ...rest, compliant, full: true });
|
|
20104
20119
|
return;
|
|
20105
20120
|
}
|
|
20106
20121
|
await runCreate({ ...opts, openapi: opts.openapi ?? opts.openapispec });
|
|
@@ -20112,8 +20127,8 @@ program.command("create").description(`Put an app that is already DEPLOYED behin
|
|
|
20112
20127
|
function collect(value, previous) {
|
|
20113
20128
|
return [...previous ?? [], value];
|
|
20114
20129
|
}
|
|
20115
|
-
program.command("check").description(`Readiness report for the Claude and ChatGPT directories (--directory-ready): what passes, every blocker with its fix, and the ${B.thingShort}'s published URL. Exit 1 while a blocker remains.`).argument("[project]", `The ${B.thingShort} (project name)`).option("--directory-ready", "The directory readiness checks (the only mode today)").option("--
|
|
20116
|
-
var connector = program.command("connector").description(`Directory-ready in one command: from a project or straight from an OpenAPI URL \u2014 creates the ${B.thingShort} if needed, applies the safe fixes, sets up the custom MCP domain (one CNAME), pre-fills every listing answer from the spec, creates the reviewer account, and writes the submission packet when every check passes (you submit it to Anthropic and OpenAI yourself)`).argument("[project-or-spec]", `The ${B.thingShort} (project name), or an OpenAPI URL/file to create a directory-ready ${B.thingShort} from first`).option("--domain <host>", "Custom hostname for the MCP server (mcp.<your domain>); asked for when missing, suggested from the spec").option("--wait <minutes>", "How long to wait for the custom domain to activate once its CNAME is in place (default 15; 0 = do not wait)").option("--name <name>", `When creating from a spec: the ${B.thingShort} name (default: derived from the spec host)`).option("--privacy-url <url>", "Public https privacy policy").option("--support <email|url>", "Support contact").option("--docs-url <url>", "Public documentation URL").option("--prompt <text>", "An example prompt (repeatable; three are needed)", collect, []).option("--server-name <name>", 'Listing name (2\u201340 chars, no "MCP"/"Plugin" suffix)').option("--tagline <text>", "One-line tagline").option("--description <text>", "Description").option("--icon-url <url>", "Square icon (https)").option("--vuln-contact <email|url>", "Vulnerability-disclosure contact").option("--attest <id>", "Attest (repeatable): guidelines \xB7 own-backend \xB7 no-financial \xB7 no-genai-media \xB7 no-prompt-injection \xB7 no-conversation-data \xB7 public-docs (Claude's seven) \xB7 no-digital-goods \xB7 content-13-no-ads \xB7 no-restricted-data (ChatGPT). Alone, this only records the attestation.", collect, []).option("--allowed-origin <origin>", "An extra browser origin allowed on the MCP host (repeatable)", collect, []).option("--openai-challenge <token>", "ChatGPT: the domain-verification token the OpenAI portal shows under Plugins \u2192 Connect MCP server; served verbatim at /.well-known/openai-apps-challenge on your MCP domain").option("--full", "Run the full flow even when only --attest was given").option("--
|
|
20130
|
+
program.command("check").description(`Readiness report for the Claude and ChatGPT directories (--directory-ready): what passes, every blocker with its fix, and the ${B.thingShort}'s published URL. Exit 1 while a blocker remains.`).argument("[project]", `The ${B.thingShort} (project name)`).option("--directory-ready", "The directory readiness checks (the only mode today)").option("--compliant <directory>", "Which directory's policies to check against: claude \xB7 chatgpt \xB7 all (default claude; repeat or comma-separate)", collect, []).addOption(new import_commander.Option("--policy <directory>", "Older spelling of --compliant").hideHelp()).addOption(new import_commander.Option("--platform <list>", "Older spelling of --compliant").hideHelp()).option("--stage <stage>", "create (relaxed: docs URL is a warning) \xB7 ready (the submission gate, default)").option("--refresh-snapshot", "Re-take the listing snapshot (after you edited the listing in the portals)").option("--no-probe", "Skip the live probes from this machine (report what the server can see)").option("--team <id|name>", "Team the project is in (defaults to your active team)").option("--apiversion <version>", "API version (defaults to the project's)").option("--json", "Print the raw report JSON (report, rendered text, target)").action(action((project, opts) => runCheck(project, { ...opts, noProbe: opts.probe === false })));
|
|
20131
|
+
var connector = program.command("connector").description(`Directory-ready in one command: from a project or straight from an OpenAPI URL \u2014 creates the ${B.thingShort} if needed, applies the safe fixes, sets up the custom MCP domain (one CNAME), pre-fills every listing answer from the spec, creates the reviewer account, and writes the submission packet when every check passes (you submit it to Anthropic and OpenAI yourself)`).argument("[project-or-spec]", `The ${B.thingShort} (project name), or an OpenAPI URL/file to create a directory-ready ${B.thingShort} from first`).option("--domain <host>", "Custom hostname for the MCP server (mcp.<your domain>); asked for when missing, suggested from the spec").option("--wait <minutes>", "How long to wait for the custom domain to activate once its CNAME is in place (default 15; 0 = do not wait)").option("--name <name>", `When creating from a spec: the ${B.thingShort} name (default: derived from the spec host)`).option("--privacy-url <url>", "Public https privacy policy").option("--support <email|url>", "Support contact").option("--docs-url <url>", "Public documentation URL").option("--prompt <text>", "An example prompt (repeatable; three are needed)", collect, []).option("--server-name <name>", 'Listing name (2\u201340 chars, no "MCP"/"Plugin" suffix)').option("--tagline <text>", "One-line tagline").option("--description <text>", "Description").option("--icon-url <url>", "Square icon (https)").option("--vuln-contact <email|url>", "Vulnerability-disclosure contact").option("--attest <id>", "Attest (repeatable): guidelines \xB7 own-backend \xB7 no-financial \xB7 no-genai-media \xB7 no-prompt-injection \xB7 no-conversation-data \xB7 public-docs (Claude's seven) \xB7 no-digital-goods \xB7 content-13-no-ads \xB7 no-restricted-data (ChatGPT). Alone, this only records the attestation.", collect, []).option("--allowed-origin <origin>", "An extra browser origin allowed on the MCP host (repeatable)", collect, []).option("--openai-challenge <token>", "ChatGPT: the domain-verification token the OpenAI portal shows under Plugins \u2192 Connect MCP server; served verbatim at /.well-known/openai-apps-challenge on your MCP domain").option("--full", "Run the full flow even when only --attest was given").option("--compliant <directory>", "Which directory's policies this run must satisfy: claude \xB7 chatgpt \xB7 all (default claude; repeat or comma-separate)", collect, []).addOption(new import_commander.Option("--policy <directory>", "Older spelling of --compliant").hideHelp()).addOption(new import_commander.Option("--platform <list>", "Older spelling of --compliant").hideHelp()).option("--out <dir>", "Where to write connector-packet-<project>.md/.json (default: current directory)").option("-y, --yes", "No questions: apply the flags, report, exit 1 on a blocker").option("--team <id|name>", "Team the project is in (defaults to your active team)").option("--apiversion <version>", "API version (defaults to the project's)").option("--json", "Output machine-readable JSON").action(action(async (project, opts) => {
|
|
20117
20132
|
if (!project) throw new Error(`Which ${B.thingShort}? ${B.cli} connector <project> \xB7 ${B.cli} connector https://\u2026/openapi.yaml \xB7 ${B.cli} connector reviewer <project>`);
|
|
20118
20133
|
await runConnector(project, opts);
|
|
20119
20134
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apiblaze",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.56",
|
|
4
4
|
"description": "APIblaze CLI — Chat with your APIs, Manage your API keys, users and groups with the APIblaze serverless proxy",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"apiblaze",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"typecheck": "tsc --noEmit",
|
|
66
66
|
"prepublishOnly": "npm run build && npm run typecheck",
|
|
67
67
|
"release": "bash release.sh",
|
|
68
|
-
"test": "node test/tail-inspector.test.js"
|
|
68
|
+
"test": "node test/tail-inspector.test.js && node test/config-missing.test.js"
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
71
|
"chalk": "^4.1.2",
|