Skip to content

Commit 68ce026

Browse files
john-walkoeclaude
andcommitted
FIX: Linux setup script now detects existing API keys from other USPTO MCPs
Problem: - Script was prompting for API keys even when ~/.uspto_api_key and ~/.mistral_api_key already existed from PFW/PTAB installations - Used manual read -s prompts instead of validation helper functions Solution: - Use prompt_and_validate_uspto_key() and prompt_and_validate_mistral_key() functions that check for existing keys first - Show masked keys (last 5 chars) and ask user if they want to reuse - Only prompt for new keys if user declines or no existing keys found - Unified storage logic to handle both keys together (matches PTAB pattern) Benefits: - Seamless cross-MCP installation experience - Prevents accidental key overwrites - Consistent behavior across all USPTO MCPs (PFW/PTAB/FPD/Citations) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 0e17e30 commit 68ce026

File tree

1 file changed

+114
-156
lines changed

1 file changed

+114
-156
lines changed

deploy/linux_setup.sh

Lines changed: 114 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -106,71 +106,60 @@ else
106106
log_info "You can run the server with: uv run fpd-mcp"
107107
fi
108108

109-
# Step 5: Secure API Key Configuration
109+
# Step 5: API Key Configuration
110110
echo ""
111-
echo "=========================================="
112-
echo "SECURE API KEY CONFIGURATION"
113-
echo "=========================================="
114-
echo ""
115-
log_info "API keys will be stored in ENCRYPTED secure storage"
116-
log_info "Location: ~/.uspto_api_key and ~/.mistral_api_key"
117-
log_info "Format: Secure file storage (Linux: file permissions 600)"
111+
log_info "API Key Configuration"
118112
echo ""
119113

120-
# Collect USPTO API key with validation
121-
echo "Enter your USPTO API key (required - get from https://data.uspto.gov/myodp/):"
122-
echo -n "> "
123-
read -s USPTO_API_KEY # Silent read (no echo to terminal)
114+
log_info "USPTO FPD MCP requires two API keys:"
115+
log_info "1. USPTO Open Data Portal API key (required)"
116+
log_info "2. Mistral API key (optional - for OCR document extraction)"
117+
echo ""
118+
log_info "Get your free USPTO API key from: https://data.uspto.gov/myodp/"
119+
log_info "Get your Mistral API key from: https://console.mistral.ai/"
124120
echo ""
125121

126-
# Validate USPTO key format
127-
while ! validate_uspto_api_key "$USPTO_API_KEY"; do
128-
echo ""
129-
log_error "Invalid USPTO API key format"
130-
echo "Expected: Exactly 30 lowercase letters (a-z)"
131-
echo ""
132-
echo "Enter your USPTO API key:"
133-
echo -n "> "
134-
read -s USPTO_API_KEY
135-
echo ""
136-
done
122+
# Prompt for USPTO API key with validation (uses secure hidden input)
123+
USPTO_API_KEY=$(prompt_and_validate_uspto_key)
124+
if [[ -z "$USPTO_API_KEY" ]]; then
125+
log_error "Failed to obtain valid USPTO API key"
126+
exit 1
127+
fi
137128

129+
log_success "USPTO API key validated and configured"
138130
echo ""
139-
log_success "USPTO API key format validated"
140131

141-
# Collect Mistral API key with validation
142-
echo ""
143-
echo "Enter your Mistral API key (optional for OCR - press Enter to skip):"
144-
echo -n "> "
145-
read -s MISTRAL_API_KEY
132+
# Prompt for Mistral API key (optional)
146133
echo ""
147-
148-
if [[ -n "$MISTRAL_API_KEY" ]]; then
149-
# Validate Mistral key format
150-
while ! validate_mistral_api_key "$MISTRAL_API_KEY"; do
151-
echo ""
152-
log_error "Invalid Mistral API key format"
153-
echo "Expected: Exactly 32 alphanumeric characters (A-Z, a-z, 0-9)"
154-
echo ""
155-
echo "Enter your Mistral API key (or press Enter to skip):"
156-
echo -n "> "
157-
read -s MISTRAL_API_KEY
158-
echo ""
159-
160-
# Allow empty to skip
161-
if [[ -z "$MISTRAL_API_KEY" ]]; then
162-
break
163-
fi
164-
done
134+
log_info "Mistral API key configuration (optional - for OCR document extraction)"
135+
read -p "Would you like to configure Mistral API key now? (Y/n): " CONFIGURE_MISTRAL
136+
CONFIGURE_MISTRAL=${CONFIGURE_MISTRAL:-Y}
137+
138+
MISTRAL_API_KEY=""
139+
if [[ "$CONFIGURE_MISTRAL" =~ ^[Yy]$ ]]; then
140+
MISTRAL_API_KEY=$(prompt_and_validate_mistral_key)
141+
if [[ -z "$MISTRAL_API_KEY" ]]; then
142+
log_warning "Failed to obtain valid Mistral API key - skipping"
143+
log_info "You can configure it later using: ./deploy/manage_api_keys.sh"
144+
else
145+
log_success "Mistral API key validated and configured"
146+
fi
147+
else
148+
log_info "Skipping Mistral API key configuration"
149+
log_info "You can configure it later using: ./deploy/manage_api_keys.sh"
165150
fi
166151

