Initial commit: Flipside Intelligence MCP Extension

- Add Go-based MCP proxy for Flipside Intelligence blockchain analytics
- Configure project structure with proper Go module naming
- Include comprehensive README focused on product vision
- Add manifest.json for Claude Desktop integration
- Setup build automation with Makefile and test scripts
- Configure .gitignore for Go project best practices

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Erik Brakke 2025-07-01 14:06:57 -06:00
commit a179b10854
10 changed files with 926 additions and 0 deletions

56
.gitignore vendored Normal file
View File

@ -0,0 +1,56 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
go.work.sum
# Build artifacts
dist/
build/
bin/
# IDE files
.vscode/
.idea/
*.swp
*.swo
*~
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Environment files
.env
.env.local
.env.*.local
# Log files
*.log
# Temporary files
tmp/
temp/
# Binary output
remote-mcp-proxy
flipside-mcp-extension

167
Makefile Normal file
View File

@ -0,0 +1,167 @@
.PHONY: build build-all clean test dxt dist deps help
# Default target
help:
@echo "Available targets:"
@echo " build - Build for current platform"
@echo " build-all - Build for all supported platforms"
@echo " dxt - Create DXT packages using official dxt CLI (recommended)"
@echo " dist - Create legacy zip-based packages"
@echo " test - Test the binary"
@echo " clean - Clean build artifacts"
@echo " deps - Install dependencies"
@echo " help - Show this help message"
# Default build for current platform
build:
go build -ldflags="-s -w" -o remote-mcp-proxy .
chmod +x remote-mcp-proxy
# Build for all supported platforms
build-all: clean
# macOS
GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w" -o dist/remote-mcp-proxy-darwin-amd64 .
chmod +x dist/remote-mcp-proxy-darwin-amd64
GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o dist/remote-mcp-proxy-darwin-arm64 .
chmod +x dist/remote-mcp-proxy-darwin-arm64
# Linux
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o dist/remote-mcp-proxy-linux-amd64 .
chmod +x dist/remote-mcp-proxy-linux-amd64
GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o dist/remote-mcp-proxy-linux-arm64 .
chmod +x dist/remote-mcp-proxy-linux-arm64
# Windows
GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o dist/remote-mcp-proxy-windows-amd64.exe .
chmod +x dist/remote-mcp-proxy-windows-amd64.exe
GOOS=windows GOARCH=arm64 go build -ldflags="-s -w" -o dist/remote-mcp-proxy-windows-arm64.exe .
chmod +x dist/remote-mcp-proxy-windows-arm64.exe
# Create DXT packages using official dxt CLI
dxt: build-all
mkdir -p dist/dxt-staging
# macOS x64
mkdir -p dist/dxt-staging/darwin-amd64
cp dist/remote-mcp-proxy-darwin-amd64 dist/dxt-staging/darwin-amd64/remote-mcp-proxy
chmod +x dist/dxt-staging/darwin-amd64/remote-mcp-proxy
@echo "Verifying permissions for darwin-amd64:"
@ls -la dist/dxt-staging/darwin-amd64/remote-mcp-proxy
cp manifest.json dist/dxt-staging/darwin-amd64/
cp README.md dist/dxt-staging/darwin-amd64/ 2>/dev/null || true
cd dist/dxt-staging/darwin-amd64 && npx @anthropic-ai/dxt pack . ../flipside-remote-mcp-proxy-darwin-amd64.dxt
# macOS ARM64
mkdir -p dist/dxt-staging/darwin-arm64
cp dist/remote-mcp-proxy-darwin-arm64 dist/dxt-staging/darwin-arm64/remote-mcp-proxy
chmod +x dist/dxt-staging/darwin-arm64/remote-mcp-proxy
@echo "Verifying permissions for darwin-arm64:"
@ls -la dist/dxt-staging/darwin-arm64/remote-mcp-proxy
cp manifest.json dist/dxt-staging/darwin-arm64/
cp README.md dist/dxt-staging/darwin-arm64/ 2>/dev/null || true
cd dist/dxt-staging/darwin-arm64 && npx @anthropic-ai/dxt pack . ../flipside-remote-mcp-proxy-darwin-arm64.dxt
# Linux x64
mkdir -p dist/dxt-staging/linux-amd64
cp dist/remote-mcp-proxy-linux-amd64 dist/dxt-staging/linux-amd64/remote-mcp-proxy
chmod +x dist/dxt-staging/linux-amd64/remote-mcp-proxy
cp manifest.json dist/dxt-staging/linux-amd64/
cp README.md dist/dxt-staging/linux-amd64/ 2>/dev/null || true
cd dist/dxt-staging/linux-amd64 && npx @anthropic-ai/dxt pack . ../flipside-remote-mcp-proxy-linux-amd64.dxt
# Linux ARM64
mkdir -p dist/dxt-staging/linux-arm64
cp dist/remote-mcp-proxy-linux-arm64 dist/dxt-staging/linux-arm64/remote-mcp-proxy
chmod +x dist/dxt-staging/linux-arm64/remote-mcp-proxy
cp manifest.json dist/dxt-staging/linux-arm64/
cp README.md dist/dxt-staging/linux-arm64/ 2>/dev/null || true
cd dist/dxt-staging/linux-arm64 && npx @anthropic-ai/dxt pack . ../flipside-remote-mcp-proxy-linux-arm64.dxt
# Windows x64
mkdir -p dist/dxt-staging/windows-amd64
cp dist/remote-mcp-proxy-windows-amd64.exe dist/dxt-staging/windows-amd64/remote-mcp-proxy.exe
chmod +x dist/dxt-staging/windows-amd64/remote-mcp-proxy.exe
cp manifest.json dist/dxt-staging/windows-amd64/
cp README.md dist/dxt-staging/windows-amd64/ 2>/dev/null || true
cd dist/dxt-staging/windows-amd64 && npx @anthropic-ai/dxt pack . ../flipside-remote-mcp-proxy-windows-amd64.dxt
# Windows ARM64
mkdir -p dist/dxt-staging/windows-arm64
cp dist/remote-mcp-proxy-windows-arm64.exe dist/dxt-staging/windows-arm64/remote-mcp-proxy.exe
chmod +x dist/dxt-staging/windows-arm64/remote-mcp-proxy.exe
cp manifest.json dist/dxt-staging/windows-arm64/
cp README.md dist/dxt-staging/windows-arm64/ 2>/dev/null || true
cd dist/dxt-staging/windows-arm64 && npx @anthropic-ai/dxt pack . ../flipside-remote-mcp-proxy-windows-arm64.dxt
# Move final DXT files to dist root
mv dist/dxt-staging/*.dxt dist/
@echo "DXT packages created:"
@ls -la dist/*.dxt
@echo ""
@echo "Alternative: Create tar.gz packages that preserve permissions:"
@cd dist/dxt-staging/darwin-amd64 && tar -czf ../../flipside-remote-mcp-proxy-darwin-amd64.tar.gz .
@cd dist/dxt-staging/darwin-arm64 && tar -czf ../../flipside-remote-mcp-proxy-darwin-arm64.tar.gz .
@ls -la dist/*.tar.gz
# Legacy zip-based distribution (kept for compatibility)
dist: build-all
mkdir -p dist/dxt
# macOS x64
mkdir -p dist/dxt/flipside-remote-mcp-proxy-darwin-amd64
cp dist/remote-mcp-proxy-darwin-amd64 dist/dxt/flipside-remote-mcp-proxy-darwin-amd64/remote-mcp-proxy
cp manifest.json dist/dxt/flipside-remote-mcp-proxy-darwin-amd64/
cp README.md dist/dxt/flipside-remote-mcp-proxy-darwin-amd64/ 2>/dev/null || true
cd dist/dxt && zip -r flipside-remote-mcp-proxy-darwin-amd64.dxt flipside-remote-mcp-proxy-darwin-amd64/
# macOS ARM64
mkdir -p dist/dxt/flipside-remote-mcp-proxy-darwin-arm64
cp dist/remote-mcp-proxy-darwin-arm64 dist/dxt/flipside-remote-mcp-proxy-darwin-arm64/remote-mcp-proxy
cp manifest.json dist/dxt/flipside-remote-mcp-proxy-darwin-arm64/
cp README.md dist/dxt/flipside-remote-mcp-proxy-darwin-arm64/ 2>/dev/null || true
cd dist/dxt && zip -r flipside-remote-mcp-proxy-darwin-arm64.dxt flipside-remote-mcp-proxy-darwin-arm64/
# Linux x64
mkdir -p dist/dxt/flipside-remote-mcp-proxy-linux-amd64
cp dist/remote-mcp-proxy-linux-amd64 dist/dxt/flipside-remote-mcp-proxy-linux-amd64/remote-mcp-proxy
cp manifest.json dist/dxt/flipside-remote-mcp-proxy-linux-amd64/
cp README.md dist/dxt/flipside-remote-mcp-proxy-linux-amd64/ 2>/dev/null || true
cd dist/dxt && zip -r flipside-remote-mcp-proxy-linux-amd64.dxt flipside-remote-mcp-proxy-linux-amd64/
# Linux ARM64
mkdir -p dist/dxt/flipside-remote-mcp-proxy-linux-arm64
cp dist/remote-mcp-proxy-linux-arm64 dist/dxt/flipside-remote-mcp-proxy-linux-arm64/remote-mcp-proxy
cp manifest.json dist/dxt/flipside-remote-mcp-proxy-linux-arm64/
cp README.md dist/dxt/flipside-remote-mcp-proxy-linux-arm64/ 2>/dev/null || true
cd dist/dxt && zip -r flipside-remote-mcp-proxy-linux-arm64.dxt flipside-remote-mcp-proxy-linux-arm64/
# Windows x64
mkdir -p dist/dxt/flipside-remote-mcp-proxy-windows-amd64
cp dist/remote-mcp-proxy-windows-amd64.exe dist/dxt/flipside-remote-mcp-proxy-windows-amd64/remote-mcp-proxy.exe
cp manifest.json dist/dxt/flipside-remote-mcp-proxy-windows-amd64/
cp README.md dist/dxt/flipside-remote-mcp-proxy-windows-amd64/ 2>/dev/null || true
cd dist/dxt && zip -r flipside-remote-mcp-proxy-windows-amd64.dxt flipside-remote-mcp-proxy-windows-amd64/
# Windows ARM64
mkdir -p dist/dxt/flipside-remote-mcp-proxy-windows-arm64
cp dist/remote-mcp-proxy-windows-arm64.exe dist/dxt/flipside-remote-mcp-proxy-windows-arm64/remote-mcp-proxy.exe
cp manifest.json dist/dxt/flipside-remote-mcp-proxy-windows-arm64/
cp README.md dist/dxt/flipside-remote-mcp-proxy-windows-arm64/ 2>/dev/null || true
cd dist/dxt && zip -r flipside-remote-mcp-proxy-windows-arm64.dxt flipside-remote-mcp-proxy-windows-arm64/
# Test the binary
test: build
@echo "Testing binary..."
@echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | MCP_REMOTE_URL=http://localhost:8080 ./remote-mcp-proxy
# Clean build artifacts
clean:
rm -rf dist/
rm -f remote-mcp-proxy remote-mcp-proxy.exe
# Install dependencies
deps:
go mod tidy
go mod download

171
README.md Normal file
View File

@ -0,0 +1,171 @@
# Flipside Intelligence via MCP
## What it is
An AI agent that acts as your personal blockchain data scientist, accessible directly through Claude Desktop via Model Context Protocol (MCP).
## How it works
Natural language interface to Flipside's curated blockchain datasets and embedded analytical workflows. Simply ask questions in plain English and get sophisticated blockchain analytics instantly.
## Key capabilities
- **Complex Analysis Made Simple**: Execute cohort analysis, user journey mapping, and trend detection through conversational queries
- **Comprehensive Data Access**: Query data across 30+ blockchain networks with billions of indexed transactions
- **Proprietary Insights**: Access Flipside's specialized scoring algorithms and predictive metrics
- **Domain Expertise**: Leverage years of blockchain growth intelligence embedded in AI workflows
## The Vision
Democratize blockchain data science expertise. For the first time, any stakeholder—from ecosystem CEOs to community managers—can conduct sophisticated blockchain analysis without years of technical training.
## Integration
Available through Claude Desktop's MCP integration, bringing enterprise-grade blockchain analytics directly into your workflow without switching tools or platforms.
---
*Flipside Intelligence transforms specialized data science expertise into accessible AI-powered tools, making blockchain growth insights available to everyone.*
## Technical Features
- **Zero Dependencies**: Self-contained Go binary with no runtime requirements
- **Cross-Platform**: Supports macOS, Linux, and Windows (x64 and ARM64)
- **Secure Connection**: Environment-based configuration with encrypted API key authentication
- **Real-time Analytics**: Direct access to live blockchain data streams
- **Optimized Performance**: Lightweight proxy design for seamless Claude Desktop integration
## Configuration
The proxy is configured via environment variables:
| Variable | Required | Description | Example |
|----------|----------|-------------|---------|
| `MCP_REMOTE_URL` | Yes | Flipside Intelligence MCP endpoint | `https://mcp.flipsidecrypto.xyz/beta/sse` |
| `FLIPSIDE_API_KEY` | Yes | Your Flipside API key for authenticated access | `your-api-key-here` |
| `MCP_DEBUG` | No | Enable debug logging | `true` or `false` |
## Installation
### As a Claude Desktop Extension (Recommended)
1. Download the appropriate `.dxt` file for your platform from releases
2. Import the DXT file into Claude Desktop
3. Configure your Flipside API key and MCP endpoint in the extension settings
4. Start analyzing blockchain data with natural language queries in Claude Desktop
### Manual Installation
1. Download the binary for your platform:
- macOS (Intel): `remote-mcp-proxy-darwin-amd64`
- macOS (Apple Silicon): `remote-mcp-proxy-darwin-arm64`
- Linux (x64): `remote-mcp-proxy-linux-amd64`
- Linux (ARM64): `remote-mcp-proxy-linux-arm64`
- Windows (x64): `remote-mcp-proxy-windows-amd64.exe`
- Windows (ARM64): `remote-mcp-proxy-windows-arm64.exe`
2. Make executable (Unix-like systems):
```bash
chmod +x remote-mcp-proxy-*
```
3. Configure environment variables:
```bash
export MCP_REMOTE_URL="https://mcp.flipsidecrypto.xyz/beta/sse"
export FLIPSIDE_API_KEY="your-api-key-here"
export MCP_DEBUG="false" # Optional
```
4. Run the proxy:
```bash
./remote-mcp-proxy-darwin-amd64
```
## Usage Examples
Once connected through Claude Desktop, you can ask natural language questions like:
- "Show me the top 10 DeFi protocols by TVL on Ethereum this week"
- "Analyze user retention patterns for Uniswap v3 over the last 6 months"
- "What's the correlation between gas prices and DEX trading volume?"
- "Create a cohort analysis of new wallet addresses on Polygon"
The extension handles all the technical complexity, translating your questions into sophisticated blockchain queries and returning actionable insights.
## Getting Your API Key
To access Flipside Intelligence:
1. Visit [flipsidecrypto.xyz](https://flipsidecrypto.xyz)
2. Create an account or sign in
3. Navigate to your API settings to generate your key
4. Use this key in the extension configuration
## Development
### Building from Source
```bash
# Install dependencies
make deps
# Build for current platform
make build
# Build for all platforms
make build-all
# Create DXT packages using official dxt CLI (recommended)
make dxt
# Create legacy zip-based packages
make dist
```
**Note**: The `make dxt` command requires Node.js and uses `npx @anthropic-ai/dxt` to create properly formatted DXT packages. This is the recommended approach for creating packages compatible with Claude Desktop.
### Project Structure
```
pkg/remote-mcp-proxy/
├── main.go # Main proxy implementation
├── manifest.json # DXT manifest file
├── Makefile # Build automation
├── README.md # This file
├── go.mod # Go module definition
└── dist/ # Build artifacts (created by make)
```
### Dependencies
- [mark3labs/mcp-go](https://github.com/mark3labs/mcp-go) - MCP protocol implementation
## Security Considerations
- The proxy forwards all requests to the configured remote URL
- Ensure your remote MCP server implements proper authentication and authorization
- Use HTTPS URLs for production deployments
- Consider network timeouts and rate limiting on the server side
## Troubleshooting
### Enable Debug Logging
Set `MCP_DEBUG=true` to see detailed request/response logs:
```bash
MCP_DEBUG=true MCP_REMOTE_URL=https://mcp.flipsidecrypto.xyz/beta/sse FLIPSIDE_API_KEY=your-key ./flipside-mcp-extension
```
### Common Issues
1. **Authentication failed**: Verify your Flipside API key is correct and active
2. **Connection refused**: Check your internet connection and firewall settings
3. **Timeout errors**: Large queries may take time; try breaking them into smaller requests
4. **Rate limiting**: Ensure you're within your API plan limits
## License
MIT License - see the project root for details.
## Support
For issues and questions:
- GitHub Issues: [flipside-org/flipside-mcp-extension](https://github.com/flipside-org/flipside-mcp-extension/issues)
- Documentation: [docs.flipsidecrypto.xyz](https://docs.flipsidecrypto.xyz)
- Email: support@flipside.xyz

11
go.mod Normal file
View File

@ -0,0 +1,11 @@
module github.com/flipside-org/flipside-mcp-extension
go 1.24.3
require github.com/mark3labs/mcp-go v0.32.0
require (
github.com/google/uuid v1.6.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
)

26
go.sum Normal file
View File

@ -0,0 +1,26 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mark3labs/mcp-go v0.32.0 h1:fgwmbfL2gbd67obg57OfV2Dnrhs1HtSdlY/i5fn7MU8=
github.com/mark3labs/mcp-go v0.32.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

286
main.go Normal file
View File

@ -0,0 +1,286 @@
package main
import (
"context"
"fmt"
"io"
"log"
"net/url"
"os"
"strconv"
"strings"
"time"
"github.com/mark3labs/mcp-go/client"
"github.com/mark3labs/mcp-go/client/transport"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
type MCPProxy struct {
remoteURL string
apiKey string
debug bool
logger *log.Logger
client *client.Client
server *server.MCPServer
}
func NewMCPProxy(remoteURL, apiKey string, debug bool) *MCPProxy {
logger := log.New(os.Stderr, "[MCP-PROXY] ", log.LstdFlags)
if !debug {
logger.SetOutput(io.Discard)
}
// Convert /sse to /mcp if needed
if strings.Contains(remoteURL, "/sse") {
remoteURL = strings.Replace(remoteURL, "/sse", "/mcp", 1)
logger.Printf("Converted SSE URL to MCP URL: %s", remoteURL)
}
return &MCPProxy{
remoteURL: remoteURL,
apiKey: apiKey,
debug: debug,
logger: logger,
}
}
func (p *MCPProxy) createRemoteClient() error {
p.logger.Printf("Creating remote MCP client for: %s", p.remoteURL)
// Parse URL and add API key as query parameter
parsedURL, err := url.Parse(p.remoteURL)
if err != nil {
return fmt.Errorf("failed to parse remote URL: %w", err)
}
query := parsedURL.Query()
query.Set("apiKey", p.apiKey)
parsedURL.RawQuery = query.Encode()
finalURL := parsedURL.String()
p.logger.Printf("Final remote URL: %s", finalURL)
// Create headers with API key
headers := map[string]string{
"Authorization": "Bearer " + p.apiKey,
"User-Agent": "flipside-mcp-proxy/1.0",
}
// Create streamable HTTP client options
options := []transport.StreamableHTTPCOption{
transport.WithHTTPHeaders(headers),
transport.WithHTTPTimeout(30 * time.Second),
}
// Create the MCP client
mcpClient, err := client.NewStreamableHttpClient(finalURL, options...)
if err != nil {
return fmt.Errorf("failed to create MCP client: %w", err)
}
p.client = mcpClient
return nil
}
func (p *MCPProxy) setupProxyServer(ctx context.Context) error {
p.logger.Printf("Setting up MCP proxy server")
// Create MCP server
mcpServer := server.NewMCPServer("flipside-remote-mcp-proxy", "1.0.0")
// Initialize remote client first
p.logger.Printf("Initializing remote client...")
_, err := p.client.Initialize(ctx, mcp.InitializeRequest{
Params: mcp.InitializeParams{
ProtocolVersion: "2024-11-05",
Capabilities: mcp.ClientCapabilities{},
ClientInfo: mcp.Implementation{
Name: "flipside-remote-mcp-proxy",
Version: "1.0.0",
},
},
})
if err != nil {
return fmt.Errorf("failed to initialize remote client: %w", err)
}
p.logger.Printf("Remote client initialized successfully")
// Get tools from remote and add them to proxy server
if err := p.addRemoteToolsToServer(ctx, mcpServer); err != nil {
return fmt.Errorf("failed to add remote tools: %w", err)
}
// Try to add resources and prompts (may not be supported)
p.addRemoteResourcesToServer(ctx, mcpServer)
p.addRemotePromptsToServer(ctx, mcpServer)
p.server = mcpServer
return nil
}
func (p *MCPProxy) addRemoteToolsToServer(ctx context.Context, mcpServer *server.MCPServer) error {
p.logger.Printf("Adding remote tools to proxy server")
// List tools from remote client
toolsResponse, err := p.client.ListTools(ctx, mcp.ListToolsRequest{})
if err != nil {
p.logger.Printf("Failed to list remote tools: %v", err)
return err
}
p.logger.Printf("Found %d remote tools", len(toolsResponse.Tools))
// Add each tool to the proxy server
for _, tool := range toolsResponse.Tools {
p.logger.Printf("Adding tool: %s", tool.Name)
// Create a closure to capture the tool
currentTool := tool
mcpServer.AddTool(currentTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
p.logger.Printf("Proxying tool call: %s", currentTool.Name)
// Forward the tool call to the remote client
response, err := p.client.CallTool(ctx, mcp.CallToolRequest{
Params: mcp.CallToolParams{
Name: request.Params.Name,
Arguments: request.Params.Arguments,
},
})
if err != nil {
p.logger.Printf("Error calling remote tool %s: %v", currentTool.Name, err)
return nil, err
}
return response, nil
})
}
return nil
}
func (p *MCPProxy) addRemoteResourcesToServer(ctx context.Context, mcpServer *server.MCPServer) {
p.logger.Printf("Adding remote resources to proxy server")
// List resources from remote client
resourcesResponse, err := p.client.ListResources(ctx, mcp.ListResourcesRequest{})
if err != nil {
p.logger.Printf("Remote server doesn't support resources: %v", err)
return
}
p.logger.Printf("Found %d remote resources", len(resourcesResponse.Resources))
// Add each resource to the proxy server
for _, resource := range resourcesResponse.Resources {
p.logger.Printf("Adding resource: %s", resource.URI)
mcpServer.AddResource(resource, func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
p.logger.Printf("Proxying read resource: %s", request.Params.URI)
response, err := p.client.ReadResource(ctx, request)
if err != nil {
return nil, err
}
return response.Contents, nil
})
}
}
func (p *MCPProxy) addRemotePromptsToServer(ctx context.Context, mcpServer *server.MCPServer) {
p.logger.Printf("Adding remote prompts to proxy server")
// List prompts from remote client
promptsResponse, err := p.client.ListPrompts(ctx, mcp.ListPromptsRequest{})
if err != nil {
p.logger.Printf("Remote server doesn't support prompts: %v", err)
return
}
p.logger.Printf("Found %d remote prompts", len(promptsResponse.Prompts))
// Add each prompt to the proxy server
for _, prompt := range promptsResponse.Prompts {
p.logger.Printf("Adding prompt: %s", prompt.Name)
currentPrompt := prompt
mcpServer.AddPrompt(currentPrompt, func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
p.logger.Printf("Proxying get prompt: %s", request.Params.Name)
response, err := p.client.GetPrompt(ctx, request)
if err != nil {
return nil, err
}
return response, nil
})
}
}
func (p *MCPProxy) run() error {
ctx := context.Background()
// Create remote client
if err := p.createRemoteClient(); err != nil {
return fmt.Errorf("failed to create remote client: %w", err)
}
// Setup proxy server (this initializes the remote client and discovers tools)
if err := p.setupProxyServer(ctx); err != nil {
return fmt.Errorf("failed to setup proxy server: %w", err)
}
p.logger.Printf("Starting MCP proxy server with stdio transport")
p.logger.Printf("Remote URL: %s", p.remoteURL)
p.logger.Printf("Debug mode: %v", p.debug)
// Start the proxy server with stdio transport
if err := server.ServeStdio(p.server); err != nil {
return fmt.Errorf("server error: %w", err)
}
return nil
}
func maskAPIKey(apiKey string) string {
if len(apiKey) <= 8 {
return "***"
}
return apiKey[:4] + "..." + apiKey[len(apiKey)-4:]
}
func main() {
// Always enable initial logging to stderr for startup diagnostics
startupLogger := log.New(os.Stderr, "[MCP-PROXY-STARTUP] ", log.LstdFlags)
startupLogger.Println("Starting Flipside MCP Remote Proxy...")
remoteURL := os.Getenv("MCP_REMOTE_URL")
if remoteURL == "" {
startupLogger.Fatal("ERROR: MCP_REMOTE_URL environment variable is required")
}
startupLogger.Printf("Remote URL configured: %s", remoteURL)
apiKey := os.Getenv("FLIPSIDE_API_KEY")
if apiKey == "" {
startupLogger.Fatal("ERROR: FLIPSIDE_API_KEY environment variable is required")
}
startupLogger.Printf("API key configured: %s", maskAPIKey(apiKey))
debugStr := os.Getenv("MCP_DEBUG")
debug, _ := strconv.ParseBool(debugStr)
startupLogger.Printf("Debug mode: %v", debug)
proxy := NewMCPProxy(remoteURL, apiKey, debug)
startupLogger.Println("Starting MCP proxy with mcp-go client/server architecture...")
if err := proxy.run(); err != nil {
startupLogger.Fatalf("Proxy error: %v", err)
}
}

59
manifest.json Normal file
View File

@ -0,0 +1,59 @@
{
"dxt_version": "1.0",
"name": "flipside-intelligence-mcp",
"version": "1.0.0",
"display_name": "Flipside Intelligence",
"description": "Your personal blockchain data scientist via MCP",
"long_description": "AI-powered blockchain analytics accessible through Claude Desktop. Execute sophisticated blockchain analysis with natural language queries - from cohort analysis to trend detection across 30+ networks with billions of indexed transactions.",
"author": {
"name": "Flipside",
"email": "support@flipside.xyz",
"url": "https://flipside.xyz"
},
"repository": {
"type": "git",
"url": "https://github.com/flipside-org/flipside-mcp-extension"
},
"homepage": "https://flipside.xyz",
"license": "MIT",
"keywords": ["blockchain", "analytics", "data-science", "mcp", "flipside", "defi", "crypto", "intelligence"],
"server": {
"type": "binary",
"entry_point": "${__dirname}/remote-mcp-proxy",
"mcp_config": {
"command": "${__dirname}/remote-mcp-proxy",
"env": {
"MCP_REMOTE_URL": "${user_config.remote_url}",
"MCP_DEBUG": "${user_config.debug}",
"FLIPSIDE_API_KEY": "${user_config.api_key}"
}
}
},
"user_config": {
"remote_url": {
"type": "string",
"title": "Flipside Intelligence Endpoint",
"description": "The MCP endpoint for Flipside Intelligence services",
"required": true,
"default": "https://mcp.flipsidecrypto.xyz/beta/sse"
},
"api_key": {
"type": "string",
"title": "Flipside API Key",
"description": "Your Flipside API key for authenticated access",
"required": true,
"sensitive": true
},
"debug": {
"type": "boolean",
"title": "Enable Debug Mode",
"description": "Enable verbose logging for troubleshooting queries and connections",
"required": false,
"default": false
}
},
"compatibility": {
"platforms": ["darwin", "linux", "win32"],
"architectures": ["amd64", "arm64"]
}
}

45
test-interactive.sh Executable file
View File

@ -0,0 +1,45 @@
#!/bin/bash
# Interactive test script for MCP remote proxy
# Starts the proxy and lets you send JSON-RPC messages manually
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Configuration
REMOTE_URL="${MCP_REMOTE_URL:-https://mcp.flipsidecrypto.xyz/beta/sse}"
API_KEY="${FLIPSIDE_API_KEY}"
DEBUG="${MCP_DEBUG:-true}"
if [ -z "$API_KEY" ]; then
echo -e "${RED}Error: FLIPSIDE_API_KEY environment variable is required${NC}"
echo "Usage: FLIPSIDE_API_KEY=your_key ./test-interactive.sh"
exit 1
fi
# Build if needed
if [ ! -f "./remote-mcp-proxy" ]; then
echo -e "${YELLOW}Building proxy binary...${NC}"
go build -o remote-mcp-proxy .
fi
echo -e "${BLUE}🔧 Starting MCP Remote Proxy in interactive mode${NC}"
echo -e "${BLUE}Remote URL: ${REMOTE_URL}${NC}"
echo -e "${BLUE}Debug Mode: ${DEBUG}${NC}"
echo ""
echo -e "${YELLOW}💡 Usage:${NC}"
echo -e " • Type JSON-RPC messages and press Enter"
echo -e " • Try: {\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}"
echo -e " • Press Ctrl+C to exit"
echo ""
echo -e "${GREEN}🚀 Proxy is ready! Enter JSON-RPC messages:${NC}"
echo ""
# Start the proxy with environment variables
exec env MCP_REMOTE_URL="$REMOTE_URL" FLIPSIDE_API_KEY="$API_KEY" MCP_DEBUG="$DEBUG" ./remote-mcp-proxy

83
test-proxy.sh Executable file
View File

@ -0,0 +1,83 @@
#!/bin/bash
# Test script for the MCP remote proxy
# This simulates how Claude Desktop would interact with the proxy
set -e
# Colors for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
REMOTE_URL="${MCP_REMOTE_URL:-https://mcp.flipsidecrypto.xyz/beta/sse}"
API_KEY="${FLIPSIDE_API_KEY}"
DEBUG="${MCP_DEBUG:-true}"
if [ -z "$API_KEY" ]; then
echo "Error: FLIPSIDE_API_KEY environment variable is required"
echo "Usage: FLIPSIDE_API_KEY=your_key ./test-proxy.sh"
exit 1
fi
echo -e "${BLUE}🧪 Testing MCP Remote Proxy${NC}"
echo -e "${BLUE}Remote URL: ${REMOTE_URL}${NC}"
echo -e "${BLUE}Debug Mode: ${DEBUG}${NC}"
echo -e "${BLUE}API Key: ${API_KEY:0:8}...${NC}"
echo ""
# Build the proxy if it doesn't exist
if [ ! -f "./remote-mcp-proxy" ]; then
echo -e "${YELLOW}Building proxy binary...${NC}"
go build -o remote-mcp-proxy .
fi
# Function to test a message
test_message() {
local message="$1"
local description="$2"
echo -e "${YELLOW}📤 Testing: ${description}${NC}"
echo -e "${BLUE}Message: ${message}${NC}"
echo -e "${GREEN}Response (press Ctrl+C when done):${NC}"
echo ""
echo "$message" | MCP_REMOTE_URL="$REMOTE_URL" FLIPSIDE_API_KEY="$API_KEY" MCP_DEBUG="$DEBUG" ./remote-mcp-proxy
echo ""
echo -e "${BLUE}────────────────────────────────────${NC}"
echo ""
}
echo -e "${GREEN}🚀 Starting proxy tests...${NC}"
echo ""
# Test 1: Initialize
echo "TEST 1: Initialize"
read -p "Press Enter to continue or Ctrl+C to skip..."
test_message '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "test-client",
"version": "1.0.0"
}
}
}' "Initialize"
# Test 2: List Tools
echo "TEST 2: List Tools"
read -p "Press Enter to continue or Ctrl+C to skip..."
test_message '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}' "List Tools"
echo -e "${GREEN}✅ All tests completed!${NC}"

22
test-simple.sh Executable file
View File

@ -0,0 +1,22 @@
#!/bin/bash
# Simple one-shot test for MCP remote proxy
if [ -z "$FLIPSIDE_API_KEY" ]; then
echo "Error: FLIPSIDE_API_KEY required"
exit 1
fi
# Build if needed
[ ! -f "./remote-mcp-proxy" ] && go build -o remote-mcp-proxy .
echo "Testing tools/list..."
echo "Press Ctrl+C after you see the response..."
echo ""
# Use a pipe to send the message
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | \
MCP_REMOTE_URL="${MCP_REMOTE_URL:-https://mcp.flipsidecrypto.xyz/beta/sse}" \
FLIPSIDE_API_KEY="$FLIPSIDE_API_KEY" \
MCP_DEBUG="${MCP_DEBUG:-true}" \
./remote-mcp-proxy