安卓Mapbox MCP包装器
一个Android库,使像Claude这样的AI代理能够通过自然语言控制Mapbox地图。该项目用模型上下文协议(MCP)工具定义封装了Mapbox Maps SDK v11,使地图可以通过LLM聊天界面进行控制。
Android相当于: mapbox地图工具mcp (JavaScript/Web版本)
演示
演示应用程序包括一个聊天界面,您可以在其中与Claude交谈以实时控制地图:
- “给我看看巴黎” → 地图平移到巴黎
- 在伦敦、罗马和马德里添加标记 → 添加3个标记
- “画一条从纽约到洛杉矶的路线” → 画一条线
- “切换到卫星视图” → 更改地图样式
特性
- 🗺️ 7 MCP工具 用于综合地图控制
- 🤖 Claude API集成 具有对话式UI
- 📍 点注释 具有可定制的颜色和弹出窗口
- 🛣️ 路线/线路图 具有样式选项
- 🗺️ 多边形叠加 具有填充和笔划自定义功能
- 📷 相机控制 (平移、缩放、调整边界)
- 🎨 样式切换 (街道、卫星、户外、黑暗)
- 🧹 层级管理 选择性清算
______________________________________________________________________
在项目中使用库

通过JitPack将Mapbox MCP Tools库添加到您的Android项目中:
步骤1:添加JitPack存储库
在你的 项目级 settings.gradle.kts (或 build.gradle):
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") } // Add this line
}
}步骤2:添加依赖关系
在你的 应用程序级别 build.gradle.kts:
dependencies {
// Mapbox MCP Tools Library
implementation("com.github.moritzzzzz:android-mapbox-map-tools-mcp-v11:v1.0.0")
// Required: Mapbox Maps SDK (if not already included)
implementation("com.mapbox.maps:android:11.17.1")
// Required: Kotlin Serialization
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
}第三步:使用图书馆
import com.mapbox.maps.MapView
import com.mapbox.mcp.MapboxMapTools
class YourActivity : AppCompatActivity() {
private lateinit var mapView: MapView
private lateinit var mapboxMapTools: MapboxMapTools
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Initialize MapView
mapView = findViewById(R.id.mapView)
// Wait for map style to load
mapView.mapboxMap.loadStyleUri(Style.MAPBOX_STREETS) {
// Create MapboxMapTools wrapper
mapboxMapTools = MapboxMapTools(mapView)
// Get tool definitions for your LLM
val tools = mapboxMapTools.getToolsForLLM()
// Send these to Claude API or your LLM provider...
// Execute a tool
val result = mapboxMapTools.executeTool(
"pan_map_to_location",
mapOf(
"latitude" to 48.8566,
"longitude" to 2.3522,
"zoom" to 12.0
)
)
}
}
}\*\*完整集成示例:\*\*请参阅 演示应用程序源代码 以实现与Claude API集成的完整工作实现。
______________________________________________________________________
快速入门-运行演示
先决条件
您需要两个API密钥(都是免费的):
- Mapbox访问令牌 -在中配置
res/values/mapbox_access_token.xml! - API密钥 -通过安全配置
local.properties
首次设置:复制 local.properties.example 到 local.properties 并添加您的Claude API密钥。看 API密钥设置 了解详情。
跑步步骤
- 克隆并打开
git clone
cd android_mapbox_mcp_wrapper/mcp_tools_demo_app打开 mcp_tools_demo_app Android Studio中的文件夹。
- 同步渐变
- Android Studio将提示您同步 - 单击“立即同步”并等待其完成
- 运行应用程序
- 点击绿色的“运行”按钮(或按Shift+F10) - 选择设备或模拟器 - 等待应用程序安装并启动
- 开始聊天!
- 在聊天框中键入消息 - 试试:“给我看看纽约市” - 观察地图对自然语言命令的响应
就是这样!该应用程序已预先配置并准备好使用。
______________________________________________________________________
配置
使用您自己的API密钥
Mapbox访问令牌
- 获取令牌:参观 Mapbox帐户 (免费版可用)
- 更新令牌:打开
app/src/main/res/values/mapbox_access_token.xml - 用您的令牌替换现有令牌:
YOUR_MAPBOX_TOKEN_HEREAPI密钥
- 拿到钥匙:参观 拟人控制台 (需要帐户)
- 复制模板:
cp local.properties.example local.properties- 添加您的密钥:编辑
local.properties并替换占位符:
claude.api.key=sk-ant-api03-YOUR_KEY_HERE- 重建:运行
./gradlew clean assembleDebug
备注: local.properties 是合法的,永远不会被承诺。这使您的API密钥保持安全!
有关更多详细信息,请参阅 API_KEY_SETUP.md.
高级配置
在 Config.kt,您可以配置:
object Config {
// Claude API Key (loaded from local.properties at build time)
val CLAUDE_API_KEY = BuildConfig.CLAUDE_API_KEY
// Model selection (sonnet is faster, opus is more capable)
const val CLAUDE_MODEL = "claude-sonnet-4-5-20250929"
// Options: "claude-sonnet-4-5-20250929", "claude-opus-4-5-20251101"
// Maximum tokens for responses
const val MAX_TOKENS = 4096
}______________________________________________________________________
在自己的应用程序中使用库
安装选项
选项1:JitPack(推荐) -请参阅 在项目中使用库 上方
选项2:手动复制 -复制 mapbox-mcp-tools 模块到您的项目中:
- 复制
mapbox-mcp-tools将文件夹放入您的Android项目中 - 增添
settings.gradle.kts:
include(":mapbox-mcp-tools")- 在应用程序中添加依赖项
build.gradle.kts:
dependencies {
implementation(project(":mapbox-mcp-tools"))
implementation("com.mapbox.maps:android:11.17.1")
}步骤2:初始化MapboxMapTools
import com.mapbox.maps.MapView
import com.mapbox.maps.Style
import com.mapbox.mcp.MapboxMapTools
import com.mapbox.mcp.models.ToolResult
class YourActivity : AppCompatActivity() {
private lateinit var mapView: MapView
private lateinit var mapboxMapTools: MapboxMapTools
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Create and setup MapView
mapView = MapView(this)
setContentView(mapView)
// Load map style first
mapView.mapboxMap.loadStyleUri(Style.MAPBOX_STREETS) {
// Initialize tools after style loads
mapboxMapTools = MapboxMapTools(mapView)
// Now you can use the tools!
useMapTools()
}
}
private fun useMapTools() {
// Get tool definitions (for sending to LLM)
val tools = mapboxMapTools.getToolsForLLM()
println("Available tools: ${tools.map { it.name }}")
// Execute a tool directly
val result = mapboxMapTools.executeTool(
"add_points_to_map",
mapOf(
"points" to listOf(
mapOf(
"lat" to 40.7128,
"lng" to -74.0060,
"title" to "New York City",
"description" to "The Big Apple"
)
),
"iconColor" to "#FF5722",
"iconSize" to 1.5
)
)
// Handle result
when (result) {
is ToolResult.Success -> {
Log.d("Map", "Success: ${result.data}")
}
is ToolResult.Error -> {
Log.e("Map", "Error: ${result.message}")
}
}
}
}步骤3:工具执行示例
添加标记
mapboxMapTools.executeTool("add_points_to_map", mapOf(
"points" to listOf(
mapOf("lat" to 48.8566, "lng" to 2.3522, "title" to "Paris"),
mapOf("lat" to 51.5074, "lng" to -0.1278, "title" to "London")
),
"layerName" to "cities",
"iconColor" to "#4CAF50"
))绘制路线
mapboxMapTools.executeTool("add_route_to_map", mapOf(
"coordinates" to listOf(
listOf(-122.4194, 37.7749), // San Francisco
listOf(-118.2437, 34.0522) // Los Angeles
),
"lineColor" to "#2196F3",
"lineWidth" to 5.0
))平移到位置
mapboxMapTools.executeTool("pan_map_to_location", mapOf(
"latitude" to 40.7128,
"longitude" to -74.0060,
"zoom" to 12.0,
"animated" to true
))清除图层
// Clear all layers
mapboxMapTools.executeTool("clear_map_layers", emptyMap())
// Clear specific layers
mapboxMapTools.executeTool("clear_map_layers", mapOf(
"layerNames" to listOf("cities", "routes")
))______________________________________________________________________
使用多个MCP工具集/扩展功能
您可以将Mapbox MCP工具与其他MCP服务器或工具提供商结合使用,让Claude一次访问多种功能。
架构概述
Claude API
↓
Your App sends combined tool list:
├─ Mapbox Tools (this library)
├─ Weather API Tools (hypothetical)
└─ Database Tools (hypothetical)
↓
Your App routes execution to correct provider步骤1:创建多个工具提供程序
class WeatherTools {
fun getToolsForLLM(): List {
return listOf(
ToolDefinition(
name = "get_weather",
description = "Get current weather for a location",
inputSchema = InputSchema(
type = "object",
properties = mapOf(
"city" to Property("string", "City name"),
"country" to Property("string", "Country code (optional)")
),
required = listOf("city")
)
)
)
}
fun executeTool(name: String, params: Map): ToolResult {
return when (name) {
"get_weather" -> {
val city = params["city"] as? String ?: return ToolResult.Error("Missing city")
// Call your weather API here...
ToolResult.Success("Weather in $city: Sunny, 72°F")
}
else -> ToolResult.Error("Unknown tool: $name")
}
}
}步骤2:更新ChatManager以组合工具
修改 ChatManager.kt 接受多个工具提供商:
class ChatManager(
private val claudeApiClient: ClaudeApiClient,
private val mapboxMapTools: MapboxMapTools,
private val weatherTools: WeatherTools // Add additional providers
) {
suspend fun processMessage(userMessage: String): String {
// ... existing code ...
// Combine all tool definitions
val allTools = buildList {
addAll(mapboxMapTools.getToolsForLLM())
addAll(weatherTools.getToolsForLLM())
// Add more tool providers here...
}
Log.d(TAG, "Available tools: ${allTools.map { it.name }}")
// Send to Claude with all tools
val response = claudeApiClient.sendMessage(
messages = conversationHistory.toList(),
tools = allTools
)
// ... rest of existing code ...
}
private suspend fun executeToolCall(toolUseBlock: ContentBlock): String {
val toolName = toolUseBlock.name ?: return "Error: No tool name"
val params = convertJsonElementMapToAny(toolUseBlock.input ?: emptyMap())
Log.d(TAG, "Executing tool: $toolName with params: $params")
// Route to appropriate tool provider based on tool name
val result = when {
toolName.startsWith("add_") ||
toolName.startsWith("pan_") ||
toolName.startsWith("fit_") ||
toolName.startsWith("clear_") ||
toolName.startsWith("set_") -> {
// Mapbox tools
mapboxMapTools.executeTool(toolName, params)
}
toolName == "get_weather" -> {
// Weather tools
weatherTools.executeTool(toolName, params)
}
else -> {
ToolResult.Error("Unknown tool: $toolName")
}
}
return when (result) {
is ToolResult.Success -> result.data ?: "Success"
is ToolResult.Error -> "Error: ${result.message}"
}
}
}步骤3:更新主活动初始化
class MainActivity : AppCompatActivity() {
private lateinit var mapboxMapTools: MapboxMapTools
private lateinit var weatherTools: WeatherTools
private lateinit var chatManager: ChatManager
private fun initializeChatManager() {
val claudeApiClient = ClaudeApiClient(CLAUDE_API_KEY)
weatherTools = WeatherTools() // Initialize additional provider
chatManager = ChatManager(
claudeApiClient,
mapboxMapTools,
weatherTools // Pass additional provider
)
Log.d(TAG, "ChatManager initialized with ${
mapboxMapTools.getToolsForLLM().size + weatherTools.getToolsForLLM().size
} tools")
}
}步骤4:尝试组合命令
现在,Claude可以使用多个提供商的工具:
User: "Show me Paris and tell me the weather there"
↓
Claude calls:
1. pan_map_to_location (Mapbox)
2. get_weather (Weather API)
↓
App: "I've centered the map on Paris. The weather is Sunny, 72°F."高级:动态刀具布线
对于更复杂的场景,请使用工具注册表:
class ToolRegistry {
private val providers = mutableMapOf()
fun register(toolNamePrefix: String, provider: ToolProvider) {
providers[toolNamePrefix] = provider
}
fun getAllTools(): List {
return providers.values.flatMap { it.getToolsForLLM() }
}
fun executeTool(toolName: String, params: Map): ToolResult {
// Find provider by checking tool name prefixes or patterns
val provider = providers.entries.find { (prefix, _) ->
toolName.startsWith(prefix)
}?.value
return provider?.executeTool(toolName, params)
?: ToolResult.Error("No provider found for tool: $toolName")
}
}
// Usage
val registry = ToolRegistry()
registry.register("map", mapboxMapTools)
registry.register("weather", weatherTools)
registry.register("db", databaseTools)
val allTools = registry.getAllTools()
val result = registry.executeTool("map_add_points", params)MCP服务器集成示例
您可能想要集成的常见MCP服务器:
- 文件系统MCP -读/写文件
implementation("com.github.user:filesystem-mcp-android:1.0.0")- 数据库MCP -查询数据库
implementation("com.github.user:sqlite-mcp-tools:1.0.0")- 日历MCP -访问设备日历
implementation("com.github.user:calendar-mcp-tools:1.0.0")- 自定义REST API工具 -包装自己的API
class MyApiTools {
fun getToolsForLLM() = listOf(/* your tools */)
fun executeTool(name: String, params: Map) = /* execute */
}多套工具的优点
更丰富的互动 -Claude可以执行复杂的多域任务 模块化 -易于添加/删除工具提供程序 可重用性 -跨不同应用程序共享工具提供商 关注点分离 -每个提供商处理自己的域
最佳实践
- 使用清晰的工具命名 -在工具名称前加上域(例如。,
map_,weather_,db_) - 文档工具交互 -注意哪些工具配合使用效果好
- 优雅地处理错误 -每个提供程序应返回一致的错误格式
- 测试工具组合 -确保克劳德能够正确地连接工具
- 监控令牌使用情况 -更多的工具=更大的上下文,考虑将相关工具分组
代币成本和性能考虑因素
输入令牌影响
⚠️ 重要提示: 7个Mapbox MCP工具添加 ~1060个输入令牌 每个API请求。
成本影响(克劳德十四行诗4.5):
Input tokens: 1,060 tokens × $3/million = $0.00318 per request
Output tokens: varies (typically 500-2000 tokens)
Example with typical 1,000 token response:
Input (tools + message): 1,160 tokens = $0.0035
Output (response): 1,000 tokens = $0.0150
─────────────────────────────────────────────
Total per request: $0.0185与没有工具的请求相比:
- 基本输入(仅限消息):~100个令牌=0.0003美元
- 工具添加10倍以上的输入令牌 (1060对100)
- 但总成本仅为2倍左右 (产出占主导地位:0.015美元对0.0003美元)
关键见解: 工具显著增加了您的输入令牌数量(约占总输入的40-60%),但输出令牌的总体成本通常更高,因此影响是适度的。
每工具代币估算:
| 工具 | 令牌 | 复杂性 |
|---|---|---|
add_points_to_map | ~200 | 高(嵌套模式) |
add_route_to_map | ~140 | 中等 |
add_polygon_to_map | ~160 | 中等 |
pan_map_to_location | ~120 | 低 |
fit_map_to_bounds | ~130 | 中等 |
clear_map_layers | ~90 | 低 |
set_map_style | ~80 | 低 |
减少代币使用的策略:
- 选择性工具加载 -仅发送与当前上下文相关的工具:
// Only send map control tools for navigation
val tools = listOf(
mapboxMapTools.createPanMapToolDefinition(),
mapboxMapTools.createFitBoundsToolDefinition()
)- 基于上下文的过滤 -启用/禁用工具类别:
val tools = when (userIntent) {
Intent.NAVIGATE -> mapboxMapTools.getNavigationTools()
Intent.ANNOTATE -> mapboxMapTools.getAnnotationTools()
Intent.ALL -> mapboxMapTools.getToolsForLLM()
}- 缓存 (如果API支持)-工具保持不变,在请求之间缓存它们
- 工具说明 -保持描述简洁明了
当多个工具集成为问题时:
- 3-4套工具(20-30个工具): 仍然可以管理(约3000-4000个代币)
- 5-8套工具(40-60个工具): 成本明显增加(约6000-8000个代币)
- 10+套工具(80+套工具): 考虑动态加载或分类
监控您的使用情况:
val toolsJson = json.encodeToString(tools)
val estimatedTokens = toolsJson.length / 3.5 // Rough estimate
Log.d("Tokens", "Sending ~${estimatedTokens.toInt()} tokens in tools")工具过多的缺点:
- ⚠️ 延迟增加 -处理更大的请求需要更长的时间
- ⚠️ 成本更高 -随刀具数量线性增加
- ⚠️ 语境淡化 -LLM有更多需要“思考”的地方
- ⚠️ 困惑 -太多类似的工具会降低精度
最佳实践: 从基本工具开始,根据实际使用模式根据需要添加更多工具。
______________________________________________________________________
可用工具
该库提供7个MCP工具:
1. add_points_to_map
在地图上添加标记/图钉。
参数:
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
points | 数组 | ✅ 是 | - | 数组 {lat, lng, title?, description?} |
layerName | 字符串 | 否 | “点” | 分组层标识符 |
iconColor | 字符串 | 否 | “#FF0000” | 标记的十六进制颜色 |
iconSize | 浮点数 | 否 | 1.0 | 大小倍数 |
例子:
mapOf(
"points" to listOf(
mapOf("lat" to 40.7128, "lng" to -74.0060, "title" to "NYC")
),
"iconColor" to "#FF5722"
)2. add_route_to_map
在地图上画一条线/路径。
参数:
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
coordinates | 数组 | ✅ 是 | - | 数组 [lng, lat] 成对 |
layerName | 字符串 | 否 | “路由” | 层标识符 |
lineColor | 字符串 | 否 | “#3b9ddd” | 十六进制颜色 |
lineWidth | 浮点数 | 否 | 4.0 | 宽度(像素) |
lineOpacity | 浮点数 | 否 | 0.8 | 不透明度(0-1) |
3. add_polygon_to_map
在地图上画一个填好的区域。
参数:
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
coordinates | 数组 | ✅ 是 | - | 数组 [lng, lat] 成对形成边界 |
layerName | 字符串 | 否 | “多边形” | 图层标识符 |
fillColor | 字符串 | 否 | “#3b9ddd” | 十六进制填充颜色 |
fillOpacity | 浮点数 | 否 | 0.5 | 填充不透明度(0-1) |
strokeColor | 字符串 | 否 | “#000000” | 边框颜色 |
strokeWidth | 浮点数 | 否 | 2.0 | 边框宽度 |
4. pan_map_to_location
将相机移动到特定位置。
参数:
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
latitude | 双 | ✅ 是 | - | 纬度坐标 |
longitude | 双 | ✅ 是 | - | 经度坐标 |
zoom | 双 | 否 | 当前 | 缩放级别(可选) |
animated | 布尔 | 否 | 真 | 动画转换 |
duration | 长 | 否 | 1000 | 动画持续时间(ms) |
5. fit_map_to_bounds
调整相机以显示所有指定点。
参数:
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
coordinates | 数组 | ✅ 是 | - | 数组 [lng, lat] 以适应视野 |
padding | Int | 否 | 50 | 像素填充 |
animated | 布尔 | 否 | 真 | 动画转换 |
6. clear_map_layers
从地图中删除注释/图层。
参数:
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
layerNames | 数组 | 否 | 空 | 要清除的层名称(空=全部) |
7. set_map_style
更改地图的视觉外观。
参数:
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
styleUrl | 字符串 | ✅ 是 | - | 地图框样式URL |
流行款式:
mapbox://styles/mapbox/streets-v12-默认街道地图mapbox://styles/mapbox/outdoors-v12-户外/徒步旅行mapbox://styles/mapbox/satellite-v9-卫星图像mapbox://styles/mapbox/satellite-streets-v12-带有标签的卫星mapbox://styles/mapbox/dark-v11-黑暗主题mapbox://styles/mapbox/light-v11-灯光主题
______________________________________________________________________
克劳德提示示例
演示运行后,尝试以下自然语言命令:
基本导航
- “给我看看东京”
- “带我去埃菲尔铁塔”
- 平移到坐标37.7749,-122.4194
- “放大中央公园”
添加标记
- “在自由女神像上加一个红色标记”
- 在巴黎、伦敦和柏林做标记
- 在坐标35.6762、139.6503处添加一个标记,标题为“东京塔”
绘制路线
- “画一条从纽约到波士顿的蓝线”
- “给我看一条连接旧金山、拉斯维加斯和洛杉矶的路线”
- 沿以下坐标绘制一条路径:\[\[0,0\],\[1,1\],\[2,0\]
多边形
- “在曼哈顿周围画一个绿色多边形”
- 创建一个半透明的蓝色区域,覆盖以下点:\[\[0,0\],\[1,0\],\[1,1\],\[0,1\]\]
地图样式
- “切换到卫星视图”
- “使用暗模式”
- “改为户外风格”
- “给我看街道地图”
复杂的多步命令
- “清除地图,然后向我展示欧洲,并为法国、德国和意大利的首都添加标记”
- “给我看加州,在旧金山加一个标记,画一条到洛杉矶的线”
- 切换到卫星视图,缩放到纽约,并在时代广场和中央公园添加标记
组合功能
- “显示北美,调整视图以显示加拿大、美国和墨西哥,然后在它们的首都添加标记”
- 清除所有图层,使用缩放级别12平移到巴黎,并添加一个红色标记
______________________________________________________________________
建筑
图书馆设计
这 mapbox-mcp-tools 库提供了一个简单、无服务器的API:
MapboxMapTools
├── getToolsForLLM() → List
│ Returns MCP tool schemas for LLM
│
└── executeTool(name, params) → ToolResult
Executes tools and returns Success/Error要点:
- ✅ 无服务器组件-纯包装库
- ✅ 线程安全(在主线程上运行映射操作)
- ✅ 有组织注释的图层跟踪
- ✅ 全面的错误处理
演示应用程序架构
┌─────────────────────────────────┐
│ User types message in chat │
└──────────────┬──────────────────┘
▼
┌─────────────────────────────────┐
│ ChatManager.processMessage() │
├─────────────────────────────────┤
│ 1. Get tools from library │
│ 2. Send to Claude API │
│ 3. Parse tool_use blocks │
│ 4. Execute via MapboxMapTools │
│ 5. Send results back to Claude │
│ 6. Return final response │
└──────────────┬──────────────────┘
▼
┌─────────────────────────────────┐
│ Display response + Update map │
└─────────────────────────────────┘流程示例:
User: "Show me Paris"
↓
Claude: [analyzes] → tool_use: pan_map_to_location(lat: 48.8566, lng: 2.3522)
↓
App: Executes tool → Map pans to Paris
↓
Claude: "I've centered the map on Paris, France (48.8566°N, 2.3522°E)"
↓
User sees response + map at Paris______________________________________________________________________
故障排除
应用程序无法构建
错误: “无法解析依赖关系…”
- 修复: 请确保您已同步Gradle。转到文件→ 同步项目与Gradle文件
错误: “无法解析:com.mapbox.maps…”
- 修复: 检查您的互联网连接。Gradle需要下载依赖项。
地图未加载
症状: 应放置地图的灰色或空白屏幕
- 修复: 在中检查您的Mapbox访问令牌
mapbox_access_token.xml - 修复: 确保您有互联网连接
- 修复: 检查Logcat是否有错误消息(查看→ 工具窗口→ Logcat)
聊天没有响应
错误: “聊天未初始化。请检查API密钥。”
- 修复: 验证Claude API密钥
Config.kt有效且非空
错误: “Claude API错误:401”
- 修复: 您的Claude API密钥无效或已过期。从获取新的https://console.anthropic.com/
错误: “Claude API错误:429”
- 修复: 你已达到利率上限。请稍等,然后重试。
地图加载但工具不起作用
症状: 聊天功能正常,但地图不响应命令
- 修复: 检查一下
MapboxMapTools在地图样式加载后初始化 - 修复: 在Logcat中查找以“MapboxMapTools”开头的错误
坐标错误
问题: 标记出现在错误的位置
- 记得: Mapbox使用
[longitude, latitude]订单,不是[lat, lng] - 修复: 在工具调用中,确保坐标
[lng, lat]
______________________________________________________________________
需求
- 最小SDK: 29(安卓10)
- 目标SDK: 36
- 编译SDK: 36
- Kotlin: 2.0.21
- Mapbox SDK: 11.17.1
- 互联网权限: 地图瓷砖和Claude API需要
______________________________________________________________________
安全最佳实践
⚠️ 重要提示: 此演示包含API密钥,以便于测试。对于生产应用程序:
❌ 不要这样做
// DON'T commit API keys to version control
const val CLAUDE_API_KEY = "sk-ant-api03-xxxx"✅ 改为这样做
选项1:使用BuildConfig
// build.gradle.kts
android {
defaultConfig {
buildConfigField(
"String",
"CLAUDE_API_KEY",
"\"${System.getenv("CLAUDE_API_KEY")}\""
)
}
}
// Config.kt
const val CLAUDE_API_KEY = BuildConfig.CLAUDE_API_KEY选项2:使用local.properties
# local.properties (add to .gitignore)
CLAUDE_API_KEY=sk-ant-api03-xxxx// build.gradle.kts
val localProperties = Properties()
localProperties.load(FileInputStream(rootProject.file("local.properties")))
android {
defaultConfig {
buildConfigField(
"String",
"CLAUDE_API_KEY",
"\"${localProperties.getProperty("CLAUDE_API_KEY")}\""
)
}
}选项3:环境变量
export CLAUDE_API_KEY="sk-ant-api03-xxxx"其他安全提示
- 添加到.gitignore:
Config.kt
local.properties
**/api_keys.xml- 使用秘密管理服务:
- AWS机密管理器 - 谷歌秘密管理员 - HashiCorp保险库
- 实施速率限制 生产中
- 监控API使用情况 用于意外活动
- 定期旋转按键
______________________________________________________________________
项目结构
android_mapbox_mcp_wrapper/
├── README.md # This file
└── mcp_tools_demo_app/ # Android Studio project
├── mapbox-mcp-tools/ # Library module
│ ├── build.gradle.kts
│ └── src/main/java/com/mapbox/mcp/
│ ├── MapboxMapTools.kt # Main API
│ ├── models/
│ │ ├── ToolDefinition.kt # MCP tool schema
│ │ ├── ToolResult.kt # Result type
│ │ ├── Point.kt # Point data
│ │ ├── Route.kt # Route data
│ │ └── Polygon.kt # Polygon data
│ └── internal/
│ └── (implementation)
│
└── app/ # Demo application
├── build.gradle.kts
└── src/main/java/com/example/mcp_tools_demo/
├── MainActivity.kt # Main UI + integration
├── Config.kt # Configuration (API keys)
├── ClaudeApiClient.kt # Claude API client
├── ChatManager.kt # Conversation orchestrator
├── ChatAdapter.kt # Chat UI adapter
└── models/
└── ChatMessage.kt # UI message model______________________________________________________________________
🤝 贡献
欢迎投稿!需要改进的地方:
- \[\]其他地图工具(3D地形、地理编码等)
- \[\]支持更多LLM提供商(OpenAI等)
- \[\]地图状态查询工具(获取当前位置等)
- \[\]批量操作以获得更好的性能
- \[\]单元测试和仪器测试
______________________________________________________________________
许可证
MIT许可证
版权所有(c)2025莫里茨福斯特
特此免费向任何获得副本的人授予许可 本软件和相关文档文件(“软件”),以处理 在软件中不受限制,包括但不限于权利 使用、复制、修改、合并、发布、分发、再许可和/或销售 软件的副本,并允许软件的接收者 根据以下条件提供:
上述版权声明和本许可声明应包含在所有 软件的副本或实质性部分。
软件按“原样”提供,不提供任何形式的明示或明示担保 隐含的,包括但不限于适销性保证, 适用于特定目的且不造成伤害。在任何情况下 作者或版权持有人对任何索赔、损害赔偿或其他 因以下原因产生的责任,无论是在合同、侵权或其他诉讼中, 出于或与软件、使用或其他交易有关 软件。
______________________________________________________________________
学分
- 灵感来源: mapbox地图工具mcp (JavaScript版本)
- 内置: 安卓版Mapbox地图SDK
- 技术支持: API克劳德 通过Anthropic
______________________________________________________________________
支持
______________________________________________________________________