167152
# Step 6: Store API keys in SECURE storage (NOT in config file!)
168153
echo ""
169-
log_info "Storing API keys in encrypted secure storage..."
154+
log_info "Storing API keys in secure storage..."
155+
log_info "Location: ~/.uspto_api_key and ~/.mistral_api_key (file permissions: 600)"
170156
echo ""
171157

172-
# Store USPTO key using environment variable (NOT command line argument)
158+
# Store USPTO key using environment variable (more secure than command line)
173159
export SETUP_USPTO_KEY="$USPTO_API_KEY"
160+
if [[ -n "$MISTRAL_API_KEY" ]]; then
161+
export SETUP_MISTRAL_KEY="$MISTRAL_API_KEY"
162+
fi
174163

175164
STORE_RESULT=$(python3 << 'EOF'
176165
import sys
@@ -181,87 +170,66 @@ from pathlib import Path
181170
sys.path.insert(0, str(Path.cwd() / 'src'))
182171
183172
try:
184-
from fpd_mcp.shared_secure_storage import store_uspto_api_key
173+
from fpd_mcp.shared_secure_storage import store_uspto_api_key, store_mistral_api_key
185174
186-
# Read from environment variable (NOT from command line - more secure)
187-
api_key = os.environ.get('SETUP_USPTO_KEY', '')
188-
if not api_key:
189-
print('ERROR: No API key provided')
175+
# Store USPTO key (required)
176+
uspto_key = os.environ.get('SETUP_USPTO_KEY', '')
177+
if not uspto_key:
178+
print('ERROR: No USPTO API key provided')
190179
sys.exit(1)
191180
192-
if store_uspto_api_key(api_key):
193-
print('SUCCESS')
194-
else:
181+
if not store_uspto_api_key(uspto_key):
195182
print('ERROR: Failed to store USPTO key')
196183
sys.exit(1)
184+
185+
# Store Mistral key (optional)
186+
mistral_key = os.environ.get('SETUP_MISTRAL_KEY', '')
187+
if mistral_key:
188+
if not store_mistral_api_key(mistral_key):
189+
print('ERROR: Failed to store Mistral key')
190+
sys.exit(1)
191+
print('SUCCESS:BOTH')
192+
else:
193+
print('SUCCESS:USPTO_ONLY')
194+
197195
except Exception as e:
198196
print(f'ERROR: {str(e)}')
199197
sys.exit(1)
200198
EOF
201199
)
202200

203-
# Clear environment variable immediately
201+
# Clear environment variables immediately
204202
unset SETUP_USPTO_KEY
203+
unset SETUP_MISTRAL_KEY
205204

206-
if [[ "$STORE_RESULT" == "SUCCESS" ]]; then
207-
log_success "USPTO API key stored in secure storage"
208-
log_info " Location: ~/.uspto_api_key"
205+
if [[ "$STORE_RESULT" == "SUCCESS:BOTH" ]]; then
206+
log_success "USPTO and Mistral API keys stored in secure storage"
207+
log_info " USPTO Location: ~/.uspto_api_key"
208+
log_info " Mistral Location: ~/.mistral_api_key"
209209
log_info " Permissions: 600 (owner read/write only)"
210-
log_audit "USPTO API key configured via linux_setup.sh"
211210

