@sanity/cli 6.3.1 → 6.4.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 +311 -452
- package/dist/actions/build/decorateIndexWithStagingScript.js +16 -0
- package/dist/actions/build/decorateIndexWithStagingScript.js.map +1 -0
- package/dist/actions/build/writeSanityRuntime.js +3 -2
- package/dist/actions/build/writeSanityRuntime.js.map +1 -1
- package/dist/actions/dataset/create.js +4 -0
- package/dist/actions/dataset/create.js.map +1 -1
- package/dist/actions/deploy/findUserApplicationForApp.js +1 -0
- package/dist/actions/deploy/findUserApplicationForApp.js.map +1 -1
- package/dist/actions/deploy/types.js +1 -1
- package/dist/actions/deploy/types.js.map +1 -1
- package/dist/actions/init/bootstrapLocalTemplate.js +16 -1
- package/dist/actions/init/bootstrapLocalTemplate.js.map +1 -1
- package/dist/actions/init/initApp.js +72 -0
- package/dist/actions/init/initApp.js.map +1 -0
- package/dist/actions/init/initHelpers.js +37 -0
- package/dist/actions/init/initHelpers.js.map +1 -0
- package/dist/actions/init/initNextJs.js +246 -0
- package/dist/actions/init/initNextJs.js.map +1 -0
- package/dist/actions/init/initStudio.js +127 -0
- package/dist/actions/init/initStudio.js.map +1 -0
- package/dist/actions/init/scaffoldTemplate.js +114 -0
- package/dist/actions/init/scaffoldTemplate.js.map +1 -0
- package/dist/actions/init/templates/appQuickstart.js +2 -1
- package/dist/actions/init/templates/appQuickstart.js.map +1 -1
- package/dist/actions/init/templates/appSanityUi.js +2 -1
- package/dist/actions/init/templates/appSanityUi.js.map +1 -1
- package/dist/actions/init/templates/nextjs/index.js +1 -2
- package/dist/actions/init/templates/nextjs/index.js.map +1 -1
- package/dist/actions/init/templates/shopify.js +6 -6
- package/dist/actions/init/templates/shopify.js.map +1 -1
- package/dist/actions/init/templates/shopifyOnline.js +2 -2
- package/dist/actions/init/templates/shopifyOnline.js.map +1 -1
- package/dist/actions/manifest/types.js +1 -1
- package/dist/actions/manifest/types.js.map +1 -1
- package/dist/actions/mcp/detectAvailableEditors.js +16 -3
- package/dist/actions/mcp/detectAvailableEditors.js.map +1 -1
- package/dist/actions/mcp/editorConfigs.js +192 -132
- package/dist/actions/mcp/editorConfigs.js.map +1 -1
- package/dist/actions/mcp/setupMCP.js +4 -1
- package/dist/actions/mcp/setupMCP.js.map +1 -1
- package/dist/actions/mcp/writeMCPConfig.js +2 -2
- package/dist/actions/mcp/writeMCPConfig.js.map +1 -1
- package/dist/actions/schema/extractSchema.js +5 -7
- package/dist/actions/schema/extractSchema.js.map +1 -1
- package/dist/actions/schema/types.js +3 -3
- package/dist/actions/schema/types.js.map +1 -1
- package/dist/actions/users/validateEmail.js +2 -2
- package/dist/actions/users/validateEmail.js.map +1 -1
- package/dist/commands/backups/disable.js +1 -1
- package/dist/commands/backups/disable.js.map +1 -1
- package/dist/commands/backups/download.js +1 -1
- package/dist/commands/backups/download.js.map +1 -1
- package/dist/commands/backups/enable.js +1 -1
- package/dist/commands/backups/enable.js.map +1 -1
- package/dist/commands/backups/list.js +1 -1
- package/dist/commands/backups/list.js.map +1 -1
- package/dist/commands/build.js +1 -1
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/cors/add.js +1 -1
- package/dist/commands/cors/add.js.map +1 -1
- package/dist/commands/cors/delete.js +1 -1
- package/dist/commands/cors/delete.js.map +1 -1
- package/dist/commands/cors/list.js +2 -2
- package/dist/commands/cors/list.js.map +1 -1
- package/dist/commands/datasets/alias/create.js +1 -1
- package/dist/commands/datasets/alias/create.js.map +1 -1
- package/dist/commands/datasets/alias/delete.js +1 -1
- package/dist/commands/datasets/alias/delete.js.map +1 -1
- package/dist/commands/datasets/alias/link.js +1 -1
- package/dist/commands/datasets/alias/link.js.map +1 -1
- package/dist/commands/datasets/alias/unlink.js +1 -1
- package/dist/commands/datasets/alias/unlink.js.map +1 -1
- package/dist/commands/datasets/copy.js +15 -1
- package/dist/commands/datasets/copy.js.map +1 -1
- package/dist/commands/datasets/create.js +1 -1
- package/dist/commands/datasets/create.js.map +1 -1
- package/dist/commands/datasets/delete.js +1 -1
- package/dist/commands/datasets/delete.js.map +1 -1
- package/dist/commands/datasets/embeddings/enable.js +11 -0
- package/dist/commands/datasets/embeddings/enable.js.map +1 -1
- package/dist/commands/datasets/export.js +2 -2
- package/dist/commands/datasets/export.js.map +1 -1
- package/dist/commands/datasets/list.js +2 -2
- package/dist/commands/datasets/list.js.map +1 -1
- package/dist/commands/debug.js +1 -1
- package/dist/commands/debug.js.map +1 -1
- package/dist/commands/deploy.js +3 -3
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.js +5 -5
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/docs/browse.js +1 -1
- package/dist/commands/docs/browse.js.map +1 -1
- package/dist/commands/documents/delete.js +1 -1
- package/dist/commands/documents/delete.js.map +1 -1
- package/dist/commands/exec.js +2 -2
- package/dist/commands/exec.js.map +1 -1
- package/dist/commands/graphql/deploy.js +2 -2
- package/dist/commands/graphql/deploy.js.map +1 -1
- package/dist/commands/graphql/list.js +2 -2
- package/dist/commands/graphql/list.js.map +1 -1
- package/dist/commands/hooks/create.js +2 -2
- package/dist/commands/hooks/create.js.map +1 -1
- package/dist/commands/hooks/delete.js +5 -5
- package/dist/commands/hooks/delete.js.map +1 -1
- package/dist/commands/hooks/list.js +3 -3
- package/dist/commands/hooks/list.js.map +1 -1
- package/dist/commands/hooks/logs.js +5 -5
- package/dist/commands/hooks/logs.js.map +1 -1
- package/dist/commands/init.js +175 -490
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.js +1 -1
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/learn.js +1 -1
- package/dist/commands/learn.js.map +1 -1
- package/dist/commands/login.js +1 -1
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.js +1 -1
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/manage.js +1 -1
- package/dist/commands/manage.js.map +1 -1
- package/dist/commands/manifest/extract.js +2 -2
- package/dist/commands/manifest/extract.js.map +1 -1
- package/dist/commands/mcp/configure.js +1 -1
- package/dist/commands/mcp/configure.js.map +1 -1
- package/dist/commands/media/delete-aspect.js +1 -1
- package/dist/commands/media/delete-aspect.js.map +1 -1
- package/dist/commands/media/export.js +1 -1
- package/dist/commands/media/export.js.map +1 -1
- package/dist/commands/preview.js +3 -3
- package/dist/commands/preview.js.map +1 -1
- package/dist/commands/projects/list.js +4 -2
- package/dist/commands/projects/list.js.map +1 -1
- package/dist/commands/schemas/deploy.js +3 -4
- package/dist/commands/schemas/deploy.js.map +1 -1
- package/dist/commands/schemas/extract.js +3 -3
- package/dist/commands/schemas/extract.js.map +1 -1
- package/dist/commands/schemas/list.js +4 -5
- package/dist/commands/schemas/list.js.map +1 -1
- package/dist/commands/telemetry/disable.js +2 -2
- package/dist/commands/telemetry/disable.js.map +1 -1
- package/dist/commands/telemetry/enable.js +2 -2
- package/dist/commands/telemetry/enable.js.map +1 -1
- package/dist/commands/telemetry/status.js +2 -2
- package/dist/commands/telemetry/status.js.map +1 -1
- package/dist/commands/tokens/add.js +1 -1
- package/dist/commands/tokens/add.js.map +1 -1
- package/dist/commands/tokens/delete.js +1 -1
- package/dist/commands/tokens/delete.js.map +1 -1
- package/dist/commands/tokens/list.js +2 -2
- package/dist/commands/tokens/list.js.map +1 -1
- package/dist/commands/users/list.js +1 -1
- package/dist/commands/users/list.js.map +1 -1
- package/dist/commands/versions.js +1 -1
- package/dist/commands/versions.js.map +1 -1
- package/dist/hooks/prerun/injectEnvVariables.js +3 -5
- package/dist/hooks/prerun/injectEnvVariables.js.map +1 -1
- package/dist/server/vite/plugin-sanity-build-entries.js +3 -2
- package/dist/server/vite/plugin-sanity-build-entries.js.map +1 -1
- package/dist/services/datasets.js +2 -1
- package/dist/services/datasets.js.map +1 -1
- package/dist/telemetry/init.telemetry.js.map +1 -1
- package/dist/util/packageManager/installationInfo/detectPackages.js +13 -7
- package/dist/util/packageManager/installationInfo/detectPackages.js.map +1 -1
- package/dist/util/telemetry/createTelemetryStore.js +27 -12
- package/dist/util/telemetry/createTelemetryStore.js.map +1 -1
- package/dist/util/update/fetchUpdateInfo.js +40 -0
- package/dist/util/update/fetchUpdateInfo.js.map +1 -0
- package/dist/util/update/fetchUpdateInfo.worker.js +19 -0
- package/dist/util/update/fetchUpdateInfo.worker.js.map +1 -0
- package/dist/util/update/getRunnerUpdateCommand.js +33 -0
- package/dist/util/update/getRunnerUpdateCommand.js.map +1 -0
- package/dist/util/update/getUpdateCommand.js +6 -7
- package/dist/util/update/getUpdateCommand.js.map +1 -1
- package/dist/util/update/packageRunner.js +10 -0
- package/dist/util/update/packageRunner.js.map +1 -0
- package/dist/util/update/resolveRunnerPackage.js +45 -0
- package/dist/util/update/resolveRunnerPackage.js.map +1 -0
- package/dist/util/update/resolveUpdateTarget.js +31 -0
- package/dist/util/update/resolveUpdateTarget.js.map +1 -0
- package/dist/util/update/showNotificationUpdate.js +8 -6
- package/dist/util/update/showNotificationUpdate.js.map +1 -1
- package/dist/util/update/updateChecker.js +73 -38
- package/dist/util/update/updateChecker.js.map +1 -1
- package/dist/util/validateProjection.js +121 -0
- package/dist/util/validateProjection.js.map +1 -0
- package/oclif.manifest.json +698 -681
- package/package.json +24 -23
- package/templates/app-quickstart/src/App.tsx +2 -2
- package/templates/app-sanity-ui/src/App.tsx +2 -2
- package/templates/shopify/schemaTypes/objects/hotspot/imageWithProductHotspotsType.ts +1 -1
- package/dist/util/update/fetchLatestVersion.js +0 -21
- package/dist/util/update/fetchLatestVersion.js.map +0 -1
|
@@ -3,127 +3,144 @@ import os from 'node:os';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { execa } from 'execa';
|
|
5
5
|
import { MCP_SERVER_URL } from '../../services/mcp.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
/** Create the real detection environment backed by process/OS globals. */ export function createDetectionEnv() {
|
|
7
|
+
return {
|
|
8
|
+
env: process.env,
|
|
9
|
+
execCommand: (cmd, args)=>execa(cmd, args, {
|
|
10
|
+
stdio: 'pipe',
|
|
11
|
+
timeout: 5000
|
|
12
|
+
}).then(()=>{}),
|
|
13
|
+
existsSync,
|
|
14
|
+
homedir: os.homedir(),
|
|
15
|
+
platform: process.platform
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The Sanity MCP server uses OAuth by default
|
|
20
|
+
* If a token is provided, the server will not use OAuth instead tool calls will use the API token
|
|
21
|
+
*/ const defaultHttpConfig = (token)=>{
|
|
22
|
+
const defaultConfig = {
|
|
10
23
|
type: 'http',
|
|
11
24
|
url: MCP_SERVER_URL
|
|
12
|
-
}
|
|
13
|
-
|
|
25
|
+
};
|
|
26
|
+
if (token) {
|
|
27
|
+
defaultConfig.headers = {
|
|
28
|
+
Authorization: `Bearer ${token}`
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return defaultConfig;
|
|
32
|
+
};
|
|
14
33
|
// -- Detect functions --
|
|
15
|
-
async function detectClaudeCode() {
|
|
34
|
+
async function detectClaudeCode(ctx) {
|
|
16
35
|
try {
|
|
17
|
-
await
|
|
36
|
+
await ctx.execCommand('claude', [
|
|
18
37
|
'--version'
|
|
19
|
-
]
|
|
20
|
-
|
|
21
|
-
timeout: 5000
|
|
22
|
-
});
|
|
23
|
-
return path.join(homeDir, '.claude.json');
|
|
38
|
+
]);
|
|
39
|
+
return path.join(ctx.homedir, '.claude.json');
|
|
24
40
|
} catch {
|
|
25
41
|
return null;
|
|
26
42
|
}
|
|
27
43
|
}
|
|
28
|
-
async function
|
|
44
|
+
async function detectAntigravity(ctx) {
|
|
45
|
+
const antigravityDir = path.join(ctx.homedir, '.gemini/antigravity');
|
|
46
|
+
return ctx.existsSync(antigravityDir) ? path.join(antigravityDir, 'mcp_config.json') : null;
|
|
47
|
+
}
|
|
48
|
+
export function getVSCodeUserDir(ctx, variant = 'stable') {
|
|
49
|
+
switch(ctx.platform){
|
|
50
|
+
case 'darwin':
|
|
51
|
+
{
|
|
52
|
+
return path.join(ctx.homedir, variant === 'insiders' ? 'Library/Application Support/Code - Insiders/User' : 'Library/Application Support/Code/User');
|
|
53
|
+
}
|
|
54
|
+
case 'win32':
|
|
55
|
+
{
|
|
56
|
+
if (!ctx.env.APPDATA) return null;
|
|
57
|
+
return path.join(ctx.env.APPDATA, variant === 'insiders' ? 'Code - Insiders/User' : 'Code/User');
|
|
58
|
+
}
|
|
59
|
+
default:
|
|
60
|
+
{
|
|
61
|
+
return path.join(ctx.homedir, variant === 'insiders' ? '.config/Code - Insiders/User' : '.config/Code/User');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function detectCline(ctx) {
|
|
66
|
+
const vscodeUserDir = getVSCodeUserDir(ctx);
|
|
67
|
+
if (!vscodeUserDir) return null;
|
|
68
|
+
const clineConfigDir = path.join(vscodeUserDir, 'globalStorage/saoudrizwan.claude-dev/settings');
|
|
69
|
+
return ctx.existsSync(clineConfigDir) ? path.join(clineConfigDir, 'cline_mcp_settings.json') : null;
|
|
70
|
+
}
|
|
71
|
+
async function detectClineCli(ctx) {
|
|
72
|
+
const clineHome = ctx.env.CLINE_DIR || path.join(ctx.homedir, '.cline');
|
|
73
|
+
if (!ctx.existsSync(clineHome)) return null;
|
|
74
|
+
return path.join(clineHome, 'data/settings/cline_mcp_settings.json');
|
|
75
|
+
}
|
|
76
|
+
async function detectCodexCli(ctx) {
|
|
29
77
|
try {
|
|
30
|
-
await
|
|
78
|
+
await ctx.execCommand('codex', [
|
|
31
79
|
'--version'
|
|
32
|
-
]
|
|
33
|
-
|
|
34
|
-
timeout: 5000
|
|
35
|
-
});
|
|
36
|
-
const codexHome = process.env.CODEX_HOME || path.join(homeDir, '.codex');
|
|
80
|
+
]);
|
|
81
|
+
const codexHome = ctx.env.CODEX_HOME || path.join(ctx.homedir, '.codex');
|
|
37
82
|
return path.join(codexHome, 'config.toml');
|
|
38
83
|
} catch {
|
|
39
84
|
return null;
|
|
40
85
|
}
|
|
41
86
|
}
|
|
42
|
-
async function detectCursor() {
|
|
43
|
-
const cursorDir = path.join(
|
|
44
|
-
return existsSync(cursorDir) ? path.join(cursorDir, 'mcp.json') : null;
|
|
87
|
+
async function detectCursor(ctx) {
|
|
88
|
+
const cursorDir = path.join(ctx.homedir, '.cursor');
|
|
89
|
+
return ctx.existsSync(cursorDir) ? path.join(cursorDir, 'mcp.json') : null;
|
|
45
90
|
}
|
|
46
|
-
async function detectGeminiCli() {
|
|
47
|
-
|
|
48
|
-
|
|
91
|
+
async function detectGeminiCli(ctx) {
|
|
92
|
+
// Antigravity stores its config under ~/.gemini/antigravity, so checking
|
|
93
|
+
// only the parent ~/.gemini directory causes false Gemini CLI detection.
|
|
94
|
+
const settingsPath = path.join(ctx.homedir, '.gemini/settings.json');
|
|
95
|
+
return ctx.existsSync(settingsPath) ? settingsPath : null;
|
|
49
96
|
}
|
|
50
|
-
async function detectGitHubCopilotCli() {
|
|
51
|
-
const copilotDir =
|
|
52
|
-
return existsSync(copilotDir) ? path.join(copilotDir, 'mcp-config.json') : null;
|
|
97
|
+
async function detectGitHubCopilotCli(ctx) {
|
|
98
|
+
const copilotDir = ctx.platform === 'linux' && ctx.env.XDG_CONFIG_HOME ? path.join(ctx.env.XDG_CONFIG_HOME, 'copilot') : path.join(ctx.homedir, '.copilot');
|
|
99
|
+
return ctx.existsSync(copilotDir) ? path.join(copilotDir, 'mcp-config.json') : null;
|
|
53
100
|
}
|
|
54
|
-
async function detectOpenCode() {
|
|
101
|
+
async function detectOpenCode(ctx) {
|
|
55
102
|
try {
|
|
56
|
-
await
|
|
103
|
+
await ctx.execCommand('opencode', [
|
|
57
104
|
'--version'
|
|
58
|
-
]
|
|
59
|
-
|
|
60
|
-
timeout: 5000
|
|
61
|
-
});
|
|
62
|
-
return path.join(homeDir, '.config/opencode/opencode.json');
|
|
105
|
+
]);
|
|
106
|
+
return path.join(ctx.homedir, '.config/opencode/opencode.json');
|
|
63
107
|
} catch {
|
|
64
108
|
return null;
|
|
65
109
|
}
|
|
66
110
|
}
|
|
67
|
-
async function detectVSCode() {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
case 'darwin':
|
|
71
|
-
{
|
|
72
|
-
configDir = path.join(homeDir, 'Library/Application Support/Code/User');
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
case 'win32':
|
|
76
|
-
{
|
|
77
|
-
if (process.env.APPDATA) {
|
|
78
|
-
configDir = path.join(process.env.APPDATA, 'Code/User');
|
|
79
|
-
}
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
default:
|
|
83
|
-
{
|
|
84
|
-
configDir = path.join(homeDir, '.config/Code/User');
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return configDir && existsSync(configDir) ? path.join(configDir, 'mcp.json') : null;
|
|
111
|
+
async function detectVSCode(ctx) {
|
|
112
|
+
const configDir = getVSCodeUserDir(ctx);
|
|
113
|
+
return configDir && ctx.existsSync(configDir) ? path.join(configDir, 'mcp.json') : null;
|
|
88
114
|
}
|
|
89
|
-
async function detectVSCodeInsiders() {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
case 'darwin':
|
|
93
|
-
{
|
|
94
|
-
configDir = path.join(homeDir, 'Library/Application Support/Code - Insiders/User');
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
case 'win32':
|
|
98
|
-
{
|
|
99
|
-
if (process.env.APPDATA) {
|
|
100
|
-
configDir = path.join(process.env.APPDATA, 'Code - Insiders/User');
|
|
101
|
-
}
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
default:
|
|
105
|
-
{
|
|
106
|
-
configDir = path.join(homeDir, '.config/Code - Insiders/User');
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return configDir && existsSync(configDir) ? path.join(configDir, 'mcp.json') : null;
|
|
115
|
+
async function detectVSCodeInsiders(ctx) {
|
|
116
|
+
const configDir = getVSCodeUserDir(ctx, 'insiders');
|
|
117
|
+
return configDir && ctx.existsSync(configDir) ? path.join(configDir, 'mcp.json') : null;
|
|
110
118
|
}
|
|
111
|
-
async function detectZed() {
|
|
119
|
+
async function detectZed(ctx) {
|
|
112
120
|
let configDir = null;
|
|
113
|
-
switch(
|
|
121
|
+
switch(ctx.platform){
|
|
114
122
|
case 'win32':
|
|
115
123
|
{
|
|
116
|
-
if (
|
|
117
|
-
configDir = path.join(
|
|
124
|
+
if (ctx.env.APPDATA) {
|
|
125
|
+
configDir = path.join(ctx.env.APPDATA, 'Zed');
|
|
118
126
|
}
|
|
119
127
|
break;
|
|
120
128
|
}
|
|
121
129
|
default:
|
|
122
130
|
{
|
|
123
|
-
configDir = path.join(
|
|
131
|
+
configDir = path.join(ctx.homedir, '.config/zed');
|
|
124
132
|
}
|
|
125
133
|
}
|
|
126
|
-
return configDir && existsSync(configDir) ? path.join(configDir, 'settings.json') : null;
|
|
134
|
+
return configDir && ctx.existsSync(configDir) ? path.join(configDir, 'settings.json') : null;
|
|
135
|
+
}
|
|
136
|
+
async function detectMCPorter(ctx) {
|
|
137
|
+
const mcporterDir = path.join(ctx.homedir, '.mcporter');
|
|
138
|
+
if (!ctx.existsSync(mcporterDir)) return null;
|
|
139
|
+
const jsonPath = path.join(mcporterDir, 'mcporter.json');
|
|
140
|
+
const jsoncPath = path.join(mcporterDir, 'mcporter.jsonc');
|
|
141
|
+
if (ctx.existsSync(jsonPath)) return jsonPath;
|
|
142
|
+
if (ctx.existsSync(jsoncPath)) return jsoncPath;
|
|
143
|
+
return jsonPath;
|
|
127
144
|
}
|
|
128
145
|
// -- Read token helpers --
|
|
129
146
|
/**
|
|
@@ -142,9 +159,31 @@ function readTokenFromHeaders(serverConfig) {
|
|
|
142
159
|
function readTokenFromHttpHeaders(serverConfig) {
|
|
143
160
|
return extractBearerToken(serverConfig.http_headers);
|
|
144
161
|
}
|
|
145
|
-
// --
|
|
146
|
-
|
|
147
|
-
|
|
162
|
+
// -- Defaults & build server config functions --
|
|
163
|
+
/** Most editors share these values — entries only need to declare `detect` + any overrides. */ const EDITOR_DEFAULTS = {
|
|
164
|
+
buildServerConfig: defaultHttpConfig,
|
|
165
|
+
configKey: 'mcpServers',
|
|
166
|
+
format: 'jsonc',
|
|
167
|
+
oauthOnly: false,
|
|
168
|
+
readToken: readTokenFromHeaders
|
|
169
|
+
};
|
|
170
|
+
function buildAntigravityServerConfig(token) {
|
|
171
|
+
return {
|
|
172
|
+
headers: {
|
|
173
|
+
Authorization: `Bearer ${token}`
|
|
174
|
+
},
|
|
175
|
+
serverUrl: MCP_SERVER_URL
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function buildClineServerConfig(token) {
|
|
179
|
+
return {
|
|
180
|
+
disabled: false,
|
|
181
|
+
headers: {
|
|
182
|
+
Authorization: `Bearer ${token}`
|
|
183
|
+
},
|
|
184
|
+
type: 'streamableHttp',
|
|
185
|
+
url: MCP_SERVER_URL
|
|
186
|
+
};
|
|
148
187
|
}
|
|
149
188
|
function buildCodexCliServerConfig(token) {
|
|
150
189
|
return {
|
|
@@ -155,12 +194,6 @@ function buildCodexCliServerConfig(token) {
|
|
|
155
194
|
url: MCP_SERVER_URL
|
|
156
195
|
};
|
|
157
196
|
}
|
|
158
|
-
function buildCursorServerConfig(token) {
|
|
159
|
-
return defaultHttpConfig(token);
|
|
160
|
-
}
|
|
161
|
-
function buildGeminiCliServerConfig(token) {
|
|
162
|
-
return defaultHttpConfig(token);
|
|
163
|
-
}
|
|
164
197
|
function buildGitHubCopilotCliServerConfig(token) {
|
|
165
198
|
return {
|
|
166
199
|
headers: {
|
|
@@ -182,12 +215,6 @@ function buildOpenCodeServerConfig(token) {
|
|
|
182
215
|
url: MCP_SERVER_URL
|
|
183
216
|
};
|
|
184
217
|
}
|
|
185
|
-
function buildVSCodeServerConfig(token) {
|
|
186
|
-
return defaultHttpConfig(token);
|
|
187
|
-
}
|
|
188
|
-
function buildVSCodeInsidersServerConfig(token) {
|
|
189
|
-
return defaultHttpConfig(token);
|
|
190
|
-
}
|
|
191
218
|
function buildZedServerConfig(token) {
|
|
192
219
|
return {
|
|
193
220
|
headers: {
|
|
@@ -199,70 +226,103 @@ function buildZedServerConfig(token) {
|
|
|
199
226
|
}
|
|
200
227
|
/**
|
|
201
228
|
* Centralized editor configuration including detection logic.
|
|
202
|
-
* To add a new editor: add an entry here
|
|
229
|
+
* To add a new editor: add an entry here — EditorName type is derived automatically.
|
|
230
|
+
*
|
|
231
|
+
* Each entry includes a doc URL pointing to the source of truth for its
|
|
232
|
+
* config path and format. When updating a path, verify against the linked
|
|
233
|
+
* documentation first.
|
|
203
234
|
*/ export const EDITOR_CONFIGS = {
|
|
235
|
+
// Doc: https://support.google.com/gemini/answer/16255176 (Antigravity / Project Mariner)
|
|
236
|
+
Antigravity: {
|
|
237
|
+
...EDITOR_DEFAULTS,
|
|
238
|
+
buildServerConfig: buildAntigravityServerConfig,
|
|
239
|
+
detect: detectAntigravity
|
|
240
|
+
},
|
|
241
|
+
// Doc: https://docs.anthropic.com/en/docs/claude-code/mcp
|
|
242
|
+
// Path: ~/.claude.json Key: mcpServers
|
|
204
243
|
'Claude Code': {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
244
|
+
...EDITOR_DEFAULTS,
|
|
245
|
+
detect: detectClaudeCode
|
|
246
|
+
},
|
|
247
|
+
// Doc: https://github.com/cline/cline — VS Code extension (saoudrizwan.claude-dev)
|
|
248
|
+
// Path: <VS Code User>/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json
|
|
249
|
+
Cline: {
|
|
250
|
+
...EDITOR_DEFAULTS,
|
|
251
|
+
buildServerConfig: buildClineServerConfig,
|
|
252
|
+
detect: detectCline
|
|
210
253
|
},
|
|
254
|
+
// Doc: https://github.com/cline/cline — standalone CLI mode
|
|
255
|
+
// Path: $CLINE_DIR || ~/.cline/data/settings/cline_mcp_settings.json
|
|
256
|
+
'Cline CLI': {
|
|
257
|
+
...EDITOR_DEFAULTS,
|
|
258
|
+
buildServerConfig: buildClineServerConfig,
|
|
259
|
+
detect: detectClineCli
|
|
260
|
+
},
|
|
261
|
+
// Doc: https://platform.openai.com/docs/guides/tools-remote-mcp#codex-cli
|
|
262
|
+
// Path: $CODEX_HOME || ~/.codex/config.toml Key: mcp_servers Format: TOML
|
|
211
263
|
'Codex CLI': {
|
|
264
|
+
...EDITOR_DEFAULTS,
|
|
212
265
|
buildServerConfig: buildCodexCliServerConfig,
|
|
213
266
|
configKey: 'mcp_servers',
|
|
214
267
|
detect: detectCodexCli,
|
|
215
268
|
format: 'toml',
|
|
216
269
|
readToken: readTokenFromHttpHeaders
|
|
217
270
|
},
|
|
271
|
+
// Doc: https://docs.cursor.com/context/model-context-protocol
|
|
272
|
+
// Path: ~/.cursor/mcp.json Key: mcpServers
|
|
218
273
|
Cursor: {
|
|
219
|
-
|
|
220
|
-
configKey: 'mcpServers',
|
|
274
|
+
...EDITOR_DEFAULTS,
|
|
221
275
|
detect: detectCursor,
|
|
222
|
-
|
|
223
|
-
readToken: readTokenFromHeaders
|
|
276
|
+
oauthOnly: true
|
|
224
277
|
},
|
|
278
|
+
// Doc: https://googlegemini.wiki/gemini-cli/mcp-servers
|
|
279
|
+
// Path: ~/.gemini/settings.json Key: mcpServers
|
|
225
280
|
'Gemini CLI': {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
detect: detectGeminiCli,
|
|
229
|
-
format: 'jsonc',
|
|
230
|
-
readToken: readTokenFromHeaders
|
|
281
|
+
...EDITOR_DEFAULTS,
|
|
282
|
+
detect: detectGeminiCli
|
|
231
283
|
},
|
|
284
|
+
// Doc: https://docs.github.com/en/copilot/customizing-copilot/extending-copilot-coding-agent-with-mcp
|
|
285
|
+
// Path: ~/.copilot/mcp-config.json (or $XDG_CONFIG_HOME/copilot on Linux) Key: mcpServers
|
|
232
286
|
'GitHub Copilot CLI': {
|
|
287
|
+
...EDITOR_DEFAULTS,
|
|
233
288
|
buildServerConfig: buildGitHubCopilotCliServerConfig,
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
289
|
+
detect: detectGitHubCopilotCli
|
|
290
|
+
},
|
|
291
|
+
// Doc: https://github.com/nicobailon/mcporter
|
|
292
|
+
// Path: ~/.mcporter/mcporter.{json,jsonc} Key: mcpServers
|
|
293
|
+
MCPorter: {
|
|
294
|
+
...EDITOR_DEFAULTS,
|
|
295
|
+
detect: detectMCPorter
|
|
238
296
|
},
|
|
297
|
+
// Doc: https://opencode.ai/docs/config
|
|
298
|
+
// Path: ~/.config/opencode/opencode.json Key: mcp
|
|
239
299
|
OpenCode: {
|
|
300
|
+
...EDITOR_DEFAULTS,
|
|
240
301
|
buildServerConfig: buildOpenCodeServerConfig,
|
|
241
302
|
configKey: 'mcp',
|
|
242
|
-
detect: detectOpenCode
|
|
243
|
-
format: 'jsonc',
|
|
244
|
-
readToken: readTokenFromHeaders
|
|
303
|
+
detect: detectOpenCode
|
|
245
304
|
},
|
|
305
|
+
// Doc: https://code.visualstudio.com/docs/copilot/chat/mcp-servers
|
|
306
|
+
// Path: <VS Code User dir>/mcp.json Key: servers
|
|
246
307
|
'VS Code': {
|
|
247
|
-
|
|
308
|
+
...EDITOR_DEFAULTS,
|
|
248
309
|
configKey: 'servers',
|
|
249
|
-
detect: detectVSCode
|
|
250
|
-
format: 'jsonc',
|
|
251
|
-
readToken: readTokenFromHeaders
|
|
310
|
+
detect: detectVSCode
|
|
252
311
|
},
|
|
312
|
+
// Doc: https://code.visualstudio.com/docs/copilot/chat/mcp-servers
|
|
313
|
+
// Path: <VS Code Insiders User dir>/mcp.json Key: servers
|
|
253
314
|
'VS Code Insiders': {
|
|
254
|
-
|
|
315
|
+
...EDITOR_DEFAULTS,
|
|
255
316
|
configKey: 'servers',
|
|
256
|
-
detect: detectVSCodeInsiders
|
|
257
|
-
format: 'jsonc',
|
|
258
|
-
readToken: readTokenFromHeaders
|
|
317
|
+
detect: detectVSCodeInsiders
|
|
259
318
|
},
|
|
319
|
+
// Doc: https://zed.dev/docs/assistant/model-context-protocol
|
|
320
|
+
// Path: ~/.config/zed/settings.json (or $APPDATA/Zed on Windows) Key: context_servers
|
|
260
321
|
Zed: {
|
|
322
|
+
...EDITOR_DEFAULTS,
|
|
261
323
|
buildServerConfig: buildZedServerConfig,
|
|
262
324
|
configKey: 'context_servers',
|
|
263
|
-
detect: detectZed
|
|
264
|
-
format: 'jsonc',
|
|
265
|
-
readToken: readTokenFromHeaders
|
|
325
|
+
detect: detectZed
|
|
266
326
|
}
|
|
267
327
|
};
|
|
268
328
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/mcp/editorConfigs.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\n\nimport {execa} from 'execa'\n\nimport {MCP_SERVER_URL} from '../../services/mcp.js'\n\ninterface EditorConfig {\n buildServerConfig: (token: string) => Record<string, unknown>\n configKey: string\n /** Returns the config file path if editor is detected, null otherwise */\n detect: () => Promise<string | null>\n format: 'jsonc' | 'toml'\n /** Extracts the auth token from a parsed Sanity server config block */\n readToken: (serverConfig: Record<string, unknown>) => string | undefined\n}\n\nconst defaultHttpConfig = (token: string) => ({\n headers: {Authorization: `Bearer ${token}`},\n type: 'http',\n url: MCP_SERVER_URL,\n})\n\nconst homeDir = os.homedir()\n\n// -- Detect functions --\n\nasync function detectClaudeCode(): Promise<string | null> {\n try {\n await execa('claude', ['--version'], {stdio: 'pipe', timeout: 5000})\n return path.join(homeDir, '.claude.json')\n } catch {\n return null\n }\n}\n\nasync function detectCodexCli(): Promise<string | null> {\n try {\n await execa('codex', ['--version'], {stdio: 'pipe', timeout: 5000})\n const codexHome = process.env.CODEX_HOME || path.join(homeDir, '.codex')\n return path.join(codexHome, 'config.toml')\n } catch {\n return null\n }\n}\n\nasync function detectCursor(): Promise<string | null> {\n const cursorDir = path.join(homeDir, '.cursor')\n return existsSync(cursorDir) ? path.join(cursorDir, 'mcp.json') : null\n}\n\nasync function detectGeminiCli(): Promise<string | null> {\n const geminiDir = path.join(homeDir, '.gemini')\n return existsSync(geminiDir) ? path.join(geminiDir, 'settings.json') : null\n}\n\nasync function detectGitHubCopilotCli(): Promise<string | null> {\n const copilotDir =\n process.platform === 'linux' && process.env.XDG_CONFIG_HOME\n ? path.join(process.env.XDG_CONFIG_HOME, 'copilot')\n : path.join(homeDir, '.copilot')\n return existsSync(copilotDir) ? path.join(copilotDir, 'mcp-config.json') : null\n}\n\nasync function detectOpenCode(): Promise<string | null> {\n try {\n await execa('opencode', ['--version'], {stdio: 'pipe', timeout: 5000})\n return path.join(homeDir, '.config/opencode/opencode.json')\n } catch {\n return null\n }\n}\n\nasync function detectVSCode(): Promise<string | null> {\n let configDir: string | null = null\n switch (process.platform) {\n case 'darwin': {\n configDir = path.join(homeDir, 'Library/Application Support/Code/User')\n break\n }\n case 'win32': {\n if (process.env.APPDATA) {\n configDir = path.join(process.env.APPDATA, 'Code/User')\n }\n break\n }\n default: {\n configDir = path.join(homeDir, '.config/Code/User')\n }\n }\n return configDir && existsSync(configDir) ? path.join(configDir, 'mcp.json') : null\n}\n\nasync function detectVSCodeInsiders(): Promise<string | null> {\n let configDir: string | null = null\n switch (process.platform) {\n case 'darwin': {\n configDir = path.join(homeDir, 'Library/Application Support/Code - Insiders/User')\n break\n }\n case 'win32': {\n if (process.env.APPDATA) {\n configDir = path.join(process.env.APPDATA, 'Code - Insiders/User')\n }\n break\n }\n default: {\n configDir = path.join(homeDir, '.config/Code - Insiders/User')\n }\n }\n return configDir && existsSync(configDir) ? path.join(configDir, 'mcp.json') : null\n}\n\nasync function detectZed(): Promise<string | null> {\n let configDir: string | null = null\n switch (process.platform) {\n case 'win32': {\n if (process.env.APPDATA) {\n configDir = path.join(process.env.APPDATA, 'Zed')\n }\n break\n }\n default: {\n configDir = path.join(homeDir, '.config/zed')\n }\n }\n return configDir && existsSync(configDir) ? path.join(configDir, 'settings.json') : null\n}\n\n// -- Read token helpers --\n\n/**\n * Extract a Bearer token from a headers-like object.\n * Looks for `Authorization: \"Bearer <token>\"` and returns the token portion.\n */\nfunction extractBearerToken(headers: unknown): string | undefined {\n if (typeof headers !== 'object' || headers === null) return undefined\n const auth = (headers as Record<string, unknown>).Authorization\n if (typeof auth !== 'string') return undefined\n const match = auth.match(/^Bearer\\s+(.+)$/)\n return match?.[1]\n}\n\nfunction readTokenFromHeaders(serverConfig: Record<string, unknown>): string | undefined {\n return extractBearerToken(serverConfig.headers)\n}\n\nfunction readTokenFromHttpHeaders(serverConfig: Record<string, unknown>): string | undefined {\n return extractBearerToken(serverConfig.http_headers)\n}\n\n// -- Build server config functions --\n\nfunction buildClaudeCodeServerConfig(token: string): Record<string, unknown> {\n return defaultHttpConfig(token)\n}\n\nfunction buildCodexCliServerConfig(token: string): Record<string, unknown> {\n return {\n http_headers: {Authorization: `Bearer ${token}`},\n type: 'http',\n url: MCP_SERVER_URL,\n }\n}\n\nfunction buildCursorServerConfig(token: string): Record<string, unknown> {\n return defaultHttpConfig(token)\n}\n\nfunction buildGeminiCliServerConfig(token: string): Record<string, unknown> {\n return defaultHttpConfig(token)\n}\n\nfunction buildGitHubCopilotCliServerConfig(token: string): Record<string, unknown> {\n return {\n headers: {Authorization: `Bearer ${token}`},\n tools: ['*'],\n type: 'http',\n url: MCP_SERVER_URL,\n }\n}\n\nfunction buildOpenCodeServerConfig(token: string): Record<string, unknown> {\n return {\n headers: {Authorization: `Bearer ${token}`},\n type: 'remote',\n url: MCP_SERVER_URL,\n }\n}\n\nfunction buildVSCodeServerConfig(token: string): Record<string, unknown> {\n return defaultHttpConfig(token)\n}\n\nfunction buildVSCodeInsidersServerConfig(token: string): Record<string, unknown> {\n return defaultHttpConfig(token)\n}\n\nfunction buildZedServerConfig(token: string): Record<string, unknown> {\n return {\n headers: {Authorization: `Bearer ${token}`},\n settings: {},\n url: MCP_SERVER_URL,\n }\n}\n\n/**\n * Centralized editor configuration including detection logic.\n * To add a new editor: add an entry here - EditorName type is derived automatically.\n */\nexport const EDITOR_CONFIGS = {\n 'Claude Code': {\n buildServerConfig: buildClaudeCodeServerConfig,\n configKey: 'mcpServers',\n detect: detectClaudeCode,\n format: 'jsonc',\n readToken: readTokenFromHeaders,\n },\n 'Codex CLI': {\n buildServerConfig: buildCodexCliServerConfig,\n configKey: 'mcp_servers',\n detect: detectCodexCli,\n format: 'toml',\n readToken: readTokenFromHttpHeaders,\n },\n Cursor: {\n buildServerConfig: buildCursorServerConfig,\n configKey: 'mcpServers',\n detect: detectCursor,\n format: 'jsonc',\n readToken: readTokenFromHeaders,\n },\n 'Gemini CLI': {\n buildServerConfig: buildGeminiCliServerConfig,\n configKey: 'mcpServers',\n detect: detectGeminiCli,\n format: 'jsonc',\n readToken: readTokenFromHeaders,\n },\n 'GitHub Copilot CLI': {\n buildServerConfig: buildGitHubCopilotCliServerConfig,\n configKey: 'mcpServers',\n detect: detectGitHubCopilotCli,\n format: 'jsonc',\n readToken: readTokenFromHeaders,\n },\n OpenCode: {\n buildServerConfig: buildOpenCodeServerConfig,\n configKey: 'mcp',\n detect: detectOpenCode,\n format: 'jsonc',\n readToken: readTokenFromHeaders,\n },\n 'VS Code': {\n buildServerConfig: buildVSCodeServerConfig,\n configKey: 'servers',\n detect: detectVSCode,\n format: 'jsonc',\n readToken: readTokenFromHeaders,\n },\n 'VS Code Insiders': {\n buildServerConfig: buildVSCodeInsidersServerConfig,\n configKey: 'servers',\n detect: detectVSCodeInsiders,\n format: 'jsonc',\n readToken: readTokenFromHeaders,\n },\n Zed: {\n buildServerConfig: buildZedServerConfig,\n configKey: 'context_servers',\n detect: detectZed,\n format: 'jsonc',\n readToken: readTokenFromHeaders,\n },\n} satisfies Record<string, EditorConfig>\n\n/** Derived from EDITOR_CONFIGS keys - add a new editor there and this updates automatically */\nexport type EditorName = keyof typeof EDITOR_CONFIGS\n"],"names":["existsSync","os","path","execa","MCP_SERVER_URL","defaultHttpConfig","token","headers","Authorization","type","url","homeDir","homedir","detectClaudeCode","stdio","timeout","join","detectCodexCli","codexHome","process","env","CODEX_HOME","detectCursor","cursorDir","detectGeminiCli","geminiDir","detectGitHubCopilotCli","copilotDir","platform","XDG_CONFIG_HOME","detectOpenCode","detectVSCode","configDir","APPDATA","detectVSCodeInsiders","detectZed","extractBearerToken","undefined","auth","match","readTokenFromHeaders","serverConfig","readTokenFromHttpHeaders","http_headers","buildClaudeCodeServerConfig","buildCodexCliServerConfig","buildCursorServerConfig","buildGeminiCliServerConfig","buildGitHubCopilotCliServerConfig","tools","buildOpenCodeServerConfig","buildVSCodeServerConfig","buildVSCodeInsidersServerConfig","buildZedServerConfig","settings","EDITOR_CONFIGS","buildServerConfig","configKey","detect","format","readToken","Cursor","OpenCode","Zed"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/mcp/editorConfigs.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\n\nimport {execa} from 'execa'\n\nimport {MCP_SERVER_URL} from '../../services/mcp.js'\n\n/**\n * Environment abstraction for editor detection.\n *\n * Detect functions receive this instead of using module-level imports, making\n * each function independently testable without global mocks.\n */\nexport interface DetectionEnv {\n env: Record<string, string | undefined>\n /** Run a CLI command to check if a tool is installed. Rejects on failure. */\n execCommand: (cmd: string, args: string[]) => Promise<void>\n existsSync: (p: string) => boolean\n homedir: string\n platform: NodeJS.Platform\n}\n\n/** Create the real detection environment backed by process/OS globals. */\nexport function createDetectionEnv(): DetectionEnv {\n return {\n env: process.env,\n execCommand: (cmd, args) => execa(cmd, args, {stdio: 'pipe', timeout: 5000}).then(() => {}),\n existsSync,\n homedir: os.homedir(),\n platform: process.platform,\n }\n}\n\ninterface EditorConfig {\n /** Builds the server config with API token. If oauthOnly is true, the token is not used */\n buildServerConfig: (token: string) => Record<string, unknown>\n configKey: string\n /** Returns the config file path if editor is detected, null otherwise */\n detect: (env: DetectionEnv) => Promise<string | null>\n format: 'jsonc' | 'toml'\n /** Extracts the auth token from a parsed Sanity server config block */\n readToken: (serverConfig: Record<string, unknown>) => string | undefined\n\n /** If true, this editor uses OAuth natively and does not need an embedded API token */\n oauthOnly?: boolean\n}\n\n/**\n * The Sanity MCP server uses OAuth by default\n * If a token is provided, the server will not use OAuth instead tool calls will use the API token\n */\nconst defaultHttpConfig = (token?: string) => {\n const defaultConfig: Record<string, unknown> = {\n type: 'http',\n url: MCP_SERVER_URL,\n }\n\n if (token) {\n defaultConfig.headers = {Authorization: `Bearer ${token}`}\n }\n\n return defaultConfig\n}\n\n// -- Detect functions --\n\nasync function detectClaudeCode(ctx: DetectionEnv): Promise<string | null> {\n try {\n await ctx.execCommand('claude', ['--version'])\n return path.join(ctx.homedir, '.claude.json')\n } catch {\n return null\n }\n}\n\nasync function detectAntigravity(ctx: DetectionEnv): Promise<string | null> {\n const antigravityDir = path.join(ctx.homedir, '.gemini/antigravity')\n return ctx.existsSync(antigravityDir) ? path.join(antigravityDir, 'mcp_config.json') : null\n}\n\nexport function getVSCodeUserDir(\n ctx: DetectionEnv,\n variant: 'insiders' | 'stable' = 'stable',\n): string | null {\n switch (ctx.platform) {\n case 'darwin': {\n return path.join(\n ctx.homedir,\n variant === 'insiders'\n ? 'Library/Application Support/Code - Insiders/User'\n : 'Library/Application Support/Code/User',\n )\n }\n case 'win32': {\n if (!ctx.env.APPDATA) return null\n return path.join(\n ctx.env.APPDATA,\n variant === 'insiders' ? 'Code - Insiders/User' : 'Code/User',\n )\n }\n default: {\n return path.join(\n ctx.homedir,\n variant === 'insiders' ? '.config/Code - Insiders/User' : '.config/Code/User',\n )\n }\n }\n}\n\nasync function detectCline(ctx: DetectionEnv): Promise<string | null> {\n const vscodeUserDir = getVSCodeUserDir(ctx)\n if (!vscodeUserDir) return null\n const clineConfigDir = path.join(vscodeUserDir, 'globalStorage/saoudrizwan.claude-dev/settings')\n return ctx.existsSync(clineConfigDir)\n ? path.join(clineConfigDir, 'cline_mcp_settings.json')\n : null\n}\n\nasync function detectClineCli(ctx: DetectionEnv): Promise<string | null> {\n const clineHome = ctx.env.CLINE_DIR || path.join(ctx.homedir, '.cline')\n if (!ctx.existsSync(clineHome)) return null\n return path.join(clineHome, 'data/settings/cline_mcp_settings.json')\n}\n\nasync function detectCodexCli(ctx: DetectionEnv): Promise<string | null> {\n try {\n await ctx.execCommand('codex', ['--version'])\n const codexHome = ctx.env.CODEX_HOME || path.join(ctx.homedir, '.codex')\n return path.join(codexHome, 'config.toml')\n } catch {\n return null\n }\n}\n\nasync function detectCursor(ctx: DetectionEnv): Promise<string | null> {\n const cursorDir = path.join(ctx.homedir, '.cursor')\n return ctx.existsSync(cursorDir) ? path.join(cursorDir, 'mcp.json') : null\n}\n\nasync function detectGeminiCli(ctx: DetectionEnv): Promise<string | null> {\n // Antigravity stores its config under ~/.gemini/antigravity, so checking\n // only the parent ~/.gemini directory causes false Gemini CLI detection.\n const settingsPath = path.join(ctx.homedir, '.gemini/settings.json')\n return ctx.existsSync(settingsPath) ? settingsPath : null\n}\n\nasync function detectGitHubCopilotCli(ctx: DetectionEnv): Promise<string | null> {\n const copilotDir =\n ctx.platform === 'linux' && ctx.env.XDG_CONFIG_HOME\n ? path.join(ctx.env.XDG_CONFIG_HOME, 'copilot')\n : path.join(ctx.homedir, '.copilot')\n return ctx.existsSync(copilotDir) ? path.join(copilotDir, 'mcp-config.json') : null\n}\n\nasync function detectOpenCode(ctx: DetectionEnv): Promise<string | null> {\n try {\n await ctx.execCommand('opencode', ['--version'])\n return path.join(ctx.homedir, '.config/opencode/opencode.json')\n } catch {\n return null\n }\n}\n\nasync function detectVSCode(ctx: DetectionEnv): Promise<string | null> {\n const configDir = getVSCodeUserDir(ctx)\n return configDir && ctx.existsSync(configDir) ? path.join(configDir, 'mcp.json') : null\n}\n\nasync function detectVSCodeInsiders(ctx: DetectionEnv): Promise<string | null> {\n const configDir = getVSCodeUserDir(ctx, 'insiders')\n return configDir && ctx.existsSync(configDir) ? path.join(configDir, 'mcp.json') : null\n}\n\nasync function detectZed(ctx: DetectionEnv): Promise<string | null> {\n let configDir: string | null = null\n switch (ctx.platform) {\n case 'win32': {\n if (ctx.env.APPDATA) {\n configDir = path.join(ctx.env.APPDATA, 'Zed')\n }\n break\n }\n default: {\n configDir = path.join(ctx.homedir, '.config/zed')\n }\n }\n return configDir && ctx.existsSync(configDir) ? path.join(configDir, 'settings.json') : null\n}\n\nasync function detectMCPorter(ctx: DetectionEnv): Promise<string | null> {\n const mcporterDir = path.join(ctx.homedir, '.mcporter')\n if (!ctx.existsSync(mcporterDir)) return null\n\n const jsonPath = path.join(mcporterDir, 'mcporter.json')\n const jsoncPath = path.join(mcporterDir, 'mcporter.jsonc')\n if (ctx.existsSync(jsonPath)) return jsonPath\n if (ctx.existsSync(jsoncPath)) return jsoncPath\n return jsonPath\n}\n\n// -- Read token helpers --\n\n/**\n * Extract a Bearer token from a headers-like object.\n * Looks for `Authorization: \"Bearer <token>\"` and returns the token portion.\n */\nfunction extractBearerToken(headers: unknown): string | undefined {\n if (typeof headers !== 'object' || headers === null) return undefined\n const auth = (headers as Record<string, unknown>).Authorization\n if (typeof auth !== 'string') return undefined\n const match = auth.match(/^Bearer\\s+(.+)$/)\n return match?.[1]\n}\n\nfunction readTokenFromHeaders(serverConfig: Record<string, unknown>): string | undefined {\n return extractBearerToken(serverConfig.headers)\n}\n\nfunction readTokenFromHttpHeaders(serverConfig: Record<string, unknown>): string | undefined {\n return extractBearerToken(serverConfig.http_headers)\n}\n\n// -- Defaults & build server config functions --\n\n/** Most editors share these values — entries only need to declare `detect` + any overrides. */\nconst EDITOR_DEFAULTS = {\n buildServerConfig: defaultHttpConfig,\n configKey: 'mcpServers',\n format: 'jsonc' as const,\n oauthOnly: false,\n readToken: readTokenFromHeaders,\n}\n\nfunction buildAntigravityServerConfig(token: string): Record<string, unknown> {\n return {\n headers: {Authorization: `Bearer ${token}`},\n serverUrl: MCP_SERVER_URL,\n }\n}\n\nfunction buildClineServerConfig(token: string): Record<string, unknown> {\n return {\n disabled: false,\n headers: {Authorization: `Bearer ${token}`},\n type: 'streamableHttp',\n url: MCP_SERVER_URL,\n }\n}\n\nfunction buildCodexCliServerConfig(token: string): Record<string, unknown> {\n return {\n http_headers: {Authorization: `Bearer ${token}`},\n type: 'http',\n url: MCP_SERVER_URL,\n }\n}\n\nfunction buildGitHubCopilotCliServerConfig(token: string): Record<string, unknown> {\n return {\n headers: {Authorization: `Bearer ${token}`},\n tools: ['*'],\n type: 'http',\n url: MCP_SERVER_URL,\n }\n}\n\nfunction buildOpenCodeServerConfig(token: string): Record<string, unknown> {\n return {\n headers: {Authorization: `Bearer ${token}`},\n type: 'remote',\n url: MCP_SERVER_URL,\n }\n}\n\nfunction buildZedServerConfig(token: string): Record<string, unknown> {\n return {\n headers: {Authorization: `Bearer ${token}`},\n settings: {},\n url: MCP_SERVER_URL,\n }\n}\n\n/**\n * Centralized editor configuration including detection logic.\n * To add a new editor: add an entry here — EditorName type is derived automatically.\n *\n * Each entry includes a doc URL pointing to the source of truth for its\n * config path and format. When updating a path, verify against the linked\n * documentation first.\n */\nexport const EDITOR_CONFIGS = {\n // Doc: https://support.google.com/gemini/answer/16255176 (Antigravity / Project Mariner)\n Antigravity: {\n ...EDITOR_DEFAULTS,\n buildServerConfig: buildAntigravityServerConfig,\n detect: detectAntigravity,\n },\n // Doc: https://docs.anthropic.com/en/docs/claude-code/mcp\n // Path: ~/.claude.json Key: mcpServers\n 'Claude Code': {...EDITOR_DEFAULTS, detect: detectClaudeCode},\n // Doc: https://github.com/cline/cline — VS Code extension (saoudrizwan.claude-dev)\n // Path: <VS Code User>/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json\n Cline: {...EDITOR_DEFAULTS, buildServerConfig: buildClineServerConfig, detect: detectCline},\n // Doc: https://github.com/cline/cline — standalone CLI mode\n // Path: $CLINE_DIR || ~/.cline/data/settings/cline_mcp_settings.json\n 'Cline CLI': {\n ...EDITOR_DEFAULTS,\n buildServerConfig: buildClineServerConfig,\n detect: detectClineCli,\n },\n // Doc: https://platform.openai.com/docs/guides/tools-remote-mcp#codex-cli\n // Path: $CODEX_HOME || ~/.codex/config.toml Key: mcp_servers Format: TOML\n 'Codex CLI': {\n ...EDITOR_DEFAULTS,\n buildServerConfig: buildCodexCliServerConfig,\n configKey: 'mcp_servers',\n detect: detectCodexCli,\n format: 'toml' as const,\n readToken: readTokenFromHttpHeaders,\n },\n // Doc: https://docs.cursor.com/context/model-context-protocol\n // Path: ~/.cursor/mcp.json Key: mcpServers\n Cursor: {\n ...EDITOR_DEFAULTS,\n detect: detectCursor,\n oauthOnly: true,\n },\n // Doc: https://googlegemini.wiki/gemini-cli/mcp-servers\n // Path: ~/.gemini/settings.json Key: mcpServers\n 'Gemini CLI': {...EDITOR_DEFAULTS, detect: detectGeminiCli},\n // Doc: https://docs.github.com/en/copilot/customizing-copilot/extending-copilot-coding-agent-with-mcp\n // Path: ~/.copilot/mcp-config.json (or $XDG_CONFIG_HOME/copilot on Linux) Key: mcpServers\n 'GitHub Copilot CLI': {\n ...EDITOR_DEFAULTS,\n buildServerConfig: buildGitHubCopilotCliServerConfig,\n detect: detectGitHubCopilotCli,\n },\n // Doc: https://github.com/nicobailon/mcporter\n // Path: ~/.mcporter/mcporter.{json,jsonc} Key: mcpServers\n MCPorter: {...EDITOR_DEFAULTS, detect: detectMCPorter},\n // Doc: https://opencode.ai/docs/config\n // Path: ~/.config/opencode/opencode.json Key: mcp\n OpenCode: {\n ...EDITOR_DEFAULTS,\n buildServerConfig: buildOpenCodeServerConfig,\n configKey: 'mcp',\n detect: detectOpenCode,\n },\n // Doc: https://code.visualstudio.com/docs/copilot/chat/mcp-servers\n // Path: <VS Code User dir>/mcp.json Key: servers\n 'VS Code': {...EDITOR_DEFAULTS, configKey: 'servers', detect: detectVSCode},\n // Doc: https://code.visualstudio.com/docs/copilot/chat/mcp-servers\n // Path: <VS Code Insiders User dir>/mcp.json Key: servers\n 'VS Code Insiders': {...EDITOR_DEFAULTS, configKey: 'servers', detect: detectVSCodeInsiders},\n // Doc: https://zed.dev/docs/assistant/model-context-protocol\n // Path: ~/.config/zed/settings.json (or $APPDATA/Zed on Windows) Key: context_servers\n Zed: {\n ...EDITOR_DEFAULTS,\n buildServerConfig: buildZedServerConfig,\n configKey: 'context_servers',\n detect: detectZed,\n },\n} satisfies Record<string, EditorConfig>\n\n/** Derived from EDITOR_CONFIGS keys - add a new editor there and this updates automatically */\nexport type EditorName = keyof typeof EDITOR_CONFIGS\n"],"names":["existsSync","os","path","execa","MCP_SERVER_URL","createDetectionEnv","env","process","execCommand","cmd","args","stdio","timeout","then","homedir","platform","defaultHttpConfig","token","defaultConfig","type","url","headers","Authorization","detectClaudeCode","ctx","join","detectAntigravity","antigravityDir","getVSCodeUserDir","variant","APPDATA","detectCline","vscodeUserDir","clineConfigDir","detectClineCli","clineHome","CLINE_DIR","detectCodexCli","codexHome","CODEX_HOME","detectCursor","cursorDir","detectGeminiCli","settingsPath","detectGitHubCopilotCli","copilotDir","XDG_CONFIG_HOME","detectOpenCode","detectVSCode","configDir","detectVSCodeInsiders","detectZed","detectMCPorter","mcporterDir","jsonPath","jsoncPath","extractBearerToken","undefined","auth","match","readTokenFromHeaders","serverConfig","readTokenFromHttpHeaders","http_headers","EDITOR_DEFAULTS","buildServerConfig","configKey","format","oauthOnly","readToken","buildAntigravityServerConfig","serverUrl","buildClineServerConfig","disabled","buildCodexCliServerConfig","buildGitHubCopilotCliServerConfig","tools","buildOpenCodeServerConfig","buildZedServerConfig","settings","EDITOR_CONFIGS","Antigravity","detect","Cline","Cursor","MCPorter","OpenCode","Zed"],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { subdebug } from '@sanity/cli-core';
|
|
|
3
3
|
import { logSymbols } from '@sanity/cli-core/ux';
|
|
4
4
|
import { createMCPToken, MCP_SERVER_URL } from '../../services/mcp.js';
|
|
5
5
|
import { detectAvailableEditors } from './detectAvailableEditors.js';
|
|
6
|
+
import { EDITOR_CONFIGS } from './editorConfigs.js';
|
|
6
7
|
import { promptForMCPSetup } from './promptForMCPSetup.js';
|
|
7
8
|
import { validateEditorTokens } from './validateEditorTokens.js';
|
|
8
9
|
import { writeMCPConfig } from './writeMCPConfig.js';
|
|
@@ -77,8 +78,10 @@ const NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server f
|
|
|
77
78
|
mcpDebug('Reusing valid token from %s', validEditor.name);
|
|
78
79
|
token = validEditor.existingToken;
|
|
79
80
|
}
|
|
81
|
+
const allOAuth = selected.every((e)=>EDITOR_CONFIGS[e.name].oauthOnly);
|
|
80
82
|
// Fall back to creating a new token
|
|
81
|
-
|
|
83
|
+
// If all editors use OAuth, we don't need to create a token
|
|
84
|
+
if (!token && !allOAuth) {
|
|
82
85
|
try {
|
|
83
86
|
token = await createMCPToken();
|
|
84
87
|
} catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/mcp/setupMCP.ts"],"sourcesContent":["import {ux} from '@oclif/core'\nimport {subdebug} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\n\nimport {createMCPToken, MCP_SERVER_URL} from '../../services/mcp.js'\nimport {detectAvailableEditors} from './detectAvailableEditors.js'\nimport {type EditorName} from './editorConfigs.js'\nimport {promptForMCPSetup} from './promptForMCPSetup.js'\nimport {validateEditorTokens} from './validateEditorTokens.js'\nimport {writeMCPConfig} from './writeMCPConfig.js'\n\nconst mcpDebug = subdebug('mcp:setup')\n\nconst NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server for your editor. Visit ${MCP_SERVER_URL} for setup instructions.`\n\ninterface MCPSetupOptions {\n /**\n * Whether the user explicitly requested MCP configuration (e.g. `sanity mcp configure`).\n * When true, shows status messages even when there's nothing to do.\n * When false/undefined (e.g. called from `sanity init`), stays quiet.\n */\n explicit?: boolean\n\n /**\n * Controls how MCP setup behaves:\n * - 'prompt': Ask the user which editors to configure (default)\n * - 'auto': Auto-configure all detected editors without prompting\n * - 'skip': Skip MCP configuration entirely\n */\n mode?: 'auto' | 'prompt' | 'skip'\n}\n\ninterface MCPSetupResult {\n /** Editors that were already configured with valid credentials (nothing to do) */\n alreadyConfiguredEditors: EditorName[]\n configuredEditors: EditorName[]\n detectedEditors: EditorName[]\n skipped: boolean\n\n error?: Error\n}\n\n/**\n * Main MCP setup orchestration\n * Opt-out by default: runs automatically unless skip option is set\n */\nexport async function setupMCP(options?: MCPSetupOptions): Promise<MCPSetupResult> {\n const {explicit = false, mode = 'prompt'} = options ?? {}\n\n // 1. Check for explicit opt-out\n if (mode === 'skip') {\n mcpDebug('Skipping MCP configuration (mode: skip)')\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors: [],\n skipped: true,\n }\n }\n\n // 2. Detect available editors (filters out unparseable configs)\n const editors = await detectAvailableEditors()\n const detectedEditors = editors.map((e) => e.name)\n\n mcpDebug('Detected %d editors: %s', detectedEditors.length, detectedEditors)\n\n if (editors.length === 0) {\n if (explicit) {\n ux.warn(NO_EDITORS_DETECTED_MESSAGE)\n }\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 3. Validate existing tokens against the Sanity API\n await validateEditorTokens(editors)\n\n // 4. Check if there's anything actionable\n const actionable = editors.filter((e) => !e.configured || e.authStatus !== 'valid')\n\n if (actionable.length === 0) {\n mcpDebug('All editors configured with valid credentials')\n const alreadyConfiguredEditors = editors\n .filter((e) => e.configured && e.authStatus === 'valid')\n .map((e) => e.name)\n if (explicit) {\n ux.stdout(`${logSymbols.success} All detected editors are already configured`)\n }\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // Non-actionable editors are already configured with valid credentials\n const alreadyConfiguredEditors = editors.filter((e) => !actionable.includes(e)).map((e) => e.name)\n\n // 5. Select editors to configure — prompt interactively or auto-select all\n const selected = mode === 'auto' ? actionable : await promptForMCPSetup(actionable)\n\n if (!selected || selected.length === 0) {\n // User deselected all editors\n ux.stdout('MCP configuration skipped')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 6. Get a token — reuse a valid existing one or create a new one\n let token: string | undefined\n\n // Look for an existing valid token we can reuse\n const validEditor = editors.find((e) => e.authStatus === 'valid' && e.existingToken)\n if (validEditor?.existingToken) {\n mcpDebug('Reusing valid token from %s', validEditor.name)\n token = validEditor.existingToken\n }\n\n // Fall back to creating a new token\n if (!token) {\n try {\n token = await createMCPToken()\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error creating MCP token', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n }\n\n // 7. Write configs for each selected editor\n const configuredEditors: EditorName[] = []\n try {\n for (const editor of selected) {\n await writeMCPConfig(editor, token)\n configuredEditors.push(editor.name)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error writing MCP config', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n\n ux.stdout(`${logSymbols.success} MCP configured for ${configuredEditors.join(', ')}`)\n\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n skipped: false,\n }\n}\n"],"names":["ux","subdebug","logSymbols","createMCPToken","MCP_SERVER_URL","detectAvailableEditors","promptForMCPSetup","validateEditorTokens","writeMCPConfig","mcpDebug","NO_EDITORS_DETECTED_MESSAGE","setupMCP","options","explicit","mode","alreadyConfiguredEditors","configuredEditors","detectedEditors","skipped","editors","map","e","name","length","warn","actionable","filter","configured","authStatus","stdout","success","includes","selected","token","validEditor","find","existingToken","error","err","Error","String","message","editor","push","join"],"mappings":"AAAA,SAAQA,EAAE,QAAO,cAAa;AAC9B,SAAQC,QAAQ,QAAO,mBAAkB;AACzC,SAAQC,UAAU,QAAO,sBAAqB;AAE9C,SAAQC,cAAc,EAAEC,cAAc,QAAO,wBAAuB;AACpE,SAAQC,sBAAsB,QAAO,8BAA6B;
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/mcp/setupMCP.ts"],"sourcesContent":["import {ux} from '@oclif/core'\nimport {subdebug} from '@sanity/cli-core'\nimport {logSymbols} from '@sanity/cli-core/ux'\n\nimport {createMCPToken, MCP_SERVER_URL} from '../../services/mcp.js'\nimport {detectAvailableEditors} from './detectAvailableEditors.js'\nimport {EDITOR_CONFIGS, type EditorName} from './editorConfigs.js'\nimport {promptForMCPSetup} from './promptForMCPSetup.js'\nimport {validateEditorTokens} from './validateEditorTokens.js'\nimport {writeMCPConfig} from './writeMCPConfig.js'\n\nconst mcpDebug = subdebug('mcp:setup')\n\nconst NO_EDITORS_DETECTED_MESSAGE = `Couldn't auto-configure Sanity MCP server for your editor. Visit ${MCP_SERVER_URL} for setup instructions.`\n\ninterface MCPSetupOptions {\n /**\n * Whether the user explicitly requested MCP configuration (e.g. `sanity mcp configure`).\n * When true, shows status messages even when there's nothing to do.\n * When false/undefined (e.g. called from `sanity init`), stays quiet.\n */\n explicit?: boolean\n\n /**\n * Controls how MCP setup behaves:\n * - 'prompt': Ask the user which editors to configure (default)\n * - 'auto': Auto-configure all detected editors without prompting\n * - 'skip': Skip MCP configuration entirely\n */\n mode?: 'auto' | 'prompt' | 'skip'\n}\n\ninterface MCPSetupResult {\n /** Editors that were already configured with valid credentials (nothing to do) */\n alreadyConfiguredEditors: EditorName[]\n configuredEditors: EditorName[]\n detectedEditors: EditorName[]\n skipped: boolean\n\n error?: Error\n}\n\n/**\n * Main MCP setup orchestration\n * Opt-out by default: runs automatically unless skip option is set\n */\nexport async function setupMCP(options?: MCPSetupOptions): Promise<MCPSetupResult> {\n const {explicit = false, mode = 'prompt'} = options ?? {}\n\n // 1. Check for explicit opt-out\n if (mode === 'skip') {\n mcpDebug('Skipping MCP configuration (mode: skip)')\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors: [],\n skipped: true,\n }\n }\n\n // 2. Detect available editors (filters out unparseable configs)\n const editors = await detectAvailableEditors()\n const detectedEditors = editors.map((e) => e.name)\n\n mcpDebug('Detected %d editors: %s', detectedEditors.length, detectedEditors)\n\n if (editors.length === 0) {\n if (explicit) {\n ux.warn(NO_EDITORS_DETECTED_MESSAGE)\n }\n return {\n alreadyConfiguredEditors: [],\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 3. Validate existing tokens against the Sanity API\n await validateEditorTokens(editors)\n\n // 4. Check if there's anything actionable\n const actionable = editors.filter((e) => !e.configured || e.authStatus !== 'valid')\n\n if (actionable.length === 0) {\n mcpDebug('All editors configured with valid credentials')\n const alreadyConfiguredEditors = editors\n .filter((e) => e.configured && e.authStatus === 'valid')\n .map((e) => e.name)\n if (explicit) {\n ux.stdout(`${logSymbols.success} All detected editors are already configured`)\n }\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // Non-actionable editors are already configured with valid credentials\n const alreadyConfiguredEditors = editors.filter((e) => !actionable.includes(e)).map((e) => e.name)\n\n // 5. Select editors to configure — prompt interactively or auto-select all\n const selected = mode === 'auto' ? actionable : await promptForMCPSetup(actionable)\n\n if (!selected || selected.length === 0) {\n // User deselected all editors\n ux.stdout('MCP configuration skipped')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n skipped: true,\n }\n }\n\n // 6. Get a token — reuse a valid existing one or create a new one\n let token: string | undefined\n\n // Look for an existing valid token we can reuse\n const validEditor = editors.find((e) => e.authStatus === 'valid' && e.existingToken)\n if (validEditor?.existingToken) {\n mcpDebug('Reusing valid token from %s', validEditor.name)\n token = validEditor.existingToken\n }\n\n const allOAuth = selected.every((e) => EDITOR_CONFIGS[e.name].oauthOnly)\n\n // Fall back to creating a new token\n // If all editors use OAuth, we don't need to create a token\n if (!token && !allOAuth) {\n try {\n token = await createMCPToken()\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error creating MCP token', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors: [],\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n }\n\n // 7. Write configs for each selected editor\n const configuredEditors: EditorName[] = []\n try {\n for (const editor of selected) {\n await writeMCPConfig(editor, token)\n configuredEditors.push(editor.name)\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n mcpDebug('Error writing MCP config', error)\n ux.warn(`Could not configure MCP: ${err.message}`)\n ux.warn('You can set up MCP manually later using https://mcp.sanity.io')\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n error: err,\n skipped: false,\n }\n }\n\n ux.stdout(`${logSymbols.success} MCP configured for ${configuredEditors.join(', ')}`)\n\n return {\n alreadyConfiguredEditors,\n configuredEditors,\n detectedEditors,\n skipped: false,\n }\n}\n"],"names":["ux","subdebug","logSymbols","createMCPToken","MCP_SERVER_URL","detectAvailableEditors","EDITOR_CONFIGS","promptForMCPSetup","validateEditorTokens","writeMCPConfig","mcpDebug","NO_EDITORS_DETECTED_MESSAGE","setupMCP","options","explicit","mode","alreadyConfiguredEditors","configuredEditors","detectedEditors","skipped","editors","map","e","name","length","warn","actionable","filter","configured","authStatus","stdout","success","includes","selected","token","validEditor","find","existingToken","allOAuth","every","oauthOnly","error","err","Error","String","message","editor","push","join"],"mappings":"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"}
|
|
@@ -11,8 +11,8 @@ import { EDITOR_CONFIGS } from './editorConfigs.js';
|
|
|
11
11
|
* Note: Config parseability is already validated in detectAvailableEditors()
|
|
12
12
|
*/ export async function writeMCPConfig(editor, token) {
|
|
13
13
|
const configPath = editor.configPath;
|
|
14
|
-
const { buildServerConfig, configKey, format } = EDITOR_CONFIGS[editor.name];
|
|
15
|
-
const serverConfig = buildServerConfig(token);
|
|
14
|
+
const { buildServerConfig, configKey, format, oauthOnly } = EDITOR_CONFIGS[editor.name];
|
|
15
|
+
const serverConfig = oauthOnly ? buildServerConfig('') : buildServerConfig(token);
|
|
16
16
|
// Read existing content or start with empty object/document
|
|
17
17
|
let content = format === 'toml' ? '' : '{}';
|
|
18
18
|
if (existsSync(configPath)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/actions/mcp/writeMCPConfig.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {applyEdits, modify} from 'jsonc-parser'\nimport {parse as parseToml, stringify as stringifyToml} from 'smol-toml'\n\nimport {EDITOR_CONFIGS} from './editorConfigs.js'\nimport {Editor} from './types.js'\n\ninterface TomlConfig {\n [key: string]: Record<string, unknown> | undefined\n}\n\n/**\n * Write MCP configuration to editor config file\n * Uses jsonc-parser's modify/applyEdits to preserve comments\n *\n * Note: Config parseability is already validated in detectAvailableEditors()\n */\nexport async function writeMCPConfig(editor: Editor, token
|
|
1
|
+
{"version":3,"sources":["../../../src/actions/mcp/writeMCPConfig.ts"],"sourcesContent":["import {existsSync} from 'node:fs'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\n\nimport {applyEdits, modify} from 'jsonc-parser'\nimport {parse as parseToml, stringify as stringifyToml} from 'smol-toml'\n\nimport {EDITOR_CONFIGS} from './editorConfigs.js'\nimport {Editor} from './types.js'\n\ninterface TomlConfig {\n [key: string]: Record<string, unknown> | undefined\n}\n\n/**\n * Write MCP configuration to editor config file\n * Uses jsonc-parser's modify/applyEdits to preserve comments\n *\n * Note: Config parseability is already validated in detectAvailableEditors()\n */\nexport async function writeMCPConfig(editor: Editor, token?: string): Promise<void> {\n const configPath = editor.configPath\n const {buildServerConfig, configKey, format, oauthOnly} = EDITOR_CONFIGS[editor.name]\n const serverConfig = oauthOnly ? buildServerConfig('') : buildServerConfig(token!)\n\n // Read existing content or start with empty object/document\n let content = format === 'toml' ? '' : '{}'\n if (existsSync(configPath)) {\n const fileContent = await fs.readFile(configPath, 'utf8')\n if (fileContent.trim()) {\n content = fileContent\n }\n }\n\n if (format === 'toml') {\n const tomlConfig = content.trim() ? (parseToml(content) as TomlConfig) : {}\n const existingServers = tomlConfig[configKey]\n\n tomlConfig[configKey] = {\n ...(existingServers && typeof existingServers === 'object' ? existingServers : {}),\n Sanity: serverConfig,\n }\n\n content = stringifyToml(tomlConfig)\n } else {\n // Modify using jsonc-parser - preserves comments\n // Setting a nested path automatically creates intermediate objects\n const edits = modify(content, [configKey, 'Sanity'], serverConfig, {\n formattingOptions: {insertSpaces: true, tabSize: 2},\n })\n content = applyEdits(content, edits)\n }\n\n // Ensure parent directory exists and write\n await fs.mkdir(path.dirname(configPath), {recursive: true})\n await fs.writeFile(configPath, content, 'utf8')\n}\n"],"names":["existsSync","fs","path","applyEdits","modify","parse","parseToml","stringify","stringifyToml","EDITOR_CONFIGS","writeMCPConfig","editor","token","configPath","buildServerConfig","configKey","format","oauthOnly","name","serverConfig","content","fileContent","readFile","trim","tomlConfig","existingServers","Sanity","edits","formattingOptions","insertSpaces","tabSize","mkdir","dirname","recursive","writeFile"],"mappings":"AAAA,SAAQA,UAAU,QAAO,UAAS;AAClC,OAAOC,QAAQ,mBAAkB;AACjC,OAAOC,UAAU,YAAW;AAE5B,SAAQC,UAAU,EAAEC,MAAM,QAAO,eAAc;AAC/C,SAAQC,SAASC,SAAS,EAAEC,aAAaC,aAAa,QAAO,YAAW;AAExE,SAAQC,cAAc,QAAO,qBAAoB;AAOjD;;;;;CAKC,GACD,OAAO,eAAeC,eAAeC,MAAc,EAAEC,KAAc;IACjE,MAAMC,aAAaF,OAAOE,UAAU;IACpC,MAAM,EAACC,iBAAiB,EAAEC,SAAS,EAAEC,MAAM,EAAEC,SAAS,EAAC,GAAGR,cAAc,CAACE,OAAOO,IAAI,CAAC;IACrF,MAAMC,eAAeF,YAAYH,kBAAkB,MAAMA,kBAAkBF;IAE3E,4DAA4D;IAC5D,IAAIQ,UAAUJ,WAAW,SAAS,KAAK;IACvC,IAAIhB,WAAWa,aAAa;QAC1B,MAAMQ,cAAc,MAAMpB,GAAGqB,QAAQ,CAACT,YAAY;QAClD,IAAIQ,YAAYE,IAAI,IAAI;YACtBH,UAAUC;QACZ;IACF;IAEA,IAAIL,WAAW,QAAQ;QACrB,MAAMQ,aAAaJ,QAAQG,IAAI,KAAMjB,UAAUc,WAA0B,CAAC;QAC1E,MAAMK,kBAAkBD,UAAU,CAACT,UAAU;QAE7CS,UAAU,CAACT,UAAU,GAAG;YACtB,GAAIU,mBAAmB,OAAOA,oBAAoB,WAAWA,kBAAkB,CAAC,CAAC;YACjFC,QAAQP;QACV;QAEAC,UAAUZ,cAAcgB;IAC1B,OAAO;QACL,iDAAiD;QACjD,mEAAmE;QACnE,MAAMG,QAAQvB,OAAOgB,SAAS;YAACL;YAAW;SAAS,EAAEI,cAAc;YACjES,mBAAmB;gBAACC,cAAc;gBAAMC,SAAS;YAAC;QACpD;QACAV,UAAUjB,WAAWiB,SAASO;IAChC;IAEA,2CAA2C;IAC3C,MAAM1B,GAAG8B,KAAK,CAAC7B,KAAK8B,OAAO,CAACnB,aAAa;QAACoB,WAAW;IAAI;IACzD,MAAMhC,GAAGiC,SAAS,CAACrB,YAAYO,SAAS;AAC1C"}
|