Architecture Overview
HandsAI is built as a high-performance bridge service that connects Model Context Protocol (MCP) clients to arbitrary REST APIs through a dynamic tool registry.System Architecture Diagram
Core Components
1. HandsAI Bridge (Go)
Purpose: Protocol translation layer between MCP’s stdio-based JSON-RPC and HandsAI’s HTTP REST API. Key Responsibilities:- Accept MCP
tools/listrequests and forward to/mcp/tools/list - Accept MCP
tools/callrequests and forward to/mcp/tools/call - Translate responses back to MCP format over stdio
- Handle connection lifecycle and error propagation
2. Spring Boot API (Java 21)
Tech Stack:- Framework: Spring Boot 3.5.4 (Spring MVC)
- Java Version: Java 21 LTS
- Concurrency: Virtual Threads via
Executors.newVirtualThreadPerTaskExecutor() - Build Tool: Maven 3.8+
- Native Compilation: GraalVM Native Image support
MCPController (/mcp)
MCPController (/mcp)
Implements the Model Context Protocol for tool discovery and execution.Endpoints:
GET /mcp/tools/list- Returns all enabled, healthy tools in MCP formatPOST /mcp/tools/call- Executes a tool by name with JSON-RPC 2.0 protocol
org.dynamcorp.handsaiv2.controller.MCPControllerError Handling:-32602: Invalid params (missing required fields)-32603: Internal error (execution failure)
AdminToolController (/admin/tools/api)
AdminToolController (/admin/tools/api)
CRUD operations for individual tools (used by the frontend UI).Endpoints:
GET /admin/tools/api- List all toolsGET /admin/tools/api/{id}- Get tool by IDPOST /admin/tools/api- Create new toolPUT /admin/tools/api/{id}- Update toolDELETE /admin/tools/api/{id}- Delete tool
org.dynamcorp.handsaiv2.controller.AdminToolControllerImportController (/api/import)
ImportController (/api/import)
Batch import providers and tools from JSON.Endpoint:
POST /api/import/providersBehavior:- Upsert by
codefield (creates if new, updates if exists) - Preserves existing API keys if import value is
<YOUR_API_KEY>placeholder - Creates tools and parameters in a single transaction
org.dynamcorp.handsaiv2.controller.ImportControllerExportController (/api/export)
ExportController (/api/export)
Export providers and tools to JSON format.Endpoint:
GET /api/export/providers?ids=1,2,3Security: Automatically obfuscates API keys to <YOUR_API_KEY> in export.Location: org.dynamcorp.handsaiv2.controller.ExportController3. SQLite Database
Configuration:- File:
handsai.db(auto-created in project root) - Mode: WAL (Write-Ahead Logging) for high concurrency
- Dialect:
org.hibernate.community.dialect.SQLiteDialect - Connection Pool: HikariCP with virtual threads
API keys are encrypted at rest using Jasypt with AES-256. The encryption key is generated on first run and stored in environment variables.
4. ToolCacheManager
Purpose: In-memory cache for tool definitions to eliminate database queries on every MCP discovery request. Implementation:org.dynamcorp.handsaiv2.service.ToolCacheManager
Data Structure:
Performance Impact:
- Without Cache: 50-100ms per discovery (database query + JSON serialization)
- With Cache: < 5ms per discovery (memory lookup only)
Data Flow
Tool Discovery Flow
Tool Execution Flow
Authentication Strategies
HandsAI supports multiple authentication methods:- API Key
- Bearer Token
- Dynamic Auth (OAuth2)
- Basic Auth
Locations:
HEADER:X-API-Key: your_keyor custom header nameQUERY_PARAMETER:?key=your_keyappended to URLIN_BODY:{"api_key": "your_key"}in JSON body
Advanced Features
1. Body Payload Templates
For APIs requiring nested JSON structures, usebodyPayloadTemplate with parameter interpolation.
Example (Jules API):
{"prompt": "Fix bug", "source": "sources/github/...", "startingBranch": "main"}
HandsAI interpolates to:
2. Array Parameter Handling
LLMs can send arrays as native JSON or string-encoded JSON. HandsAI automatically deserializes both. Definition:ToolExecutionService.resolveArrayParams() at line 385
3. Path Parameter Substitution
Dynamic URL building for RESTful endpoints. Definition:4. Logging & Analytics
Batch Processing: Execution logs are queued in-memory and persisted in batches to reduce SQLite write contention. Logged Data:- Tool name and session ID
- Request payload (obfuscated)
- Response payload (obfuscated)
- Execution time (ms)
- Success/failure status
- Error messages
org.dynamcorp.handsaiv2.service.LogBatchProcessor
Obfuscation: API keys and sensitive headers are redacted in logs via LogObfuscator.
Virtual Threads (Java 21)
HandsAI uses Virtual Threads for all async operations, providing:- High Concurrency: Handle thousands of tool executions simultaneously
- Low Overhead: Virtual threads are lightweight (< 1KB stack)
- Simplified Code: No need for reactive programming or callbacks
org.dynamcorp.handsaiv2.config.VirtualThreadConfig
GraalVM Native Image
Compilation:- Startup: < 1.5 seconds (vs. 3-5s on JVM)
- Memory: ~100MB RSS (vs. 300-500MB on JVM)
- Ideal For: Local AI agents, serverless, edge deployments
NativeHintsConfig.
Example (Registering Jasypt for encryption):
org.dynamcorp.handsaiv2.config.NativeHintsConfig
Scalability & Performance
Tool Discovery
Cached: < 5msUncached: 50-100ms(Typical: 100% cache hit rate)
Tool Execution
Local: 10-50msRemote API: 100-500ms(Depends on external API latency)
Concurrency
Virtual Threads: 10,000+ concurrent requestsSQLite WAL: Handles high read/write concurrency
Memory
JVM Mode: 300-500MBNative Mode: ~100MB(Scales with cache size)
Security Considerations
API Key Encryption
API Key Encryption
- All API keys encrypted at rest using Jasypt (AES-256)
- Encryption key stored in environment variables
- Keys decrypted in-memory only during execution
- Logs automatically obfuscate sensitive values
Request Validation
Request Validation
- Input validated against tool parameter schemas
- Required parameters enforced
- Type checking for STRING, NUMBER, BOOLEAN, ARRAY
- Malformed JSON rejected with 400 errors
Rate Limiting
Rate Limiting
- Not implemented in HandsAI (delegated to external APIs)
- Logging tracks execution frequency per tool
- Consider adding Spring rate limiting for production
CORS Configuration
CORS Configuration
- Default:
@CrossOrigin(origins = "*")for development - Production: Configure specific origins in
application.properties
Next Steps
API Reference
Complete endpoint documentation with request/response examples
Quickstart
Get HandsAI running with your first tool in 5 minutes
Use Cases
Explore pre-built integrations:
- Weather API
- Email (Resend)
- Social Media (Ayrshare)
- GitHub automation
- Jules Agent API
Contributing
Read
AGENTS.md for architecture rules and GraalVM compatibility guidelines