212-
# Verify file permissions
211+
# CRITICAL SECURITY: Set file permissions on both API key files
213212
if [ -f "$HOME/.uspto_api_key" ]; then
214-
PERMS=$(stat -c '%a' "$HOME/.uspto_api_key" 2>/dev/null || stat -f '%A' "$HOME/.uspto_api_key" 2>/dev/null)
215-
if [[ "$PERMS" == "600" ]]; then
216-
log_success " Verified: File permissions are secure (600)"
217-
else
218-
log_warning " Warning: File permissions are $PERMS (expected 600)"
219-
# Try to fix
220-
chmod 600 "$HOME/.uspto_api_key" 2>/dev/null || true
221-
fi
213+
set_secure_file_permissions "$HOME/.uspto_api_key"
222214
fi
223-
else
224-
log_error "Failed to store USPTO API key: $STORE_RESULT"
225-
exit 1
226-
fi
227-
228-
# Store Mistral key if provided
229-
if [[ -n "$MISTRAL_API_KEY" ]]; then
230-
echo ""
231-
export SETUP_MISTRAL_KEY="$MISTRAL_API_KEY"
232-
233-
STORE_RESULT=$(python3 << 'EOF'
234-
import sys
235-
import os
236-
from pathlib import Path
237-
238-
sys.path.insert(0, str(Path.cwd() / 'src'))
239-
240-
try:
241-
from fpd_mcp.shared_secure_storage import store_mistral_api_key
242215

243-
api_key = os.environ.get('SETUP_MISTRAL_KEY', '')
244-
if store_mistral_api_key(api_key):
245-
print('SUCCESS')
246-
else:
247-
print('ERROR: Failed to store Mistral key')
248-
sys.exit(1)
249-
except Exception as e:
250-
print(f'ERROR: {str(e)}')
251-
sys.exit(1)
252-
EOF
253-
)
216+
if [ -f "$HOME/.mistral_api_key" ]; then
217+
set_secure_file_permissions "$HOME/.mistral_api_key"
218+
fi
254219

255-
unset SETUP_MISTRAL_KEY
220+
elif [[ "$STORE_RESULT" == "SUCCESS:USPTO_ONLY" ]]; then
221+
log_success "USPTO API key stored in secure storage"
222+
log_info " Location: ~/.uspto_api_key"
223+
log_info " Permissions: 600 (owner read/write only)"
256224

257-
if [[ "$STORE_RESULT" == "SUCCESS" ]]; then
258-
log_success "Mistral API key stored in secure storage"
259-
log_info " Location: ~/.mistral_api_key"
260-
log_info " Permissions: 600 (owner read/write only)"
261-
log_audit "Mistral API key configured via linux_setup.sh"
262-
else
263-
log_warning "Failed to store Mistral API key: $STORE_RESULT"
225+
# CRITICAL SECURITY: Set file permissions on USPTO API key file
226+
if [ -f "$HOME/.uspto_api_key" ]; then
227+
set_secure_file_permissions "$HOME/.uspto_api_key"
264228
fi
229+
230+
else
231+
log_error "Failed to store API keys: $STORE_RESULT"
232+
exit 1
265233
fi
266234

267235
# CRITICAL: Clear sensitive variables from memory
@@ -270,10 +238,6 @@ unset MISTRAL_API_KEY
270238
unset SETUP_USPTO_KEY
271239
unset SETUP_MISTRAL_KEY
272240

273-
echo ""
274-
log_success "API keys stored securely - NOT in Claude Code config file!"
275-
log_info "Keys will be loaded automatically from encrypted storage at runtime"
276-
277241
# Step 7: PFW MCP Detection
278242
echo ""
279243
log_info "USPTO MCP Ecosystem Integration"
@@ -448,67 +412,61 @@ except Exception as e:
448412
fi
449413

450414
log_success "Claude Code configuration complete!"
451-
log_audit "Claude Code configured via linux_setup.sh (no API keys in config)"
415+
416+
# Display configuration method used
417+
echo ""
418+
log_success "Security Configuration:"
419+
log_info " - USPTO API key stored in secure storage: ~/.uspto_api_key"
420+
if [ -f "$HOME/.mistral_api_key" ]; then
421+
log_info " - Mistral API key stored in secure storage: ~/.mistral_api_key"
422+
fi
423+
log_info " - File permissions: 600 (owner read/write only)"
424+
log_info " - API keys NOT in Claude Desktop config file"
425+
log_info " - Config directory permissions: 700 (owner only)"
426+
log_info " - Shared storage across all USPTO MCPs (PFW/PTAB/FPD/Citations)"
452427
else
453-
log_info "Skipping Claude Code configuration"
454-
log_info "You can manually configure later"
428+
log_info "Skipping Claude Code configuration"
429+
log_info "You can manually configure later by editing $CLAUDE_CONFIG_FILE"
430+
log_info "See README.md for configuration template"
455431
fi
456432

