Commit f73b2a7
Add MCP install command and next steps after login (#26)
* Add tiger mcp install command specification
- Add new `tiger mcp install <editor>` command to automate MCP configuration
- Support for claude-code/claude and cursor editors
- Automatic detection of configuration file locations
- Backup creation by default with --no-backup option
- Custom configuration path support with --config-path
- Merges with existing MCP server configurations
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Implement tiger mcp install command with toolhive integration
- Add complete MCP install functionality in mcp_install.go
- Support for Claude Code, Cursor, and Windsurf editors
- Use toolhive library for client discovery and configuration
- Implement robust JSON patching with hujson for config updates
- Add file locking for concurrent safety using gofrs/flock
- Use atomic writes with renameio/v2 for data integrity
- Create config-driven editor mapping for maintainability
- Add dynamic help text generation from supported clients config
- Optimize to skip toolhive discovery when explicit config path provided
- Move directory creation into addTigerMCPServer for better organization
- Add comprehensive error handling and validation
- Include proper Apache License 2.0 attribution for toolhive code
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Implement timestamp-based backup naming to prevent overwrites
- Modify createConfigBackup to return actual backup path created
- Use Unix timestamp in backup filename (config.backup.1758790175)
- Update success message to show actual backup filename with timestamp
- Ensure unique backups on each run without overwriting previous ones
- Simplify backup logic compared to incremental numbering approach
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add Codex MCP support with generic CLI-based installation framework
- Create TigerMCPClient enum to handle both toolhive and custom clients
- Add InstallCommand and ConfigPaths fields to clientConfig for flexibility
- Implement generic addTigerMCPServerViaCLI for any CLI-based MCP installation
- Add Codex support using `codex mcp add tigerdata tiger mcp` command
- Support CODEX_HOME environment variable and ~/.codex/config.toml fallback
- Refactor installation logic to use presence of InstallCommand vs toolhive approach
- Add path expansion utilities for environment variables and home directory
- Create config-driven approach that makes adding new CLI clients trivial
Key improvements:
- Installation method determined by InstallCommand presence (not toolhive absence)
- Config discovery determined by ConfigPaths presence (not toolhive absence)
- More explicit and intention-revealing conditional logic
- Unified framework supports both JSON patching and CLI command approaches
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove toolhive dependency from MCP install system
- Replace toolhive discovery with internal ConfigPaths system for all clients
- Migrate ClaudeCode, Cursor, and Windsurf to use ConfigPaths instead of toolhive
- Remove unused toolhive imports and struct fields from production code
- Add comprehensive tests validating ConfigPaths equivalence and fallback behavior
- Simplify client configuration by removing ToolhiveClientType field
- Maintain toolhive dependency only for test validation (test-only import)
- Add safety check for clients missing both ConfigPaths and InstallCommand
All clients now use internal systems: ConfigPaths for JSON clients, CLI commands for others.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Clean up naming and migrate ClaudeCode to CLI-based installation
- Rename TigerMCPClient type to MCPClient for cleaner naming
- Rename TigerClientType field to ClientType in all configurations
- Remove Tiger prefix from all constants: ClaudeCode, Cursor, Windsurf, Codex
- Migrate ClaudeCode to use InstallCommand with claude CLI instead of JSON manipulation
- Keep ConfigPaths for ClaudeCode to support backup functionality
- Remove MCPServersPathPrefix for CLI-based clients (ClaudeCode, Codex)
System now uses CLI commands for ClaudeCode and Codex, JSON manipulation for Cursor and Windsurf.
All clients maintain ConfigPaths for backup discovery regardless of installation method.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add comprehensive test coverage for MCP install functions
- Add 100% coverage for mapEditorToTigerClientType, findOurClientConfig,
addTigerMCPServerViaCLI, and findClientConfigFile functions
- Add 90%+ coverage for ensurePathExists function
- Add integration tests for installMCPForEditor using Cursor JSON config
- Improve overall package coverage from 58.2% to 62.3%
- Add tests for edge cases, error handling, and boundary conditions
- Include comprehensive validation of client config structure
- Add environment variable and path expansion testing
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Enhance MCP install success message with comprehensive usage examples
- Add structured examples showing users what they can ask their AI assistant
- Organize capabilities into three clear categories:
• Service management (list, create, manage TigerData services)
• Documentation queries (PostgreSQL and TigerData docs access)
• AI guides for common workflows (schema creation, hypertables setup)
- Update MCP server command to use "mcp start" for proper server initialization
- Improve user onboarding by providing concrete, actionable examples
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use full Tiger executable path in MCP server configurations
- Add getTigerExecutablePath() function to get current executable path
- Update addTigerMCPServer() to use full path instead of assuming "tiger" in PATH
- Update addTigerMCPServerViaCLI() to replace "tiger" placeholder with full path
- Ensures MCP server configurations work regardless of PATH environment
- Fixes potential issues when Tiger is not globally installed or accessible
This prevents MCP server startup failures when the "tiger" command is not
available in the user's PATH environment variable.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add interactive editor selection to MCP install command
- Change 'tiger mcp install <editor>' to 'tiger mcp install [editor]'
- Add Bubble Tea-based interactive chooser when no editor specified
- Support same navigation as project picker (arrows, numbers, q to quit)
- Display editors in alphabetical order for consistent UX
- Maintain backward compatibility with explicit editor arguments
- Clean, minimal display showing just editor names without redundant descriptions
Users can now run 'tiger mcp install' for interactive selection or continue
using 'tiger mcp install <editor>' for direct installation.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add Gemini CLI and VS Code support, fix CLI-only client handling
- Add Gemini CLI with 'gemini mcp add -s user' command format
- Add VS Code with 'code --add-mcp' JSON command format
- Fix logic to properly handle CLI-only clients with empty ConfigPaths
- Skip backup creation for CLI-only clients (no config file to backup)
- Improve success messages for CLI-only vs JSON-based clients
- Add go run detection to use 'tiger' instead of temp executable paths
- Support JSON command argument replacement for VS Code format
- New clients available in interactive chooser: Gemini CLI, VS Code
Fixes issue where CLI-only clients would error out due to empty ConfigPaths
before reaching InstallCommand logic. Now supports hybrid approach where
clients can have both config paths (for backup) and install commands.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix test failures and improve function naming for MCP installation
- Rename addTigerMCPServer to addTigerMCPServerViaJSON for clarity
- Add testing.Testing() detection to return "tiger" for consistent test results
- Update all test expectations to match new "mcp start" args format
- Fix client config validation to allow empty ConfigPaths for CLI-only clients
- Ensure all tests pass with new Gemini CLI and VS Code support
This commit resolves test failures caused by:
1. Dynamic executable paths in test environments
2. Updated MCP server command arguments
3. New CLI-only client validation requirements
All tests now pass consistently across different environments while
maintaining production functionality with full executable paths.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add helpful next steps message after successful login
After a user successfully logs in via 'tiger auth login', display a message with suggested next steps:
- Install MCP server for AI coding tools
- List existing services
- Create a new service
This helps guide users on what to do after authentication.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Address PR feedback for MCP installation command
- Remove testing package import from production code
- Refactor getTigerExecutablePath to use function variable for test overrides
- Update tests to override the function instead of using testing.Testing()
- Add ValidArgs field for better shell completions
- Dynamically generate ValidArgs from supportedClients configuration
- Improves tab completion experience for users
- Fix alias display formatting in help text
- Simplify to only show primary client name
- Remove confusing nested parentheses formatting
- Update terminology from "editor" to "client"
- Support broader MCP client types beyond just code editors
- Rename functions, variables, and user-facing text consistently
- Update error messages and help text
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove 'claude' alias to differentiate Claude Code from Claude Desktop
- Remove 'claude' from Claude Code EditorNames array
- Keep only 'claude-code' as the supported name
- Update help text examples to remove 'claude' alias
- Update tests to remove 'claude' test cases
This clarifies that Claude Code and Claude Desktop are separate clients
with different configuration methods.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Consolidate client lookup functions to reduce code duplication
- Merge mapClientToTigerClientType and findOurClientConfig into single findClientConfig function
- Both functions were looping over supportedClients separately
- New function directly returns *clientConfig from client name in one pass
- Update all tests to use consolidated function
- Simplifies code and improves performance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove outdated toolhive references from comments
- Remove "extends beyond toolhive support" from MCPClient comment
- Update "toolhive-supported clients" to "JSON-config clients"
- Keep toolhive reference in supportedClients comment as it's still useful
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Simplify conditional logic by removing no-op branch
- Convert InstallCommand check from positive to negative condition
- Remove redundant assignment of empty string to configPath
- Make code flow clearer by checking for error case directly
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Change config path selection to use first path as default
Updated the logic to use the first path in ConfigPaths array as the
default when no existing config file is found, instead of using the
last path. This follows a more intuitive "priority order" pattern where
the preferred default path is listed first.
Changes:
- Reversed Codex ConfigPaths order to put default first
- Updated findClientConfigFile to use configPaths[0] instead of last
- Updated tests to expect first path as default
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Omit empty MCPServersPathPrefix fields in client configs
Removed explicit empty string assignments for MCPServersPathPrefix in
CLI-based client configs (Claude Code, Codex, Gemini, VS Code). These
clients don't use JSON path manipulation so the field can be omitted
entirely, making the config cleaner and the distinction clearer.
The field is still present and populated for JSON-config clients
(Cursor, Windsurf) where it's actually used.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use filepath.Clean to normalize paths for cross-platform compatibility
Added filepath.Clean after path expansion to ensure proper path
normalization on Windows. Also added empty string check to preserve
empty path behavior (Clean converts "" to ".").
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Replace os.IsNotExist with errors.Is(err, fs.ErrNotExist)
Updated to use the modern error checking pattern as recommended by Go docs.
The os.IsNotExist function predates errors.Is and only supports errors
from the os package.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Check for fs.ErrNotExist before using empty JSON fallback
Added proper error checking before falling back to empty JSON. If the
error is something other than file not existing (e.g., permission
denied), we should return the error instead of overwriting the file
with an empty object.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove renameio dependency for Windows compatibility
Replaced renameio.WriteFile with os.WriteFile. The renameio library
doesn't work on Windows, and atomic writes aren't critical here since:
1. We don't use atomic writes elsewhere in the codebase
2. The file locking already prevents concurrent modifications
3. Simpler code is preferable
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove flock dependency to simplify code
Removed file locking as it:
1. Only prevents concurrent Tiger CLI instances, not other programs
2. Users won't run `tiger mcp install` concurrently in practice
3. Lock files may not be cleaned up if program exits unexpectedly
4. Has platform-specific behaviors that can cause issues
Simpler code is more maintainable and eliminates a dependency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove gjson dependency and simplify JSON manipulation
Replaced gjson with hujson's built-in Find method for checking path
existence. This reduces dependencies while maintaining functionality.
- Removed the ensurePathExists function entirely
- Use hujson.Find() to check if parent path exists
- Only create parent path if it doesn't exist
- Added test to verify multiple sibling servers are preserved
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Refactor: Move password storage to dedicated package and consolidate path expansion
This commit addresses PR review feedback by restructuring the codebase to eliminate import cycles
and consolidate duplicate functionality:
- Move password storage functionality from util to new dedicated password package
- Breaks import cycle: util tests → api → config → util
- Create shared util/path.go for path expansion logic
- Remove duplicate expandPath implementations from config and mcp_install
- Update all imports to use new password package structure
- Fix test types to avoid cross-package dependencies
The restructuring improves code organization and maintainability while resolving
circular dependency issues that emerged during testing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix Claude Code MCP installation to use User scope
The Claude CLI defaults to Local scope when adding MCP servers, but we want
Tiger MCP to be available across all projects. This commit adds the `-s user`
flag to ensure User scope installation.
Also clarified in the help text that Claude Code installs with User scope.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update MCP spec to list all supported editors
The spec now includes all 6 editors/clients that the MCP install command supports:
- Claude Code
- Cursor
- Windsurf
- Codex
- Gemini CLI
- VS Code
Also added the interactive editor selection option to the examples section.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Address Copilot PR feedback for MCP install command
- Fix spec_mcp.md examples to show correct args ["mcp", "start"]
- Add comprehensive idempotency test verifying config value updates
- Fix loop variable pointer issue in findClientConfig
- Update misleading comment about file locking
- Add proper error handling for os.UserHomeDir in path.go
- Fix test comment from "last path" to "first path"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Address latest Copilot and Nathan's PR feedback
Copilot feedback:
- Expand --config-path for ~ and environment variables
- Preserve original file permissions for backups and config files
- Use UnixNano timestamps for backups to avoid collisions
- Use getValidEditorNames() instead of duplicated code
Nathan's feedback:
- Unify ExpandPath error handling (both cases use if err == nil)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix comment grammar per Copilot nitpick
- Capitalize acronyms (IDE, CLI)
- Add space after //
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Address remaining PR feedback
- Update spec to recommend CLI install instead of manual config
- Make ESC key quit the editor selector (matches help text)
- Fix backup test to expect preserved file permissions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Refactor MCP install command builder to use function-based approach
Replace static InstallCommand arrays with buildInstallCommand functions
to avoid ambiguity between binary name and server name (both "tiger").
Changes:
- Add buildInstallCommand function field to clientConfig
- Replace static command arrays with builder functions that take tigerPath
- Remove complex string replacement logic from addTigerMCPServerViaCLI
- Update all client configs to use builder functions
- Change server name from "tigerdata" to "tiger" for consistency
- Export ServerName constant for reuse across packages
- Update tests to use new builder pattern
- Update spec documentation to recommend CLI install approach
This ensures server name and binary path are explicitly constructed
in the right positions, preventing accidental replacement of the
server name with the full binary path.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 460a6ef commit f73b2a7
File tree
20 files changed
+2282
-165
lines changed- internal/tiger
- cmd
- config
- mcp
- password
- util
- specs
20 files changed
+2282
-165
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
12 | | - | |
13 | | - | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
14 | 19 | | |
15 | | - | |
| 20 | + | |
16 | 21 | | |
17 | | - | |
18 | | - | |
| 22 | + | |
| 23 | + | |
19 | 24 | | |
20 | 25 | | |
21 | 26 | | |
22 | 27 | | |
23 | | - | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
24 | 33 | | |
25 | 34 | | |
| 35 | + | |
26 | 36 | | |
27 | 37 | | |
28 | | - | |
| 38 | + | |
29 | 39 | | |
30 | 40 | | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
31 | 44 | | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
32 | 53 | | |
| 54 | + | |
| 55 | + | |
33 | 56 | | |
34 | | - | |
35 | | - | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
36 | 62 | | |
37 | | - | |
38 | | - | |
39 | | - | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
40 | 82 | | |
41 | | - | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
42 | 88 | | |
| 89 | + | |
| 90 | + | |
43 | 91 | | |
44 | 92 | | |
45 | 93 | | |
46 | 94 | | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
47 | 98 | | |
48 | | - | |
49 | | - | |
| 99 | + | |
| 100 | + | |
50 | 101 | | |
51 | 102 | | |
52 | 103 | | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
53 | 109 | | |
54 | 110 | | |
55 | 111 | | |
56 | 112 | | |
| 113 | + | |
| 114 | + | |
57 | 115 | | |
58 | 116 | | |
59 | 117 | | |
60 | 118 | | |
61 | | - | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
62 | 122 | | |
| 123 | + | |
| 124 | + | |
63 | 125 | | |
64 | | - | |
65 | | - | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
66 | 129 | | |
67 | 130 | | |
68 | | - | |
69 | | - | |
70 | | - | |
| 131 | + | |
| 132 | + | |
71 | 133 | | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
72 | 140 | | |
| 141 | + | |
73 | 142 | | |
74 | 143 | | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
75 | 150 | | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
82 | 169 | | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
83 | 180 | | |
0 commit comments