A powerful, modular Android application that implements a Server-Sent Events (SSE) Model Context Protocol (MCP) server. This application enables AI assistants to safely and securely interact with Android device capabilities through a standardized protocol.
✨ Core Capabilities
- 🔌 SSE-Based MCP Server: Runs as an Android foreground service using Ktor
- 🧩 Modular Architecture: Pluggable tool modules for different device capabilities
- 🔐 Privacy-Focused: Each tool requires explicit user permission with clear disclaimers
- 🔑 Bearer Token Authentication: Secure connections with authentication tokens
- 🎛️ Dynamic Tool Management: Enable/disable tools at runtime with user consent
- 🤝 External Tool Support: Third-party apps can expose MCP tools via Content Providers
- 📱 SMS: Send SMS messages (requires permission)
- 📱 SMS Intent: Send SMS via Intent (no permission required)
- 📷 Camera: Access camera and take photos
- 👥 Contacts: Read contacts list
- 📡 Sensor: Access device sensors (accelerometer, gyroscope, etc.)
- 🎯 Ads: Display ads (example tool)
- 🔌 External Tools: Auto-discover and integrate tools from other apps
- Download from Google Play: Available on Google Play Store
- Or build from source:
git clone https://github.com/yourusername/android-mcp-server cd android-mcp-server ./gradlew installDebug
- Launch the app and grant necessary permissions
- Enable tools you want to expose:
- Review the disclaimer for each tool
- Toggle individual tools on/off
- Start the server - Get your authentication token
- Connect your MCP client to
http://your-device:3001/ssewith the bearer token
# Example using curl with SSE
curl -H "Authorization: Bearer YOUR_TOKEN" \
http://your-device:3001/sseThe application follows a clean, modular architecture with clear separation of concerns:
android-mcp-server/
├── app/ # Main application module
├── core/ # Core interfaces (McpTool)
├── mcp-provider/ # Library for external tool integration
├── externalmcptool/ # Example external tool
└── tools/ # Individual tool modules
├── sms/
├── camera/
├── contacts/
├── sensor/
├── smsintent/
├── ads/
└── externaltools/
Contains the UI, server logic, and service management:
McpServerService: Foreground service running the Ktor SSE serverMainActivity: Jetpack Compose UI for server controlToolService: Manages tool states and preferencesAuthRepository: Manages authentication tokens
Defines the McpTool interface that all tools implement:
interface McpTool {
val id: String
val name: String
val enabledByDefault: Boolean
val disclaim: String?
fun configure(server: Server)
fun requiredPermissions(): Set<String>
}Library for creating external tool providers that third-party apps can use.
Individual modules implementing specific device capabilities, each following a standard architecture pattern.
| Layer | Technology |
|---|---|
| Language | Kotlin 2.1.21, JVM 21 |
| Build System | Gradle with Kotlin DSL |
| DI | Hilt (Dagger) |
| Async | Kotlin Coroutines |
| HTTP Server | Ktor Server (CIO engine) |
| MCP Protocol | io.modelcontextprotocol:kotlin-sdk |
| UI | Jetpack Compose + Material 3 |
| Database | DataStore (Preferences) |
| Camera | CameraX |
| Min SDK | 24 (Android 7.0) |
| Target SDK | 36 |
- Android Studio (latest stable or canary)
- Java/Kotlin toolchain (JVM 21)
- Android SDK 36
- Minimum SDK 26 for testing
# Clone the repository
git clone https://github.com/yourusername/android-mcp-server
cd android-mcp-server
# Build the project
./gradlew build
# Install on device/emulator
./gradlew installDebug
# Run tests
./gradlew testTools follow a standardized structure. To create a new tool:
-
Create module structure:
mkdir -p tools/newtool/src/main/{java/se/premex/mcp/newtool/{configurator,di,repositories,tool},AndroidManifest.xml} -
Implement required files:
build.gradle.kts- Module build configurationAndroidManifest.xml- Permissions declarationNewtoolTool.kt- McpTool implementationNewtoolToolModule.kt- Hilt moduleNewtoolRepository.kt&NewtoolRepositoryImpl.kt- Data accessNewtoolToolConfigurator.kt&NewtoolToolConfiguratorImpl.kt- MCP configuration
-
Register in
settings.gradle.kts:include(":tools:newtool") -
Add to app dependencies in
app/build.gradle.kts
See CREATE_MODULE_INSTRUCTIONS.md for detailed step-by-step instructions.
- Each tool requires explicit user permission
- Clear disclaimers explain what data is accessed
- No data collection or transmission without user consent
- Users can disable tools at any time
🔐 Security
- Bearer token-based authentication
- HTTPS/TLS support
- Permission verification before tool execution
- Secure credential storage using Android Keystore
- Always declare required permissions in
AndroidManifest.xml - Implement
requiredPermissions()accurately - Set
enabledByDefault = falsefor sensitive tools - Provide comprehensive
disclaimmessages - Validate all user inputs before processing
- Handle errors gracefully without exposing sensitive data
The server can be configured through the app UI:
- Port: Configurable (default: 3001)
- Token Management: Generate/revoke tokens
- Tool Management: Enable/disable tools with permission verification
- Persistent Notification: Shows server status
Server-Sent Events endpoint for MCP transport
- Auth: Bearer token required
- Headers:
Authorization: Bearer YOUR_TOKEN
Tools are registered with the following schema:
{
"name": "phone_tool_name",
"description": "Tool description",
"inputSchema": {
"type": "object",
"properties": {
"param": {
"type": "string",
"description": "Parameter description"
}
},
"required": ["param"]
}
}- Verify
@IntoSetannotation in Hilt module - Check module is included in
settings.gradle.kts - Ensure Hilt module is
@InstallIn(SingletonComponent::class) - Rebuild:
./gradlew clean build
- Verify
configure()is called inMcpToolimplementation - Check
server.addTool()is invoked with correct parameters - Review logcat for registration errors
- Verify tool is enabled in app UI
- Declare permissions in module's
AndroidManifest.xml - Return correct permissions from
requiredPermissions() - Check Android OS permission is granted before tool execution
- Handle permission denial gracefully
- Ensure device and client are on same network
- Verify bearer token in Authorization header
- Check device IP address and port are correct
- Review server logs in app UI
This project is licensed under the MIT License - see the LICENSE file for details.
Made with ❤️ by Stefan and contributors
