chrome-devtools-mcp-for-extension 0.18.1 → 0.18.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -48,7 +48,25 @@ export function resolveUserDataDir(opts) {
|
|
|
48
48
|
clientId = sanitize(detected);
|
|
49
49
|
console.error(`[profiles] Auto-detected client from parent process: ${clientId}`);
|
|
50
50
|
}
|
|
51
|
-
//
|
|
51
|
+
// 0a) MCP_SHARED_PROFILE → shared profile across all projects
|
|
52
|
+
// - Uses a single profile for all projects to avoid re-login
|
|
53
|
+
if (opts.env.MCP_SHARED_PROFILE === 'true') {
|
|
54
|
+
const key = 'shared';
|
|
55
|
+
const p = projectProfilePath(key, clientId, channel);
|
|
56
|
+
const result = {
|
|
57
|
+
path: p,
|
|
58
|
+
reason: 'MCP_USER_DATA_DIR', // Treat as explicit user choice
|
|
59
|
+
projectKey: key,
|
|
60
|
+
projectName: 'shared',
|
|
61
|
+
hash: '00000000',
|
|
62
|
+
clientId,
|
|
63
|
+
channel,
|
|
64
|
+
};
|
|
65
|
+
console.error(`[profiles] resolved(MCP_SHARED_PROFILE): ${result.path} (client=${clientId})`);
|
|
66
|
+
console.error(`[profiles] ℹ️ Using shared profile - login state persists across all projects`);
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
// 0b) CI detection → ephemeral session directory (unless MCP_PERSIST_PROFILES)
|
|
52
70
|
// - This happens before other priorities to keep CI clean by default.
|
|
53
71
|
if (isCI(opts.env) && !opts.env.MCP_PERSIST_PROFILES) {
|
|
54
72
|
const sessionId = `${process.pid}-${Date.now()}`;
|
|
@@ -181,27 +181,30 @@ export const askGeminiWeb = defineTool({
|
|
|
181
181
|
response.appendResponseLine('質問を送信中...');
|
|
182
182
|
// Input text using the textbox element
|
|
183
183
|
// Gemini uses a textbox with role="textbox" or a div with contenteditable
|
|
184
|
+
// NOTE: Gemini has Trusted Types CSP, so we cannot use innerHTML directly
|
|
184
185
|
const questionSent = await page.evaluate((questionText) => {
|
|
186
|
+
// Helper to clear element content without innerHTML (CSP-safe)
|
|
187
|
+
const clearElement = (el) => {
|
|
188
|
+
while (el.firstChild) {
|
|
189
|
+
el.removeChild(el.firstChild);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
185
192
|
// Try textbox first (Gemini's current implementation)
|
|
186
193
|
const textbox = document.querySelector('[role="textbox"]');
|
|
187
194
|
if (textbox) {
|
|
188
195
|
textbox.focus();
|
|
189
|
-
// Clear existing content
|
|
190
|
-
textbox
|
|
191
|
-
// Insert text
|
|
192
|
-
|
|
193
|
-
p.textContent = questionText;
|
|
194
|
-
textbox.appendChild(p);
|
|
196
|
+
// Clear existing content (CSP-safe)
|
|
197
|
+
clearElement(textbox);
|
|
198
|
+
// Insert text using textContent (CSP-safe)
|
|
199
|
+
textbox.textContent = questionText;
|
|
195
200
|
textbox.dispatchEvent(new Event('input', { bubbles: true }));
|
|
196
201
|
return true;
|
|
197
202
|
}
|
|
198
203
|
// Fallback to contenteditable
|
|
199
204
|
const editor = document.querySelector('div[contenteditable="true"]');
|
|
200
205
|
if (editor) {
|
|
201
|
-
editor
|
|
202
|
-
|
|
203
|
-
p.textContent = questionText;
|
|
204
|
-
editor.appendChild(p);
|
|
206
|
+
clearElement(editor);
|
|
207
|
+
editor.textContent = questionText;
|
|
205
208
|
editor.dispatchEvent(new Event('input', { bubbles: true }));
|
|
206
209
|
return true;
|
|
207
210
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrome-devtools-mcp-for-extension",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.3",
|
|
4
4
|
"description": "MCP server for Chrome extension development with Web Store automation. Fork of chrome-devtools-mcp with extension-specific tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": "./scripts/cli.mjs",
|