diff --git a/.dxtignore b/.dxtignore deleted file mode 100644 index 18df3a3..0000000 --- a/.dxtignore +++ /dev/null @@ -1,36 +0,0 @@ -# Exclude source files and build artifacts that aren't needed in the extension -cmd/ -internal/ -examples/ -docs/ -dist/ -build/ -screenshots/ -test-claude-path/ - -# Exclude development files -.git/ -.github/ -.dockerignore -.golangci.yml -.goreleaser.yml -docker-compose.yml -Dockerfile -go.mod -go.sum -Makefile -release.config.js -renovate.json -trino-conf/ - -# Exclude documentation files (not needed for runtime) -CHANGELOG.md -CLAUDE.md -README.md -SOLUTION.md -STEPS.md - -# Keep only essential files: -# - manifest.json (required) -# - server/ directory with binaries (required) -# - install.sh (fallback installation script) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1fd0412..d79a2c2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -46,7 +46,7 @@ jobs: TAG_PREFIX: v VERBOSE: true - - name: Run GoReleaser + - name: Validate GoReleaser config and release uses: goreleaser/goreleaser-action@v6 if: steps.tag.outputs.new_tag != '' with: @@ -56,6 +56,24 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Create MCPB bundle + if: steps.tag.outputs.new_tag != '' + run: | + GORELEASER_VERSION=${{ steps.tag.outputs.new_tag }} make pack-mcpb-from-dist + ls -la ${{ github.event.repository.name }}.mcpb || (echo "MCPB bundle not found" && exit 1) + + - name: Upload MCPB bundle to release + if: steps.tag.outputs.new_tag != '' + run: | + if [ -f "${{ github.event.repository.name }}.mcpb" ]; then + gh release upload ${{ steps.tag.outputs.new_tag }} ${{ github.event.repository.name }}.mcpb --clobber + else + echo "Error: MCPB bundle not found for upload" + exit 1 + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Docker meta id: meta if: steps.tag.outputs.new_tag != '' @@ -87,6 +105,7 @@ jobs: platforms: 'arm64,amd64,arm' - name: downcase REPO + if: steps.tag.outputs.new_tag != '' run: | echo "IMAGE_NAME=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV diff --git a/CLAUDE.md b/CLAUDE.md index 75f5cbe..1ad4b12 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -32,9 +32,10 @@ make docker-compose-down # Stop Docker Compose make run-docker # Build and run Docker image locally # Release and packaging -make release-snapshot # Create snapshot release with GoReleaser -make build-dxt # Build platform-specific binaries for DXT -make pack-dxt # Package DXT extension +make release-snapshot # Create snapshot release with GoReleaser +make build-platform-binaries # Build platform-specific binaries for MCPB +make build-mcpb # Build MCPB bundle +make pack-mcpb-from-dist # Create MCPB from GoReleaser binaries # Testing individual components go test ./internal/config # Test configuration package diff --git a/Makefile b/Makefile index 97fc425..fe5a7c9 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -.PHONY: build build-dxt pack-dxt test clean run-dev release-snapshot run-docker run docker-compose-up docker-compose-down lint docker-test +.PHONY: build build-platform-binaries build-mcpb pack-mcpb-from-dist test clean run-dev release-snapshot run-docker run docker-compose-up docker-compose-down lint docker-test # Variables -BINARY_NAME=mcp-trino +BINARY_NAME ?= $(shell basename $(shell git remote get-url origin) .git | sed 's/.*\///') VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") BUILD_DIR=bin @@ -10,10 +10,10 @@ build: mkdir -p $(BUILD_DIR) go build -ldflags "-X main.Version=$(VERSION)" -o $(BUILD_DIR)/$(BINARY_NAME) ./cmd -# Build all platform-specific binaries for DXT packaging -build-dxt: +# Build all platform-specific binaries for MCPB packaging +build-platform-binaries: mkdir -p server - @echo "Building platform-specific binaries for DXT..." + @echo "Building platform-specific binaries for MCPB..." GOOS=darwin GOARCH=arm64 go build -ldflags "-X main.Version=$(VERSION)" -o server/$(BINARY_NAME)-darwin-arm64 ./cmd GOOS=darwin GOARCH=amd64 go build -ldflags "-X main.Version=$(VERSION)" -o server/$(BINARY_NAME)-darwin-amd64 ./cmd GOOS=linux GOARCH=amd64 go build -ldflags "-X main.Version=$(VERSION)" -o server/$(BINARY_NAME)-linux-amd64 ./cmd @@ -21,11 +21,60 @@ build-dxt: chmod +x server/$(BINARY_NAME)-* @echo "All platform binaries built in server/ directory" -# Package DXT extension -pack-dxt: build-dxt - @echo "Packaging DXT extension..." - dxt pack - @echo "DXT package created: $(BINARY_NAME).dxt" +# Build MCPB bundle +build-mcpb: build-platform-binaries + @echo "Creating MCPB bundle..." + @if [ ! -f "manifest.json" ]; then \ + echo "Error: manifest.json not found"; \ + exit 1; \ + fi + mkdir -p mcpb-bundle/server + cp server/* mcpb-bundle/server/ + # Update version and name in manifest.json to match build version and binary name + sed -e 's/"version": ".*"/"version": "$(VERSION)"/' -e 's/"name": "$(BINARY_NAME)"/"name": "$(BINARY_NAME)"/' manifest.json > mcpb-bundle/manifest.json + cd mcpb-bundle && zip -r ../$(BINARY_NAME).mcpb . && cd .. + rm -rf mcpb-bundle + @echo "MCPB bundle created: $(BINARY_NAME).mcpb" + +# Pack MCPB from GoReleaser dist/ folder +pack-mcpb-from-dist: + @echo "Creating MCPB bundle from GoReleaser binaries..." + mkdir -p mcpb-bundle/server + @# Copy specific platform binaries with explicit names + @found_count=0; \ + for platform in "linux_amd64" "darwin_amd64" "darwin_arm64" "windows_amd64"; do \ + found=$$(find dist -path "*_$${platform}_*" -name "$(BINARY_NAME)*" -type f | head -1); \ + if [ -n "$$found" ]; then \ + case "$$platform" in \ + "linux_amd64") cp "$$found" "mcpb-bundle/server/$(BINARY_NAME)-linux-amd64" ;; \ + "darwin_amd64") cp "$$found" "mcpb-bundle/server/$(BINARY_NAME)-darwin-amd64" ;; \ + "darwin_arm64") cp "$$found" "mcpb-bundle/server/$(BINARY_NAME)-darwin-arm64" ;; \ + "windows_amd64") cp "$$found" "mcpb-bundle/server/$(BINARY_NAME)-windows-amd64.exe" ;; \ + esac; \ + echo "Copied $$found -> $(BINARY_NAME)-$$platform"; \ + found_count=$$((found_count + 1)); \ + else \ + echo "Warning: No binary found for $$platform"; \ + fi; \ + done; \ + if [ $$found_count -eq 0 ]; then \ + echo "Error: No binaries found in dist/ directory"; \ + exit 1; \ + fi + @if [ ! -f "manifest.json" ]; then \ + echo "Error: manifest.json not found"; \ + rm -rf mcpb-bundle; \ + exit 1; \ + fi + # Update version and name in manifest.json to match GoReleaser version and binary name + @if [ -n "$(GORELEASER_VERSION)" ]; then \ + sed -e 's/"version": ".*"/"version": "$(GORELEASER_VERSION)"/' -e 's/"name": "$(BINARY_NAME)"/"name": "$(BINARY_NAME)"/' manifest.json > mcpb-bundle/manifest.json; \ + else \ + sed -e 's/"version": ".*"/"version": "$(VERSION)"/' -e 's/"name": "$(BINARY_NAME)"/"name": "$(BINARY_NAME)"/' manifest.json > mcpb-bundle/manifest.json; \ + fi + cd mcpb-bundle && zip -r ../$(BINARY_NAME).mcpb . && cd .. + rm -rf mcpb-bundle + @echo "MCPB bundle created: $(BINARY_NAME).mcpb" # Run tests test: @@ -35,7 +84,9 @@ test: clean: rm -rf $(BUILD_DIR) rm -rf server - rm -f $(BINARY_NAME).dxt $(BINARY_NAME)-*.dxt + rm -rf mcpb-bundle + rm -rf dist + rm -f $(BINARY_NAME).mcpb # Run the application in development mode run-dev: @@ -44,9 +95,10 @@ run-dev: # Create a release snapshot using GoReleaser release-snapshot: goreleaser release --snapshot --clean + make pack-mcpb-from-dist # Run the application using the built binary -run: +run: build ./$(BUILD_DIR)/$(BINARY_NAME) # Build and run Docker image diff --git a/manifest.json b/manifest.json index e216d5b..9f1f976 100644 --- a/manifest.json +++ b/manifest.json @@ -1,8 +1,8 @@ { - "dxt_version": "0.1", + "manifest_version": "0.1", "name": "mcp-trino", "display_name": "Trino MCP Server", - "version": "1.5.0", + "version": "2.2.1", "description": "A high-performance Model Context Protocol (MCP) server that enables AI assistants to interact with Trino's distributed SQL query engine through standardized MCP tools", "long_description": "This MCP server provides comprehensive access to Trino's distributed SQL query engine with features including:\n\n- Execute SQL queries with security restrictions\n- Discover catalogs, schemas, and tables\n- Retrieve table structure and column information\n- SSL/TLS support for secure connections\n- Configurable query timeouts\n- Cross-platform binaries for macOS, Windows, and Linux\n\nCompatible with Claude Desktop, Cursor, Windsurf, ChatWise, and any MCP-compatible clients.", "author": { @@ -17,15 +17,18 @@ "support": "https://github.com/tuannvm/mcp-trino/issues", "license": "MIT", "compatibility": { - "claude_desktop": ">=0.10.0", + "claude_desktop": ">=0.12.129", "platforms": ["darwin", "win32", "linux"] }, "server": { "type": "binary", - "entry_point": "server/mcp-trino-darwin-arm64", + "entry_point": { + "darwin-arm64": "server/mcp-trino-darwin-arm64", + "darwin-amd64": "server/mcp-trino-darwin-amd64", + "linux-amd64": "server/mcp-trino-linux-amd64", + "win32-amd64": "server/mcp-trino-windows-amd64.exe" + }, "mcp_config": { - "command": "sh", - "args": ["-c", "chmod +x \"${__dirname}/server/mcp-trino-darwin-arm64\" && \"${__dirname}/server/mcp-trino-darwin-arm64\""], "env": { "TRINO_HOST": "${user_config.trino_host}", "TRINO_PORT": "${user_config.trino_port}", @@ -36,15 +39,6 @@ "TRINO_SSL_INSECURE": "${user_config.trino_ssl_insecure}", "TRINO_ALLOW_WRITE_QUERIES": "${user_config.trino_allow_write_queries}", "TRINO_QUERY_TIMEOUT": "${user_config.trino_query_timeout}" - }, - "platforms": { - "win32": { - "command": "${__dirname}/server/mcp-trino-windows-amd64.exe" - }, - "linux": { - "command": "sh", - "args": ["-c", "chmod +x \"${__dirname}/server/mcp-trino-linux-amd64\" && \"${__dirname}/server/mcp-trino-linux-amd64\""] - } } } }, @@ -134,15 +128,10 @@ { "name": "get_table_schema", "description": "Retrieve table structure and column information" + }, + { + "name": "explain_query", + "description": "Analyze query execution plans without running expensive queries" } - ], - "features": [ - "STDIO and HTTP transport support", - "Server-Sent Events (SSE) for web clients", - "SQL injection protection with read-only enforcement", - "Configurable query timeouts", - "SSL/TLS support for secure connections", - "Multi-platform binary support", - "Docker container support" ] } diff --git a/server.json b/server.json new file mode 100644 index 0000000..c87ddee --- /dev/null +++ b/server.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json", + "name": "io.github.tuannvm/mcp-trino", + "description": "MCP server for Trino distributed SQL query engine access", + "status": "active", + "repository": { + "url": "https://github.com/tuannvm/mcp-trino", + "source": "github" + }, + "version": "2.2.1", + "packages": [ + { + "registry_type": "mcpb", + "identifier": "https://github.com/tuannvm/mcp-trino/releases/download/v2.2.1/mcp-trino.mcpb", + "version": "2.2.1", + "file_sha256": "PLACEHOLDER_SHA256", + "transport": { + "type": "stdio" + }, + "environment_variables": [ + { + "description": "Trino server hostname", + "is_required": true, + "format": "string", + "is_secret": false, + "name": "TRINO_HOST" + }, + { + "description": "Trino server port", + "is_required": false, + "format": "string", + "is_secret": false, + "name": "TRINO_PORT" + }, + { + "description": "Trino username", + "is_required": true, + "format": "string", + "is_secret": false, + "name": "TRINO_USER" + }, + { + "description": "Trino password", + "is_required": false, + "format": "string", + "is_secret": true, + "name": "TRINO_PASSWORD" + } + ] + } + ] +} \ No newline at end of file