gemini-computer-use 0.1.2
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/LICENSE +21 -0
- package/README.md +196 -0
- package/bin/cli.js +27 -0
- package/core/__init__.py +0 -0
- package/core/agent.py +57 -0
- package/core/agent_harness.py +60 -0
- package/core/code_cache.py +232 -0
- package/core/hooks.py +61 -0
- package/core/policies.py +99 -0
- package/core/schemas.py +49 -0
- package/core/server.py +69 -0
- package/core/subagents.py +55 -0
- package/core/triggers.py +70 -0
- package/core/vitals.py +117 -0
- package/install.ps1 +339 -0
- package/install.sh +777 -0
- package/package.json +41 -0
- package/skills/orchestrator.md +14 -0
package/install.ps1
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# Antigravity Mesh - Windows PowerShell Universal Installer
|
|
3
|
+
# ==============================================================================
|
|
4
|
+
param(
|
|
5
|
+
[switch]$Quick,
|
|
6
|
+
[string]$Mode = "tunnel",
|
|
7
|
+
[string]$User = "",
|
|
8
|
+
[string]$Token = "",
|
|
9
|
+
[string]$Gateway = "smart-server.online",
|
|
10
|
+
[int]$Port = 8096,
|
|
11
|
+
[string]$Lang = "en",
|
|
12
|
+
[switch]$DryRun
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
# Ensure UTF-8 output encoding in PowerShell console
|
|
16
|
+
try {
|
|
17
|
+
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
18
|
+
$OutputEncoding = [System.Text.Encoding]::UTF8
|
|
19
|
+
} catch {}
|
|
20
|
+
|
|
21
|
+
$ErrorActionPreference = "Stop"
|
|
22
|
+
|
|
23
|
+
$Hostname = $env:COMPUTERNAME.ToLower() -replace '[^a-z0-9_-]', ''
|
|
24
|
+
$IsLaptop = [bool](Get-CimInstance -ClassName Win32_Battery -ErrorAction SilentlyContinue)
|
|
25
|
+
|
|
26
|
+
if ($Lang -eq "ru") {
|
|
27
|
+
$DetectedType = if ($IsLaptop) { "Windows Ноутбук (Laptop)" } else { "Windows Десктоп / Сервер" }
|
|
28
|
+
Write-Host "+----------------------------------------------------------------------+" -ForegroundColor Cyan
|
|
29
|
+
Write-Host "| [*] Обнаружено устройство: |" -ForegroundColor Cyan
|
|
30
|
+
Write-Host "| * Имя хоста : $Hostname" -ForegroundColor Green
|
|
31
|
+
Write-Host "| * Тип : $DetectedType" -ForegroundColor Yellow
|
|
32
|
+
Write-Host "| * ОС : Windows $([System.Environment]::OSVersion.Version)" -ForegroundColor White
|
|
33
|
+
Write-Host "+----------------------------------------------------------------------+" -ForegroundColor Cyan
|
|
34
|
+
} else {
|
|
35
|
+
$DetectedType = if ($IsLaptop) { "Windows Laptop" } else { "Windows Desktop / Server" }
|
|
36
|
+
Write-Host "+----------------------------------------------------------------------+" -ForegroundColor Cyan
|
|
37
|
+
Write-Host "| [*] Detected Device: |" -ForegroundColor Cyan
|
|
38
|
+
Write-Host "| * Hostname : $Hostname" -ForegroundColor Green
|
|
39
|
+
Write-Host "| * Type : $DetectedType" -ForegroundColor Yellow
|
|
40
|
+
Write-Host "| * OS : Windows $([System.Environment]::OSVersion.Version)" -ForegroundColor White
|
|
41
|
+
Write-Host "+----------------------------------------------------------------------+" -ForegroundColor Cyan
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if ($DryRun) {
|
|
45
|
+
if ($Lang -eq "ru") {
|
|
46
|
+
Write-Host "[DRY-RUN] Проверка зависимостей и задач: OK"
|
|
47
|
+
} else {
|
|
48
|
+
Write-Host "[DRY-RUN] Dependency and task verification: OK"
|
|
49
|
+
}
|
|
50
|
+
exit 0
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# Python check & auto-install
|
|
54
|
+
$hasPython = $false
|
|
55
|
+
try {
|
|
56
|
+
$pyVer = python --version 2>&1
|
|
57
|
+
if ($LASTEXITCODE -eq 0 -or $pyVer -match "Python 3") {
|
|
58
|
+
if ($Lang -eq "ru") {
|
|
59
|
+
Write-Host "[1/3] Python обнаружен: $pyVer" -ForegroundColor Green
|
|
60
|
+
} else {
|
|
61
|
+
Write-Host "[1/3] Python detected: $pyVer" -ForegroundColor Green
|
|
62
|
+
}
|
|
63
|
+
$hasPython = $true
|
|
64
|
+
}
|
|
65
|
+
} catch {
|
|
66
|
+
$hasPython = $false
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (-not $hasPython) {
|
|
70
|
+
$localPyDir = "$env:LOCALAPPDATA\Programs\Python\Python312"
|
|
71
|
+
if (Test-Path "$localPyDir\python.exe") {
|
|
72
|
+
$env:Path = "$localPyDir;$localPyDir\Scripts;$env:Path"
|
|
73
|
+
$hasPython = $true
|
|
74
|
+
if ($Lang -eq "ru") {
|
|
75
|
+
Write-Host "[1/3] Python обнаружен: $localPyDir" -ForegroundColor Green
|
|
76
|
+
} else {
|
|
77
|
+
Write-Host "[1/3] Python detected: $localPyDir" -ForegroundColor Green
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (-not $hasPython) {
|
|
83
|
+
if ($Lang -eq "ru") {
|
|
84
|
+
Write-Host "[1/3] Python не найден. Автоматическая установка через winget..." -ForegroundColor Yellow
|
|
85
|
+
} else {
|
|
86
|
+
Write-Host "[1/3] Python not found. Installing automatically via winget..." -ForegroundColor Yellow
|
|
87
|
+
}
|
|
88
|
+
if (Get-Command winget -ErrorAction SilentlyContinue) {
|
|
89
|
+
winget install --id Python.Python.3.12 -e --silent --accept-source-agreements --accept-package-agreements
|
|
90
|
+
$localPyDir = "$env:LOCALAPPDATA\Programs\Python\Python312"
|
|
91
|
+
if (Test-Path "$localPyDir\python.exe") {
|
|
92
|
+
$env:Path = "$localPyDir;$localPyDir\Scripts;$env:Path"
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
try {
|
|
96
|
+
if ($Lang -eq "ru") { Write-Host "[1/3] Загрузка официального установщика Python 3.12..." -ForegroundColor Yellow } else { Write-Host "[1/3] Downloading official Python 3.12 installer..." -ForegroundColor Yellow }
|
|
97
|
+
$pyInstaller = "$env:TEMP\python-3.12.5-amd64.exe"
|
|
98
|
+
Invoke-WebRequest -Uri "https://www.python.org/ftp/python/3.12.5/python-3.12.5-amd64.exe" -OutFile $pyInstaller -UseBasicParsing
|
|
99
|
+
Start-Process -FilePath $pyInstaller -ArgumentList "/quiet InstallAllUsers=0 PrependPath=1 Include_test=0" -Wait
|
|
100
|
+
$pyPaths = @("$env:LOCALAPPDATA\Programs\Python\Python312", "$env:ProgramFiles\Python312")
|
|
101
|
+
foreach ($p in $pyPaths) {
|
|
102
|
+
if (Test-Path "$p\python.exe") {
|
|
103
|
+
$env:Path = "$p;$p\Scripts;$env:Path"
|
|
104
|
+
$hasPython = $true
|
|
105
|
+
break
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
} catch {
|
|
109
|
+
Write-Error "Python 3 auto-installation failed: $_"
|
|
110
|
+
exit 1
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
# Install dependencies
|
|
116
|
+
if ($Lang -eq "ru") {
|
|
117
|
+
Write-Host "[2/3] Проверка библиотек (websockets)..." -ForegroundColor Yellow
|
|
118
|
+
} else {
|
|
119
|
+
Write-Host "[2/3] Checking dependencies (websockets)..." -ForegroundColor Yellow
|
|
120
|
+
}
|
|
121
|
+
python -m pip install websockets --quiet 2>$null; if ($LASTEXITCODE -ne 0) { python -m ensurepip --default-pip 2>$null; python -m pip install websockets --quiet }
|
|
122
|
+
|
|
123
|
+
$ConfigDir = "$env:USERPROFILE\.config\antigravity-mesh"
|
|
124
|
+
if (!(Test-Path $ConfigDir)) { New-Item -ItemType Directory -Path $ConfigDir -Force | Out-Null }
|
|
125
|
+
|
|
126
|
+
# Bootstrap project files if piped from irm/iex
|
|
127
|
+
$ScriptDir = if ($MyInvocation.MyCommand -and $MyInvocation.MyCommand.Path) { Split-Path -Parent $MyInvocation.MyCommand.Path } else { $null }
|
|
128
|
+
if (-not $ScriptDir -or -not (Test-Path "$ScriptDir\core\agent.py")) {
|
|
129
|
+
$BootstrapDir = "$env:USERPROFILE\.gemini-computer-use"
|
|
130
|
+
$CoreDir = "$BootstrapDir\core"
|
|
131
|
+
$SkillsDir = "$BootstrapDir\skills"
|
|
132
|
+
if (!(Test-Path $CoreDir)) { New-Item -ItemType Directory -Path $CoreDir -Force | Out-Null }
|
|
133
|
+
if (!(Test-Path $SkillsDir)) { New-Item -ItemType Directory -Path $SkillsDir -Force | Out-Null }
|
|
134
|
+
|
|
135
|
+
$files = @(
|
|
136
|
+
"core/agent.py",
|
|
137
|
+
"core/server.py",
|
|
138
|
+
"core/vitals.py",
|
|
139
|
+
"core/__init__.py",
|
|
140
|
+
"skills/orchestrator.md"
|
|
141
|
+
)
|
|
142
|
+
foreach ($f in $files) {
|
|
143
|
+
$dest = "$BootstrapDir\$($f -replace '/', '\')"
|
|
144
|
+
try {
|
|
145
|
+
Invoke-WebRequest -Uri "https://$Gateway/$f" -OutFile $dest -UseBasicParsing -ErrorAction Stop
|
|
146
|
+
} catch {
|
|
147
|
+
try {
|
|
148
|
+
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/LevRa7/Computer-use-for-Gemini-App-Web/main/$f" -OutFile $dest -UseBasicParsing
|
|
149
|
+
} catch {}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
$ScriptDir = $BootstrapDir
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function Print-McpBox($Title, $Url, $CopiedText, $BorderColor = "Green") {
|
|
156
|
+
$MinLen = [Math]::Max($Title.Length, $Url.Length)
|
|
157
|
+
if ($CopiedText) {
|
|
158
|
+
$MinLen = [Math]::Max($MinLen, $CopiedText.Length)
|
|
159
|
+
}
|
|
160
|
+
$ContentWidth = [Math]::Max($MinLen + 4, 84)
|
|
161
|
+
$Border = " +" + ("-" * $ContentWidth) + "+"
|
|
162
|
+
$Empty = " |" + (" " * $ContentWidth) + "|"
|
|
163
|
+
|
|
164
|
+
Write-Host $Border -ForegroundColor $BorderColor
|
|
165
|
+
|
|
166
|
+
$padTitle = $ContentWidth - 2 - $Title.Length
|
|
167
|
+
Write-Host " | " -NoNewline -ForegroundColor $BorderColor
|
|
168
|
+
Write-Host $Title -NoNewline -ForegroundColor White
|
|
169
|
+
Write-Host ((" " * $padTitle) + " |") -ForegroundColor $BorderColor
|
|
170
|
+
|
|
171
|
+
Write-Host $Empty -ForegroundColor $BorderColor
|
|
172
|
+
|
|
173
|
+
$padUrl = $ContentWidth - 2 - $Url.Length
|
|
174
|
+
Write-Host " | " -NoNewline -ForegroundColor $BorderColor
|
|
175
|
+
Write-Host $Url -NoNewline -ForegroundColor Yellow
|
|
176
|
+
Write-Host ((" " * $padUrl) + " |") -ForegroundColor $BorderColor
|
|
177
|
+
|
|
178
|
+
Write-Host $Empty -ForegroundColor $BorderColor
|
|
179
|
+
|
|
180
|
+
if ($CopiedText) {
|
|
181
|
+
$padCopy = $ContentWidth - 2 - $CopiedText.Length
|
|
182
|
+
Write-Host " | " -NoNewline -ForegroundColor $BorderColor
|
|
183
|
+
Write-Host $CopiedText -NoNewline -ForegroundColor Green
|
|
184
|
+
Write-Host ((" " * $padCopy) + " |") -ForegroundColor $BorderColor
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
Write-Host $Border -ForegroundColor $BorderColor
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if ($Mode -eq "standalone") {
|
|
191
|
+
if ($Lang -eq "ru") {
|
|
192
|
+
Write-Host "=== Запуск в режиме Local Standalone на порту $Port ===" -ForegroundColor Blue
|
|
193
|
+
} else {
|
|
194
|
+
Write-Host "=== Starting in Local Standalone Mode on port $Port ===" -ForegroundColor Blue
|
|
195
|
+
}
|
|
196
|
+
Start-Process python -ArgumentList "-m core.server --port=$Port" -WorkingDirectory $ScriptDir -WindowStyle Hidden
|
|
197
|
+
$LocalUrl = "http://localhost:$Port/sse"
|
|
198
|
+
$Copied = $false
|
|
199
|
+
try {
|
|
200
|
+
Set-Clipboard -Value $LocalUrl -ErrorAction Stop
|
|
201
|
+
$Copied = $true
|
|
202
|
+
} catch {
|
|
203
|
+
try { $LocalUrl | clip.exe 2>$null; $Copied = $true } catch {}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
Clear-Host
|
|
207
|
+
|
|
208
|
+
if ($Lang -eq "ru") {
|
|
209
|
+
Write-Host ""
|
|
210
|
+
$copyMsg = if ($Copied) { "[OK] ССЫЛКА СКОПИРОВАНА В БУФЕР ОБМЕНА! (Вставьте через Ctrl+V)" } else { "Скопируйте ссылку выше" }
|
|
211
|
+
Print-McpBox "ССЫЛКА ЛОКАЛЬНОГО MCP-СЕРВЕРА (СКОПИРУЙТЕ):" $LocalUrl $copyMsg
|
|
212
|
+
Write-Host ""
|
|
213
|
+
Write-Host " Куда вставлять ссылку в Google Gemini:" -ForegroundColor Yellow
|
|
214
|
+
Write-Host " 1. Откройте в браузере: https://gemini.google.com/spark/apps" -ForegroundColor Cyan
|
|
215
|
+
Write-Host " 2. Нажмите 'Добавить приложение' (Add app / Настройки MCP)"
|
|
216
|
+
Write-Host " 3. Вставьте скопированную ссылку в поле 'URL сервера' (Ctrl+V) и нажмите Подключить." -ForegroundColor White
|
|
217
|
+
Write-Host ""
|
|
218
|
+
} else {
|
|
219
|
+
Write-Host ""
|
|
220
|
+
$copyMsg = if ($Copied) { "[OK] URL COPIED TO CLIPBOARD! (Press Ctrl+V to paste)" } else { "Copy the URL above" }
|
|
221
|
+
Print-McpBox "LOCAL MCP SERVER URL (COPY THIS):" $LocalUrl $copyMsg
|
|
222
|
+
Write-Host ""
|
|
223
|
+
Write-Host " Where to paste this URL in Google Gemini:" -ForegroundColor Yellow
|
|
224
|
+
Write-Host " 1. Open in your browser: https://gemini.google.com/spark/apps" -ForegroundColor Cyan
|
|
225
|
+
Write-Host " 2. Click 'Add app' (or navigate to MCP settings)"
|
|
226
|
+
Write-Host " 3. Paste the URL into the 'Server URL' field (Ctrl+V) and click Connect." -ForegroundColor White
|
|
227
|
+
Write-Host ""
|
|
228
|
+
}
|
|
229
|
+
exit 0
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
# Gateway Tunnel Mode
|
|
233
|
+
if ([string]::IsNullOrWhiteSpace($User)) {
|
|
234
|
+
$User = $Hostname
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if ($Lang -eq "ru") {
|
|
238
|
+
Write-Host "[2/3] Регистрация субдомена '$User' на шлюзе ($Gateway)..." -ForegroundColor Yellow
|
|
239
|
+
} else {
|
|
240
|
+
Write-Host "[2/3] Registering subdomain '$User' on gateway ($Gateway)..." -ForegroundColor Yellow
|
|
241
|
+
}
|
|
242
|
+
$detectedMac = ""
|
|
243
|
+
try {
|
|
244
|
+
$nic = Get-CimInstance Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 'TRUE'" -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
245
|
+
if ($nic -and $nic.MACAddress) {
|
|
246
|
+
$detectedMac = $nic.MACAddress
|
|
247
|
+
}
|
|
248
|
+
} catch {}
|
|
249
|
+
if ([string]::IsNullOrWhiteSpace($detectedMac)) {
|
|
250
|
+
try {
|
|
251
|
+
$detectedMac = python -c "import uuid; print(':'.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) for ele in range(0,8*6,8)][::-1]))" 2>$null
|
|
252
|
+
} catch {}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
$detectedOs = "Windows $([System.Environment]::OSVersion.Version.ToString())"
|
|
256
|
+
|
|
257
|
+
$regPayloadObj = @{
|
|
258
|
+
username = $User
|
|
259
|
+
auto_suffix = $true
|
|
260
|
+
mac_address = $detectedMac
|
|
261
|
+
os = $detectedOs
|
|
262
|
+
}
|
|
263
|
+
if (-not [string]::IsNullOrWhiteSpace($Token)) {
|
|
264
|
+
$regPayloadObj.token = $Token
|
|
265
|
+
}
|
|
266
|
+
$regPayload = $regPayloadObj | ConvertTo-Json
|
|
267
|
+
$response = Invoke-RestMethod -Uri "https://$Gateway/api/register" -Method Post -Body $regPayload -ContentType "application/json"
|
|
268
|
+
|
|
269
|
+
$AssignedUser = $response.username
|
|
270
|
+
$AssignedToken = $response.token
|
|
271
|
+
$SseUrl = $response.sse_url
|
|
272
|
+
|
|
273
|
+
# Quick Copy to Clipboard
|
|
274
|
+
$Copied = $false
|
|
275
|
+
try {
|
|
276
|
+
Set-Clipboard -Value $SseUrl -ErrorAction Stop
|
|
277
|
+
$Copied = $true
|
|
278
|
+
} catch {
|
|
279
|
+
try {
|
|
280
|
+
$SseUrl | clip.exe 2>$null
|
|
281
|
+
$Copied = $true
|
|
282
|
+
} catch {}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if ($Lang -eq "ru") {
|
|
286
|
+
Write-Host "[3/3] Настройка автозапуска в Windows..." -ForegroundColor Green
|
|
287
|
+
} else {
|
|
288
|
+
Write-Host "[3/3] Configuring Windows background autostart..." -ForegroundColor Green
|
|
289
|
+
}
|
|
290
|
+
$envFile = "$ConfigDir\agent.env"
|
|
291
|
+
@"
|
|
292
|
+
MESH_GATEWAY=$Gateway
|
|
293
|
+
MESH_USER=$AssignedUser
|
|
294
|
+
MESH_TOKEN=$AssignedToken
|
|
295
|
+
"@ | Out-File -FilePath $envFile -Encoding utf8
|
|
296
|
+
|
|
297
|
+
# Start agent in background
|
|
298
|
+
$env:MESH_GATEWAY = $Gateway
|
|
299
|
+
$env:MESH_USER = $AssignedUser
|
|
300
|
+
$env:MESH_TOKEN = $AssignedToken
|
|
301
|
+
|
|
302
|
+
# Create Windows Startup launcher for persistent autostart
|
|
303
|
+
$startupDir = [Environment]::GetFolderPath("Startup")
|
|
304
|
+
$startupVbs = "$startupDir\antigravity-agent.vbs"
|
|
305
|
+
@"
|
|
306
|
+
Set WshShell = CreateObject("WScript.Shell")
|
|
307
|
+
WshShell.Environment("PROCESS")("MESH_GATEWAY") = "$Gateway"
|
|
308
|
+
WshShell.Environment("PROCESS")("MESH_USER") = "$AssignedUser"
|
|
309
|
+
WshShell.Environment("PROCESS")("MESH_TOKEN") = "$AssignedToken"
|
|
310
|
+
WshShell.CurrentDirectory = "$ScriptDir"
|
|
311
|
+
WshShell.Run "python -m core.agent", 0, False
|
|
312
|
+
"@ | Out-File -FilePath $startupVbs -Encoding ascii
|
|
313
|
+
|
|
314
|
+
# Launch now
|
|
315
|
+
Start-Process python -ArgumentList "-m core.agent" -WorkingDirectory $ScriptDir -WindowStyle Hidden
|
|
316
|
+
|
|
317
|
+
Clear-Host
|
|
318
|
+
|
|
319
|
+
if ($Lang -eq "ru") {
|
|
320
|
+
Write-Host ""
|
|
321
|
+
$copyMsg = if ($Copied) { "[OK] ССЫЛКА СКОПИРОВАНА В БУФЕР ОБМЕНА! (Вставьте через Ctrl+V)" } else { "Скопируйте ссылку выше" }
|
|
322
|
+
Print-McpBox "ССЫЛКА MCP-СЕРВЕРА ДЛЯ ПОДКЛЮЧЕНИЯ (СКОПИРУЙТЕ):" $SseUrl $copyMsg
|
|
323
|
+
Write-Host ""
|
|
324
|
+
Write-Host " Куда вставлять ссылку в Google Gemini:" -ForegroundColor Yellow
|
|
325
|
+
Write-Host " 1. Откройте в браузере: https://gemini.google.com/spark/apps" -ForegroundColor Cyan
|
|
326
|
+
Write-Host " 2. Нажмите 'Добавить приложение' (Add app / Настройки MCP)"
|
|
327
|
+
Write-Host " 3. Вставьте скопированную ссылку в поле 'URL сервера' (Ctrl+V) и нажмите Подключить." -ForegroundColor White
|
|
328
|
+
Write-Host ""
|
|
329
|
+
} else {
|
|
330
|
+
Write-Host ""
|
|
331
|
+
$copyMsg = if ($Copied) { "[OK] URL COPIED TO CLIPBOARD! (Press Ctrl+V to paste)" } else { "Copy the URL above" }
|
|
332
|
+
Print-McpBox "MCP SERVER URL (COPY THIS):" $SseUrl $copyMsg
|
|
333
|
+
Write-Host ""
|
|
334
|
+
Write-Host " Where to paste this URL in Google Gemini:" -ForegroundColor Yellow
|
|
335
|
+
Write-Host " 1. Open in your browser: https://gemini.google.com/spark/apps" -ForegroundColor Cyan
|
|
336
|
+
Write-Host " 2. Click 'Add app' (or navigate to MCP settings)"
|
|
337
|
+
Write-Host " 3. Paste the URL into the 'Server URL' field (Ctrl+V) and click Connect." -ForegroundColor White
|
|
338
|
+
Write-Host ""
|
|
339
|
+
}
|