457-
echo ""
458-
echo "=========================================="
459-
log_success "Linux setup complete!"
460-
echo "=========================================="
461433
echo ""
462434

435+
# Step 9: Final Summary
436+
echo -e "${GREEN}[OK] Linux setup complete!${NC}"
463437
log_warning "Please restart Claude Code to load the MCP server"
464-
echo ""
465438

466-
log_info "Configuration Summary:"
467439
echo ""
468-
log_success "✓ USPTO API Key: Stored in encrypted secure storage"
469-
log_info " File: ~/.uspto_api_key (permissions: 600)"
470-
log_info " Encryption: File permissions + Linux security"
471-
440+
log_info "Configuration Summary:"
441+
log_success "USPTO API Key: Stored in secure storage (~/.uspto_api_key)"
472442
if [ -f "$HOME/.mistral_api_key" ]; then
473-
log_success "✓ Mistral API Key: Stored in encrypted secure storage"
474-
log_info " File: ~/.mistral_api_key (permissions: 600)"
475-
log_info " OCR: Enabled"
443+
log_success "Mistral API Key: Stored in secure storage (~/.mistral_api_key)"
476444
else
477-
log_info "Mistral API Key: Not configured (OCR disabled)"
445+
log_warning "Mistral API Key: Not configured (optional - for OCR)"
478446
fi
447+
log_success "Dependencies: Installed"
448+
log_success "Package: Available as command"
449+
log_success "Installation Directory: $PROJECT_DIR"
450+
log_success "Security: File permissions 600 (owner only)"
451+
log_success "Security: Config directory permissions 700 (owner only)"
479452

480453
echo ""
481-
log_success "✓ Installation Directory: $PROJECT_DIR"
482-
echo ""
483-
484-
if [ -f "$HOME/.claude.json" ]; then
485-
log_success "✓ Claude Code config: $HOME/.claude.json"
486-
log_info " API keys: NOT in config (loaded from secure storage)"
487-
488-
# Verify permissions
489-
PERMS=$(stat -c '%a' "$HOME/.claude.json" 2>/dev/null || stat -f '%A' "$HOME/.claude.json" 2>/dev/null)
490-
log_info " Permissions: $PERMS"
491-
else
492-
log_info "ℹ Claude Code config: Not configured"
493-
fi
454+
log_info "Test the server:"
455+
echo " uv run fpd-mcp --help"
494456

495457
echo ""
496-
log_info "Security Features:"
497-
echo " ✓ API keys stored in encrypted secure storage (NOT plain text)"
498-
echo " ✓ File permissions: 600 on all sensitive files"
499-
echo " ✓ Directory permissions: 700 on config directories"
500-
echo " ✓ API key format validation (prevents typos)"
501-
echo " ✓ Audit logging enabled (~/.uspto_mcp_audit.log)"
502-
echo ""
458+
log_info "Test with Claude Code:"
459+
echo " Ask Claude: 'Use fpd_search_petitions_minimal to search for petitions'"
460+
echo " Ask Claude: 'Use fpd_get_tool_reflections to learn about FPD MCP features'"
503461

504-
log_info "Test the server:"
505-
echo " uv run fpd-mcp --help"
506462
echo ""
463+
log_info "Verify MCP is running:"
464+
echo " claude mcp list"
507465

508-
log_info "Test with Claude Code:"
509-
echo " Ask Claude: 'Use fpd_search_petitions_minimal to search for patents'"
510466
echo ""
467+
log_info "Manage API keys later:"
468+
echo " (Future enhancement - currently use deployment script to update)"
511469

512-
log_info "Manage API keys:"
513-
echo " Run: ./deploy/manage_api_keys.ps1 (Windows) or edit secure storage files"
470+
echo ""
471+
echo -e "${GREEN}=== Setup Complete! ===${NC}"
514472
echo ""

0 commit comments

Comments
 (0)