@sanity/cli 8.25.0 → 8.27.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/README.md +3 -2
- package/dist/actions/build/shouldAutoUpdate.js +1 -26
- package/dist/actions/build/shouldAutoUpdate.js.map +1 -1
- package/dist/actions/context/mcpEndpoint.js +165 -0
- package/dist/actions/context/mcpEndpoint.js.map +1 -0
- package/dist/actions/context/resolveOrganizationId.js +8 -1
- package/dist/actions/context/resolveOrganizationId.js.map +1 -1
- package/dist/actions/deploy/deployApp.js +10 -3
- package/dist/actions/deploy/deployApp.js.map +1 -1
- package/dist/actions/deploy/deployStudio.js +11 -4
- package/dist/actions/deploy/deployStudio.js.map +1 -1
- package/dist/actions/init/initAction.js +3 -3
- package/dist/actions/init/initAction.js.map +1 -1
- package/dist/actions/init/plan/verifyCoupon.js +0 -1
- package/dist/actions/init/plan/verifyCoupon.js.map +1 -1
- package/dist/actions/init/scaffoldTemplate.js +1 -1
- package/dist/actions/init/scaffoldTemplate.js.map +1 -1
- package/dist/commands/api.js +10 -0
- package/dist/commands/api.js.map +1 -1
- package/dist/commands/backups/download.js +6 -0
- package/dist/commands/backups/download.js.map +1 -1
- package/dist/commands/context/create.js +8 -22
- package/dist/commands/context/create.js.map +1 -1
- package/dist/commands/context/delete.js +8 -1
- package/dist/commands/context/delete.js.map +1 -1
- package/dist/commands/context/issues/list.js +0 -5
- package/dist/commands/context/issues/list.js.map +1 -1
- package/dist/commands/context/list.js +6 -14
- package/dist/commands/context/list.js.map +1 -1
- package/dist/commands/context/mcp/create.js +152 -0
- package/dist/commands/context/mcp/create.js.map +1 -0
- package/dist/commands/context/mcp/delete.js +82 -0
- package/dist/commands/context/mcp/delete.js.map +1 -0
- package/dist/commands/context/mcp/get.js +42 -0
- package/dist/commands/context/mcp/get.js.map +1 -0
- package/dist/commands/context/mcp/list.js +87 -0
- package/dist/commands/context/mcp/list.js.map +1 -0
- package/dist/commands/context/mcp/status.js +98 -0
- package/dist/commands/context/mcp/status.js.map +1 -0
- package/dist/commands/context/mcp/update.js +225 -0
- package/dist/commands/context/mcp/update.js.map +1 -0
- package/dist/commands/context/query.js +6 -14
- package/dist/commands/context/query.js.map +1 -1
- package/dist/commands/context/update.js +12 -1
- package/dist/commands/context/update.js.map +1 -1
- package/dist/commands/datasets/create.js +6 -0
- package/dist/commands/datasets/create.js.map +1 -1
- package/dist/commands/datasets/embeddings/enable.js +6 -0
- package/dist/commands/datasets/embeddings/enable.js.map +1 -1
- package/dist/commands/datasets/import.js +6 -0
- package/dist/commands/datasets/import.js.map +1 -1
- package/dist/commands/deploy.js +7 -0
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/documents/validate.js +6 -0
- package/dist/commands/documents/validate.js.map +1 -1
- package/dist/commands/exec.js +4 -2
- package/dist/commands/exec.js.map +1 -1
- package/dist/commands/init.js +13 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/manifest/extract.js +6 -0
- package/dist/commands/manifest/extract.js.map +1 -1
- package/dist/commands/media/create-aspect.js +7 -0
- package/dist/commands/media/create-aspect.js.map +1 -1
- package/dist/commands/migrations/run.js +6 -0
- package/dist/commands/migrations/run.js.map +1 -1
- package/dist/commands/organizations/create.js +6 -0
- package/dist/commands/organizations/create.js.map +1 -1
- package/dist/commands/organizations/update.js +6 -0
- package/dist/commands/organizations/update.js.map +1 -1
- package/dist/commands/schemas/delete.js +6 -0
- package/dist/commands/schemas/delete.js.map +1 -1
- package/dist/commands/schemas/deploy.js +6 -0
- package/dist/commands/schemas/deploy.js.map +1 -1
- package/dist/commands/schemas/extract.js +28 -3
- package/dist/commands/schemas/extract.js.map +1 -1
- package/dist/commands/schemas/list.js +6 -0
- package/dist/commands/schemas/list.js.map +1 -1
- package/dist/commands/schemas/validate.js +6 -0
- package/dist/commands/schemas/validate.js.map +1 -1
- package/dist/commands/tokens/rotate.js +6 -0
- package/dist/commands/tokens/rotate.js.map +1 -1
- package/dist/commands/typegen/generate.js +25 -1
- package/dist/commands/typegen/generate.js.map +1 -1
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js +6 -0
- package/dist/exports/invokeSanityCli/commandPolicies/mcpPolicy.js.map +1 -1
- package/dist/generated/apiRoutes.js +22 -0
- package/dist/generated/apiRoutes.js.map +1 -1
- package/dist/hooks/prerun/setupTelemetry.js +2 -3
- package/dist/hooks/prerun/setupTelemetry.js.map +1 -1
- package/dist/prompts/promptForText.js +12 -0
- package/dist/prompts/promptForText.js.map +1 -0
- package/dist/services/context.js +174 -1
- package/dist/services/context.js.map +1 -1
- package/dist/services/telemetry.js +4 -2
- package/dist/services/telemetry.js.map +1 -1
- package/dist/telemetry/cli.telemetry.js +1 -1
- package/dist/telemetry/cli.telemetry.js.map +1 -1
- package/dist/telemetry/init.telemetry.js +1 -1
- package/dist/telemetry/init.telemetry.js.map +1 -1
- package/dist/telemetry/typegen.telemetry.js +12 -0
- package/dist/telemetry/typegen.telemetry.js.map +1 -0
- package/dist/util/parseArguments.js +12 -40
- package/dist/util/parseArguments.js.map +1 -1
- package/dist/util/sharedFlags.js.map +1 -1
- package/dist/util/telemetry/cliCommandIdentity.js +222 -0
- package/dist/util/telemetry/cliCommandIdentity.js.map +1 -0
- package/dist/util/telemetry/cliTelemetryFlags.js +186 -0
- package/dist/util/telemetry/cliTelemetryFlags.js.map +1 -0
- package/dist/util/telemetry/commandTelemetry.js +56 -11
- package/dist/util/telemetry/commandTelemetry.js.map +1 -1
- package/dist/util/telemetry/createTelemetryStore.js +13 -5
- package/dist/util/telemetry/createTelemetryStore.js.map +1 -1
- package/dist/util/telemetry/createTraceId.js +3 -3
- package/dist/util/telemetry/createTraceId.js.map +1 -1
- package/dist/util/telemetry/flushTelemetryFiles.js +14 -4
- package/dist/util/telemetry/flushTelemetryFiles.js.map +1 -1
- package/dist/util/telemetry/logger.js +1 -1
- package/dist/util/telemetry/logger.js.map +1 -1
- package/dist/util/telemetry/readNDJSON.js +1 -1
- package/dist/util/telemetry/readNDJSON.js.map +1 -1
- package/dist/util/telemetry/sanitizeTelemetryEvent.js +304 -0
- package/dist/util/telemetry/sanitizeTelemetryEvent.js.map +1 -0
- package/dist/util/telemetry/trace.js +4 -7
- package/dist/util/telemetry/trace.js.map +1 -1
- package/oclif.config.js +1 -1
- package/oclif.manifest.json +2380 -1526
- package/package.json +8 -11
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
|
|
3
|
+
import { getErrorMessage } from '@sanity/cli-core/errors';
|
|
4
|
+
import { confirm } from '@sanity/cli-core/ux';
|
|
5
|
+
import { isHttpError } from '@sanity/client';
|
|
6
|
+
import { findMcpEndpoint, mcpEndpointNameArg, mcpEndpointOrganizationFlag } from '../../../actions/context/mcpEndpoint.js';
|
|
7
|
+
import { resolveOrganizationId } from '../../../actions/context/resolveOrganizationId.js';
|
|
8
|
+
import { deleteMcpEndpoint, describeBlueprintManager, getMcpEndpointBlueprintOwnership } from '../../../services/context.js';
|
|
9
|
+
const deleteMcpDebug = subdebug('context:mcp:delete');
|
|
10
|
+
export class DeleteMcpEndpointCommand extends SanityCommand {
|
|
11
|
+
static args = {
|
|
12
|
+
name: mcpEndpointNameArg
|
|
13
|
+
};
|
|
14
|
+
static description = 'Delete a Context MCP endpoint, which disconnects any agents using it';
|
|
15
|
+
static examples = [
|
|
16
|
+
{
|
|
17
|
+
command: '<%= config.bin %> <%= command.id %> support',
|
|
18
|
+
description: 'Delete an MCP endpoint after confirmation'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
command: '<%= config.bin %> <%= command.id %> support --yes',
|
|
22
|
+
description: 'Delete an MCP endpoint without confirmation prompt'
|
|
23
|
+
}
|
|
24
|
+
];
|
|
25
|
+
static flags = {
|
|
26
|
+
...mcpEndpointOrganizationFlag,
|
|
27
|
+
yes: Flags.boolean({
|
|
28
|
+
char: 'y',
|
|
29
|
+
default: false,
|
|
30
|
+
description: 'Skip confirmation prompt (unattended mode)'
|
|
31
|
+
})
|
|
32
|
+
};
|
|
33
|
+
async run() {
|
|
34
|
+
const { name } = this.args;
|
|
35
|
+
const { organization, yes: skipConfirmation } = this.flags;
|
|
36
|
+
const organizationId = await resolveOrganizationId({
|
|
37
|
+
configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,
|
|
38
|
+
flagOrganizationId: organization,
|
|
39
|
+
// Not `isUnattended()`: `--yes` skips the confirmation, not the organization picker
|
|
40
|
+
unattended: !this.resolveIsInteractive()
|
|
41
|
+
});
|
|
42
|
+
const endpoint = await findMcpEndpoint(organizationId, name);
|
|
43
|
+
const ownership = await getMcpEndpointBlueprintOwnership(organizationId, endpoint);
|
|
44
|
+
if (ownership.managed) {
|
|
45
|
+
const manager = describeBlueprintManager(ownership.stackName);
|
|
46
|
+
this.error(`${manager} manages MCP endpoint "${name}", so the next deploy would recreate it. To delete it, remove it from the blueprint and run \`sanity blueprints deploy\`.`, {
|
|
47
|
+
exit: exitCodes.USAGE_ERROR
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (this.isUnattended() && !skipConfirmation) {
|
|
51
|
+
this.error('Deletion requires confirmation. Pass `--yes` to delete the MCP endpoint.', {
|
|
52
|
+
exit: exitCodes.USAGE_ERROR
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (!skipConfirmation) {
|
|
56
|
+
const confirmed = await confirm({
|
|
57
|
+
default: false,
|
|
58
|
+
message: `Delete MCP endpoint "${name}"? Agents connected through it lose access.`
|
|
59
|
+
});
|
|
60
|
+
if (!confirmed) {
|
|
61
|
+
this.log('MCP endpoint not deleted');
|
|
62
|
+
this.exit(exitCodes.USER_ABORT);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
await deleteMcpEndpoint(organizationId, endpoint.name);
|
|
67
|
+
this.log('MCP endpoint deleted');
|
|
68
|
+
} catch (error) {
|
|
69
|
+
deleteMcpDebug('Error deleting MCP endpoint', error);
|
|
70
|
+
if (isHttpError(error) && error.statusCode === 404) {
|
|
71
|
+
this.error(`MCP endpoint "${name}" not found`, {
|
|
72
|
+
exit: exitCodes.RUNTIME_ERROR
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
this.error(`Failed to delete MCP endpoint: ${getErrorMessage(error)}`, {
|
|
76
|
+
exit: exitCodes.RUNTIME_ERROR
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/context/mcp/delete.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {confirm} from '@sanity/cli-core/ux'\nimport {isHttpError} from '@sanity/client'\n\nimport {\n findMcpEndpoint,\n mcpEndpointNameArg,\n mcpEndpointOrganizationFlag,\n} from '../../../actions/context/mcpEndpoint.js'\nimport {resolveOrganizationId} from '../../../actions/context/resolveOrganizationId.js'\nimport {\n deleteMcpEndpoint,\n describeBlueprintManager,\n getMcpEndpointBlueprintOwnership,\n} from '../../../services/context.js'\n\nconst deleteMcpDebug = subdebug('context:mcp:delete')\n\nexport class DeleteMcpEndpointCommand extends SanityCommand<typeof DeleteMcpEndpointCommand> {\n static override args = {\n name: mcpEndpointNameArg,\n }\n\n static override description =\n 'Delete a Context MCP endpoint, which disconnects any agents using it'\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> support',\n description: 'Delete an MCP endpoint after confirmation',\n },\n {\n command: '<%= config.bin %> <%= command.id %> support --yes',\n description: 'Delete an MCP endpoint without confirmation prompt',\n },\n ]\n\n static override flags = {\n ...mcpEndpointOrganizationFlag,\n yes: Flags.boolean({\n char: 'y',\n default: false,\n description: 'Skip confirmation prompt (unattended mode)',\n }),\n } satisfies FlagInput\n\n public async run(): Promise<void> {\n const {name} = this.args\n const {organization, yes: skipConfirmation} = this.flags\n\n const organizationId = await resolveOrganizationId({\n configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,\n flagOrganizationId: organization,\n // Not `isUnattended()`: `--yes` skips the confirmation, not the organization picker\n unattended: !this.resolveIsInteractive(),\n })\n\n const endpoint = await findMcpEndpoint(organizationId, name)\n\n const ownership = await getMcpEndpointBlueprintOwnership(organizationId, endpoint)\n if (ownership.managed) {\n const manager = describeBlueprintManager(ownership.stackName)\n this.error(\n `${manager} manages MCP endpoint \"${name}\", so the next deploy would recreate it. To delete it, remove it from the blueprint and run \\`sanity blueprints deploy\\`.`,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n if (this.isUnattended() && !skipConfirmation) {\n this.error('Deletion requires confirmation. Pass `--yes` to delete the MCP endpoint.', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n\n if (!skipConfirmation) {\n const confirmed = await confirm({\n default: false,\n message: `Delete MCP endpoint \"${name}\"? Agents connected through it lose access.`,\n })\n\n if (!confirmed) {\n this.log('MCP endpoint not deleted')\n this.exit(exitCodes.USER_ABORT)\n }\n }\n\n try {\n await deleteMcpEndpoint(organizationId, endpoint.name)\n this.log('MCP endpoint deleted')\n } catch (error) {\n deleteMcpDebug('Error deleting MCP endpoint', error)\n if (isHttpError(error) && error.statusCode === 404) {\n this.error(`MCP endpoint \"${name}\" not found`, {exit: exitCodes.RUNTIME_ERROR})\n }\n this.error(`Failed to delete MCP endpoint: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["Flags","exitCodes","SanityCommand","subdebug","getErrorMessage","confirm","isHttpError","findMcpEndpoint","mcpEndpointNameArg","mcpEndpointOrganizationFlag","resolveOrganizationId","deleteMcpEndpoint","describeBlueprintManager","getMcpEndpointBlueprintOwnership","deleteMcpDebug","DeleteMcpEndpointCommand","args","name","description","examples","command","flags","yes","boolean","char","default","run","organization","skipConfirmation","organizationId","configuredOrganizationId","tryGetCliConfig","app","flagOrganizationId","unattended","resolveIsInteractive","endpoint","ownership","managed","manager","stackName","error","exit","USAGE_ERROR","isUnattended","confirmed","message","log","USER_ABORT","statusCode","RUNTIME_ERROR"],"mappings":"AAAA,SAAQA,KAAK,QAAO,cAAa;AAEjC,SAAQC,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,eAAe,QAAO,0BAAyB;AACvD,SAAQC,OAAO,QAAO,sBAAqB;AAC3C,SAAQC,WAAW,QAAO,iBAAgB;AAE1C,SACEC,eAAe,EACfC,kBAAkB,EAClBC,2BAA2B,QACtB,0CAAyC;AAChD,SAAQC,qBAAqB,QAAO,oDAAmD;AACvF,SACEC,iBAAiB,EACjBC,wBAAwB,EACxBC,gCAAgC,QAC3B,+BAA8B;AAErC,MAAMC,iBAAiBX,SAAS;AAEhC,OAAO,MAAMY,iCAAiCb;IAC5C,OAAgBc,OAAO;QACrBC,MAAMT;IACR,EAAC;IAED,OAAgBU,cACd,uEAAsE;IAExE,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTF,aAAa;QACf;QACA;YACEE,SAAS;YACTF,aAAa;QACf;KACD,CAAA;IAED,OAAgBG,QAAQ;QACtB,GAAGZ,2BAA2B;QAC9Ba,KAAKtB,MAAMuB,OAAO,CAAC;YACjBC,MAAM;YACNC,SAAS;YACTP,aAAa;QACf;IACF,EAAqB;IAErB,MAAaQ,MAAqB;QAChC,MAAM,EAACT,IAAI,EAAC,GAAG,IAAI,CAACD,IAAI;QACxB,MAAM,EAACW,YAAY,EAAEL,KAAKM,gBAAgB,EAAC,GAAG,IAAI,CAACP,KAAK;QAExD,MAAMQ,iBAAiB,MAAMnB,sBAAsB;YACjDoB,0BAA0B,AAAC,CAAA,MAAM,IAAI,CAACC,eAAe,EAAC,EAAGC,GAAG,EAAEH;YAC9DI,oBAAoBN;YACpB,oFAAoF;YACpFO,YAAY,CAAC,IAAI,CAACC,oBAAoB;QACxC;QAEA,MAAMC,WAAW,MAAM7B,gBAAgBsB,gBAAgBZ;QAEvD,MAAMoB,YAAY,MAAMxB,iCAAiCgB,gBAAgBO;QACzE,IAAIC,UAAUC,OAAO,EAAE;YACrB,MAAMC,UAAU3B,yBAAyByB,UAAUG,SAAS;YAC5D,IAAI,CAACC,KAAK,CACR,GAAGF,QAAQ,uBAAuB,EAAEtB,KAAK,yHAAyH,CAAC,EACnK;gBAACyB,MAAMzC,UAAU0C,WAAW;YAAA;QAEhC;QAEA,IAAI,IAAI,CAACC,YAAY,MAAM,CAAChB,kBAAkB;YAC5C,IAAI,CAACa,KAAK,CAAC,4EAA4E;gBACrFC,MAAMzC,UAAU0C,WAAW;YAC7B;QACF;QAEA,IAAI,CAACf,kBAAkB;YACrB,MAAMiB,YAAY,MAAMxC,QAAQ;gBAC9BoB,SAAS;gBACTqB,SAAS,CAAC,qBAAqB,EAAE7B,KAAK,2CAA2C,CAAC;YACpF;YAEA,IAAI,CAAC4B,WAAW;gBACd,IAAI,CAACE,GAAG,CAAC;gBACT,IAAI,CAACL,IAAI,CAACzC,UAAU+C,UAAU;YAChC;QACF;QAEA,IAAI;YACF,MAAMrC,kBAAkBkB,gBAAgBO,SAASnB,IAAI;YACrD,IAAI,CAAC8B,GAAG,CAAC;QACX,EAAE,OAAON,OAAO;YACd3B,eAAe,+BAA+B2B;YAC9C,IAAInC,YAAYmC,UAAUA,MAAMQ,UAAU,KAAK,KAAK;gBAClD,IAAI,CAACR,KAAK,CAAC,CAAC,cAAc,EAAExB,KAAK,WAAW,CAAC,EAAE;oBAACyB,MAAMzC,UAAUiD,aAAa;gBAAA;YAC/E;YACA,IAAI,CAACT,KAAK,CAAC,CAAC,+BAA+B,EAAErC,gBAAgBqC,QAAQ,EAAE;gBACrEC,MAAMzC,UAAUiD,aAAa;YAC/B;QACF;IACF;AACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { SanityCommand } from '@sanity/cli-core';
|
|
2
|
+
import { findMcpEndpoint, formatMcpEndpoint, mcpEndpointNameArg, mcpEndpointOrganizationFlag } from '../../../actions/context/mcpEndpoint.js';
|
|
3
|
+
import { resolveOrganizationId } from '../../../actions/context/resolveOrganizationId.js';
|
|
4
|
+
export class GetMcpEndpointCommand extends SanityCommand {
|
|
5
|
+
static args = {
|
|
6
|
+
name: mcpEndpointNameArg
|
|
7
|
+
};
|
|
8
|
+
static description = 'Get details of a Context MCP endpoint, including its URL';
|
|
9
|
+
static enableJsonFlag = true;
|
|
10
|
+
static examples = [
|
|
11
|
+
{
|
|
12
|
+
command: '<%= config.bin %> <%= command.id %> support',
|
|
13
|
+
description: 'Get details of the "support" MCP endpoint'
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
command: '<%= config.bin %> <%= command.id %> support --organization org-abc123 --json',
|
|
17
|
+
description: 'Output an MCP endpoint in a specific organization as JSON'
|
|
18
|
+
}
|
|
19
|
+
];
|
|
20
|
+
static flags = {
|
|
21
|
+
...mcpEndpointOrganizationFlag
|
|
22
|
+
};
|
|
23
|
+
async run() {
|
|
24
|
+
const { name } = this.args;
|
|
25
|
+
const { json, organization } = this.flags;
|
|
26
|
+
const organizationId = await resolveOrganizationId({
|
|
27
|
+
configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,
|
|
28
|
+
flagOrganizationId: organization,
|
|
29
|
+
unattended: this.isUnattended()
|
|
30
|
+
});
|
|
31
|
+
const endpoint = await findMcpEndpoint(organizationId, name);
|
|
32
|
+
if (json) {
|
|
33
|
+
this.logJson(endpoint);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
for (const line of formatMcpEndpoint(endpoint)){
|
|
37
|
+
this.log(line);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=get.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/context/mcp/get.ts"],"sourcesContent":["import {type FlagInput} from '@oclif/core/interfaces'\nimport {SanityCommand} from '@sanity/cli-core'\n\nimport {\n findMcpEndpoint,\n formatMcpEndpoint,\n mcpEndpointNameArg,\n mcpEndpointOrganizationFlag,\n} from '../../../actions/context/mcpEndpoint.js'\nimport {resolveOrganizationId} from '../../../actions/context/resolveOrganizationId.js'\n\nexport class GetMcpEndpointCommand extends SanityCommand<typeof GetMcpEndpointCommand> {\n static override args = {\n name: mcpEndpointNameArg,\n }\n\n static override description = 'Get details of a Context MCP endpoint, including its URL'\n\n static override enableJsonFlag = true\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> support',\n description: 'Get details of the \"support\" MCP endpoint',\n },\n {\n command: '<%= config.bin %> <%= command.id %> support --organization org-abc123 --json',\n description: 'Output an MCP endpoint in a specific organization as JSON',\n },\n ]\n\n static override flags = {\n ...mcpEndpointOrganizationFlag,\n } satisfies FlagInput\n\n public async run(): Promise<void> {\n const {name} = this.args\n const {json, organization} = this.flags\n\n const organizationId = await resolveOrganizationId({\n configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,\n flagOrganizationId: organization,\n unattended: this.isUnattended(),\n })\n\n const endpoint = await findMcpEndpoint(organizationId, name)\n\n if (json) {\n this.logJson(endpoint)\n return\n }\n\n for (const line of formatMcpEndpoint(endpoint)) {\n this.log(line)\n }\n }\n}\n"],"names":["SanityCommand","findMcpEndpoint","formatMcpEndpoint","mcpEndpointNameArg","mcpEndpointOrganizationFlag","resolveOrganizationId","GetMcpEndpointCommand","args","name","description","enableJsonFlag","examples","command","flags","run","json","organization","organizationId","configuredOrganizationId","tryGetCliConfig","app","flagOrganizationId","unattended","isUnattended","endpoint","logJson","line","log"],"mappings":"AACA,SAAQA,aAAa,QAAO,mBAAkB;AAE9C,SACEC,eAAe,EACfC,iBAAiB,EACjBC,kBAAkB,EAClBC,2BAA2B,QACtB,0CAAyC;AAChD,SAAQC,qBAAqB,QAAO,oDAAmD;AAEvF,OAAO,MAAMC,8BAA8BN;IACzC,OAAgBO,OAAO;QACrBC,MAAML;IACR,EAAC;IAED,OAAgBM,cAAc,2DAA0D;IAExF,OAAgBC,iBAAiB,KAAI;IAErC,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGT,2BAA2B;IAChC,EAAqB;IAErB,MAAaU,MAAqB;QAChC,MAAM,EAACN,IAAI,EAAC,GAAG,IAAI,CAACD,IAAI;QACxB,MAAM,EAACQ,IAAI,EAAEC,YAAY,EAAC,GAAG,IAAI,CAACH,KAAK;QAEvC,MAAMI,iBAAiB,MAAMZ,sBAAsB;YACjDa,0BAA0B,AAAC,CAAA,MAAM,IAAI,CAACC,eAAe,EAAC,EAAGC,GAAG,EAAEH;YAC9DI,oBAAoBL;YACpBM,YAAY,IAAI,CAACC,YAAY;QAC/B;QAEA,MAAMC,WAAW,MAAMvB,gBAAgBgB,gBAAgBT;QAEvD,IAAIO,MAAM;YACR,IAAI,CAACU,OAAO,CAACD;YACb;QACF;QAEA,KAAK,MAAME,QAAQxB,kBAAkBsB,UAAW;YAC9C,IAAI,CAACG,GAAG,CAACD;QACX;IACF;AACF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
|
|
2
|
+
import { getErrorMessage } from '@sanity/cli-core/errors';
|
|
3
|
+
import { resolveOrganizationId } from '../../../actions/context/resolveOrganizationId.js';
|
|
4
|
+
import { listMcpEndpoints } from '../../../services/context.js';
|
|
5
|
+
import { Table } from '../../../util/responsiveTable.js';
|
|
6
|
+
import { getOrganizationFlag } from '../../../util/sharedFlags.js';
|
|
7
|
+
const listMcpDebug = subdebug('context:mcp:list');
|
|
8
|
+
export class ListMcpEndpointsCommand extends SanityCommand {
|
|
9
|
+
static description = 'List Context MCP endpoints in an organization';
|
|
10
|
+
static enableJsonFlag = true;
|
|
11
|
+
static examples = [
|
|
12
|
+
{
|
|
13
|
+
command: '<%= config.bin %> <%= command.id %>',
|
|
14
|
+
description: 'List MCP endpoints, selecting the organization interactively'
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
command: '<%= config.bin %> <%= command.id %> --organization org-abc123 --json',
|
|
18
|
+
description: 'Output the MCP endpoints of a specific organization as JSON'
|
|
19
|
+
}
|
|
20
|
+
];
|
|
21
|
+
static flags = {
|
|
22
|
+
...getOrganizationFlag({
|
|
23
|
+
description: 'Organization to list MCP endpoints for',
|
|
24
|
+
semantics: 'override'
|
|
25
|
+
})
|
|
26
|
+
};
|
|
27
|
+
async run() {
|
|
28
|
+
const { json, organization } = this.flags;
|
|
29
|
+
const organizationId = await resolveOrganizationId({
|
|
30
|
+
configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,
|
|
31
|
+
flagOrganizationId: organization,
|
|
32
|
+
unattended: this.isUnattended()
|
|
33
|
+
});
|
|
34
|
+
let endpoints;
|
|
35
|
+
try {
|
|
36
|
+
endpoints = await listMcpEndpoints(organizationId);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
listMcpDebug('Error listing MCP endpoints', error);
|
|
39
|
+
this.error(`Failed to list MCP endpoints: ${getErrorMessage(error)}`, {
|
|
40
|
+
exit: exitCodes.RUNTIME_ERROR
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (json) {
|
|
44
|
+
this.logJson(endpoints);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (endpoints.length === 0) {
|
|
48
|
+
this.log('No MCP endpoints found');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const table = new Table({
|
|
52
|
+
columns: [
|
|
53
|
+
{
|
|
54
|
+
alignment: 'left',
|
|
55
|
+
name: 'name',
|
|
56
|
+
title: 'Name'
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
alignment: 'left',
|
|
60
|
+
name: 'title',
|
|
61
|
+
title: 'Title'
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
alignment: 'left',
|
|
65
|
+
name: 'sources',
|
|
66
|
+
title: 'Sources'
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
alignment: 'left',
|
|
70
|
+
name: 'url',
|
|
71
|
+
title: 'URL'
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
});
|
|
75
|
+
for (const { name, sources, title, url } of endpoints){
|
|
76
|
+
table.addRow({
|
|
77
|
+
name,
|
|
78
|
+
sources: sources.map((source)=>source.id).join(', '),
|
|
79
|
+
title,
|
|
80
|
+
url
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
this.log(table.render());
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/context/mcp/list.ts"],"sourcesContent":["import {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\n\nimport {resolveOrganizationId} from '../../../actions/context/resolveOrganizationId.js'\nimport {listMcpEndpoints} from '../../../services/context.js'\nimport {Table} from '../../../util/responsiveTable.js'\nimport {getOrganizationFlag} from '../../../util/sharedFlags.js'\n\nconst listMcpDebug = subdebug('context:mcp:list')\n\nexport class ListMcpEndpointsCommand extends SanityCommand<typeof ListMcpEndpointsCommand> {\n static override description = 'List Context MCP endpoints in an organization'\n\n static override enableJsonFlag = true\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %>',\n description: 'List MCP endpoints, selecting the organization interactively',\n },\n {\n command: '<%= config.bin %> <%= command.id %> --organization org-abc123 --json',\n description: 'Output the MCP endpoints of a specific organization as JSON',\n },\n ]\n\n static override flags = {\n ...getOrganizationFlag({\n description: 'Organization to list MCP endpoints for',\n semantics: 'override',\n }),\n } satisfies FlagInput\n\n public async run(): Promise<void> {\n const {json, organization} = this.flags\n\n const organizationId = await resolveOrganizationId({\n configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,\n flagOrganizationId: organization,\n unattended: this.isUnattended(),\n })\n\n let endpoints\n try {\n endpoints = await listMcpEndpoints(organizationId)\n } catch (error) {\n listMcpDebug('Error listing MCP endpoints', error)\n this.error(`Failed to list MCP endpoints: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (json) {\n this.logJson(endpoints)\n return\n }\n\n if (endpoints.length === 0) {\n this.log('No MCP endpoints found')\n return\n }\n\n const table = new Table({\n columns: [\n {alignment: 'left', name: 'name', title: 'Name'},\n {alignment: 'left', name: 'title', title: 'Title'},\n {alignment: 'left', name: 'sources', title: 'Sources'},\n {alignment: 'left', name: 'url', title: 'URL'},\n ],\n })\n\n for (const {name, sources, title, url} of endpoints) {\n table.addRow({name, sources: sources.map((source) => source.id).join(', '), title, url})\n }\n\n this.log(table.render())\n }\n}\n"],"names":["exitCodes","SanityCommand","subdebug","getErrorMessage","resolveOrganizationId","listMcpEndpoints","Table","getOrganizationFlag","listMcpDebug","ListMcpEndpointsCommand","description","enableJsonFlag","examples","command","flags","semantics","run","json","organization","organizationId","configuredOrganizationId","tryGetCliConfig","app","flagOrganizationId","unattended","isUnattended","endpoints","error","exit","RUNTIME_ERROR","logJson","length","log","table","columns","alignment","name","title","sources","url","addRow","map","source","id","join","render"],"mappings":"AACA,SAAQA,SAAS,EAAEC,aAAa,EAAEC,QAAQ,QAAO,mBAAkB;AACnE,SAAQC,eAAe,QAAO,0BAAyB;AAEvD,SAAQC,qBAAqB,QAAO,oDAAmD;AACvF,SAAQC,gBAAgB,QAAO,+BAA8B;AAC7D,SAAQC,KAAK,QAAO,mCAAkC;AACtD,SAAQC,mBAAmB,QAAO,+BAA8B;AAEhE,MAAMC,eAAeN,SAAS;AAE9B,OAAO,MAAMO,gCAAgCR;IAC3C,OAAgBS,cAAc,gDAA+C;IAE7E,OAAgBC,iBAAiB,KAAI;IAErC,OAAgBC,WAAW;QACzB;YACEC,SAAS;YACTH,aAAa;QACf;QACA;YACEG,SAAS;YACTH,aAAa;QACf;KACD,CAAA;IAED,OAAgBI,QAAQ;QACtB,GAAGP,oBAAoB;YACrBG,aAAa;YACbK,WAAW;QACb,EAAE;IACJ,EAAqB;IAErB,MAAaC,MAAqB;QAChC,MAAM,EAACC,IAAI,EAAEC,YAAY,EAAC,GAAG,IAAI,CAACJ,KAAK;QAEvC,MAAMK,iBAAiB,MAAMf,sBAAsB;YACjDgB,0BAA0B,AAAC,CAAA,MAAM,IAAI,CAACC,eAAe,EAAC,EAAGC,GAAG,EAAEH;YAC9DI,oBAAoBL;YACpBM,YAAY,IAAI,CAACC,YAAY;QAC/B;QAEA,IAAIC;QACJ,IAAI;YACFA,YAAY,MAAMrB,iBAAiBc;QACrC,EAAE,OAAOQ,OAAO;YACdnB,aAAa,+BAA+BmB;YAC5C,IAAI,CAACA,KAAK,CAAC,CAAC,8BAA8B,EAAExB,gBAAgBwB,QAAQ,EAAE;gBACpEC,MAAM5B,UAAU6B,aAAa;YAC/B;QACF;QAEA,IAAIZ,MAAM;YACR,IAAI,CAACa,OAAO,CAACJ;YACb;QACF;QAEA,IAAIA,UAAUK,MAAM,KAAK,GAAG;YAC1B,IAAI,CAACC,GAAG,CAAC;YACT;QACF;QAEA,MAAMC,QAAQ,IAAI3B,MAAM;YACtB4B,SAAS;gBACP;oBAACC,WAAW;oBAAQC,MAAM;oBAAQC,OAAO;gBAAM;gBAC/C;oBAACF,WAAW;oBAAQC,MAAM;oBAASC,OAAO;gBAAO;gBACjD;oBAACF,WAAW;oBAAQC,MAAM;oBAAWC,OAAO;gBAAS;gBACrD;oBAACF,WAAW;oBAAQC,MAAM;oBAAOC,OAAO;gBAAK;aAC9C;QACH;QAEA,KAAK,MAAM,EAACD,IAAI,EAAEE,OAAO,EAAED,KAAK,EAAEE,GAAG,EAAC,IAAIb,UAAW;YACnDO,MAAMO,MAAM,CAAC;gBAACJ;gBAAME,SAASA,QAAQG,GAAG,CAAC,CAACC,SAAWA,OAAOC,EAAE,EAAEC,IAAI,CAAC;gBAAOP;gBAAOE;YAAG;QACxF;QAEA,IAAI,CAACP,GAAG,CAACC,MAAMY,MAAM;IACvB;AACF"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
|
|
2
|
+
import { getErrorMessage } from '@sanity/cli-core/errors';
|
|
3
|
+
import { isHttpError } from '@sanity/client';
|
|
4
|
+
import { findMcpEndpoint, mcpEndpointNameArg, mcpEndpointOrganizationFlag } from '../../../actions/context/mcpEndpoint.js';
|
|
5
|
+
import { resolveOrganizationId } from '../../../actions/context/resolveOrganizationId.js';
|
|
6
|
+
import { formatKeyValue } from '../../../actions/debug/output.js';
|
|
7
|
+
import { getMcpEndpointStatus } from '../../../services/context.js';
|
|
8
|
+
const statusMcpDebug = subdebug('context:mcp:status');
|
|
9
|
+
export class McpEndpointStatusCommand extends SanityCommand {
|
|
10
|
+
static args = {
|
|
11
|
+
name: mcpEndpointNameArg
|
|
12
|
+
};
|
|
13
|
+
static description = 'Check whether an agent connecting with your credentials can use a Context MCP endpoint';
|
|
14
|
+
static enableJsonFlag = true;
|
|
15
|
+
static examples = [
|
|
16
|
+
{
|
|
17
|
+
command: '<%= config.bin %> <%= command.id %> support',
|
|
18
|
+
description: 'Check the "support" MCP endpoint'
|
|
19
|
+
}
|
|
20
|
+
];
|
|
21
|
+
static flags = {
|
|
22
|
+
...mcpEndpointOrganizationFlag
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { name } = this.args;
|
|
26
|
+
const { json, organization } = this.flags;
|
|
27
|
+
const organizationId = await resolveOrganizationId({
|
|
28
|
+
configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,
|
|
29
|
+
flagOrganizationId: organization,
|
|
30
|
+
unattended: this.isUnattended()
|
|
31
|
+
});
|
|
32
|
+
const endpoint = await findMcpEndpoint(organizationId, name);
|
|
33
|
+
let status;
|
|
34
|
+
try {
|
|
35
|
+
// The status route only takes names, not IDs
|
|
36
|
+
status = await getMcpEndpointStatus(organizationId, endpoint.name);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
statusMcpDebug('Error checking MCP endpoint', error);
|
|
39
|
+
if (isHttpError(error) && error.statusCode === 404) {
|
|
40
|
+
this.error(`MCP endpoint "${name}" not found`, {
|
|
41
|
+
exit: exitCodes.RUNTIME_ERROR
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
this.error(`Failed to check MCP endpoint: ${getErrorMessage(error)}`, {
|
|
45
|
+
exit: exitCodes.RUNTIME_ERROR
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (json) {
|
|
49
|
+
this.logJson(status);
|
|
50
|
+
} else {
|
|
51
|
+
this.printStatus(status);
|
|
52
|
+
}
|
|
53
|
+
// Like `sanity doctor`: fail when agents can't use the endpoint. Semantic search never affects `requiredOk`
|
|
54
|
+
if (!status.requiredOk) this.exit(exitCodes.RUNTIME_ERROR);
|
|
55
|
+
}
|
|
56
|
+
printStatus(status) {
|
|
57
|
+
const { knowledgeBases, schema, semanticSearch, studio } = status.checks;
|
|
58
|
+
const padTo = 15 // "Knowledge bases" and "Semantic search" are the longest keys
|
|
59
|
+
;
|
|
60
|
+
this.log(formatKeyValue('Studio', formatCheck(studio, (check)=>`workspace "${check.workspace}"`), {
|
|
61
|
+
padTo
|
|
62
|
+
}));
|
|
63
|
+
this.log(formatKeyValue('Schema', formatCheck(schema, (check)=>`${check.documentTypes} document types, ${check.perspective} perspective`), {
|
|
64
|
+
padTo
|
|
65
|
+
}));
|
|
66
|
+
this.log(formatKeyValue('Knowledge bases', formatCheck(knowledgeBases, (check)=>check.resolved.join(', ')), {
|
|
67
|
+
padTo
|
|
68
|
+
}));
|
|
69
|
+
this.log(formatKeyValue('Semantic search', formatSemanticSearch(semanticSearch), {
|
|
70
|
+
padTo
|
|
71
|
+
}));
|
|
72
|
+
this.log(formatKeyValue('Ready', status.requiredOk ? 'yes' : 'no', {
|
|
73
|
+
padTo
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A check is `null` when it doesn't apply to the endpoint
|
|
79
|
+
*/ function formatCheck(check, describe) {
|
|
80
|
+
if (!check) return '-';
|
|
81
|
+
return isPassed(check) ? `ok (${describe(check)})` : `failed: ${check.error}`;
|
|
82
|
+
}
|
|
83
|
+
function isPassed(check) {
|
|
84
|
+
return check.ok;
|
|
85
|
+
}
|
|
86
|
+
const INACTIVE_REASONS = {
|
|
87
|
+
datasetEmbeddingsNotReady: 'embeddings are still being prepared',
|
|
88
|
+
turnedOff: 'turned off',
|
|
89
|
+
usageLimitReached: 'embeddings usage limit reached'
|
|
90
|
+
};
|
|
91
|
+
function formatSemanticSearch(check) {
|
|
92
|
+
if (!check) return '-';
|
|
93
|
+
if (!isPassed(check)) return `failed: ${check.error}`;
|
|
94
|
+
if (check.active) return 'active';
|
|
95
|
+
return check.inactiveReason ? `inactive (${INACTIVE_REASONS[check.inactiveReason]})` : 'inactive';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/context/mcp/status.ts"],"sourcesContent":["import {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {type Context, isHttpError} from '@sanity/client'\n\nimport {\n findMcpEndpoint,\n mcpEndpointNameArg,\n mcpEndpointOrganizationFlag,\n} from '../../../actions/context/mcpEndpoint.js'\nimport {resolveOrganizationId} from '../../../actions/context/resolveOrganizationId.js'\nimport {formatKeyValue} from '../../../actions/debug/output.js'\nimport {getMcpEndpointStatus} from '../../../services/context.js'\n\nconst statusMcpDebug = subdebug('context:mcp:status')\n\nexport class McpEndpointStatusCommand extends SanityCommand<typeof McpEndpointStatusCommand> {\n static override args = {\n name: mcpEndpointNameArg,\n }\n\n static override description =\n 'Check whether an agent connecting with your credentials can use a Context MCP endpoint'\n\n static override enableJsonFlag = true\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> support',\n description: 'Check the \"support\" MCP endpoint',\n },\n ]\n\n static override flags = {\n ...mcpEndpointOrganizationFlag,\n } satisfies FlagInput\n\n public async run(): Promise<void> {\n const {name} = this.args\n const {json, organization} = this.flags\n\n const organizationId = await resolveOrganizationId({\n configuredOrganizationId: (await this.tryGetCliConfig()).app?.organizationId,\n flagOrganizationId: organization,\n unattended: this.isUnattended(),\n })\n\n const endpoint = await findMcpEndpoint(organizationId, name)\n\n let status\n try {\n // The status route only takes names, not IDs\n status = await getMcpEndpointStatus(organizationId, endpoint.name)\n } catch (error) {\n statusMcpDebug('Error checking MCP endpoint', error)\n if (isHttpError(error) && error.statusCode === 404) {\n this.error(`MCP endpoint \"${name}\" not found`, {exit: exitCodes.RUNTIME_ERROR})\n }\n this.error(`Failed to check MCP endpoint: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n\n if (json) {\n this.logJson(status)\n } else {\n this.printStatus(status)\n }\n\n // Like `sanity doctor`: fail when agents can't use the endpoint. Semantic search never affects `requiredOk`\n if (!status.requiredOk) this.exit(exitCodes.RUNTIME_ERROR)\n }\n\n private printStatus(status: Context.McpEndpointStatus): void {\n const {knowledgeBases, schema, semanticSearch, studio} = status.checks\n const padTo = 15 // \"Knowledge bases\" and \"Semantic search\" are the longest keys\n this.log(\n formatKeyValue(\n 'Studio',\n formatCheck(studio, (check) => `workspace \"${check.workspace}\"`),\n {padTo},\n ),\n )\n this.log(\n formatKeyValue(\n 'Schema',\n formatCheck(\n schema,\n (check) => `${check.documentTypes} document types, ${check.perspective} perspective`,\n ),\n {padTo},\n ),\n )\n this.log(\n formatKeyValue(\n 'Knowledge bases',\n formatCheck(knowledgeBases, (check) => check.resolved.join(', ')),\n {padTo},\n ),\n )\n this.log(formatKeyValue('Semantic search', formatSemanticSearch(semanticSearch), {padTo}))\n this.log(formatKeyValue('Ready', status.requiredOk ? 'yes' : 'no', {padTo}))\n }\n}\n\n/**\n * A check is `null` when it doesn't apply to the endpoint\n */\nfunction formatCheck<Check extends {error?: string; ok: boolean}>(\n check: Check | null,\n describe: (check: Extract<Check, {ok: true}>) => string,\n): string {\n if (!check) return '-'\n return isPassed(check) ? `ok (${describe(check)})` : `failed: ${check.error}`\n}\n\nfunction isPassed<Check extends {ok: boolean}>(check: Check): check is Extract<Check, {ok: true}> {\n return check.ok\n}\n\ntype SemanticSearchCheck = Context.McpEndpointStatus['checks']['semanticSearch']\n\nconst INACTIVE_REASONS = {\n datasetEmbeddingsNotReady: 'embeddings are still being prepared',\n turnedOff: 'turned off',\n usageLimitReached: 'embeddings usage limit reached',\n} satisfies Record<NonNullable<Extract<SemanticSearchCheck, {ok: true}>['inactiveReason']>, string>\n\nfunction formatSemanticSearch(check: SemanticSearchCheck): string {\n if (!check) return '-'\n if (!isPassed(check)) return `failed: ${check.error}`\n if (check.active) return 'active'\n return check.inactiveReason ? `inactive (${INACTIVE_REASONS[check.inactiveReason]})` : 'inactive'\n}\n"],"names":["exitCodes","SanityCommand","subdebug","getErrorMessage","isHttpError","findMcpEndpoint","mcpEndpointNameArg","mcpEndpointOrganizationFlag","resolveOrganizationId","formatKeyValue","getMcpEndpointStatus","statusMcpDebug","McpEndpointStatusCommand","args","name","description","enableJsonFlag","examples","command","flags","run","json","organization","organizationId","configuredOrganizationId","tryGetCliConfig","app","flagOrganizationId","unattended","isUnattended","endpoint","status","error","statusCode","exit","RUNTIME_ERROR","logJson","printStatus","requiredOk","knowledgeBases","schema","semanticSearch","studio","checks","padTo","log","formatCheck","check","workspace","documentTypes","perspective","resolved","join","formatSemanticSearch","describe","isPassed","ok","INACTIVE_REASONS","datasetEmbeddingsNotReady","turnedOff","usageLimitReached","active","inactiveReason"],"mappings":"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"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { exitCodes, SanityCommand, subdebug } from '@sanity/cli-core';
|
|
3
|
+
import { getErrorMessage } from '@sanity/cli-core/errors';
|
|
4
|
+
import { spinner } from '@sanity/cli-core/ux';
|
|
5
|
+
import { isHttpError } from '@sanity/client';
|
|
6
|
+
import { datasetSourceId, editSources, findMcpEndpoint, formatMcpEndpoint, mcpEndpointNameArg, mcpEndpointOrganizationFlag, parseNonEmpty } from '../../../actions/context/mcpEndpoint.js';
|
|
7
|
+
import { resolveOrganizationId } from '../../../actions/context/resolveOrganizationId.js';
|
|
8
|
+
import { describeBlueprintManager, getMcpEndpointBlueprintOwnership, updateMcpEndpoint } from '../../../services/context.js';
|
|
9
|
+
import { getDatasetFlag, getProjectIdFlag } from '../../../util/sharedFlags.js';
|
|
10
|
+
import { defineCommandTelemetry } from '../../../util/telemetry/commandTelemetry.js';
|
|
11
|
+
const updateMcpDebug = subdebug('context:mcp:update');
|
|
12
|
+
const UPDATE_FLAGS = [
|
|
13
|
+
'title',
|
|
14
|
+
'add-knowledge-base',
|
|
15
|
+
'remove-knowledge-base',
|
|
16
|
+
'knowledge-base',
|
|
17
|
+
'dataset',
|
|
18
|
+
'no-dataset',
|
|
19
|
+
'workspace',
|
|
20
|
+
'perspective',
|
|
21
|
+
'semantic-search',
|
|
22
|
+
'instructions',
|
|
23
|
+
'groq-filter'
|
|
24
|
+
];
|
|
25
|
+
const flags = {
|
|
26
|
+
...mcpEndpointOrganizationFlag,
|
|
27
|
+
'add-knowledge-base': Flags.string({
|
|
28
|
+
atLeastOne: UPDATE_FLAGS,
|
|
29
|
+
description: 'Knowledge base to add to the endpoint; repeat the flag to add several',
|
|
30
|
+
helpValue: '<id>',
|
|
31
|
+
multiple: true,
|
|
32
|
+
parse: parseNonEmpty('add-knowledge-base')
|
|
33
|
+
}),
|
|
34
|
+
...getDatasetFlag({
|
|
35
|
+
atLeastOne: UPDATE_FLAGS,
|
|
36
|
+
description: 'Dataset the endpoint serves, replacing its current dataset',
|
|
37
|
+
semantics: 'specify'
|
|
38
|
+
}),
|
|
39
|
+
...getProjectIdFlag({
|
|
40
|
+
dependsOn: [
|
|
41
|
+
'dataset'
|
|
42
|
+
],
|
|
43
|
+
description: 'Project the dataset belongs to',
|
|
44
|
+
semantics: 'override'
|
|
45
|
+
}),
|
|
46
|
+
'groq-filter': Flags.string({
|
|
47
|
+
atLeastOne: UPDATE_FLAGS,
|
|
48
|
+
description: 'GROQ filter that limits which dataset documents the endpoint serves ("" removes it)'
|
|
49
|
+
}),
|
|
50
|
+
instructions: Flags.string({
|
|
51
|
+
atLeastOne: UPDATE_FLAGS,
|
|
52
|
+
description: 'Instructions the endpoint serves to connecting agents ("" removes them)'
|
|
53
|
+
}),
|
|
54
|
+
'knowledge-base': Flags.string({
|
|
55
|
+
atLeastOne: UPDATE_FLAGS,
|
|
56
|
+
hidden: true,
|
|
57
|
+
multiple: true
|
|
58
|
+
}),
|
|
59
|
+
'no-dataset': Flags.boolean({
|
|
60
|
+
atLeastOne: UPDATE_FLAGS,
|
|
61
|
+
description: 'Stop serving the dataset, which also removes the GROQ filter',
|
|
62
|
+
exclusive: [
|
|
63
|
+
'dataset'
|
|
64
|
+
]
|
|
65
|
+
}),
|
|
66
|
+
perspective: Flags.custom({
|
|
67
|
+
atLeastOne: UPDATE_FLAGS,
|
|
68
|
+
description: 'Perspective agents query the dataset with',
|
|
69
|
+
options: [
|
|
70
|
+
'published',
|
|
71
|
+
'drafts',
|
|
72
|
+
'raw'
|
|
73
|
+
]
|
|
74
|
+
})(),
|
|
75
|
+
'remove-knowledge-base': Flags.string({
|
|
76
|
+
atLeastOne: UPDATE_FLAGS,
|
|
77
|
+
description: 'Knowledge base to remove from the endpoint; repeat the flag to remove several',
|
|
78
|
+
helpValue: '<id>',
|
|
79
|
+
multiple: true,
|
|
80
|
+
parse: parseNonEmpty('remove-knowledge-base')
|
|
81
|
+
}),
|
|
82
|
+
'semantic-search': Flags.boolean({
|
|
83
|
+
allowNo: true,
|
|
84
|
+
atLeastOne: UPDATE_FLAGS,
|
|
85
|
+
description: 'Let agents use semantic search on the dataset (--no-semantic-search to turn it off)'
|
|
86
|
+
}),
|
|
87
|
+
title: Flags.string({
|
|
88
|
+
atLeastOne: UPDATE_FLAGS,
|
|
89
|
+
description: 'New MCP endpoint title',
|
|
90
|
+
parse: parseNonEmpty('title')
|
|
91
|
+
}),
|
|
92
|
+
workspace: Flags.string({
|
|
93
|
+
atLeastOne: UPDATE_FLAGS,
|
|
94
|
+
description: 'Studio workspace whose schema agents use ("" goes back to the first workspace)'
|
|
95
|
+
})
|
|
96
|
+
};
|
|
97
|
+
export class UpdateMcpEndpointCommand extends SanityCommand {
|
|
98
|
+
static args = {
|
|
99
|
+
name: mcpEndpointNameArg
|
|
100
|
+
};
|
|
101
|
+
static description = `Update a Context MCP endpoint
|
|
102
|
+
|
|
103
|
+
Only the settings you pass change. Dataset settings (--workspace, --perspective, --semantic-search) apply to the endpoint's dataset and start from the defaults when --dataset switches to another dataset.`;
|
|
104
|
+
static examples = [
|
|
105
|
+
{
|
|
106
|
+
command: '<%= config.bin %> <%= command.id %> support --title "Customer support"',
|
|
107
|
+
description: 'Rename an MCP endpoint'
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
command: '<%= config.bin %> <%= command.id %> support --add-knowledge-base kb-def456 --remove-knowledge-base kb-abc123',
|
|
111
|
+
description: 'Serve a different knowledge base'
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
command: '<%= config.bin %> <%= command.id %> catalog --project abc123 --dataset staging --perspective drafts',
|
|
115
|
+
description: 'Switch to another dataset and query its drafts'
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
command: '<%= config.bin %> <%= command.id %> support --no-dataset',
|
|
119
|
+
description: 'Stop serving the dataset'
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
command: '<%= config.bin %> <%= command.id %> support --instructions ""',
|
|
123
|
+
description: 'Remove the instructions'
|
|
124
|
+
}
|
|
125
|
+
];
|
|
126
|
+
static flags = flags;
|
|
127
|
+
static telemetry = defineCommandTelemetry(flags, {
|
|
128
|
+
redact: [
|
|
129
|
+
'title',
|
|
130
|
+
'instructions',
|
|
131
|
+
'groq-filter'
|
|
132
|
+
]
|
|
133
|
+
});
|
|
134
|
+
async run() {
|
|
135
|
+
const { name } = this.args;
|
|
136
|
+
const { 'add-knowledge-base': addKnowledgeBases = [], dataset, 'groq-filter': groqFilter, instructions, 'knowledge-base': knowledgeBase, 'no-dataset': noDataset, organization, perspective, project, 'remove-knowledge-base': removeKnowledgeBases = [], 'semantic-search': semanticSearch, title, workspace } = this.flags;
|
|
137
|
+
if (knowledgeBase !== undefined) {
|
|
138
|
+
this.error('`--knowledge-base` only works with `sanity context mcp create`. Use `--add-knowledge-base` or `--remove-knowledge-base` to change the knowledge bases of an endpoint.', {
|
|
139
|
+
exit: exitCodes.USAGE_ERROR
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
if (noDataset && [
|
|
143
|
+
groqFilter,
|
|
144
|
+
perspective,
|
|
145
|
+
semanticSearch,
|
|
146
|
+
workspace
|
|
147
|
+
].some((v)=>v !== undefined)) {
|
|
148
|
+
this.error('`--no-dataset` cannot be combined with `--groq-filter`, `--perspective`, `--semantic-search` or `--workspace`, which only apply to a dataset.', {
|
|
149
|
+
exit: exitCodes.USAGE_ERROR
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const addedAndRemoved = addKnowledgeBases.find((id)=>removeKnowledgeBases.includes(id));
|
|
153
|
+
if (addedAndRemoved) {
|
|
154
|
+
this.error(`"${addedAndRemoved}" is passed to both \`--add-knowledge-base\` and \`--remove-knowledge-base\`.`, {
|
|
155
|
+
exit: exitCodes.USAGE_ERROR
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
const cliConfig = await this.tryGetCliConfig();
|
|
159
|
+
const datasetId = datasetSourceId(dataset, project ?? cliConfig.api?.projectId);
|
|
160
|
+
const params = {};
|
|
161
|
+
if (title !== undefined) params.title = title;
|
|
162
|
+
if (instructions !== undefined) params.instructions = instructions.trim() || null;
|
|
163
|
+
if (groqFilter !== undefined) params.groqFilter = groqFilter.trim() || null;
|
|
164
|
+
const settings = {};
|
|
165
|
+
if (workspace !== undefined) settings.workspace = workspace.trim() || null;
|
|
166
|
+
if (perspective !== undefined) settings.perspective = perspective;
|
|
167
|
+
if (semanticSearch !== undefined) settings.semanticSearch = semanticSearch;
|
|
168
|
+
const changesSources = addKnowledgeBases.length > 0 || removeKnowledgeBases.length > 0 || dataset !== undefined || noDataset || Object.keys(settings).length > 0;
|
|
169
|
+
const needsDataset = Object.keys(settings).length > 0 || Boolean(params.groqFilter);
|
|
170
|
+
const organizationId = await resolveOrganizationId({
|
|
171
|
+
configuredOrganizationId: cliConfig.app?.organizationId,
|
|
172
|
+
flagOrganizationId: organization,
|
|
173
|
+
unattended: this.isUnattended()
|
|
174
|
+
});
|
|
175
|
+
const current = await findMcpEndpoint(organizationId, name);
|
|
176
|
+
const ownership = await getMcpEndpointBlueprintOwnership(organizationId, current);
|
|
177
|
+
if (ownership.managed) {
|
|
178
|
+
const manager = describeBlueprintManager(ownership.stackName);
|
|
179
|
+
this.error(`${manager} manages MCP endpoint "${name}", so the next deploy would undo this change. Change it in the blueprint and run \`sanity blueprints deploy\` instead.`, {
|
|
180
|
+
exit: exitCodes.USAGE_ERROR
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
if (changesSources || needsDataset) {
|
|
184
|
+
const { notes, sources } = editSources(current.sources, {
|
|
185
|
+
addKnowledgeBases,
|
|
186
|
+
dataset: noDataset ? null : datasetId,
|
|
187
|
+
removeKnowledgeBases,
|
|
188
|
+
settings
|
|
189
|
+
});
|
|
190
|
+
if (needsDataset && !sources.some((source)=>source.type === 'dataset')) {
|
|
191
|
+
this.error(`MCP endpoint "${name}" has no dataset source. Pass \`--dataset\` to add one.`, {
|
|
192
|
+
exit: exitCodes.USAGE_ERROR
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
if (sources.length === 0) {
|
|
196
|
+
this.error('An MCP endpoint needs at least one knowledge base or dataset', {
|
|
197
|
+
exit: exitCodes.USAGE_ERROR
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
for (const note of notes)this.warn(note);
|
|
201
|
+
if (changesSources) params.sources = sources;
|
|
202
|
+
}
|
|
203
|
+
const spin = spinner('Updating MCP endpoint').start();
|
|
204
|
+
try {
|
|
205
|
+
const endpoint = await updateMcpEndpoint(organizationId, current.name, params);
|
|
206
|
+
spin.succeed('MCP endpoint updated');
|
|
207
|
+
for (const line of formatMcpEndpoint(endpoint)){
|
|
208
|
+
this.log(line);
|
|
209
|
+
}
|
|
210
|
+
} catch (error) {
|
|
211
|
+
spin.fail();
|
|
212
|
+
updateMcpDebug('Error updating MCP endpoint', error);
|
|
213
|
+
if (isHttpError(error) && error.statusCode === 404) {
|
|
214
|
+
this.error(`MCP endpoint "${name}" not found`, {
|
|
215
|
+
exit: exitCodes.RUNTIME_ERROR
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
this.error(`Failed to update MCP endpoint: ${getErrorMessage(error)}`, {
|
|
219
|
+
exit: exitCodes.RUNTIME_ERROR
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/context/mcp/update.ts"],"sourcesContent":["import {Flags} from '@oclif/core'\nimport {type FlagInput} from '@oclif/core/interfaces'\nimport {exitCodes, SanityCommand, subdebug} from '@sanity/cli-core'\nimport {getErrorMessage} from '@sanity/cli-core/errors'\nimport {spinner} from '@sanity/cli-core/ux'\nimport {type Context, isHttpError} from '@sanity/client'\n\nimport {\n type DatasetSettings,\n datasetSourceId,\n editSources,\n findMcpEndpoint,\n formatMcpEndpoint,\n mcpEndpointNameArg,\n mcpEndpointOrganizationFlag,\n parseNonEmpty,\n} from '../../../actions/context/mcpEndpoint.js'\nimport {resolveOrganizationId} from '../../../actions/context/resolveOrganizationId.js'\nimport {\n describeBlueprintManager,\n getMcpEndpointBlueprintOwnership,\n updateMcpEndpoint,\n} from '../../../services/context.js'\nimport {getDatasetFlag, getProjectIdFlag} from '../../../util/sharedFlags.js'\nimport {defineCommandTelemetry} from '../../../util/telemetry/commandTelemetry.js'\n\nconst updateMcpDebug = subdebug('context:mcp:update')\n\nconst UPDATE_FLAGS = [\n 'title',\n 'add-knowledge-base',\n 'remove-knowledge-base',\n 'knowledge-base',\n 'dataset',\n 'no-dataset',\n 'workspace',\n 'perspective',\n 'semantic-search',\n 'instructions',\n 'groq-filter',\n]\n\nconst flags = {\n ...mcpEndpointOrganizationFlag,\n 'add-knowledge-base': Flags.string({\n atLeastOne: UPDATE_FLAGS,\n description: 'Knowledge base to add to the endpoint; repeat the flag to add several',\n helpValue: '<id>',\n multiple: true,\n parse: parseNonEmpty('add-knowledge-base'),\n }),\n ...getDatasetFlag({\n atLeastOne: UPDATE_FLAGS,\n description: 'Dataset the endpoint serves, replacing its current dataset',\n semantics: 'specify',\n }),\n ...getProjectIdFlag({\n dependsOn: ['dataset'],\n description: 'Project the dataset belongs to',\n semantics: 'override',\n }),\n 'groq-filter': Flags.string({\n atLeastOne: UPDATE_FLAGS,\n description:\n 'GROQ filter that limits which dataset documents the endpoint serves (\"\" removes it)',\n }),\n instructions: Flags.string({\n atLeastOne: UPDATE_FLAGS,\n description: 'Instructions the endpoint serves to connecting agents (\"\" removes them)',\n }),\n 'knowledge-base': Flags.string({\n atLeastOne: UPDATE_FLAGS,\n hidden: true,\n multiple: true,\n }),\n 'no-dataset': Flags.boolean({\n atLeastOne: UPDATE_FLAGS,\n description: 'Stop serving the dataset, which also removes the GROQ filter',\n exclusive: ['dataset'],\n }),\n perspective: Flags.custom<'drafts' | 'published' | 'raw'>({\n atLeastOne: UPDATE_FLAGS,\n description: 'Perspective agents query the dataset with',\n options: ['published', 'drafts', 'raw'],\n })(),\n 'remove-knowledge-base': Flags.string({\n atLeastOne: UPDATE_FLAGS,\n description: 'Knowledge base to remove from the endpoint; repeat the flag to remove several',\n helpValue: '<id>',\n multiple: true,\n parse: parseNonEmpty('remove-knowledge-base'),\n }),\n 'semantic-search': Flags.boolean({\n allowNo: true,\n atLeastOne: UPDATE_FLAGS,\n description:\n 'Let agents use semantic search on the dataset (--no-semantic-search to turn it off)',\n }),\n title: Flags.string({\n atLeastOne: UPDATE_FLAGS,\n description: 'New MCP endpoint title',\n parse: parseNonEmpty('title'),\n }),\n workspace: Flags.string({\n atLeastOne: UPDATE_FLAGS,\n description: 'Studio workspace whose schema agents use (\"\" goes back to the first workspace)',\n }),\n} satisfies FlagInput\n\nexport class UpdateMcpEndpointCommand extends SanityCommand<typeof UpdateMcpEndpointCommand> {\n static override args = {\n name: mcpEndpointNameArg,\n }\n\n static override description = `Update a Context MCP endpoint\n\nOnly the settings you pass change. Dataset settings (--workspace, --perspective, --semantic-search) apply to the endpoint's dataset and start from the defaults when --dataset switches to another dataset.`\n\n static override examples = [\n {\n command: '<%= config.bin %> <%= command.id %> support --title \"Customer support\"',\n description: 'Rename an MCP endpoint',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> support --add-knowledge-base kb-def456 --remove-knowledge-base kb-abc123',\n description: 'Serve a different knowledge base',\n },\n {\n command:\n '<%= config.bin %> <%= command.id %> catalog --project abc123 --dataset staging --perspective drafts',\n description: 'Switch to another dataset and query its drafts',\n },\n {\n command: '<%= config.bin %> <%= command.id %> support --no-dataset',\n description: 'Stop serving the dataset',\n },\n {\n command: '<%= config.bin %> <%= command.id %> support --instructions \"\"',\n description: 'Remove the instructions',\n },\n ]\n\n static override flags = flags\n\n static telemetry = defineCommandTelemetry(flags, {\n redact: ['title', 'instructions', 'groq-filter'],\n })\n\n public async run(): Promise<void> {\n const {name} = this.args\n const {\n 'add-knowledge-base': addKnowledgeBases = [],\n dataset,\n 'groq-filter': groqFilter,\n instructions,\n 'knowledge-base': knowledgeBase,\n 'no-dataset': noDataset,\n organization,\n perspective,\n project,\n 'remove-knowledge-base': removeKnowledgeBases = [],\n 'semantic-search': semanticSearch,\n title,\n workspace,\n } = this.flags\n\n if (knowledgeBase !== undefined) {\n this.error(\n '`--knowledge-base` only works with `sanity context mcp create`. Use `--add-knowledge-base` or `--remove-knowledge-base` to change the knowledge bases of an endpoint.',\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n if (\n noDataset &&\n [groqFilter, perspective, semanticSearch, workspace].some((v) => v !== undefined)\n ) {\n this.error(\n '`--no-dataset` cannot be combined with `--groq-filter`, `--perspective`, `--semantic-search` or `--workspace`, which only apply to a dataset.',\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n const addedAndRemoved = addKnowledgeBases.find((id) => removeKnowledgeBases.includes(id))\n if (addedAndRemoved) {\n this.error(\n `\"${addedAndRemoved}\" is passed to both \\`--add-knowledge-base\\` and \\`--remove-knowledge-base\\`.`,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n const cliConfig = await this.tryGetCliConfig()\n const datasetId = datasetSourceId(dataset, project ?? cliConfig.api?.projectId)\n\n const params: Context.EditMcpEndpointParams = {}\n if (title !== undefined) params.title = title\n if (instructions !== undefined) params.instructions = instructions.trim() || null\n if (groqFilter !== undefined) params.groqFilter = groqFilter.trim() || null\n\n const settings: DatasetSettings = {}\n if (workspace !== undefined) settings.workspace = workspace.trim() || null\n if (perspective !== undefined) settings.perspective = perspective\n if (semanticSearch !== undefined) settings.semanticSearch = semanticSearch\n const changesSources =\n addKnowledgeBases.length > 0 ||\n removeKnowledgeBases.length > 0 ||\n dataset !== undefined ||\n noDataset ||\n Object.keys(settings).length > 0\n const needsDataset = Object.keys(settings).length > 0 || Boolean(params.groqFilter)\n\n const organizationId = await resolveOrganizationId({\n configuredOrganizationId: cliConfig.app?.organizationId,\n flagOrganizationId: organization,\n unattended: this.isUnattended(),\n })\n\n const current = await findMcpEndpoint(organizationId, name)\n\n const ownership = await getMcpEndpointBlueprintOwnership(organizationId, current)\n if (ownership.managed) {\n const manager = describeBlueprintManager(ownership.stackName)\n this.error(\n `${manager} manages MCP endpoint \"${name}\", so the next deploy would undo this change. Change it in the blueprint and run \\`sanity blueprints deploy\\` instead.`,\n {exit: exitCodes.USAGE_ERROR},\n )\n }\n\n if (changesSources || needsDataset) {\n const {notes, sources} = editSources(current.sources, {\n addKnowledgeBases,\n dataset: noDataset ? null : datasetId,\n removeKnowledgeBases,\n settings,\n })\n if (needsDataset && !sources.some((source) => source.type === 'dataset')) {\n this.error(`MCP endpoint \"${name}\" has no dataset source. Pass \\`--dataset\\` to add one.`, {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n if (sources.length === 0) {\n this.error('An MCP endpoint needs at least one knowledge base or dataset', {\n exit: exitCodes.USAGE_ERROR,\n })\n }\n for (const note of notes) this.warn(note)\n if (changesSources) params.sources = sources\n }\n\n const spin = spinner('Updating MCP endpoint').start()\n try {\n const endpoint = await updateMcpEndpoint(organizationId, current.name, params)\n spin.succeed('MCP endpoint updated')\n for (const line of formatMcpEndpoint(endpoint)) {\n this.log(line)\n }\n } catch (error) {\n spin.fail()\n updateMcpDebug('Error updating MCP endpoint', error)\n if (isHttpError(error) && error.statusCode === 404) {\n this.error(`MCP endpoint \"${name}\" not found`, {exit: exitCodes.RUNTIME_ERROR})\n }\n this.error(`Failed to update MCP endpoint: ${getErrorMessage(error)}`, {\n exit: exitCodes.RUNTIME_ERROR,\n })\n }\n }\n}\n"],"names":["Flags","exitCodes","SanityCommand","subdebug","getErrorMessage","spinner","isHttpError","datasetSourceId","editSources","findMcpEndpoint","formatMcpEndpoint","mcpEndpointNameArg","mcpEndpointOrganizationFlag","parseNonEmpty","resolveOrganizationId","describeBlueprintManager","getMcpEndpointBlueprintOwnership","updateMcpEndpoint","getDatasetFlag","getProjectIdFlag","defineCommandTelemetry","updateMcpDebug","UPDATE_FLAGS","flags","string","atLeastOne","description","helpValue","multiple","parse","semantics","dependsOn","instructions","hidden","boolean","exclusive","perspective","custom","options","allowNo","title","workspace","UpdateMcpEndpointCommand","args","name","examples","command","telemetry","redact","run","addKnowledgeBases","dataset","groqFilter","knowledgeBase","noDataset","organization","project","removeKnowledgeBases","semanticSearch","undefined","error","exit","USAGE_ERROR","some","v","addedAndRemoved","find","id","includes","cliConfig","tryGetCliConfig","datasetId","api","projectId","params","trim","settings","changesSources","length","Object","keys","needsDataset","Boolean","organizationId","configuredOrganizationId","app","flagOrganizationId","unattended","isUnattended","current","ownership","managed","manager","stackName","notes","sources","source","type","note","warn","spin","start","endpoint","succeed","line","log","fail","statusCode","RUNTIME_ERROR"],"mappings":"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"}
|