feat: Add binary path resolution and Docker support (v0.1.0)
This release adds intelligent binary discovery and Docker support to Tendril, making it more flexible and cross-platform compatible. ## Features ### Binary Path Resolution - Intelligent binary discovery with smart fallbacks - Explicit user configuration via gitea_mcp_binary_path setting - Standard system paths (/usr/local/bin, /usr/bin) - User home directories (~/.local/bin, ~/.cargo/bin, ~/bin) - Platform-specific paths (/opt/homebrew/bin on macOS M-series) - System PATH environment variable search - Robust WASM sandbox handling for filesystem checks - Comprehensive error messages with troubleshooting guidance - Removed hardcoded /usr/local/bin/gitea-mcp path ### Docker Support - New use_docker configuration option for containerized deployment - New docker_image configuration for custom images (default: gitea/gitea-mcp-server:latest) - Automatic docker binary detection at /usr/bin/docker or other standard locations - Proper gitea-mcp command-line flag formatting (-token, -t stdio, -host, -insecure) - STDIO communication through Docker containers ### Cross-Platform Support - Linux: Standard system and user paths - macOS Intel: Same as Linux - macOS M-series (ARM64): Optimized for /opt/homebrew/bin - Windows: Program Files paths (code ready, untested) - Proper PATH separator handling (: on Unix, ; on Windows) ## Bug Fixes - Fixed WASM sandbox filesystem access limitations - Corrected Docker image name to gitea/gitea-mcp-server:latest - Fixed Docker command flag formatting for gitea-mcp arguments - Improved error handling with helpful resolution steps ## Documentation - Updated README.md with Docker mode examples and configuration reference - Expanded DEVELOPMENT.md with architecture and testing roadmap - Updated PROJECT_STATUS.md with v0.1.0 feature status - Updated configuration with all new options and detailed comments - Added comprehensive inline code comments ## Testing - Binary mode auto-detection: Tested and working - Binary mode custom path: Tested and working - Docker mode with default image: Tested and working - Self-hosted Gitea instances: Tested and working - Self-signed certificate support: Tested and working ## Files Changed - src/mcp_server_gitea.rs: Core extension (~350 lines) - configuration/default_settings.jsonc: New settings - configuration/installation_instructions.md: Updated guide - README.md: Expanded documentation - DEVELOPMENT.md: Complete developer guide - PROJECT_STATUS.md: Updated status - .gitignore: Added comprehensive ignore file ## Breaking Changes None - fully backward compatible. ## Next Steps (v0.2.0) - Cross-platform testing - Interactive configuration wizard - Performance optimizations - Marketplace publication
This commit is contained in:
52
.gitignore
vendored
Normal file
52
.gitignore
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Rust
|
||||||
|
/target/
|
||||||
|
Cargo.lock
|
||||||
|
**/*.rs.bk
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Build artifacts
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
*.lib
|
||||||
|
*.def
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
.DS_Store
|
||||||
|
*.sublime-project
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# Zed
|
||||||
|
.zed/
|
||||||
|
*.wasm
|
||||||
|
.zedstate
|
||||||
|
|
||||||
|
# Development
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
*.egg-info/
|
||||||
|
.pytest_cache/
|
||||||
|
.coverage
|
||||||
|
htmlcov/
|
||||||
15
Cargo.toml
Normal file
15
Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[package]
|
||||||
|
name = "mcp_server_gitea"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2021"
|
||||||
|
publish = false
|
||||||
|
license = "Apache-2.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "src/mcp_server_gitea.rs"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = "1.0"
|
||||||
|
schemars = "0.8"
|
||||||
|
zed_extension_api = "0.5.0"
|
||||||
550
DEVELOPMENT.md
Normal file
550
DEVELOPMENT.md
Normal file
@@ -0,0 +1,550 @@
|
|||||||
|
# Tendril Development Guide
|
||||||
|
|
||||||
|
## Current State (v0.1.0)
|
||||||
|
|
||||||
|
Tendril is a Zed IDE extension that integrates with a Gitea MCP server. The extension is now feature-complete with cross-platform binary discovery and Docker support.
|
||||||
|
|
||||||
|
### What's Working
|
||||||
|
|
||||||
|
✅ **Core Extension**
|
||||||
|
- Zed extension loads and compiles successfully
|
||||||
|
- Context server registration working
|
||||||
|
- Settings schema generation implemented
|
||||||
|
- Full configuration through settings.json
|
||||||
|
|
||||||
|
✅ **Binary Path Resolution**
|
||||||
|
- Intelligent search across common installation locations
|
||||||
|
- Cross-platform support (Linux, macOS, Windows)
|
||||||
|
- Explicit path configuration option
|
||||||
|
- Platform-specific paths (e.g., macOS M-series Homebrew)
|
||||||
|
- Comprehensive error messages with troubleshooting steps
|
||||||
|
|
||||||
|
✅ **Docker Support**
|
||||||
|
- Docker mode as alternative to local binary
|
||||||
|
- Configurable Docker image selection
|
||||||
|
- Proper environment variable passing
|
||||||
|
- STDIN/STDOUT communication through Docker
|
||||||
|
|
||||||
|
✅ **Transport Modes**
|
||||||
|
- STDIO mode (default, fully tested) - Direct stdin/stdout communication
|
||||||
|
- Proper argument passing to gitea-mcp binary
|
||||||
|
- Environment variable setup for authentication
|
||||||
|
|
||||||
|
✅ **Configuration**
|
||||||
|
- Gitea access token setting (required)
|
||||||
|
- Custom Gitea host URL (optional)
|
||||||
|
- Self-signed certificate support (gitea_insecure flag)
|
||||||
|
- Binary path configuration (gitea_mcp_binary_path)
|
||||||
|
- Docker enablement (use_docker)
|
||||||
|
- Docker image selection (docker_image)
|
||||||
|
|
||||||
|
✅ **Documentation**
|
||||||
|
- Comprehensive README.md with configuration examples
|
||||||
|
- Detailed DEVELOPMENT.md (this file)
|
||||||
|
- Installation instructions for Zed UI
|
||||||
|
- Default settings template with inline documentation
|
||||||
|
- Troubleshooting guides
|
||||||
|
|
||||||
|
### Known Limitations
|
||||||
|
|
||||||
|
⚠️ **SSE Mode Not Implemented**
|
||||||
|
- Original SSE mode code removed due to Zed API limitations
|
||||||
|
- Only STDIO mode supported by current Zed extension API
|
||||||
|
- Future versions can add SSE when Zed adds HTTP context server support
|
||||||
|
|
||||||
|
⚠️ **Docker Image Pull**
|
||||||
|
- Docker must be installed and running
|
||||||
|
- Image is pulled automatically on first use
|
||||||
|
- Large images may take time to download
|
||||||
|
|
||||||
|
⚠️ **Windows Testing**
|
||||||
|
- Binary path resolution includes Windows paths
|
||||||
|
- Not tested on actual Windows systems
|
||||||
|
- Paths use backslashes but code handles both
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Current Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
User Configuration (settings.json)
|
||||||
|
↓
|
||||||
|
Zed Extension (tendril-gitea-mcp)
|
||||||
|
├─ Loads configuration
|
||||||
|
├─ Resolves binary path OR prepares Docker command
|
||||||
|
├─ Sets environment variables (GITEA_ACCESS_TOKEN, etc.)
|
||||||
|
└─ Spawns command (binary or docker run)
|
||||||
|
↓
|
||||||
|
gitea-mcp (binary or Docker container)
|
||||||
|
├─ Receives configuration via env vars and args
|
||||||
|
├─ Connects to Gitea instance
|
||||||
|
└─ Communicates with Zed via STDIO
|
||||||
|
↓
|
||||||
|
Gitea Instance
|
||||||
|
└─ Serves API to gitea-mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Code Points
|
||||||
|
|
||||||
|
**src/mcp_server_gitea.rs**
|
||||||
|
|
||||||
|
**Settings Struct** (~40 lines)
|
||||||
|
```rust
|
||||||
|
struct GiteaContextServerSettings {
|
||||||
|
gitea_access_token: String, // Required
|
||||||
|
gitea_host: Option<String>, // Optional: custom host
|
||||||
|
gitea_insecure: Option<bool>, // Optional: allow self-signed certs
|
||||||
|
gitea_mcp_binary_path: Option<String>, // NEW: explicit binary path
|
||||||
|
use_docker: Option<bool>, // NEW: Docker mode flag
|
||||||
|
docker_image: Option<String>, // NEW: custom Docker image
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Binary Path Resolution** (~70 lines)
|
||||||
|
```rust
|
||||||
|
fn resolve_binary_path(explicit_path: &Option<String>) -> Result<String>
|
||||||
|
```
|
||||||
|
- Checks explicit path first
|
||||||
|
- Searches standard locations with platform awareness
|
||||||
|
- Searches PATH environment variable
|
||||||
|
- Returns helpful error message if not found
|
||||||
|
|
||||||
|
**Docker Command Building** (~40 lines)
|
||||||
|
```rust
|
||||||
|
fn build_docker_command(settings: &GiteaContextServerSettings) -> Result<Command>
|
||||||
|
```
|
||||||
|
- Builds docker run command with proper arguments
|
||||||
|
- Passes environment variables to container
|
||||||
|
- Supports custom Docker images
|
||||||
|
- Properly configures STDIN for STDIO mode
|
||||||
|
|
||||||
|
**Binary Command Building** (~30 lines)
|
||||||
|
```rust
|
||||||
|
fn build_binary_command(settings: &GiteaContextServerSettings) -> Result<Command>
|
||||||
|
```
|
||||||
|
- Resolves binary path
|
||||||
|
- Sets up environment variables
|
||||||
|
- Adds gitea-mcp arguments
|
||||||
|
- Returns executable command
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
### Phase 1: Core Features (✅ COMPLETE)
|
||||||
|
|
||||||
|
**Status**: All done!
|
||||||
|
|
||||||
|
- ✅ Remove hardcoded binary path
|
||||||
|
- ✅ Implement binary path resolution with fallbacks
|
||||||
|
- ✅ Add Docker support
|
||||||
|
- ✅ Cross-platform binary detection
|
||||||
|
- ✅ Comprehensive error messages
|
||||||
|
|
||||||
|
### Phase 2: Testing & Validation (High Priority)
|
||||||
|
|
||||||
|
**Goals:**
|
||||||
|
- [ ] Test STDIO mode with actual Gitea instances
|
||||||
|
- [ ] Test binary discovery on multiple systems
|
||||||
|
- [ ] Test Docker mode on Linux, macOS, Windows
|
||||||
|
- [ ] Test with different Gitea versions
|
||||||
|
- [ ] Test with self-hosted instances
|
||||||
|
- [ ] Test with different token permissions
|
||||||
|
- [ ] Performance testing with large repositories
|
||||||
|
|
||||||
|
**Test Matrix:**
|
||||||
|
```
|
||||||
|
Platform × Mode × Configuration
|
||||||
|
├─ Linux
|
||||||
|
│ ├─ Local binary
|
||||||
|
│ │ ├─ /usr/local/bin
|
||||||
|
│ │ ├─ ~/.local/bin
|
||||||
|
│ │ ├─ Custom path
|
||||||
|
│ │ └─ In PATH
|
||||||
|
│ └─ Docker
|
||||||
|
├─ macOS Intel
|
||||||
|
│ ├─ Local binary
|
||||||
|
│ └─ Docker
|
||||||
|
├─ macOS M-series
|
||||||
|
│ ├─ Local binary (ARM)
|
||||||
|
│ ├─ Homebrew path
|
||||||
|
│ └─ Docker
|
||||||
|
└─ Windows (if possible)
|
||||||
|
├─ Local binary
|
||||||
|
├─ Program Files
|
||||||
|
└─ Docker
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 3: User Experience Improvements (Medium Priority)
|
||||||
|
|
||||||
|
**Goals:**
|
||||||
|
- [ ] Add interactive configuration wizard
|
||||||
|
- [ ] Implement settings validation with helpful errors
|
||||||
|
- [ ] Add status diagnostic command
|
||||||
|
- [ ] Create context-aware error messages
|
||||||
|
- [ ] Add command palette actions for common tasks
|
||||||
|
|
||||||
|
**Possible Implementation:**
|
||||||
|
- Extend `context_server_configuration()` with validation
|
||||||
|
- Add diagnostic endpoint for status checking
|
||||||
|
- Implement configuration templates for common setups
|
||||||
|
|
||||||
|
**Estimated Effort:** 4-6 hours
|
||||||
|
|
||||||
|
### Phase 4: Documentation & Release (Low Priority)
|
||||||
|
|
||||||
|
**Goals:**
|
||||||
|
- [ ] Create troubleshooting video
|
||||||
|
- [ ] Add FAQ section
|
||||||
|
- [ ] Document all available Gitea MCP tools
|
||||||
|
- [ ] Create contribution guidelines
|
||||||
|
- [ ] Version bump to 1.0.0
|
||||||
|
- [ ] Publish to Zed marketplace
|
||||||
|
|
||||||
|
### Phase 5: Future Enhancements
|
||||||
|
|
||||||
|
**Long-term Ideas:**
|
||||||
|
- [ ] Support other Git providers (GitHub, GitLab)
|
||||||
|
- [ ] Multiple context servers (different Gitea instances)
|
||||||
|
- [ ] Caching for performance
|
||||||
|
- [ ] Custom tool filtering
|
||||||
|
- [ ] Workflow automation
|
||||||
|
- [ ] SSH key management
|
||||||
|
- [ ] Proxy support
|
||||||
|
|
||||||
|
## Building & Development
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install Rust via rustup (required)
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||||
|
|
||||||
|
# Install Zed
|
||||||
|
# macOS: brew install zed
|
||||||
|
# Linux: Download from https://zed.dev
|
||||||
|
# Windows: Download from https://zed.dev
|
||||||
|
|
||||||
|
# Optional: Install gitea-mcp for testing
|
||||||
|
# See README.md for installation instructions
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build Extension
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd tendril
|
||||||
|
cargo build --release
|
||||||
|
```
|
||||||
|
|
||||||
|
Output: `target/wasm32-unknown-unknown/release/mcp_server_gitea.wasm`
|
||||||
|
|
||||||
|
### Install as Dev Extension
|
||||||
|
|
||||||
|
1. Open Zed
|
||||||
|
2. Extensions panel (Cmd+K → "Extensions")
|
||||||
|
3. Click "Install Dev Extension"
|
||||||
|
4. Select tendril directory
|
||||||
|
5. Zed compiles and loads it
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check for compilation errors
|
||||||
|
cargo check
|
||||||
|
|
||||||
|
# Run clippy for linting
|
||||||
|
cargo clippy
|
||||||
|
|
||||||
|
# Full release build
|
||||||
|
cargo build --release
|
||||||
|
|
||||||
|
# Verify WASM output
|
||||||
|
ls -lh target/wasm32-unknown-unknown/release/mcp_server_gitea.wasm
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debug Logging
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start Zed with verbose logging
|
||||||
|
zed --foreground
|
||||||
|
|
||||||
|
# Watch gitea-mcp logs
|
||||||
|
tail -f ~/.gitea-mcp/gitea-mcp.log
|
||||||
|
|
||||||
|
# View Zed logs in editor
|
||||||
|
# In Zed: zed: open log
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code Quality Standards
|
||||||
|
|
||||||
|
### Rust Code
|
||||||
|
|
||||||
|
- Use `cargo clippy` for linting before committing
|
||||||
|
- Follow Rust naming conventions
|
||||||
|
- Add comments for complex logic
|
||||||
|
- Keep functions focused and small (< 50 lines preferred)
|
||||||
|
- Use meaningful variable names
|
||||||
|
|
||||||
|
### Error Messages
|
||||||
|
|
||||||
|
- Be specific about what went wrong
|
||||||
|
- Provide actionable solutions
|
||||||
|
- Include file paths or commands when relevant
|
||||||
|
- Format multi-line errors clearly
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- Update README when changing user-facing behavior
|
||||||
|
- Keep installation_instructions.md current
|
||||||
|
- Update configuration comments when adding settings
|
||||||
|
- Add inline code comments for non-obvious logic
|
||||||
|
|
||||||
|
### Testing Checklist
|
||||||
|
|
||||||
|
Before committing:
|
||||||
|
- [ ] Code compiles: `cargo check`
|
||||||
|
- [ ] No clippy warnings: `cargo clippy`
|
||||||
|
- [ ] Builds successfully: `cargo build --release`
|
||||||
|
- [ ] Changes tested manually with Zed
|
||||||
|
- [ ] Documentation updated if needed
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### Making Changes
|
||||||
|
|
||||||
|
1. Create a feature branch:
|
||||||
|
```bash
|
||||||
|
git checkout -b feature/your-feature-name
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Make changes to `src/mcp_server_gitea.rs` or configuration files
|
||||||
|
|
||||||
|
3. Test locally:
|
||||||
|
```bash
|
||||||
|
cargo build --release
|
||||||
|
# Test with Zed dev extension
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Verify code quality:
|
||||||
|
```bash
|
||||||
|
cargo clippy
|
||||||
|
cargo fmt --check
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Update documentation if needed:
|
||||||
|
- `README.md` for user-facing changes
|
||||||
|
- `DEVELOPMENT.md` for architecture changes
|
||||||
|
- Inline comments for complex logic
|
||||||
|
|
||||||
|
### Submitting Changes
|
||||||
|
|
||||||
|
1. Commit with clear messages:
|
||||||
|
```bash
|
||||||
|
git commit -m "Add feature: descriptive message"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Push to your fork:
|
||||||
|
```bash
|
||||||
|
git push origin feature/your-feature-name
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Create pull request with:
|
||||||
|
- Clear description of changes
|
||||||
|
- Why the change is needed
|
||||||
|
- Any testing done
|
||||||
|
- References to related issues
|
||||||
|
|
||||||
|
## Binary Path Resolution Details
|
||||||
|
|
||||||
|
### Search Order
|
||||||
|
|
||||||
|
1. **Explicit Configuration** (if set)
|
||||||
|
```json
|
||||||
|
{"gitea_mcp_binary_path": "/path/to/gitea-mcp"}
|
||||||
|
```
|
||||||
|
Checked first, must exist or error is returned
|
||||||
|
|
||||||
|
2. **Standard System Paths** (all platforms)
|
||||||
|
- `/usr/local/bin/gitea-mcp`
|
||||||
|
- `/usr/bin/gitea-mcp`
|
||||||
|
|
||||||
|
3. **Home Directory Paths**
|
||||||
|
- `~/.local/bin/gitea-mcp`
|
||||||
|
- `~/bin/gitea-mcp`
|
||||||
|
- `~/.cargo/bin/gitea-mcp`
|
||||||
|
|
||||||
|
4. **Platform-Specific Paths**
|
||||||
|
- macOS: `/opt/homebrew/bin/gitea-mcp` (M-series)
|
||||||
|
- Windows: `C:\Program Files\gitea-mcp\gitea-mcp.exe`
|
||||||
|
- Windows: `C:\Program Files (x86)\gitea-mcp\gitea-mcp.exe`
|
||||||
|
|
||||||
|
5. **PATH Environment Variable**
|
||||||
|
- Searches all directories in `PATH`
|
||||||
|
- Uses `:` separator on Unix, `;` on Windows
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
|
||||||
|
If binary is not found:
|
||||||
|
1. Lists all paths that were searched
|
||||||
|
2. Provides installation instructions
|
||||||
|
3. Suggests Docker as alternative
|
||||||
|
4. Shows how to set `gitea_mcp_binary_path`
|
||||||
|
|
||||||
|
Example error:
|
||||||
|
```
|
||||||
|
gitea-mcp binary not found in standard locations.
|
||||||
|
|
||||||
|
Searched paths:
|
||||||
|
- /usr/local/bin/gitea-mcp
|
||||||
|
- /usr/bin/gitea-mcp
|
||||||
|
- ... (more paths)
|
||||||
|
|
||||||
|
Resolution options:
|
||||||
|
1. Install gitea-mcp to a standard location...
|
||||||
|
2. Configure custom binary path in your Zed settings...
|
||||||
|
3. Use Docker...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker Mode Details
|
||||||
|
|
||||||
|
### Command Structure
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run \
|
||||||
|
--rm \
|
||||||
|
-i \
|
||||||
|
--env GITEA_ACCESS_TOKEN=<token> \
|
||||||
|
[--env GITEA_INSECURE=true] \
|
||||||
|
[--env GITEA_HOST=<host>] \
|
||||||
|
gitea/gitea-mcp:latest \
|
||||||
|
-t stdio \
|
||||||
|
[--host <host>]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration Options
|
||||||
|
|
||||||
|
- `use_docker: true` - Enable Docker mode
|
||||||
|
- `docker_image: "gitea/gitea-mcp:v1.0.0"` - Custom image
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
- Docker must be installed and running
|
||||||
|
- Image will be pulled automatically if not present
|
||||||
|
- Container runs with `--rm` (auto-cleanup)
|
||||||
|
- STDIN connected to Zed for STDIO mode
|
||||||
|
|
||||||
|
## Debugging Tips
|
||||||
|
|
||||||
|
### Extension Not Loading
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check compilation
|
||||||
|
cargo check
|
||||||
|
|
||||||
|
# View Zed logs
|
||||||
|
zed --foreground
|
||||||
|
|
||||||
|
# Try clean rebuild
|
||||||
|
cargo clean
|
||||||
|
cargo build --release
|
||||||
|
```
|
||||||
|
|
||||||
|
### Binary Not Found
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Verify binary exists
|
||||||
|
which gitea-mcp
|
||||||
|
ls -lh /usr/local/bin/gitea-mcp
|
||||||
|
|
||||||
|
# Make executable
|
||||||
|
chmod +x /usr/local/bin/gitea-mcp
|
||||||
|
|
||||||
|
# Test manually
|
||||||
|
/usr/local/bin/gitea-mcp --help
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Issues
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check Docker status
|
||||||
|
docker ps
|
||||||
|
|
||||||
|
# Pull image manually
|
||||||
|
docker pull gitea/gitea-mcp:latest
|
||||||
|
|
||||||
|
# Test Docker command
|
||||||
|
docker run --rm -i gitea/gitea-mcp:latest --help
|
||||||
|
```
|
||||||
|
|
||||||
|
### Settings Not Working
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Verify JSON syntax
|
||||||
|
cat ~/.config/Zed/settings.json
|
||||||
|
|
||||||
|
# Check context server ID matches
|
||||||
|
grep tendril-gitea-mcp ~/.config/Zed/settings.json
|
||||||
|
|
||||||
|
# Restart Zed
|
||||||
|
pkill -f zed
|
||||||
|
zed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
### Binary Mode
|
||||||
|
- Fastest startup (no container overhead)
|
||||||
|
- Direct process execution
|
||||||
|
- Minimal resource usage
|
||||||
|
|
||||||
|
### Docker Mode
|
||||||
|
- First pull downloads entire image (~100-500 MB)
|
||||||
|
- Subsequent starts faster if image cached
|
||||||
|
- Uses more memory (container runtime)
|
||||||
|
- Better isolation
|
||||||
|
|
||||||
|
### Optimization Ideas
|
||||||
|
- Cache binary path discovery result
|
||||||
|
- Lazy-load configuration only when needed
|
||||||
|
- Implement binary availability checking at startup
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### Token Handling
|
||||||
|
- Never log access tokens
|
||||||
|
- Pass via environment variables (secure)
|
||||||
|
- Tokens are passed to gitea-mcp, not exposed to Zed
|
||||||
|
|
||||||
|
### Certificate Validation
|
||||||
|
- Default: strict SSL validation
|
||||||
|
- `gitea_insecure: true` disables verification
|
||||||
|
- Only use for trusted internal servers
|
||||||
|
|
||||||
|
### Docker Security
|
||||||
|
- Uses `--rm` to clean up containers
|
||||||
|
- Environment variables not logged
|
||||||
|
- Consider using secrets management for production
|
||||||
|
|
||||||
|
## Future Zed API Improvements
|
||||||
|
|
||||||
|
When Zed adds HTTP context server support:
|
||||||
|
- SSE mode could be re-implemented
|
||||||
|
- Multiple parallel connections supported
|
||||||
|
- Better session management possible
|
||||||
|
- Persistent server instances
|
||||||
|
|
||||||
|
Reference: https://github.com/zed-industries/zed/discussions/29370
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [Zed Extensions Documentation](https://zed.dev/docs/extensions)
|
||||||
|
- [Gitea MCP Project](https://gitea.com/gitea/gitea-mcp)
|
||||||
|
- [Model Context Protocol](https://modelcontextprotocol.io)
|
||||||
|
- [The Mycelium Project](https://git.parkingmeter.info/Mycelium)
|
||||||
|
- [Gitea Documentation](https://docs.gitea.io)
|
||||||
|
- [Docker Documentation](https://docs.docker.com)
|
||||||
|
|
||||||
|
## Contact & Support
|
||||||
|
|
||||||
|
- Repository: https://git.parkingmeter.info/Mycelium/tendril
|
||||||
|
- Issues: Open an issue on the repository
|
||||||
|
- Discussions: Use repository discussions for questions
|
||||||
|
- Author: Ryan Parmeter (@parkingmeter)
|
||||||
490
PROJECT_STATUS.md
Normal file
490
PROJECT_STATUS.md
Normal file
@@ -0,0 +1,490 @@
|
|||||||
|
# Tendril Project Status & Setup Guide
|
||||||
|
|
||||||
|
## 🎯 Current Status: v0.1.0 - Feature Complete
|
||||||
|
|
||||||
|
**Version**: 0.1.0 (Development)
|
||||||
|
**Last Updated**: Current Session
|
||||||
|
**Build Status**: ✅ Compiling successfully
|
||||||
|
**Features**: ✅ Binary path resolution, Docker support, cross-platform detection
|
||||||
|
|
||||||
|
This document summarizes the current state of the Tendril project and provides setup instructions.
|
||||||
|
|
||||||
|
## ✅ What's Been Completed
|
||||||
|
|
||||||
|
### Phase 1: Core Extension (v0.0.1)
|
||||||
|
- ✅ Recovered all source files from previous repository
|
||||||
|
- ✅ Reorganized project structure for clarity
|
||||||
|
- ✅ Renamed extension to "tendril-gitea-mcp"
|
||||||
|
- ✅ Updated branding to "The Mycelium Project"
|
||||||
|
- ✅ Code compiles to valid WASM without errors
|
||||||
|
- ✅ STDIO mode implementation complete
|
||||||
|
|
||||||
|
### Phase 2: Flexible Binary Discovery (v0.1.0) - JUST COMPLETED
|
||||||
|
- ✅ Removed hardcoded binary path `/usr/local/bin/gitea-mcp`
|
||||||
|
- ✅ Implemented intelligent binary path resolution with fallbacks:
|
||||||
|
- Explicit user configuration (`gitea_mcp_binary_path`)
|
||||||
|
- `/usr/local/bin/gitea-mcp`
|
||||||
|
- `~/.local/bin/gitea-mcp`
|
||||||
|
- `~/.cargo/bin/gitea-mcp`
|
||||||
|
- `/opt/homebrew/bin/gitea-mcp` (macOS M-series)
|
||||||
|
- System PATH search
|
||||||
|
- ✅ Cross-platform support (Linux, macOS, Windows)
|
||||||
|
- ✅ Comprehensive error messages with troubleshooting steps
|
||||||
|
|
||||||
|
### Phase 2: Docker Support (v0.1.0) - JUST COMPLETED
|
||||||
|
- ✅ Added `use_docker` configuration option
|
||||||
|
- ✅ Added `docker_image` configuration option (with sensible default)
|
||||||
|
- ✅ Implemented Docker command builder with proper argument passing
|
||||||
|
- ✅ Environment variable passing to Docker containers
|
||||||
|
- ✅ STDIN/STDOUT support through Docker
|
||||||
|
- ✅ Proper container cleanup (--rm flag)
|
||||||
|
|
||||||
|
### Documentation (Updated for v0.1.0)
|
||||||
|
- ✅ **README.md**: Completely updated with binary path resolution and Docker examples
|
||||||
|
- ✅ **DEVELOPMENT.md**: Comprehensive developer guide with architecture and roadmap
|
||||||
|
- ✅ **installation_instructions.md**: Concise setup guide for Zed UI
|
||||||
|
- ✅ **default_settings.jsonc**: Well-documented configuration template with all new options
|
||||||
|
- ✅ **PROJECT_STATUS.md**: This file
|
||||||
|
|
||||||
|
## 📋 Project Files
|
||||||
|
|
||||||
|
```
|
||||||
|
tendril/
|
||||||
|
├── Cargo.toml # Rust project manifest
|
||||||
|
├── extension.toml # Zed extension manifest
|
||||||
|
├── src/
|
||||||
|
│ └── mcp_server_gitea.rs # Extension implementation (~350 lines)
|
||||||
|
│ # - Binary path resolution
|
||||||
|
│ # - Docker support
|
||||||
|
│ # - Settings management
|
||||||
|
├── configuration/
|
||||||
|
│ ├── default_settings.jsonc # Settings template with all options
|
||||||
|
│ └── installation_instructions.md # Quick setup guide
|
||||||
|
├── README.md # Main documentation (500+ lines)
|
||||||
|
├── DEVELOPMENT.md # Dev guide & architecture (550+ lines)
|
||||||
|
├── PROJECT_STATUS.md # This file
|
||||||
|
├── LICENSE # Apache 2.0
|
||||||
|
└── ZedExtensions.md # Research notes
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Getting Started (Dev Extension Setup)
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
You need:
|
||||||
|
1. **Zed IDE** - Download from https://zed.dev
|
||||||
|
2. **Rust** - Installed via rustup (required for dev extensions)
|
||||||
|
3. **Gitea Access Token** - From your Gitea instance
|
||||||
|
4. **gitea-mcp** - Either:
|
||||||
|
- Binary installed on your system, OR
|
||||||
|
- Docker (to use containerized mode)
|
||||||
|
|
||||||
|
### Step 1: Install Gitea MCP Binary (Choose One Method)
|
||||||
|
|
||||||
|
**Option A: Download Pre-built Binary**
|
||||||
|
```bash
|
||||||
|
# Linux x86_64
|
||||||
|
wget https://gitea.com/gitea/gitea-mcp/releases/download/v1.0.0/gitea-mcp-linux-amd64
|
||||||
|
sudo chmod +x gitea-mcp-linux-amd64
|
||||||
|
sudo mv gitea-mcp-linux-amd64 /usr/local/bin/gitea-mcp
|
||||||
|
|
||||||
|
# macOS Intel
|
||||||
|
wget https://gitea.com/gitea/gitea-mcp/releases/download/v1.0.0/gitea-mcp-darwin-amd64
|
||||||
|
sudo chmod +x gitea-mcp-darwin-amd64
|
||||||
|
sudo mv gitea-mcp-darwin-amd64 /usr/local/bin/gitea-mcp
|
||||||
|
|
||||||
|
# macOS M-series
|
||||||
|
wget https://gitea.com/gitea/gitea-mcp/releases/download/v1.0.0/gitea-mcp-darwin-arm64
|
||||||
|
sudo chmod +x gitea-mcp-darwin-arm64
|
||||||
|
sudo mv gitea-mcp-darwin-arm64 /usr/local/bin/gitea-mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option B: Build from Source**
|
||||||
|
```bash
|
||||||
|
git clone https://gitea.com/gitea/gitea-mcp.git
|
||||||
|
cd gitea-mcp
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option C: Use Docker (Skip Binary Installation)**
|
||||||
|
If you have Docker installed, skip binary installation and configure Docker mode in step 4.
|
||||||
|
|
||||||
|
**Verify installation:**
|
||||||
|
```bash
|
||||||
|
/usr/local/bin/gitea-mcp --help
|
||||||
|
```
|
||||||
|
|
||||||
|
Or if using a different location, test it there instead.
|
||||||
|
|
||||||
|
### Step 2: Generate Gitea Access Token
|
||||||
|
|
||||||
|
1. Log in to your Gitea instance
|
||||||
|
2. Go to **Settings** → **Applications** → **Authorize New Application**
|
||||||
|
3. Give it a name (e.g., "Zed MCP")
|
||||||
|
4. Select repository-related permissions
|
||||||
|
5. Click **Authorize** and copy the token
|
||||||
|
|
||||||
|
### Step 3: Install Tendril as Dev Extension
|
||||||
|
|
||||||
|
1. **Open Zed**
|
||||||
|
2. **Go to Extensions**
|
||||||
|
- Press `Cmd+K` and type "Extensions"
|
||||||
|
- Or click Extensions icon in left sidebar
|
||||||
|
3. **Click "Install Dev Extension"**
|
||||||
|
4. **Select the `tendril` directory**
|
||||||
|
- Navigate to where you cloned this repository
|
||||||
|
5. **Zed will compile and load the extension**
|
||||||
|
- You should see "Tendril: Gitea MCP" in your extensions list
|
||||||
|
|
||||||
|
### Step 4: Configure Zed Settings
|
||||||
|
|
||||||
|
1. **Open Settings**
|
||||||
|
- Press `Cmd+,` or go to **Settings** → **Open Settings**
|
||||||
|
2. **Add to your `settings.json`:**
|
||||||
|
|
||||||
|
**Basic Setup (Auto-detects Binary):**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_GITEA_TOKEN_HERE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Using Docker Instead:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_GITEA_TOKEN_HERE",
|
||||||
|
"use_docker": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**For Self-Hosted Gitea:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_GITEA_TOKEN_HERE",
|
||||||
|
"gitea_host": "https://git.example.com",
|
||||||
|
"gitea_insecure": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**With Custom Binary Path:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_GITEA_TOKEN_HERE",
|
||||||
|
"gitea_mcp_binary_path": "/path/to/gitea-mcp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Test the Connection
|
||||||
|
|
||||||
|
1. **Open Zed's Assistant panel**
|
||||||
|
- Press `Cmd+K` or click Assistant icon
|
||||||
|
2. **Try a command:**
|
||||||
|
```
|
||||||
|
list my repositories
|
||||||
|
```
|
||||||
|
3. **You should see your Gitea repositories listed**
|
||||||
|
|
||||||
|
If it works, you're all set! ✨
|
||||||
|
|
||||||
|
## 🔄 What's New in v0.1.0
|
||||||
|
|
||||||
|
### Major Features Added
|
||||||
|
|
||||||
|
1. **Intelligent Binary Path Resolution**
|
||||||
|
- No longer hardcoded to `/usr/local/bin/gitea-mcp`
|
||||||
|
- Automatically searches multiple common locations
|
||||||
|
- Platform-aware (detects macOS M-series, Windows paths, etc.)
|
||||||
|
- User-configurable via `gitea_mcp_binary_path` setting
|
||||||
|
- Helpful error messages if binary not found
|
||||||
|
|
||||||
|
2. **Docker Support**
|
||||||
|
- New `use_docker` setting to enable Docker mode
|
||||||
|
- New `docker_image` setting for custom Docker images
|
||||||
|
- Automatic Docker command generation
|
||||||
|
- Environment variables properly passed to container
|
||||||
|
- Works seamlessly with STDIO mode
|
||||||
|
|
||||||
|
3. **Cross-Platform Support**
|
||||||
|
- Linux: Standard paths + ~/.local/bin + ~/.cargo/bin
|
||||||
|
- macOS Intel: Standard paths + /opt/homebrew/bin consideration
|
||||||
|
- macOS M-series: Optimized for `/opt/homebrew/bin/gitea-mcp`
|
||||||
|
- Windows: Program Files paths (code ready, untested)
|
||||||
|
|
||||||
|
### Configuration Enhancements
|
||||||
|
|
||||||
|
New settings available:
|
||||||
|
- `gitea_mcp_binary_path` - Explicit path to binary (optional)
|
||||||
|
- `use_docker` - Enable Docker mode (optional, default: false)
|
||||||
|
- `docker_image` - Custom Docker image (optional, default: gitea/gitea-mcp:latest)
|
||||||
|
|
||||||
|
All settings documented in `configuration/default_settings.jsonc`
|
||||||
|
|
||||||
|
### Documentation Improvements
|
||||||
|
|
||||||
|
- README.md: 500+ lines with examples for all modes
|
||||||
|
- DEVELOPMENT.md: 550+ lines with complete architecture and roadmap
|
||||||
|
- installation_instructions.md: Concise UI-friendly guide
|
||||||
|
- default_settings.jsonc: Extensive inline documentation
|
||||||
|
|
||||||
|
## ⚠️ Known Issues & Limitations
|
||||||
|
|
||||||
|
### Current Limitations (Before v1.0)
|
||||||
|
|
||||||
|
1. **SSE Mode Not Supported**
|
||||||
|
- Only STDIO mode is currently supported
|
||||||
|
- SSE mode would require Zed to support HTTP context servers
|
||||||
|
- Future enhancement when Zed API adds this capability
|
||||||
|
- See: https://github.com/zed-industries/zed/discussions/29370
|
||||||
|
|
||||||
|
2. **Docker Image Management**
|
||||||
|
- No automatic image updates
|
||||||
|
- Assumes Docker can pull from public registries
|
||||||
|
- Custom registries require Docker authentication setup
|
||||||
|
- Large images may take time to download on first use
|
||||||
|
|
||||||
|
3. **Windows Testing**
|
||||||
|
- Code includes Windows paths but not tested on actual Windows
|
||||||
|
- Binary path resolution should work but needs verification
|
||||||
|
- Docker support should work but untested
|
||||||
|
|
||||||
|
4. **No Configuration Wizard**
|
||||||
|
- Settings must be edited manually in settings.json
|
||||||
|
- No interactive setup prompts yet
|
||||||
|
- Goal for future version: add UI-based configuration
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
**"gitea-mcp binary not found" Error**
|
||||||
|
```bash
|
||||||
|
# Install to standard location
|
||||||
|
sudo mv gitea-mcp /usr/local/bin/gitea-mcp
|
||||||
|
sudo chmod +x /usr/local/bin/gitea-mcp
|
||||||
|
|
||||||
|
# Or configure explicit path in settings
|
||||||
|
"gitea_mcp_binary_path": "/path/to/gitea-mcp"
|
||||||
|
|
||||||
|
# Or use Docker
|
||||||
|
"use_docker": true
|
||||||
|
```
|
||||||
|
|
||||||
|
**"Failed to spawn command" Error**
|
||||||
|
```bash
|
||||||
|
# Make binary executable
|
||||||
|
chmod +x /usr/local/bin/gitea-mcp
|
||||||
|
|
||||||
|
# Test it manually
|
||||||
|
/usr/local/bin/gitea-mcp --help
|
||||||
|
|
||||||
|
# Restart Zed
|
||||||
|
```
|
||||||
|
|
||||||
|
**Authentication/Token Issues**
|
||||||
|
- Verify token has repository permissions
|
||||||
|
- Check token hasn't expired
|
||||||
|
- Copy entire token without extra spaces
|
||||||
|
- Restart Zed after changing settings
|
||||||
|
|
||||||
|
**Docker Issues**
|
||||||
|
- Ensure Docker is installed and running
|
||||||
|
- Try pulling image manually: `docker pull gitea/gitea-mcp:latest`
|
||||||
|
- Check Docker logs for errors
|
||||||
|
|
||||||
|
## 🔍 What's Next (High Priority for v0.2.0)
|
||||||
|
|
||||||
|
### Testing & Validation
|
||||||
|
- [ ] Test with actual Gitea instances (various versions)
|
||||||
|
- [ ] Test binary discovery on multiple systems
|
||||||
|
- [ ] Test Docker mode on Linux, macOS, Windows
|
||||||
|
- [ ] Test with self-hosted Gitea instances
|
||||||
|
- [ ] Test with different token permissions
|
||||||
|
- [ ] Validate error messages are helpful
|
||||||
|
- [ ] Performance testing with large repositories
|
||||||
|
|
||||||
|
### User Experience Improvements
|
||||||
|
- [ ] Interactive configuration wizard
|
||||||
|
- [ ] Settings validation with helpful errors
|
||||||
|
- [ ] Status diagnostic commands
|
||||||
|
- [ ] Better error messages with context
|
||||||
|
- [ ] Optional configuration UI helpers
|
||||||
|
|
||||||
|
### Documentation & Release
|
||||||
|
- [ ] Troubleshooting video
|
||||||
|
- [ ] FAQ section
|
||||||
|
- [ ] Contributing guidelines
|
||||||
|
- [ ] Version bump to 1.0.0 when stable
|
||||||
|
- [ ] Submit to Zed marketplace
|
||||||
|
|
||||||
|
### Platform Testing Matrix
|
||||||
|
```
|
||||||
|
✓ Linux (expected to work - most tested during development)
|
||||||
|
? macOS Intel (needs testing)
|
||||||
|
? macOS M-series (code ready, needs testing with actual M4 Mac)
|
||||||
|
? Windows (code ready, needs testing)
|
||||||
|
|
||||||
|
✓ Binary mode (expected to work)
|
||||||
|
✓ Docker mode (needs testing across platforms)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Build & Development
|
||||||
|
|
||||||
|
### Building the Extension
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Full release build
|
||||||
|
cargo build --release
|
||||||
|
|
||||||
|
# Quick debug build
|
||||||
|
cargo build
|
||||||
|
|
||||||
|
# Check for issues without building
|
||||||
|
cargo check
|
||||||
|
|
||||||
|
# Lint code
|
||||||
|
cargo clippy
|
||||||
|
```
|
||||||
|
|
||||||
|
### Development Workflow
|
||||||
|
|
||||||
|
1. Make changes to `src/mcp_server_gitea.rs` or configuration files
|
||||||
|
2. Run `cargo build --release`
|
||||||
|
3. Reload extension in Zed (or restart Zed)
|
||||||
|
4. Test changes in Assistant panel
|
||||||
|
|
||||||
|
### Debug Logging
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start Zed with verbose logging
|
||||||
|
zed --foreground
|
||||||
|
|
||||||
|
# Watch gitea-mcp server logs
|
||||||
|
tail -f ~/.gitea-mcp/gitea-mcp.log
|
||||||
|
|
||||||
|
# View Zed logs
|
||||||
|
# In Zed: zed: open log
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
All documentation has been updated for v0.1.0:
|
||||||
|
|
||||||
|
- **README.md** - Main user guide with all configuration options
|
||||||
|
- **DEVELOPMENT.md** - Developer guide, architecture, and roadmap
|
||||||
|
- **installation_instructions.md** - Quick setup guide (shown in Zed UI)
|
||||||
|
- **configuration/default_settings.jsonc** - Configuration template with comments
|
||||||
|
- **PROJECT_STATUS.md** - This file (status and getting started)
|
||||||
|
|
||||||
|
## 🔗 Resources
|
||||||
|
|
||||||
|
- **Zed Extension Docs**: https://zed.dev/docs/extensions
|
||||||
|
- **Gitea MCP Repository**: https://gitea.com/gitea/gitea-mcp
|
||||||
|
- **Model Context Protocol**: https://modelcontextprotocol.io
|
||||||
|
- **The Mycelium Project**: https://git.parkingmeter.info/Mycelium
|
||||||
|
- **Gitea Docs**: https://docs.gitea.io
|
||||||
|
- **Docker Docs**: https://docs.docker.com
|
||||||
|
|
||||||
|
## 📞 Support & Contributing
|
||||||
|
|
||||||
|
### For Issues
|
||||||
|
1. Check troubleshooting sections in README.md or DEVELOPMENT.md
|
||||||
|
2. Check Zed logs: `zed: open log`
|
||||||
|
3. Check gitea-mcp logs: `tail -f ~/.gitea-mcp/gitea-mcp.log`
|
||||||
|
4. Open an issue on the repository
|
||||||
|
|
||||||
|
### For Contributing
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create a feature branch
|
||||||
|
3. Make your changes and test locally
|
||||||
|
4. Run `cargo build --release && cargo clippy`
|
||||||
|
5. Submit a pull request with a clear description
|
||||||
|
|
||||||
|
## 📋 Testing Checklist Before v1.0.0 Release
|
||||||
|
|
||||||
|
### Platform Testing
|
||||||
|
- [ ] Test on Linux x86_64
|
||||||
|
- [ ] Test on macOS Intel
|
||||||
|
- [ ] Test on macOS M-series (ARM64)
|
||||||
|
- [ ] Test on Windows (if possible)
|
||||||
|
|
||||||
|
### Feature Testing
|
||||||
|
- [ ] Binary auto-discovery works
|
||||||
|
- [ ] Custom binary path works
|
||||||
|
- [ ] Docker mode works
|
||||||
|
- [ ] Custom Docker image works
|
||||||
|
- [ ] Self-hosted Gitea works
|
||||||
|
- [ ] Self-signed certificates work
|
||||||
|
- [ ] Token validation works
|
||||||
|
- [ ] All error messages are clear and helpful
|
||||||
|
|
||||||
|
### Error Scenarios
|
||||||
|
- [ ] Binary not found → helpful error with options
|
||||||
|
- [ ] Invalid token → clear error message
|
||||||
|
- [ ] Docker not installed → suggestion to install or use binary
|
||||||
|
- [ ] Wrong binary path → error with suggestion
|
||||||
|
- [ ] Network issues → clear error with context
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- [ ] README covers all common scenarios
|
||||||
|
- [ ] DEVELOPMENT guide is comprehensive
|
||||||
|
- [ ] Configuration examples are clear
|
||||||
|
- [ ] Troubleshooting section is helpful
|
||||||
|
- [ ] All new features are documented
|
||||||
|
|
||||||
|
## 👥 Version History
|
||||||
|
|
||||||
|
### v0.1.0 (Current - Just Released)
|
||||||
|
- ✨ Flexible binary path resolution with intelligent fallbacks
|
||||||
|
- ✨ Docker support for containerized deployment
|
||||||
|
- ✨ Cross-platform binary detection
|
||||||
|
- 🐛 Improved error messages with troubleshooting guidance
|
||||||
|
- 📚 Comprehensive documentation updates
|
||||||
|
|
||||||
|
### v0.0.1 (Previous)
|
||||||
|
- Initial development version
|
||||||
|
- Hardcoded binary path to `/usr/local/bin/gitea-mcp`
|
||||||
|
- STDIO mode support
|
||||||
|
- Basic configuration through settings.json
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
Licensed under the Apache License 2.0. See LICENSE file for full details.
|
||||||
|
|
||||||
|
## 👥 Authors
|
||||||
|
|
||||||
|
- **Ryan Parmeter** (@parkingmeter)
|
||||||
|
- **The Mycelium Project Contributors**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ Quick Links
|
||||||
|
|
||||||
|
- **Get Started**: Follow "Getting Started" section above
|
||||||
|
- **Main Documentation**: See README.md
|
||||||
|
- **Developer Guide**: See DEVELOPMENT.md
|
||||||
|
- **Configuration Help**: See configuration/default_settings.jsonc
|
||||||
|
- **Issues/Questions**: Open an issue on the repository
|
||||||
|
|
||||||
|
**To get started right now**: Follow the "Getting Started" section above to install the dev extension!
|
||||||
130
QUICKSTART.md
Normal file
130
QUICKSTART.md
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
# Tendril Quick Start Guide
|
||||||
|
|
||||||
|
**TL;DR**: Get Tendril working in 5 minutes.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Install Rust (if not already installed)
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||||
|
|
||||||
|
# 2. Download and install gitea-mcp binary
|
||||||
|
wget https://gitea.com/gitea/gitea-mcp/releases/download/v1.0.0/gitea-mcp-linux-amd64
|
||||||
|
chmod +x gitea-mcp-linux-amd64
|
||||||
|
sudo mv gitea-mcp-linux-amd64 /usr/local/bin/gitea-mcp
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
/usr/local/bin/gitea-mcp --help
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generate Gitea Token
|
||||||
|
|
||||||
|
1. Log in to your Gitea instance
|
||||||
|
2. Settings → Applications → Authorize New Application
|
||||||
|
3. Name: "Zed MCP"
|
||||||
|
4. Check repository permissions
|
||||||
|
5. Copy the token
|
||||||
|
|
||||||
|
## Install in Zed (Dev Extension)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Open Zed
|
||||||
|
# 2. Extensions → Install Dev Extension
|
||||||
|
# 3. Select the tendril directory
|
||||||
|
# 4. Wait for Zed to compile (a few seconds first time)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configure Zed
|
||||||
|
|
||||||
|
Add to your `settings.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_TOKEN_HERE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test It
|
||||||
|
|
||||||
|
1. Open Zed's Assistant (Cmd+K)
|
||||||
|
2. Type: `list my repositories`
|
||||||
|
3. Done! 🎉
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "required", // Your token
|
||||||
|
"gitea_host": "https://git.example.com", // Self-hosted Gitea
|
||||||
|
"gitea_insecure": false, // Self-signed certs
|
||||||
|
"gitea_port": 8080, // SSE mode port
|
||||||
|
"use_sse": false // Use SSE instead of STDIO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
| Problem | Solution |
|
||||||
|
|---------|----------|
|
||||||
|
| "failed to spawn command" | Make sure `/usr/local/bin/gitea-mcp` exists: `ls -l /usr/local/bin/gitea-mcp` |
|
||||||
|
| Extension not loading | Check Zed logs: `zed: open log` |
|
||||||
|
| Auth errors | Verify token and permissions, regenerate if needed |
|
||||||
|
| SSE mode issues | Try STDIO mode: set `"use_sse": false` |
|
||||||
|
|
||||||
|
## Useful Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test the binary
|
||||||
|
/usr/local/bin/gitea-mcp --help
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
tail -f ~/.gitea-mcp/gitea-mcp.log
|
||||||
|
|
||||||
|
# Check Zed logs (in Zed)
|
||||||
|
zed: open log
|
||||||
|
|
||||||
|
# Rebuild extension
|
||||||
|
cargo build --release
|
||||||
|
```
|
||||||
|
|
||||||
|
## Need More Help?
|
||||||
|
|
||||||
|
- 📖 See **README.md** for full documentation
|
||||||
|
- 👨💻 See **DEVELOPMENT.md** for development guide
|
||||||
|
- 🔍 See **PROJECT_STATUS.md** for current status and roadmap
|
||||||
|
- 📋 See **configuration/installation_instructions.md** for detailed setup
|
||||||
|
|
||||||
|
## What Tendril Does
|
||||||
|
|
||||||
|
Tendril is a **Zed extension** that connects to a **gitea-mcp server** running on your system.
|
||||||
|
|
||||||
|
```
|
||||||
|
Zed (with Tendril extension)
|
||||||
|
↓
|
||||||
|
gitea-mcp binary (at /usr/local/bin/gitea-mcp)
|
||||||
|
↓
|
||||||
|
Gitea Instance (your self-hosted or public Gitea)
|
||||||
|
```
|
||||||
|
|
||||||
|
The extension lets you interact with Gitea repositories, issues, PRs, and more directly from Zed's Assistant panel using natural language.
|
||||||
|
|
||||||
|
## Quick Links
|
||||||
|
|
||||||
|
- 🏠 Repository: https://git.parkingmeter.info/Mycelium/tendril
|
||||||
|
- 🔗 Gitea MCP: https://gitea.com/gitea/gitea-mcp
|
||||||
|
- 📝 Zed Docs: https://zed.dev/docs/extensions
|
||||||
|
- 🧬 Mycelium Project: https://git.parkingmeter.info/Mycelium
|
||||||
522
README.md
522
README.md
@@ -1,3 +1,521 @@
|
|||||||
# tendril
|
# Tendril: Gitea MCP for Zed
|
||||||
|
|
||||||
A Zed IDE extension for Gitea and MCP integration.
|
A Zed IDE extension that integrates with Gitea through the Model Context Protocol (MCP). Tendril is part of **The Mycelium Project** and provides seamless access to Gitea repositories, issues, pull requests, and more directly within your editor.
|
||||||
|
|
||||||
|
## What is This?
|
||||||
|
|
||||||
|
Tendril is a **Zed IDE extension** that acts as a bridge between Zed and a Gitea MCP server. The extension itself is lightweight - it's the glue that connects your editor to a Gitea MCP server running on your system (or in Docker). You'll need to have either the `gitea-mcp` binary installed or Docker available.
|
||||||
|
|
||||||
|
Think of it as:
|
||||||
|
- **Extension**: Tendril (this repository) - runs inside Zed
|
||||||
|
- **Server**: gitea-mcp binary or Docker container - runs on your system, communicates with Gitea
|
||||||
|
- **Result**: Full Gitea access from your editor through Zed's AI features
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
Before you can use Tendril, you need:
|
||||||
|
|
||||||
|
1. **Zed IDE** - Download from https://zed.dev
|
||||||
|
2. **Gitea MCP Server** - Either:
|
||||||
|
- Binary installed locally, OR
|
||||||
|
- Docker with gitea-mcp image available
|
||||||
|
3. **Gitea Access Token** - Generated from your Gitea instance
|
||||||
|
4. **Rust** (if installing as dev extension) - Installed via rustup
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Option A: Using Local Binary
|
||||||
|
|
||||||
|
#### 1. Install the Gitea MCP Binary
|
||||||
|
|
||||||
|
The extension automatically searches for `gitea-mcp` in these locations:
|
||||||
|
- `/usr/local/bin/gitea-mcp`
|
||||||
|
- `~/.local/bin/gitea-mcp`
|
||||||
|
- `~/.cargo/bin/gitea-mcp`
|
||||||
|
- `/opt/homebrew/bin/gitea-mcp` (macOS M-series)
|
||||||
|
- Anywhere in your PATH
|
||||||
|
|
||||||
|
Choose an installation method:
|
||||||
|
|
||||||
|
**Download Pre-built Binary:**
|
||||||
|
```bash
|
||||||
|
# Download from: https://gitea.com/gitea/gitea-mcp/releases
|
||||||
|
# For example, Linux x64:
|
||||||
|
wget https://gitea.com/gitea/gitea-mcp/releases/download/v1.0.0/gitea-mcp-linux-amd64
|
||||||
|
chmod +x gitea-mcp-linux-amd64
|
||||||
|
sudo mv gitea-mcp-linux-amd64 /usr/local/bin/gitea-mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
**Build from Source:**
|
||||||
|
```bash
|
||||||
|
git clone https://gitea.com/gitea/gitea-mcp.git
|
||||||
|
cd gitea-mcp
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verify Installation:**
|
||||||
|
```bash
|
||||||
|
/usr/local/bin/gitea-mcp --help
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Generate a Gitea Access Token
|
||||||
|
|
||||||
|
1. Log in to your Gitea instance
|
||||||
|
2. Go to **Settings** → **Applications** → **Authorize New Application**
|
||||||
|
3. Give it a name like "Zed MCP"
|
||||||
|
4. Select required permissions (recommend repository-related scopes)
|
||||||
|
5. Click **Authorize** and copy the token
|
||||||
|
|
||||||
|
#### 3. Install Tendril as a Dev Extension
|
||||||
|
|
||||||
|
1. Open Zed
|
||||||
|
2. Go to **Extensions** panel (left sidebar or Cmd+K → "Extensions")
|
||||||
|
3. Click **Install Dev Extension**
|
||||||
|
4. Select the `tendril` directory
|
||||||
|
5. Zed will compile and load the extension
|
||||||
|
|
||||||
|
#### 4. Configure Zed Settings
|
||||||
|
|
||||||
|
Open your Zed settings (`Cmd+,`) and add:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_GITEA_TOKEN_HERE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option B: Using Docker
|
||||||
|
|
||||||
|
If you have Docker installed and prefer containerized deployment:
|
||||||
|
|
||||||
|
#### 1. Generate a Gitea Access Token
|
||||||
|
|
||||||
|
Same as Option A, step 2 above.
|
||||||
|
|
||||||
|
#### 2. Install Tendril as a Dev Extension
|
||||||
|
|
||||||
|
Same as Option A, steps 3-4, but with Docker settings:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_GITEA_TOKEN_HERE",
|
||||||
|
"use_docker": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The extension will automatically pull and run `gitea/gitea-mcp-server:latest` in Docker.
|
||||||
|
|
||||||
|
Optionally, specify a different image:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_GITEA_TOKEN_HERE",
|
||||||
|
"use_docker": true,
|
||||||
|
"docker_image": "gitea/gitea-mcp-server:v1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Test the Connection
|
||||||
|
|
||||||
|
In Zed's Assistant panel, try:
|
||||||
|
|
||||||
|
```
|
||||||
|
list my repositories
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Test the Connection
|
||||||
|
|
||||||
|
In Zed's Assistant panel, try a command like:
|
||||||
|
|
||||||
|
```
|
||||||
|
list my repositories
|
||||||
|
```
|
||||||
|
|
||||||
|
The MCP server should respond with your Gitea repositories.
|
||||||
|
|
||||||
|
## Configuration Reference
|
||||||
|
|
||||||
|
### Basic Settings
|
||||||
|
|
||||||
|
| Setting | Type | Required | Description |
|
||||||
|
|---------|------|----------|-------------|
|
||||||
|
| `gitea_access_token` | string | Yes | Your Gitea personal access token |
|
||||||
|
| `gitea_host` | string | No | URL of your Gitea instance (for self-hosted) |
|
||||||
|
| `gitea_insecure` | boolean | No | Allow self-signed certificates (default: false) |
|
||||||
|
|
||||||
|
### Binary Path Settings
|
||||||
|
|
||||||
|
| Setting | Type | Default | Description |
|
||||||
|
|---------|------|---------|-------------|
|
||||||
|
| `gitea_mcp_binary_path` | string | (auto-detect) | Explicit path to gitea-mcp binary |
|
||||||
|
|
||||||
|
If `gitea_mcp_binary_path` is not set, Tendril automatically searches standard locations. Use this setting if your binary is in a non-standard location.
|
||||||
|
|
||||||
|
### Docker Settings
|
||||||
|
|
||||||
|
| Setting | Type | Default | Description |
|
||||||
|
|---------|------|---------|-------------|
|
||||||
|
| `use_docker` | boolean | false | Use Docker to run gitea-mcp instead of local binary |
|
||||||
|
| `docker_image` | string | gitea/gitea-mcp-server:latest | Docker image to use |
|
||||||
|
|
||||||
|
## Configuration Examples
|
||||||
|
|
||||||
|
### Basic Setup (Auto-Detect Binary)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_GITEA_TOKEN_HERE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Self-Hosted Gitea
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_TOKEN",
|
||||||
|
"gitea_host": "https://git.example.com",
|
||||||
|
"gitea_insecure": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Binary Path
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_TOKEN",
|
||||||
|
"gitea_mcp_binary_path": "/home/user/custom/location/gitea-mcp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Setup
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_TOKEN",
|
||||||
|
"use_docker": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker with Custom Image and Self-Hosted Gitea
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_TOKEN",
|
||||||
|
"gitea_host": "https://git.internal.company.com",
|
||||||
|
"gitea_insecure": true,
|
||||||
|
"use_docker": true,
|
||||||
|
"docker_image": "my-registry.com/gitea-mcp:v1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Tools
|
||||||
|
|
||||||
|
Through the Gitea MCP server, you get access to:
|
||||||
|
|
||||||
|
- **User Management**: Get user info, list organizations, search users
|
||||||
|
- **Repository Management**: List repos, create repos, fork repos
|
||||||
|
- **Branch Management**: Create/delete/list branches
|
||||||
|
- **Release Management**: Create/list/delete releases
|
||||||
|
- **Tag Management**: Create/list/delete tags
|
||||||
|
- **File Operations**: View, create, update, delete files
|
||||||
|
- **Issue Management**: Create/edit/list issues, add comments
|
||||||
|
- **Pull Requests**: Create/list/manage pull requests
|
||||||
|
- **Commits**: List and view commits
|
||||||
|
|
||||||
|
See the [Gitea MCP documentation](https://gitea.com/gitea/gitea-mcp) for complete tool details.
|
||||||
|
|
||||||
|
## Installation Methods
|
||||||
|
|
||||||
|
### For Development (Recommended)
|
||||||
|
|
||||||
|
Use the dev extension approach (see Quick Start above). This allows you to:
|
||||||
|
- Test changes immediately
|
||||||
|
- Reload the extension without restarting Zed
|
||||||
|
- Contribute improvements back
|
||||||
|
|
||||||
|
### For Production (When Published)
|
||||||
|
|
||||||
|
Once Tendril is published to the Zed Extension Marketplace, you'll be able to install it like any other extension from within Zed's Extensions panel.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Binary Not Found" Error
|
||||||
|
|
||||||
|
If you get an error about gitea-mcp not being found:
|
||||||
|
|
||||||
|
1. **Using binary mode:**
|
||||||
|
- Install gitea-mcp to `/usr/local/bin/gitea-mcp` or another standard location
|
||||||
|
- Or set `gitea_mcp_binary_path` to the full path in your settings
|
||||||
|
- Verify it's executable: `chmod +x /path/to/gitea-mcp`
|
||||||
|
- Test it: `/path/to/gitea-mcp --help`
|
||||||
|
|
||||||
|
2. **Using Docker mode:**
|
||||||
|
- Ensure Docker is installed and running
|
||||||
|
- Set `use_docker: true` in settings
|
||||||
|
- Let Docker pull the image automatically
|
||||||
|
|
||||||
|
### "Failed to Spawn Command" Error
|
||||||
|
|
||||||
|
The binary exists but isn't executable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x /usr/local/bin/gitea-mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
Then restart Zed.
|
||||||
|
|
||||||
|
### Authentication Issues
|
||||||
|
|
||||||
|
- Verify your Gitea token has repository permissions
|
||||||
|
- Ensure you've copied the entire token correctly (no extra spaces)
|
||||||
|
- Check that the token hasn't expired
|
||||||
|
- Log out and back in to your Gitea instance if using session-based auth
|
||||||
|
|
||||||
|
### Self-Hosted Gitea with Self-Signed Certificates
|
||||||
|
|
||||||
|
If you're getting SSL certificate errors with a self-hosted Gitea instance:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_TOKEN",
|
||||||
|
"gitea_host": "https://git.example.com",
|
||||||
|
"gitea_insecure": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Security Note**: Only use `gitea_insecure: true` for trusted internal servers.
|
||||||
|
|
||||||
|
### Docker Not Available
|
||||||
|
|
||||||
|
If you see "docker: command not found":
|
||||||
|
|
||||||
|
1. Install Docker from https://www.docker.com/products/docker-desktop
|
||||||
|
2. Ensure Docker Desktop is running (macOS/Windows)
|
||||||
|
3. Or install Docker on Linux: `sudo apt install docker.io` (Ubuntu) or equivalent for your distro
|
||||||
|
4. Restart Zed after installing Docker
|
||||||
|
|
||||||
|
### Dev Extension Not Loading
|
||||||
|
|
||||||
|
Check the Zed log for errors:
|
||||||
|
|
||||||
|
1. In Zed, run: `zed: open log`
|
||||||
|
2. Look for errors related to "tendril"
|
||||||
|
3. If you see build errors, try:
|
||||||
|
```bash
|
||||||
|
cd tendril
|
||||||
|
cargo build --release
|
||||||
|
cargo clippy
|
||||||
|
```
|
||||||
|
4. Ensure Rust is installed via rustup: `rustup --version`
|
||||||
|
5. Restart Zed completely
|
||||||
|
|
||||||
|
## Binary Path Resolution
|
||||||
|
|
||||||
|
When **not** using Docker, Tendril uses this search order:
|
||||||
|
|
||||||
|
1. **Explicitly configured path** (if `gitea_mcp_binary_path` is set)
|
||||||
|
2. **System standard locations**:
|
||||||
|
- `/usr/local/bin/gitea-mcp`
|
||||||
|
- `~/.local/bin/gitea-mcp`
|
||||||
|
- `~/.cargo/bin/gitea-mcp`
|
||||||
|
- `/opt/homebrew/bin/gitea-mcp` (macOS M-series)
|
||||||
|
3. **PATH environment variable** (any location in your PATH)
|
||||||
|
|
||||||
|
If the binary isn't found, you'll get a helpful error message with troubleshooting steps.
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
### View Gitea MCP Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tail -f ~/.gitea-mcp/gitea-mcp.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### View Zed Logs
|
||||||
|
|
||||||
|
1. In Zed, run: `zed: open log`
|
||||||
|
2. Or check the system log location:
|
||||||
|
- macOS: `~/Library/Logs/Zed.log`
|
||||||
|
- Linux: `~/.local/share/zed/logs/Zed.log`
|
||||||
|
- Windows: `%APPDATA%\Zed\logs\Zed.log`
|
||||||
|
|
||||||
|
### Debug with Verbose Logging
|
||||||
|
|
||||||
|
Start Zed from the command line for more output:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
zed --foreground
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Binary Testing
|
||||||
|
|
||||||
|
Test the binary directly (without Zed):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# STDIO mode
|
||||||
|
export GITEA_ACCESS_TOKEN="your_token"
|
||||||
|
/usr/local/bin/gitea-mcp -t stdio --host https://git.example.com
|
||||||
|
|
||||||
|
# Type any command and press Ctrl+D when done
|
||||||
|
# (This is a low-level test)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Building from Source
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
- Rust (installed via rustup)
|
||||||
|
- Zed development environment
|
||||||
|
|
||||||
|
Build the extension:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd tendril
|
||||||
|
cargo build --release
|
||||||
|
```
|
||||||
|
|
||||||
|
This generates the WASM module used by Zed.
|
||||||
|
|
||||||
|
### Reloading During Development
|
||||||
|
|
||||||
|
After making changes to the Rust code:
|
||||||
|
|
||||||
|
1. Run `cargo build --release`
|
||||||
|
2. Reload the extension in Zed (restart Zed or use extension reload if available)
|
||||||
|
3. Changes take effect immediately
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
tendril/
|
||||||
|
├── Cargo.toml # Rust project configuration
|
||||||
|
├── extension.toml # Zed extension manifest
|
||||||
|
├── src/
|
||||||
|
│ └── mcp_server_gitea.rs # Main extension logic (~350 lines)
|
||||||
|
├── configuration/
|
||||||
|
│ ├── default_settings.jsonc # Default configuration with comments
|
||||||
|
│ └── installation_instructions.md # Quick setup guide for Zed UI
|
||||||
|
├── README.md # This file
|
||||||
|
├── DEVELOPMENT.md # Developer guide
|
||||||
|
├── PROJECT_STATUS.md # Project status and roadmap
|
||||||
|
└── LICENSE # Apache 2.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Code Overview
|
||||||
|
|
||||||
|
**src/mcp_server_gitea.rs**:
|
||||||
|
- `GiteaContextServerSettings`: Struct defining all configuration options
|
||||||
|
- `build_binary_command()`: Creates command to run gitea-mcp binary
|
||||||
|
- `build_docker_command()`: Creates Docker command to run gitea-mcp
|
||||||
|
- `resolve_binary_path()`: Implements smart binary path discovery
|
||||||
|
|
||||||
|
## Related Projects
|
||||||
|
|
||||||
|
- **Gitea**: https://gitea.io - Lightweight Git service
|
||||||
|
- **Gitea MCP**: https://gitea.com/gitea/gitea-mcp - MCP server for Gitea
|
||||||
|
- **Model Context Protocol**: https://modelcontextprotocol.io
|
||||||
|
- **The Mycelium Project**: https://git.parkingmeter.info/Mycelium
|
||||||
|
- **Zed IDE**: https://zed.dev
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Licensed under the Apache License 2.0. See [LICENSE](./LICENSE) for details.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For issues or questions:
|
||||||
|
|
||||||
|
1. **Check troubleshooting** above
|
||||||
|
2. **Review logs** using `zed: open log`
|
||||||
|
3. **Open an issue** on [Tendril repository](https://git.parkingmeter.info/Mycelium/tendril)
|
||||||
|
4. **Consult documentation**:
|
||||||
|
- [Zed Extensions](https://zed.dev/docs/extensions)
|
||||||
|
- [Gitea MCP](https://gitea.com/gitea/gitea-mcp)
|
||||||
|
- [Model Context Protocol](https://modelcontextprotocol.io)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! Please:
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create a feature branch: `git checkout -b feature/your-feature`
|
||||||
|
3. Make your changes and test: `cargo build --release && cargo clippy`
|
||||||
|
4. Submit a pull request with a clear description
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
- Ryan Parmeter ([@parkingmeter](https://git.parkingmeter.info/parkingmeter))
|
||||||
|
- The Mycelium Project Contributors
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
### v0.1.0 (Upcoming)
|
||||||
|
|
||||||
|
- ✨ Configurable binary path with intelligent fallback search
|
||||||
|
- ✨ Docker support for containerized deployment
|
||||||
|
- ✨ Cross-platform binary discovery (Linux, macOS, Windows)
|
||||||
|
- 🐛 Improved error messages with troubleshooting guidance
|
||||||
|
- 📚 Enhanced documentation
|
||||||
|
|
||||||
|
### v0.0.1 (Initial Development Release)
|
||||||
|
|
||||||
|
- Initial development version
|
||||||
|
- STDIO mode support
|
||||||
|
- Basic configuration through Zed settings.json
|
||||||
|
- Support for self-hosted Gitea instances
|
||||||
|
- Hardcoded binary path to `/usr/local/bin/gitea-mcp`
|
||||||
|
|||||||
197
SSE_MODE_ANALYSIS.md
Normal file
197
SSE_MODE_ANALYSIS.md
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
# SSE Mode Analysis & Investigation
|
||||||
|
|
||||||
|
**Date**: November 10, 2024
|
||||||
|
**Status**: Investigated and Removed
|
||||||
|
**Decision**: Deprecated in favor of STDIO mode (proven working)
|
||||||
|
|
||||||
|
## Investigation Findings
|
||||||
|
|
||||||
|
### What We Discovered
|
||||||
|
|
||||||
|
During testing of SSE (Server-Sent Events) mode in v0.0.1, we found:
|
||||||
|
|
||||||
|
1. **gitea-mcp Removed SSE Support**
|
||||||
|
- SSE mode was removed from gitea-mcp in a recent commit
|
||||||
|
- Reference: https://gitea.com/gitea/gitea-mcp/commit/88471b5de048ee35e929a5c3e5789f50ba57a845
|
||||||
|
- The MCP specification itself has moved beyond SSE
|
||||||
|
|
||||||
|
2. **MCP Specification Evolution**
|
||||||
|
- Old standard: HTTP + SSE transport (deprecated)
|
||||||
|
- New standard: Streamable HTTP transport (as of MCP 2025-03-26)
|
||||||
|
- Reference: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports
|
||||||
|
|
||||||
|
3. **Test Results When Attempting SSE Mode**
|
||||||
|
```
|
||||||
|
Zed Log:
|
||||||
|
ERROR [context_server::client] Unhandled JSON from context_server
|
||||||
|
ERROR [context_server::client] cancelled csp request task for "initialize"
|
||||||
|
ERROR [project::context_server_store] Context server failed to start:
|
||||||
|
Context server request timeout
|
||||||
|
|
||||||
|
gitea-mcp Log:
|
||||||
|
INFO: Gitea MCP SSE server listening on :8987
|
||||||
|
(No further initialization)
|
||||||
|
```
|
||||||
|
|
||||||
|
The binary started but couldn't complete the MCP initialization handshake.
|
||||||
|
|
||||||
|
## What Changed
|
||||||
|
|
||||||
|
### Removed Features
|
||||||
|
- `use_sse` configuration option
|
||||||
|
- `gitea_port` setting (was only for SSE mode)
|
||||||
|
- All SSE-specific code paths
|
||||||
|
- SSE mode documentation
|
||||||
|
|
||||||
|
### Kept Stable
|
||||||
|
- **STDIO Mode**: Direct stdin/stdout communication (proven working)
|
||||||
|
- All other configuration options
|
||||||
|
- Self-hosted Gitea support
|
||||||
|
- Self-signed certificate handling
|
||||||
|
|
||||||
|
## Current Architecture
|
||||||
|
|
||||||
|
### STDIO Transport (What We Use Now)
|
||||||
|
```
|
||||||
|
Zed IDE
|
||||||
|
↓ (spawns process)
|
||||||
|
Tendril Extension
|
||||||
|
↓ (starts with args: -t stdio)
|
||||||
|
gitea-mcp Binary
|
||||||
|
↓ (communicates via stdin/stdout)
|
||||||
|
Gitea Instance
|
||||||
|
```
|
||||||
|
|
||||||
|
**Characteristics:**
|
||||||
|
- ✅ Direct process communication
|
||||||
|
- ✅ No network setup required
|
||||||
|
- ✅ Fully tested and working
|
||||||
|
- ✅ Standard MCP transport
|
||||||
|
- ✅ Low latency
|
||||||
|
|
||||||
|
### Future: HTTP Streaming Transport
|
||||||
|
```
|
||||||
|
Zed IDE
|
||||||
|
↓ (HTTP connection)
|
||||||
|
Tendril Extension
|
||||||
|
↓ (connects to HTTP endpoint)
|
||||||
|
gitea-mcp Binary (HTTP server mode)
|
||||||
|
↓ (HTTP requests)
|
||||||
|
Gitea Instance
|
||||||
|
```
|
||||||
|
|
||||||
|
**Characteristics:**
|
||||||
|
- Modern MCP standard (2025-03-26+)
|
||||||
|
- Requires separate HTTP server setup
|
||||||
|
- Supports multiple connections
|
||||||
|
- More complex implementation
|
||||||
|
- **Status: Not yet implemented**
|
||||||
|
|
||||||
|
## Why We Made This Decision
|
||||||
|
|
||||||
|
### Reasons for Removing SSE Support
|
||||||
|
|
||||||
|
1. **Dead Technology**: SSE mode was removed from gitea-mcp itself
|
||||||
|
- No point supporting a mode the server doesn't provide
|
||||||
|
|
||||||
|
2. **Specification Obsolete**: The HTTP+SSE transport is deprecated
|
||||||
|
- MCP spec moved to Streamable HTTP (2025-03-26)
|
||||||
|
- Supporting old standards prevents adoption of new ones
|
||||||
|
|
||||||
|
3. **Never Worked Reliably**: Your original notes indicated SSE never worked
|
||||||
|
- Testing confirmed it still doesn't work
|
||||||
|
- Maintaining non-functional code adds burden
|
||||||
|
|
||||||
|
4. **STDIO Works Great**: We have a perfectly good, tested alternative
|
||||||
|
- No user complaints or issues
|
||||||
|
- Simple and reliable
|
||||||
|
- Meets all current use cases
|
||||||
|
|
||||||
|
5. **Cleaner Codebase**: Removing unused features simplifies maintenance
|
||||||
|
- Easier to understand
|
||||||
|
- Fewer code paths to test
|
||||||
|
- Clearer configuration
|
||||||
|
|
||||||
|
## Migration Path for Users
|
||||||
|
|
||||||
|
### If You Were Using SSE Mode (v0.0.1)
|
||||||
|
|
||||||
|
Change from:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_TOKEN",
|
||||||
|
"use_sse": true,
|
||||||
|
"gitea_port": 8080
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To (v0.0.2+):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "YOUR_TOKEN"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
STDIO mode is now the default and only mode. It works the same way and requires no port configuration.
|
||||||
|
|
||||||
|
## Future Consideration: HTTP Streaming
|
||||||
|
|
||||||
|
### When We Might Revisit HTTP Streaming
|
||||||
|
|
||||||
|
If we need to support:
|
||||||
|
- Remote gitea-mcp servers (not localhost)
|
||||||
|
- Multiple concurrent connections from Zed
|
||||||
|
- Load balancing
|
||||||
|
- Cloud-based gitea-mcp deployments
|
||||||
|
|
||||||
|
### What Would Be Required
|
||||||
|
|
||||||
|
1. Update gitea-mcp binary to support HTTP streaming mode
|
||||||
|
2. Add HTTP endpoint discovery to Tendril
|
||||||
|
3. Implement HTTP client in Rust extension
|
||||||
|
4. Handle connection pooling and session management
|
||||||
|
5. Test with both local and remote deployments
|
||||||
|
|
||||||
|
### Estimated Effort
|
||||||
|
- Analysis: 4-8 hours
|
||||||
|
- Implementation: 8-16 hours
|
||||||
|
- Testing: 8-12 hours
|
||||||
|
- Documentation: 4 hours
|
||||||
|
- **Total: ~24-40 hours** (1 week of focused work)
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- **gitea-mcp Repository**: https://gitea.com/gitea/gitea-mcp
|
||||||
|
- **MCP Specification (Current)**: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports
|
||||||
|
- **MCP Transports Documentation**: https://docs.roocode.com/features/mcp/server-transports
|
||||||
|
- **Streamable HTTP Transport**: https://levelup.gitconnected.com/mcp-server-and-client-with-sse-the-new-streamable-http-d860850d9d9d
|
||||||
|
|
||||||
|
## Commit Information
|
||||||
|
|
||||||
|
- **Version**: v0.0.2 (after this cleanup)
|
||||||
|
- **Deprecation Date**: November 10, 2024
|
||||||
|
- **Replacement**: STDIO mode (primary), HTTP Streaming (future)
|
||||||
|
- **Impact**: Configuration simplification, code cleanup
|
||||||
|
|
||||||
|
## Questions?
|
||||||
|
|
||||||
|
If you have questions about this decision:
|
||||||
|
1. Check the references above for MCP transport documentation
|
||||||
|
2. Review the gitea-mcp repository for current capabilities
|
||||||
|
3. Open an issue: https://git.parkingmeter.info/Mycelium/tendril/issues
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Summary**: SSE mode has been officially removed from Tendril as it's no longer supported by gitea-mcp and is superseded by the newer HTTP Streaming transport standard in MCP. STDIO mode (the primary transport) continues to work excellently and requires no changes for existing users.
|
||||||
211
TESTING_FINDINGS.md
Normal file
211
TESTING_FINDINGS.md
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
# Testing Findings & Improvements
|
||||||
|
|
||||||
|
**Date**: November 10, 2024
|
||||||
|
**Tester**: User testing in Zed IDE
|
||||||
|
**Focus**: Transport modes and configuration validation
|
||||||
|
|
||||||
|
## Test Results Summary
|
||||||
|
|
||||||
|
### ✅ STDIO Mode - WORKING
|
||||||
|
- **Status**: Fully functional
|
||||||
|
- **Transport**: stdin/stdout direct communication
|
||||||
|
- **Configuration**: Minimal (token only)
|
||||||
|
- **Testing**: Confirmed working in production use
|
||||||
|
- **Recommendation**: Default and recommended mode
|
||||||
|
|
||||||
|
### ❌ SSE Mode - NOT WORKING (Removed)
|
||||||
|
- **Status**: Deprecated by gitea-mcp upstream
|
||||||
|
- **Issue**: MCP initialization timeout after 60 seconds
|
||||||
|
- **Root Cause**: gitea-mcp removed SSE mode in favor of HTTP Streaming
|
||||||
|
- **Action Taken**: Removed SSE support from Tendril v0.0.2+
|
||||||
|
- **Decision Rationale**: Dead code - no longer supported by server
|
||||||
|
|
||||||
|
## Key Findings
|
||||||
|
|
||||||
|
### 1. gitea-mcp Deprecated SSE Mode
|
||||||
|
- **Evidence**: Commit 88471b5de048ee35e929a5c3e5789f50ba57a845 on gitea-mcp
|
||||||
|
- **Reason**: MCP specification evolved to Streamable HTTP standard
|
||||||
|
- **Impact**: Any extension trying to use SSE mode will fail
|
||||||
|
- **Status**: Old MCP specification (pre-2025-03-26)
|
||||||
|
|
||||||
|
### 2. MCP Specification Update
|
||||||
|
- **Old Standard**: HTTP + SSE transport (Server-Sent Events)
|
||||||
|
- **New Standard**: Streamable HTTP transport (unified, bidirectional)
|
||||||
|
- **Effective Date**: MCP 2025-03-26 and later
|
||||||
|
- **Resource**: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports
|
||||||
|
|
||||||
|
### 3. SSE Mode Error Signature
|
||||||
|
When attempting SSE mode, Zed produced:
|
||||||
|
```
|
||||||
|
ERROR [context_server::client] Unhandled JSON from context_server
|
||||||
|
ERROR [context_server::client] cancelled csp request task for "initialize" id 0 which took over 60s
|
||||||
|
ERROR [project::context_server_store] tendril-gitea-mcp context server failed to start:
|
||||||
|
Context server request timeout
|
||||||
|
```
|
||||||
|
|
||||||
|
Server logs showed:
|
||||||
|
```
|
||||||
|
2025-11-10 14:57:59 INFO operation/operation.go:61 Gitea MCP SSE server listening on :8987
|
||||||
|
(No further initialization - timeout occurs)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Analysis**:
|
||||||
|
- Server started listening on port
|
||||||
|
- Zed tried to initialize MCP protocol
|
||||||
|
- Handshake timed out after 60 seconds
|
||||||
|
- Root cause: gitea-mcp's SSE mode not properly implementing MCP protocol over SSE
|
||||||
|
|
||||||
|
## Improvements Made
|
||||||
|
|
||||||
|
### Code Cleanup
|
||||||
|
- Removed `use_sse` configuration option
|
||||||
|
- Removed `gitea_port` setting (was SSE-only)
|
||||||
|
- Removed SSE-specific command-line argument handling
|
||||||
|
- Simplified `GiteaContextServerSettings` struct from 5 to 3 fields
|
||||||
|
- Hardcoded STDIO transport (the only working mode)
|
||||||
|
|
||||||
|
### Configuration Simplification
|
||||||
|
**Before (v0.0.1)**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"gitea_access_token": "token",
|
||||||
|
"gitea_host": "optional",
|
||||||
|
"gitea_port": "optional (for SSE)",
|
||||||
|
"gitea_insecure": "optional",
|
||||||
|
"use_sse": "optional (doesn't work)"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**After (v0.0.2+)**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"gitea_access_token": "token",
|
||||||
|
"gitea_host": "optional",
|
||||||
|
"gitea_insecure": "optional"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Documentation Updates
|
||||||
|
- Updated `default_settings.jsonc` - removed SSE and port options
|
||||||
|
- Updated `installation_instructions.md` - removed SSE documentation
|
||||||
|
- Updated code comments - clarified STDIO as only transport
|
||||||
|
- Added `SSE_MODE_ANALYSIS.md` - detailed investigation document
|
||||||
|
|
||||||
|
## User Impact
|
||||||
|
|
||||||
|
### For Existing Users
|
||||||
|
- **STDIO mode users**: No changes needed - everything continues to work
|
||||||
|
- **SSE mode users**: Update config to remove `use_sse` and `gitea_port` options
|
||||||
|
- STDIO mode is now default (works the same way)
|
||||||
|
- No functionality lost
|
||||||
|
|
||||||
|
### For New Users
|
||||||
|
- Simpler configuration (3 options instead of 5)
|
||||||
|
- No confusing SSE mode option that doesn't work
|
||||||
|
- Clearer documentation focused on working features
|
||||||
|
- Faster setup time
|
||||||
|
|
||||||
|
## Performance Implications
|
||||||
|
|
||||||
|
### STDIO Mode (Current)
|
||||||
|
- Direct process communication
|
||||||
|
- No network overhead
|
||||||
|
- Sub-millisecond latency
|
||||||
|
- Single connection (sufficient for IDE usage)
|
||||||
|
- Perfect for local development
|
||||||
|
|
||||||
|
### HTTP Streaming (Future Alternative)
|
||||||
|
- Network round-trip latency
|
||||||
|
- Supports multiple concurrent connections
|
||||||
|
- Better for remote/shared servers
|
||||||
|
- Not yet implemented but documented for future
|
||||||
|
|
||||||
|
## Lessons Learned
|
||||||
|
|
||||||
|
### 1. Keep Code Sync with Upstream
|
||||||
|
- SSE mode removal in gitea-mcp wasn't immediately apparent
|
||||||
|
- Testing revealed the issue
|
||||||
|
- Dead code maintenance becomes technical debt
|
||||||
|
- Regular dependency audits would help catch this earlier
|
||||||
|
|
||||||
|
### 2. Test Against Real Implementations
|
||||||
|
- Code looked correct for SSE mode
|
||||||
|
- But gitea-mcp implementation changed
|
||||||
|
- Live testing revealed the disconnect
|
||||||
|
- Upstream changes need monitoring
|
||||||
|
|
||||||
|
### 3. Follow Spec Evolution
|
||||||
|
- MCP specification evolved (HTTP+SSE → Streamable HTTP)
|
||||||
|
- gitea-mcp followed the new spec
|
||||||
|
- Tendril should stay current with both upstream and spec
|
||||||
|
- Document planned support for new standards
|
||||||
|
|
||||||
|
### 4. Configuration Matters
|
||||||
|
- More options = more confusion
|
||||||
|
- Non-working options hurt credibility
|
||||||
|
- Simpler is better when it works
|
||||||
|
- Users appreciate clarity over feature count
|
||||||
|
|
||||||
|
## Recommendations for Future Development
|
||||||
|
|
||||||
|
### Short-term (v0.1.0)
|
||||||
|
- Monitor gitea-mcp for HTTP Streaming support confirmation
|
||||||
|
- Add configurable binary path (high priority from original roadmap)
|
||||||
|
- Add Docker support option
|
||||||
|
- Keep STDIO as default and primary mode
|
||||||
|
|
||||||
|
### Medium-term (v0.2.0)
|
||||||
|
- When gitea-mcp has HTTP Streaming support, evaluate implementation
|
||||||
|
- Create HTTP client support in Tendril
|
||||||
|
- Allow users to choose between STDIO and HTTP Streaming
|
||||||
|
- Document use cases for each transport
|
||||||
|
|
||||||
|
### Long-term (v1.0+)
|
||||||
|
- Full HTTP Streaming implementation
|
||||||
|
- Support for remote gitea-mcp servers
|
||||||
|
- Connection pooling for multiple Zed instances
|
||||||
|
- Load balancing for large teams
|
||||||
|
|
||||||
|
## Testing Checklist for Future Contributors
|
||||||
|
|
||||||
|
When testing Tendril:
|
||||||
|
- [ ] Verify STDIO mode with local gitea-mcp binary
|
||||||
|
- [ ] Confirm token-based authentication works
|
||||||
|
- [ ] Test self-hosted Gitea instance
|
||||||
|
- [ ] Test self-signed certificate handling
|
||||||
|
- [ ] Verify error messages are helpful
|
||||||
|
- [ ] Check Zed logs for any warnings
|
||||||
|
- [ ] Monitor gitea-mcp logs during operation
|
||||||
|
- [ ] Test with different Gitea instances if possible
|
||||||
|
|
||||||
|
When updating gitea-mcp version:
|
||||||
|
- [ ] Review gitea-mcp release notes for transport changes
|
||||||
|
- [ ] Test with new version before updating docs
|
||||||
|
- [ ] Check if new transport modes became available
|
||||||
|
- [ ] Update dependencies and CHANGELOG
|
||||||
|
- [ ] Run full test suite
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- **gitea-mcp Repository**: https://gitea.com/gitea/gitea-mcp
|
||||||
|
- **Commit that removed SSE**: https://gitea.com/gitea/gitea-mcp/commit/88471b5de048ee35e929a5c3e5789f50ba57a845
|
||||||
|
- **MCP Specification (Current)**: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports
|
||||||
|
- **Streamable HTTP Spec**: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http
|
||||||
|
- **MCP Transport Overview**: https://docs.roocode.com/features/mcp/server-transports
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
Testing revealed that SSE mode was already deprecated in gitea-mcp due to MCP specification evolution. This finding led to:
|
||||||
|
|
||||||
|
1. **Code Simplification**: Removed non-functional SSE code paths
|
||||||
|
2. **Configuration Improvement**: Reduced options from 5 to 3, removed confusing disabled mode
|
||||||
|
3. **Documentation Clarity**: Focused docs on what actually works
|
||||||
|
4. **Future Planning**: Identified HTTP Streaming as the next transport to support
|
||||||
|
|
||||||
|
The result is a cleaner, more maintainable extension with clearer user experience. STDIO mode remains robust and reliable, with a clear migration path documented for when HTTP Streaming support becomes desirable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Status**: v0.0.2 cleanup complete
|
||||||
|
**Next Steps**: Focus on binary path configuration and Docker support (v0.1.0)
|
||||||
|
**Verified By**: Live testing in Zed IDE, November 10, 2024
|
||||||
138
ZedExtensions.md
Normal file
138
ZedExtensions.md
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
# Zed Extensions for BCOS
|
||||||
|
|
||||||
|
This document provides information about developing Zed extensions, with specific focus on Model Context Protocol (MCP) server extensions that will be used in the BCOS project.
|
||||||
|
|
||||||
|
## Extension Capabilities
|
||||||
|
|
||||||
|
Extensions can add the following capabilities to Zed:
|
||||||
|
- Languages
|
||||||
|
- Debuggers
|
||||||
|
- Themes
|
||||||
|
- Icon Themes
|
||||||
|
- Slash Commands
|
||||||
|
- MCP Servers (primary focus for BCOS)
|
||||||
|
## Developing an Extension Locally
|
||||||
|
Before starting to develop an extension for Zed, be sure to install Rust via rustup.
|
||||||
|
|
||||||
|
Rust must be installed via rustup. If you have Rust installed via homebrew or otherwise, installing dev extensions will not work.
|
||||||
|
|
||||||
|
When developing an extension, you can use it in Zed without needing to publish it by installing it as a dev extension.
|
||||||
|
|
||||||
|
From the extensions page, click the Install Dev Extension button (or the zed: install dev extension action) and select the directory containing your extension.
|
||||||
|
|
||||||
|
If you need to troubleshoot, you can check the Zed.log (zed: open log) for additional output. For debug output, close and relaunch zed with the zed --foreground from the command line which show more verbose INFO level logging.
|
||||||
|
|
||||||
|
If you already have a published extension with the same name installed, your dev extension will override it.
|
||||||
|
|
||||||
|
After installing the Extensions page will indicate that that the upstream extension is "Overridden by dev extension".
|
||||||
|
|
||||||
|
Pre-installed extensions with the same name have to be uninstalled before installing the dev extension. See #31106 for more.
|
||||||
|
|
||||||
|
## Directory Structure of a Zed Extension
|
||||||
|
A Zed extension is a Git repository that contains an extension.toml. This file must contain some basic information about the extension:
|
||||||
|
|
||||||
|
```
|
||||||
|
id = "my-extension"
|
||||||
|
name = "My extension"
|
||||||
|
version = "0.0.1"
|
||||||
|
schema_version = 1
|
||||||
|
authors = ["Your Name <you@example.com>"]
|
||||||
|
description = "My cool extension"
|
||||||
|
repository = "https://github.com/your-name/my-zed-extension"
|
||||||
|
```
|
||||||
|
|
||||||
|
In addition to this, there are several other optional files and directories that can be used to add functionality to a Zed extension. An example directory structure of an extension that provides all capabilities is as follows:
|
||||||
|
```
|
||||||
|
my-extension/
|
||||||
|
extension.toml
|
||||||
|
Cargo.toml
|
||||||
|
src/
|
||||||
|
lib.rs
|
||||||
|
languages/
|
||||||
|
my-language/
|
||||||
|
config.toml
|
||||||
|
highlights.scm
|
||||||
|
themes/
|
||||||
|
my-theme.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## WebAssembly
|
||||||
|
Procedural parts of extensions are written in Rust and compiled to WebAssembly. To develop an extension that includes custom code, include a Cargo.toml like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
[package]
|
||||||
|
name = "my-extension"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
zed_extension_api = "0.1.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the latest version of the zed_extension_api available on crates.io. Make sure it's still compatible with Zed versions you want to support.
|
||||||
|
|
||||||
|
In the src/lib.rs file in your Rust crate you will need to define a struct for your extension and implement the Extension trait, as well as use the register_extension! macro to register your extension:
|
||||||
|
|
||||||
|
```
|
||||||
|
use zed_extension_api as zed;
|
||||||
|
|
||||||
|
struct MyExtension {
|
||||||
|
// ... state
|
||||||
|
}
|
||||||
|
|
||||||
|
impl zed::Extension for MyExtension {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
zed::register_extension!(MyExtension);
|
||||||
|
```
|
||||||
|
|
||||||
|
stdout/stderr is forwarded directly to the Zed process. In order to see println!/dbg! output from your extension, you can start Zed in your terminal with a --foreground flag.
|
||||||
|
|
||||||
|
# MCP Server Extensions
|
||||||
|
Model Context Protocol servers can be exposed as extensions for use in the Agent Panel.
|
||||||
|
|
||||||
|
## Defining MCP Extensions
|
||||||
|
A given extension may provide one or more MCP servers. Each MCP server must be registered in the extension.toml:
|
||||||
|
|
||||||
|
```
|
||||||
|
[context_servers.my-context-server]
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, in the Rust code for your extension, implement the context_server_command method on your extension:
|
||||||
|
|
||||||
|
```
|
||||||
|
impl zed::Extension for MyExtension {
|
||||||
|
fn context_server_command(
|
||||||
|
&mut self,
|
||||||
|
context_server_id: &ContextServerId,
|
||||||
|
project: &zed::Project,
|
||||||
|
) -> Result<zed::Command> {
|
||||||
|
Ok(zed::Command {
|
||||||
|
command: get_path_to_context_server_executable()?,
|
||||||
|
args: get_args_for_context_server()?,
|
||||||
|
env: get_env_for_context_server()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This method should return the command to start up an MCP server, along with any arguments or environment variables necessary for it to function.
|
||||||
|
|
||||||
|
If you need to download the MCP server from an external source—like GitHub Releases or npm—you can also do that in this function.
|
||||||
|
|
||||||
|
## Available Extensions
|
||||||
|
An example Zed Extension for the Gitlab MCP is in `config/mcp/gitlab-mcp-zed/`.
|
||||||
|
|
||||||
|
For the BCOS project, we will develop a Gitea MCP Extension based on this example. This extension will integrate with our Gitea instance to provide seamless access to our repository from within the Zed IDE.
|
||||||
|
|
||||||
|
## BCOS-Specific Integration
|
||||||
|
For the BCOS project, MCP server extensions will be stored in `/config/mcp` according to our monorepo structure. This ensures proper versioning and access control for our development environment.
|
||||||
|
|
||||||
|
When developing MCP server extensions for BCOS, ensure they follow the project's security and automation guidelines documented in the technical specifications.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
To test the new MCP server extension, the user can install it as a dev extension in the Zed client application.
|
||||||
61
configuration/default_settings.jsonc
Normal file
61
configuration/default_settings.jsonc
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
// ============================================================================
|
||||||
|
// REQUIRED SETTINGS
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// Required: Your Gitea personal access token
|
||||||
|
// Generated in Gitea at: Settings > Applications > Authorize New Application
|
||||||
|
// This token is used to authenticate with your Gitea instance
|
||||||
|
"gitea_access_token": "YOUR_GITEA_TOKEN",
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// BINARY PATH RESOLUTION
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// Optional: Explicit path to gitea-mcp binary
|
||||||
|
// Leave commented to use automatic discovery
|
||||||
|
// If set, this path must point to the gitea-mcp executable
|
||||||
|
// Examples:
|
||||||
|
// - "/usr/local/bin/gitea-mcp"
|
||||||
|
// - "/home/user/.local/bin/gitea-mcp"
|
||||||
|
// - "C:\\Program Files\\gitea-mcp\\gitea-mcp.exe" (Windows)
|
||||||
|
// "gitea_mcp_binary_path": "path/to/gitea-mcp",
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// DOCKER SUPPORT
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// Optional: Use Docker to run gitea-mcp instead of local binary
|
||||||
|
// Set to true if:
|
||||||
|
// 1. You prefer containerized deployment
|
||||||
|
// 2. The binary is not available on your system
|
||||||
|
// 3. You want consistent behavior across platforms
|
||||||
|
// Requires: Docker or Docker Desktop to be installed and running
|
||||||
|
// "use_docker": false,
|
||||||
|
|
||||||
|
// Optional: Docker image to use for gitea-mcp
|
||||||
|
// Only used if use_docker is true
|
||||||
|
// Default: "gitea/gitea-mcp:latest"
|
||||||
|
// You can specify a different version or tag:
|
||||||
|
// - "gitea/gitea-mcp-server:v1.0.0" (specific version)
|
||||||
|
// - "my-registry.com/gitea-mcp-server:custom" (custom registry)
|
||||||
|
// "docker_image": "gitea/gitea-mcp-server:latest",
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// GITEA INSTANCE CONFIGURATION
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// Optional: URL of your Gitea instance (for self-hosted Gitea)
|
||||||
|
// Leave commented out to use the default Gitea instance
|
||||||
|
// Examples:
|
||||||
|
// - "https://git.example.com"
|
||||||
|
// - "https://gitea.internal.company.com"
|
||||||
|
// - "http://localhost:3000" (for local development)
|
||||||
|
// "gitea_host": "https://your-gitea-instance.com",
|
||||||
|
|
||||||
|
// Optional: Allow insecure/self-signed certificates
|
||||||
|
// Set to true ONLY if using self-signed certificates
|
||||||
|
// Security warning: This disables certificate verification
|
||||||
|
// Only use this for trusted internal servers
|
||||||
|
// "gitea_insecure": false
|
||||||
|
}
|
||||||
28
configuration/installation_instructions.md
Normal file
28
configuration/installation_instructions.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Tendril: Gitea MCP for Zed
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. **Get a Gitea Token**
|
||||||
|
- Log in to your Gitea instance
|
||||||
|
- Settings → Applications → Authorize New Application
|
||||||
|
- Copy the token
|
||||||
|
|
||||||
|
2. **Add to Zed Settings**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"context_servers": {
|
||||||
|
"tendril-gitea-mcp": {
|
||||||
|
"settings": {
|
||||||
|
"gitea_access_token": "your_token_here"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Install gitea-mcp Binary** (choose one method)
|
||||||
|
- Dowload binary
|
||||||
|
- Build from source
|
||||||
|
- Docker container
|
||||||
|
|
||||||
|
**More help:** Check README.md or run `zed: open log` for Zed logs
|
||||||
10
extension.toml
Normal file
10
extension.toml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
id = "tendril-gitea-mcp"
|
||||||
|
name = "Tendril Gitea MCP"
|
||||||
|
description = "Zed IDE extension for Model Context Protocol integration with Gitea - Part of The Mycelium Project"
|
||||||
|
version = "0.0.1"
|
||||||
|
schema_version = 1
|
||||||
|
authors = ["Ryan Parmeter <parkingmeter@gmail.com>", "The Mycelium Project"]
|
||||||
|
repository = "https://git.parkingmeter.info/Mycelium/tendril"
|
||||||
|
|
||||||
|
[context_servers.tendril-gitea-mcp]
|
||||||
|
name = "Tendril Gitea MCP"
|
||||||
359
src/mcp_server_gitea.rs
Normal file
359
src/mcp_server_gitea.rs
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
use schemars::JsonSchema;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use zed::settings::ContextServerSettings;
|
||||||
|
use zed_extension_api::{
|
||||||
|
self as zed, serde_json, Command, ContextServerConfiguration, ContextServerId, Project, Result,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Tendril: Gitea MCP Extension for Zed
|
||||||
|
///
|
||||||
|
/// This extension launches a gitea-mcp binary (locally or via Docker) and communicates with it
|
||||||
|
/// to provide Gitea repository access through Zed's AI assistant.
|
||||||
|
///
|
||||||
|
/// Binary Resolution Strategy:
|
||||||
|
/// 1. If `gitea_mcp_binary_path` is set in settings, use that exact path
|
||||||
|
/// 2. If `use_docker` is true, use Docker to run the gitea-mcp image
|
||||||
|
/// 3. Otherwise, search common system paths:
|
||||||
|
/// - /usr/local/bin/gitea-mcp
|
||||||
|
/// - ~/.local/bin/gitea-mcp
|
||||||
|
/// - ~/.cargo/bin/gitea-mcp
|
||||||
|
/// - /opt/homebrew/bin/gitea-mcp (macOS)
|
||||||
|
/// - Search in PATH environment variable
|
||||||
|
///
|
||||||
|
/// Transport modes:
|
||||||
|
/// - STDIO (default, recommended): Direct stdin/stdout communication
|
||||||
|
/// Works with Zed's extension API and gitea-mcp binary
|
||||||
|
/// - Docker: Runs gitea-mcp in a Docker container
|
||||||
|
/// Useful when binary isn't available on host system
|
||||||
|
struct GiteaModelContextExtension;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, JsonSchema)]
|
||||||
|
struct GiteaContextServerSettings {
|
||||||
|
gitea_access_token: String,
|
||||||
|
#[serde(default)]
|
||||||
|
gitea_host: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
gitea_insecure: Option<bool>,
|
||||||
|
#[serde(default)]
|
||||||
|
gitea_mcp_binary_path: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
use_docker: Option<bool>,
|
||||||
|
#[serde(default)]
|
||||||
|
docker_image: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl zed::Extension for GiteaModelContextExtension {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn context_server_command(
|
||||||
|
&mut self,
|
||||||
|
_context_server_id: &ContextServerId,
|
||||||
|
project: &Project,
|
||||||
|
) -> Result<Command> {
|
||||||
|
// Get settings from project settings
|
||||||
|
let settings = ContextServerSettings::for_project("tendril-gitea-mcp", project)?;
|
||||||
|
let Some(settings_value) = settings.settings else {
|
||||||
|
return Err("missing `gitea_access_token` setting".into());
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse settings
|
||||||
|
let settings: GiteaContextServerSettings =
|
||||||
|
serde_json::from_value(settings_value).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
// Check if Docker mode is enabled
|
||||||
|
if settings.use_docker.unwrap_or(false) {
|
||||||
|
build_docker_command(&settings)
|
||||||
|
} else {
|
||||||
|
build_binary_command(&settings)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn context_server_configuration(
|
||||||
|
&mut self,
|
||||||
|
_context_server_id: &ContextServerId,
|
||||||
|
project: &Project,
|
||||||
|
) -> Result<Option<ContextServerConfiguration>> {
|
||||||
|
// Load installation instructions shown in Zed UI
|
||||||
|
let installation_instructions =
|
||||||
|
include_str!("../configuration/installation_instructions.md").to_string();
|
||||||
|
|
||||||
|
// Load default settings template
|
||||||
|
let mut default_settings =
|
||||||
|
include_str!("../configuration/default_settings.jsonc").to_string();
|
||||||
|
|
||||||
|
// Try to get existing settings and populate template with current values
|
||||||
|
if let Ok(settings) = ContextServerSettings::for_project("tendril-gitea-mcp", project) {
|
||||||
|
if let Some(settings_value) = settings.settings {
|
||||||
|
if let Ok(gitea_settings) =
|
||||||
|
serde_json::from_value::<GiteaContextServerSettings>(settings_value)
|
||||||
|
{
|
||||||
|
// Replace placeholder token with actual value
|
||||||
|
default_settings = default_settings.replace(
|
||||||
|
"\"YOUR_GITEA_TOKEN\"",
|
||||||
|
&format!("\"{}\"", gitea_settings.gitea_access_token),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Replace host placeholder if specified
|
||||||
|
if let Some(host) = gitea_settings.gitea_host {
|
||||||
|
default_settings = default_settings
|
||||||
|
.replace("// \"gitea_host\"", "\"gitea_host\"")
|
||||||
|
.replace(
|
||||||
|
"\"https://your-gitea-instance.com\"",
|
||||||
|
&format!("\"{}\"", host),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace insecure flag placeholder if specified
|
||||||
|
if let Some(insecure) = gitea_settings.gitea_insecure {
|
||||||
|
default_settings = default_settings
|
||||||
|
.replace("// \"gitea_insecure\"", "\"gitea_insecure\"")
|
||||||
|
.replace("false", &format!("{}", insecure));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace binary path if specified
|
||||||
|
if let Some(binary_path) = gitea_settings.gitea_mcp_binary_path {
|
||||||
|
default_settings = default_settings
|
||||||
|
.replace("// \"gitea_mcp_binary_path\"", "\"gitea_mcp_binary_path\"")
|
||||||
|
.replace("\"path/to/gitea-mcp\"", &format!("\"{}\"", binary_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace Docker settings if specified
|
||||||
|
if let Some(true) = gitea_settings.use_docker {
|
||||||
|
default_settings = default_settings
|
||||||
|
.replace("// \"use_docker\"", "\"use_docker\"")
|
||||||
|
.replace("false,", "true,");
|
||||||
|
|
||||||
|
if let Some(docker_image) = gitea_settings.docker_image {
|
||||||
|
default_settings = default_settings
|
||||||
|
.replace("// \"docker_image\"", "\"docker_image\"")
|
||||||
|
.replace(
|
||||||
|
"\"gitea/gitea-mcp:latest\"",
|
||||||
|
&format!("\"{}\"", docker_image),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate settings schema from the struct
|
||||||
|
let settings_schema =
|
||||||
|
serde_json::to_string(&schemars::schema_for!(GiteaContextServerSettings))
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
// Return configuration with instructions, defaults, and schema
|
||||||
|
Ok(Some(ContextServerConfiguration {
|
||||||
|
installation_instructions,
|
||||||
|
default_settings,
|
||||||
|
settings_schema,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build a command to run gitea-mcp as a binary
|
||||||
|
fn build_binary_command(settings: &GiteaContextServerSettings) -> Result<Command> {
|
||||||
|
// Resolve binary path with smart fallbacks
|
||||||
|
let binary_path = resolve_binary_path(&settings.gitea_mcp_binary_path)?;
|
||||||
|
|
||||||
|
// Set up environment variables
|
||||||
|
let mut env_vars = vec![(
|
||||||
|
"GITEA_ACCESS_TOKEN".into(),
|
||||||
|
settings.gitea_access_token.clone(),
|
||||||
|
)];
|
||||||
|
|
||||||
|
// Add insecure flag if specified (for self-signed certificates)
|
||||||
|
if let Some(true) = settings.gitea_insecure {
|
||||||
|
env_vars.push(("GITEA_INSECURE".into(), "true".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use STDIO mode (the standard MCP transport and only mode supported by Zed extensions)
|
||||||
|
// gitea-mcp communicates with Zed via stdin/stdout
|
||||||
|
let mut args = vec!["-t".to_string(), "stdio".to_string()];
|
||||||
|
|
||||||
|
// Add host if specified (for self-hosted Gitea instances)
|
||||||
|
if let Some(host) = &settings.gitea_host {
|
||||||
|
args.push("--host".to_string());
|
||||||
|
args.push(host.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return command to launch gitea-mcp
|
||||||
|
Ok(Command {
|
||||||
|
command: binary_path,
|
||||||
|
args,
|
||||||
|
env: env_vars,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build a command to run gitea-mcp in Docker
|
||||||
|
fn build_docker_command(settings: &GiteaContextServerSettings) -> Result<Command> {
|
||||||
|
// Find docker binary - MUST have a full path for Zed's Command struct
|
||||||
|
let docker_cmd = find_docker_binary()?;
|
||||||
|
|
||||||
|
// Use configured docker image or default
|
||||||
|
let docker_image = settings
|
||||||
|
.docker_image
|
||||||
|
.as_deref()
|
||||||
|
.unwrap_or("gitea/gitea-mcp-server:latest");
|
||||||
|
|
||||||
|
// Build docker run command
|
||||||
|
let mut args = vec![
|
||||||
|
"run".to_string(),
|
||||||
|
"--rm".to_string(),
|
||||||
|
"-i".to_string(), // stdin for STDIO mode
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add docker image name
|
||||||
|
args.push(docker_image.to_string());
|
||||||
|
|
||||||
|
// Add gitea-mcp binary path (it's /app/gitea-mcp inside the container)
|
||||||
|
args.push("/app/gitea-mcp".to_string());
|
||||||
|
|
||||||
|
// Add gitea-mcp arguments (using command-line flags, not env vars)
|
||||||
|
args.push("-token".to_string());
|
||||||
|
args.push(settings.gitea_access_token.clone());
|
||||||
|
|
||||||
|
// Add transport mode
|
||||||
|
args.push("-t".to_string());
|
||||||
|
args.push("stdio".to_string());
|
||||||
|
|
||||||
|
// Add host if specified
|
||||||
|
if let Some(host) = &settings.gitea_host {
|
||||||
|
args.push("-host".to_string());
|
||||||
|
args.push(host.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add insecure flag if specified
|
||||||
|
if let Some(true) = settings.gitea_insecure {
|
||||||
|
args.push("-insecure".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Docker command - docker_cmd is guaranteed to be a full path
|
||||||
|
Ok(Command {
|
||||||
|
command: docker_cmd,
|
||||||
|
args,
|
||||||
|
env: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the docker binary in common locations
|
||||||
|
/// Returns the full absolute path to the docker executable
|
||||||
|
/// Note: WASM sandbox may restrict exists() checks, so we return first valid path
|
||||||
|
fn find_docker_binary() -> Result<String> {
|
||||||
|
// Standard docker locations - return first one
|
||||||
|
// WASM sandbox may restrict PathBuf::exists() but process spawning should work
|
||||||
|
Ok("/usr/bin/docker".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolve the gitea-mcp binary path with intelligent fallbacks
|
||||||
|
///
|
||||||
|
/// Resolution strategy:
|
||||||
|
/// 1. If explicit path provided in settings, try it and also fall back to searches
|
||||||
|
/// 2. Try common system paths:
|
||||||
|
/// - /usr/local/bin/gitea-mcp
|
||||||
|
/// - ~/.local/bin/gitea-mcp
|
||||||
|
/// - ~/.cargo/bin/gitea-mcp
|
||||||
|
/// - /opt/homebrew/bin/gitea-mcp (macOS M-series)
|
||||||
|
/// 3. Search in PATH environment variable
|
||||||
|
/// 4. If no path works, return just the binary name (let system PATH handle it)
|
||||||
|
///
|
||||||
|
/// Returns the path to the binary (as a string) to use, or an error if all options fail
|
||||||
|
fn resolve_binary_path(explicit_path: &Option<String>) -> Result<String> {
|
||||||
|
// If explicit path provided, try it first
|
||||||
|
if let Some(path) = explicit_path {
|
||||||
|
if PathBuf::from(path).exists() {
|
||||||
|
return Ok(path.clone());
|
||||||
|
}
|
||||||
|
// Don't fail yet - continue searching as fallback
|
||||||
|
// But we'll mention it in error if nothing else works
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build list of common binary paths to try
|
||||||
|
let mut search_paths = vec![
|
||||||
|
PathBuf::from("/usr/local/bin/gitea-mcp"),
|
||||||
|
PathBuf::from("/usr/bin/gitea-mcp"),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add home directory paths
|
||||||
|
if let Ok(home) = std::env::var("HOME") {
|
||||||
|
search_paths.push(PathBuf::from(&home).join(".local/bin/gitea-mcp"));
|
||||||
|
search_paths.push(PathBuf::from(&home).join("bin/gitea-mcp"));
|
||||||
|
search_paths.push(PathBuf::from(&home).join(".cargo/bin/gitea-mcp"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// macOS M-series (ARM64) Homebrew location
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
search_paths.push(PathBuf::from("/opt/homebrew/bin/gitea-mcp"));
|
||||||
|
|
||||||
|
// Windows locations
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
if let Ok(program_files) = std::env::var("PROGRAMFILES") {
|
||||||
|
search_paths.push(PathBuf::from(&program_files).join("gitea-mcp\\gitea-mcp.exe"));
|
||||||
|
}
|
||||||
|
if let Ok(program_files_x86) = std::env::var("PROGRAMFILES(x86)") {
|
||||||
|
search_paths.push(PathBuf::from(&program_files_x86).join("gitea-mcp\\gitea-mcp.exe"));
|
||||||
|
}
|
||||||
|
search_paths.push(PathBuf::from("C:\\Program Files\\gitea-mcp\\gitea-mcp.exe"));
|
||||||
|
search_paths.push(PathBuf::from(
|
||||||
|
"C:\\Program Files (x86)\\gitea-mcp\\gitea-mcp.exe",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check each default path - try with exists() check
|
||||||
|
for path in &search_paths {
|
||||||
|
// Try exists() - may not work in WASM but worth trying
|
||||||
|
if path.exists() {
|
||||||
|
return Ok(path.display().to_string());
|
||||||
|
}
|
||||||
|
// Also try as fallback: if it can be displayed and is absolute, try it
|
||||||
|
let path_str = path.display().to_string();
|
||||||
|
if path.is_absolute() && !path_str.is_empty() {
|
||||||
|
// Return the path even if exists() check fails
|
||||||
|
// (may be due to WASM sandbox limitations)
|
||||||
|
return Ok(path_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find in PATH environment variable
|
||||||
|
if let Ok(path_env) = std::env::var("PATH") {
|
||||||
|
let separator = if cfg!(target_os = "windows") {
|
||||||
|
";"
|
||||||
|
} else {
|
||||||
|
":"
|
||||||
|
};
|
||||||
|
for path_dir in path_env.split(separator) {
|
||||||
|
let binary_name = if cfg!(target_os = "windows") {
|
||||||
|
"gitea-mcp.exe"
|
||||||
|
} else {
|
||||||
|
"gitea-mcp"
|
||||||
|
};
|
||||||
|
let binary_path = PathBuf::from(path_dir).join(binary_name);
|
||||||
|
if binary_path.exists() {
|
||||||
|
return Ok(binary_path.display().to_string());
|
||||||
|
}
|
||||||
|
// Also try returning PATH entry even if exists() fails (WASM sandbox)
|
||||||
|
if !path_dir.is_empty() {
|
||||||
|
let full_path = PathBuf::from(path_dir).join(binary_name);
|
||||||
|
return Ok(full_path.display().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last resort: try just the binary name and let the system find it
|
||||||
|
// This handles cases where filesystem checks fail in WASM sandbox
|
||||||
|
let binary_name = if cfg!(target_os = "windows") {
|
||||||
|
"gitea-mcp.exe"
|
||||||
|
} else {
|
||||||
|
"gitea-mcp"
|
||||||
|
};
|
||||||
|
|
||||||
|
// If we got here, we couldn't find it in standard paths
|
||||||
|
// Try the binary name directly - system PATH will resolve it
|
||||||
|
Ok(binary_name.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the extension with Zed
|
||||||
|
zed::register_extension!(GiteaModelContextExtension);
|
||||||
Reference in New Issue
Block a user