-
Notifications
You must be signed in to change notification settings - Fork 0
Add OAuth retry logic and improve error handling in setup flow #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
KHAEntertainment
merged 5 commits into
master
from
claude/web-desktop-skills-access-cAsiT
Apr 1, 2026
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
4d7a9fa
fix: OAuth UX improvements — PKCE retry, macOS timeout, set-key fallback
claude 4198c63
feat: add MCP server for native Claude Code tool integration (#30, #31)
claude f958906
fix: address CodeRabbit review findings on PR #32
claude c56804c
docs: update SKILL files, README, and setup.sh for MCP architecture
claude 50f1791
fix: Windows compatibility for MCP server bin entry (#33)
claude File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #!/usr/bin/env node | ||
| /** | ||
| * Cross-platform wrapper for the Grok Swarm MCP server. | ||
| * Spawns python3 (or python on Windows) to run grok_server.py, | ||
| * forwarding stdin/stdout for the MCP stdio transport. | ||
| */ | ||
| const { spawn } = require('child_process'); | ||
| const path = require('path'); | ||
|
|
||
| const serverScript = path.join(__dirname, '..', 'src', 'mcp', 'grok_server.py'); | ||
|
|
||
| // Try python3 first, fall back to python (common on Windows) | ||
| const pythonCandidates = process.platform === 'win32' | ||
| ? ['python3', 'python'] | ||
| : ['python3']; | ||
|
|
||
| function trySpawn(candidates) { | ||
| const cmd = candidates[0]; | ||
| if (!cmd) { | ||
| process.stderr.write( | ||
| 'ERROR: Python 3 not found. Install Python 3.8+ and ensure python3 (or python) is on PATH.\n' | ||
| ); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| const child = spawn(cmd, [serverScript], { | ||
| stdio: ['inherit', 'inherit', 'inherit'], | ||
| }); | ||
|
|
||
| child.on('error', (err) => { | ||
| if (err.code === 'ENOENT' && candidates.length > 1) { | ||
| // python3 not found, try next candidate | ||
| trySpawn(candidates.slice(1)); | ||
| } else { | ||
| process.stderr.write(`ERROR: Failed to start MCP server: ${err.message}\n`); | ||
| process.exit(1); | ||
| } | ||
| }); | ||
|
|
||
| child.on('exit', (code) => { | ||
| process.exit(code || 0); | ||
| }); | ||
| } | ||
|
|
||
| trySpawn(pythonCandidates); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| --- | ||
| name: set-key | ||
| description: Manually save an OpenRouter API key to config. Last-resort fallback when OAuth fails. WARNING - key will be visible in conversation context. | ||
| argument-hint: YOUR_API_KEY | ||
| allowed-tools: | ||
| - Bash | ||
| --- | ||
|
|
||
| # Set Grok Swarm API Key (Manual Fallback) | ||
|
|
||
| **Use this only when the OAuth flow (`/grok-swarm:setup`) has failed repeatedly.** | ||
|
|
||
| ## Step 1 — Display security warning | ||
|
|
||
| Before doing anything else, output this warning verbatim to the user: | ||
|
|
||
| --- | ||
|
|
||
| > **WARNING: Security Risk** | ||
| > | ||
| > You are about to paste your OpenRouter API key directly into this conversation. | ||
| > This means your API key **will be visible in the LLM context window** and may be | ||
| > stored in conversation logs. | ||
| > | ||
| > **Only proceed if you understand and accept these risks.** The recommended method | ||
| > is `/grok-swarm:setup` which uses OAuth so your key never enters the conversation. | ||
| > | ||
| > Type **yes** to confirm you accept this risk, or anything else to cancel. | ||
|
|
||
| --- | ||
|
|
||
| Wait for the user's response. If they do not reply with exactly `yes` (case-insensitive), stop here and remind them to use `/grok-swarm:setup` instead. | ||
|
|
||
| ## Step 2 — Validate the key argument | ||
|
|
||
| The API key is the argument passed to this command (e.g. `/grok-swarm:set-key sk-or-v1-...`). | ||
|
|
||
| If no argument was provided, ask the user to re-run with their key: | ||
| ``` | ||
| /grok-swarm:set-key YOUR_API_KEY_HERE | ||
| ``` | ||
| Do not ask them to type the key in a follow-up message. | ||
|
|
||
| ## Step 3 — Save the key | ||
|
|
||
| Run (pass the key via environment variable so it is never interpolated into shell or Python source): | ||
| ```bash | ||
| mkdir -p ~/.config/grok-swarm | ||
| GROK_SET_KEY="<the key argument>" python3 -c " | ||
| import json, os | ||
| from pathlib import Path | ||
|
|
||
| api_key = os.environ['GROK_SET_KEY'] | ||
| config_file = Path.home() / '.config' / 'grok-swarm' / 'config.json' | ||
| existing = {} | ||
| if config_file.exists(): | ||
| try: | ||
| existing = json.loads(config_file.read_text()) | ||
| except Exception: | ||
| pass | ||
| existing['api_key'] = api_key | ||
| json_bytes = (json.dumps(existing, indent=2) + '\n').encode() | ||
| tmp = str(config_file.parent / f'.config.json.tmp.{os.getpid()}') | ||
| fd = os.open(tmp, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) | ||
| try: | ||
| os.write(fd, json_bytes) | ||
| os.fsync(fd) | ||
| finally: | ||
| os.close(fd) | ||
| os.replace(tmp, str(config_file)) | ||
| print('saved') | ||
| " | ||
| ``` | ||
|
|
||
| ## Step 4 — Confirm success | ||
|
|
||
| Tell the user: | ||
| - Key saved to `~/.config/grok-swarm/config.json` (permissions: 600) | ||
| - Show only the first 8 characters: `sk-or-v1-...` → `sk-or-v1-` + `[redacted]` | ||
| - Suggest running `/grok-swarm:analyze Hello world` to verify the key works | ||
|
|
||
| ## Notes | ||
|
|
||
| - This command exists as a last resort. Always prefer `/grok-swarm:setup` (OAuth flow). | ||
| - The key is saved with file permissions 600 (owner read/write only). | ||
| - If you need to rotate the key later, run this command again or re-run `/grok-swarm:setup`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.