mapbox-create-map-mcp 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +151 -119
  2. package/bin/cli.js +11 -0
  3. package/package.json +6 -2
  4. package/src/server.js +301 -0
package/README.md CHANGED
@@ -1,184 +1,216 @@
1
- # @gis/mapbox-create-map
1
+ # mapbox-create-map-mcp
2
2
 
3
- 一个基于Mapbox的地理数据可视化工具(MCP),可以根据用户需求和地理数据生成一次性临时的地图可视化展示。
3
+ 一个基于Mapbox的地理数据可视化MCP工具,根据用户需求和地理数据生成图层配置信息。
4
4
 
5
5
  ## 安装
6
6
 
7
7
  ```bash
8
- npm install @gis/mapbox-create-map mapbox-gl
8
+ npm install mapbox-create-map-mcp
9
9
  ```
10
10
 
11
- ## 使用方法
11
+ ## MCP 服务使用
12
+
13
+ ### 直接启动
14
+
15
+ ```bash
16
+ npx mapbox-create-map-mcp
17
+ ```
18
+
19
+ ### MCP 客户端配置
20
+
21
+ 在 MCP 客户端(如 Claude Desktop、Cursor 等)的配置文件中添加:
22
+
23
+ ```json
24
+ {
25
+ "mcpServers": {
26
+ "mapbox-createmap": {
27
+ "command": "npx",
28
+ "args": ["mapbox-create-map-mcp"]
29
+ }
30
+ }
31
+ }
32
+ ```
33
+
34
+ ### MCP 工具
35
+
36
+ **CreateMap** - 根据配置生成地图图层配置信息
37
+
38
+ 输入参数:
39
+ - `title` (string, 必需): 地图标题
40
+ - `description` (string, 必需): 地图描述
41
+ - `layers` (array, 必需): 图层配置数组
42
+ - `baseStyle` (string, 可选): 底图样式
43
+ - `center` (array, 可选): 中心点 [经度, 纬度]
44
+ - `zoom` (number, 可选): 缩放级别
45
+
46
+ ## JavaScript 库使用
12
47
 
13
48
  ### 基本使用
14
49
 
15
50
  ```javascript
16
- import CreateMap from '@gis/mapbox-create-map';
51
+ import CreateMap from 'mapbox-create-map-mcp';
17
52
 
18
53
  // 初始化工具
19
- const createMap = new CreateMap('map-container-id', 'your-mapbox-access-token');
54
+ const createMap = new CreateMap();
20
55
 
21
56
  // 配置地图
22
57
  const config = {
23
58
  title: "我的地图标题",
24
59
  description: "地图描述信息",
25
- baseStyle: "light", // 底图样式
26
- center: [116.3974, 39.9092], // 中心点
27
- zoom: 10, // 缩放级别
60
+ baseStyle: "light",
61
+ center: [116.3974, 39.9092],
62
+ zoom: 10,
28
63
  layers: [
29
- // 图层配置
64
+ {
65
+ type: "point",
66
+ id: "my-points",
67
+ fileUrl: "https://example.com/points.geojson",
68
+ config: {
69
+ 'circle-color': '#FF0000',
70
+ 'circle-radius': 8,
71
+ 'circle-opacity': 0.8
72
+ }
73
+ }
30
74
  ]
31
75
  };
32
76
 
33
- // 生成地图配置信息
77
+ // 生成图层配置信息
34
78
  createMap.create(config)
35
79
  .then(result => {
36
- console.log("地图配置信息生成成功", result);
37
- // result 是 GeoJSON 格式的图层配置信息,可用于自定义渲染
80
+ console.log("生成成功", result);
81
+ // result 是 FeatureCollection 格式,包含图层配置信息
38
82
  })
39
83
  .catch(error => {
40
- console.error("地图配置信息生成失败", error);
84
+ console.error("生成失败", error);
41
85
  });
42
86
  ```
43
87
 
44
- ### 图层类型
45
-
46
- #### 点类型要素图层
88
+ ### 返回格式
47
89
 
48
- ##### 散点 (scatter)
49
90
  ```javascript
50
91
  {
51
- type: 'scatter',
52
- id: 'my-scatter-layer',
53
- data: geojsonData, // 或 fileUrl: 'path/to/data.geojson'
54
- color: '#3f87db', // 填充颜色
55
- size: 8, // 点大小,默认8px
56
- opacity: 100, // 透明度,0-100
57
- strokeColor: '#ffffff',// 描边颜色
58
- strokeWidth: 0 // 描边宽度
92
+ type: "FeatureCollection",
93
+ features: [
94
+ {
95
+ data: "https://example.com/points.geojson",
96
+ properties: {
97
+ name: "my-points",
98
+ type: "point",
99
+ style: {
100
+ type: "point",
101
+ "circle-color": "#FF0000",
102
+ "circle-radius": 8,
103
+ "circle-opacity": 0.8
104
+ }
105
+ }
106
+ }
107
+ ]
59
108
  }
60
109
  ```
61
110
 
62
- ##### 图标点 (icon)
63
- ```javascript
64
- {
65
- type: 'icon',
66
- id: 'my-icon-layer',
67
- data: geojsonData,
68
- iconImage: 'car-15', // 图标图片
69
- iconRotate: 0, // 图标旋转角度
70
- size: 24 // 图标大小
71
- }
72
- ```
111
+ ## 图层类型
73
112
 
74
- ##### 文字点 (text)
75
- ```javascript
76
- {
77
- type: 'text',
78
- id: 'my-text-layer',
79
- data: geojsonData,
80
- textColor: '#000000', // 文字颜色
81
- textSize: 12, // 字体大小
82
- textHaloColor: '#ffffff', // 文字描边颜色
83
- textHaloWidth: 2 // 文字描边宽度
84
- }
85
- ```
113
+ 仅支持三种几何类型:`point`、`linestring`、`polygon`
86
114
 
87
- ##### 热力点 (heatmap)
88
- ```javascript
89
- {
90
- type: 'heatmap',
91
- id: 'my-heatmap-layer',
92
- data: geojsonData,
93
- color: ['#3288bd', '#abdda4', '#fee08b', '#f46d43', '#d53e4f'], // 色带
94
- radius: 20, // 热力半径
95
- weight: 1 // 热力点权重
96
- }
97
- ```
115
+ ### point(点图层)
116
+
117
+ 对应 Mapbox circle 图层
98
118
 
99
- ##### 3D热力点 (heatmap3d)
100
119
  ```javascript
101
120
  {
102
- type: 'heatmap3d',
103
- id: 'my-heatmap3d-layer',
104
- data: geojsonData,
105
- color: ['#000', '#555', '#fff'], // 色带
106
- radius: 20, // 热力半径
107
- weight: 1 // 热力点权重
121
+ type: "point",
122
+ id: "my-points",
123
+ fileUrl: "path/to/data.geojson",
124
+ config: {
125
+ 'circle-color': '#0000FF', // 填充颜色
126
+ 'circle-radius': 5, // 半径(像素)
127
+ 'circle-opacity': 1, // 填充透明度 0-1
128
+ 'circle-stroke-color': '#000000', // 边框颜色
129
+ 'circle-stroke-width': 0, // 边框宽度(像素)
130
+ 'circle-stroke-opacity': 1, // 边框透明度 0-1
131
+ 'circle-blur': 0, // 模糊量(像素)
132
+ 'circle-translate': [0, 0], // 偏移量 [x, y]
133
+ 'circle-translate-anchor': 'map', // 偏移参考 'map' | 'viewport'
134
+ 'circle-pitch-scale': 'map', // 倾斜缩放 'map' | 'viewport'
135
+ 'circle-pitch-alignment': 'viewport' // 倾斜方向 'map' | 'viewport'
136
+ }
108
137
  }
109
138
  ```
110
139
 
111
- #### 线类型要素图层
140
+ ### linestring(线图层)
141
+
142
+ 对应 Mapbox line 图层
112
143
 
113
- ##### 线 (line)
114
144
  ```javascript
115
145
  {
116
- type: 'line',
117
- id: 'my-line-layer',
118
- data: geojsonData,
119
- color: '#3f87db', // 线颜色
120
- opacity: 100, // 透明度
121
- width: 2, // 线宽度
122
- dash: 'solid' // 实线或虚线 ('solid' 或 'dash')
146
+ type: "linestring",
147
+ id: "my-lines",
148
+ fileUrl: "path/to/data.geojson",
149
+ config: {
150
+ 'line-color': '#FF0000', // 线条颜色
151
+ 'line-width': 1, // 线条宽度
152
+ 'line-opacity': 1, // 透明度 0-1
153
+ 'line-blur': 0, // 模糊度
154
+ 'line-gap-width': 0, // 间隙宽度
155
+ 'line-offset': 0, // 偏移量
156
+ 'line-dasharray': null // 虚线样式,如 [2, 2]
157
+ }
123
158
  }
124
159
  ```
125
160
 
126
- #### 面类型要素图层
161
+ ### polygon(面图层)
127
162
 
128
- ##### 填充面 (fill)
129
- ```javascript
130
- {
131
- type: 'fill',
132
- id: 'my-fill-layer',
133
- data: geojsonData,
134
- color: '#3f87db', // 填充颜色
135
- opacity: 50, // 透明度
136
- strokeColor: '#ffffff',// 描边颜色
137
- strokeWidth: 1 // 描边宽度
138
- }
139
- ```
163
+ 对应 Mapbox fill 图层
140
164
 
141
- ##### 三维拉伸面 (extrusion)
142
165
  ```javascript
143
166
  {
144
- type: 'extrusion',
145
- id: 'my-extrusion-layer',
146
- data: geojsonData,
147
- color: '#3f87db', // 填充颜色
148
- opacity: 80, // 透明度
149
- height: 100 // 拉伸高度(米)
167
+ type: "polygon",
168
+ id: "my-polygons",
169
+ fileUrl: "path/to/data.geojson",
170
+ config: {
171
+ 'fill-color': '#FFFF00', // 填充颜色
172
+ 'fill-opacity': 1, // 填充透明度 0-1
173
+ 'fill-outline-color': '#000000', // 边框颜色
174
+ 'fill-antialias': true, // 抗锯齿
175
+ 'fill-z-offset': 0 // 高程偏移(米)
176
+ }
150
177
  }
151
178
  ```
152
179
 
153
- ### 底图样式
180
+ ## 底图样式
154
181
 
155
- - `whitesmoke`: 淡白色
156
- - `light`: 白色
157
- - `dark`: 黑色
158
- - `blue`: 靛青蓝
159
- - `darkblue`: 深蓝
160
- - `grey`: 灰色
161
- - `fresh`: 草绿色
182
+ - `standard`: 标准
183
+ - `light`: 浅色
184
+ - `dark`: 深色
162
185
  - `satellite`: 卫星图
163
186
 
164
187
  ## API
165
188
 
166
- ### CreateMap(container, accessToken)
189
+ ### CreateMap()
167
190
 
168
- 构造函数,初始化CreateMap实例。
169
-
170
- - `container`: DOM容器ID或DOM元素
171
- - `accessToken`: Mapbox访问令牌(可选,如果不传则需提前设置)
191
+ 构造函数,初始化实例。
172
192
 
173
193
  ### create(config)
174
194
 
175
- 创建地图。
195
+ 生成图层配置信息。
196
+
197
+ **参数:**
198
+ - `config.title` (string, 必需): 地图标题
199
+ - `config.description` (string, 必需): 地图描述
200
+ - `config.layers` (array, 必需): 图层配置数组
201
+ - `config.baseStyle` (string, 可选): 底图样式,默认 'light'
202
+ - `config.center` (array, 可选): 中心点 [经度, 纬度]
203
+ - `config.zoom` (number, 可选): 缩放级别
204
+
205
+ **返回:** Promise,resolve 后返回 FeatureCollection 格式的配置信息
206
+
207
+ ### metadata
176
208
 
177
- - `config`: 配置对象
209
+ 获取参数元数据定义,包含所有参数的类型、默认值、描述等信息。
178
210
 
179
- ### destroy()
211
+ ### layerMetadata
180
212
 
181
- 销毁地图实例,清理资源。
213
+ 获取各图层类型的配置属性元数据。
182
214
 
183
215
  ## 开发
184
216
 
@@ -186,19 +218,19 @@ createMap.create(config)
186
218
  # 安装依赖
187
219
  npm install
188
220
 
189
- # 开发模式(监听变化)
221
+ # 开发模式
190
222
  npm run dev
191
223
 
192
- # 构建生产版本
224
+ # 构建
193
225
  npm run build
194
226
 
195
- # 运行测试
227
+ # 测试
196
228
  npm test
197
229
 
198
- # 代码检查
199
- npm run lint
230
+ # 发布
231
+ npm run publish:npm
200
232
  ```
201
233
 
202
234
  ## 许可证
203
235
 
204
- MIT
236
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * mapbox-create-map-mcp CLI
5
+ * MCP 服务端入口
6
+ */
7
+
8
+ const { McpServer } = require('../src/server.js');
9
+
10
+ const server = new McpServer();
11
+ server.start();
package/package.json CHANGED
@@ -1,13 +1,17 @@
1
1
  {
2
2
  "name": "mapbox-create-map-mcp",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "A Mapbox-based MCP tool for creating geographic data visualizations",
5
5
  "main": "dist/index.js",
6
6
  "module": "src/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "mapbox-create-map-mcp": "./bin/cli.js"
10
+ },
8
11
  "files": [
9
12
  "dist",
10
- "src"
13
+ "src",
14
+ "bin"
11
15
  ],
12
16
  "scripts": {
13
17
  "build": "webpack --mode production",
package/src/server.js ADDED
@@ -0,0 +1,301 @@
1
+ /**
2
+ * MCP Server - mapbox-create-map-mcp
3
+ * 实现 Model Context Protocol 服务端
4
+ */
5
+
6
+ const readline = require('readline');
7
+ const path = require('path');
8
+
9
+ // 尝试加载打包后的版本,如果不存在则提示构建
10
+ let CreateMap;
11
+ try {
12
+ const distPath = path.join(__dirname, '../dist/index.js');
13
+ const module = require(distPath);
14
+ // UMD格式导出的是MapboxCreateMap,默认导出在.default中
15
+ CreateMap = module.default || module;
16
+ } catch (e) {
17
+ console.error('Error: Please run "npm run build" first');
18
+ console.error(e.message);
19
+ process.exit(1);
20
+ }
21
+
22
+ class McpServer {
23
+ constructor() {
24
+ this.createMap = new CreateMap();
25
+ this.serverInfo = {
26
+ name: 'mapbox-create-map-mcp',
27
+ version: '1.0.0',
28
+ description: '基于Mapbox的地理数据可视化MCP工具'
29
+ };
30
+ }
31
+
32
+ /**
33
+ * 启动MCP服务
34
+ */
35
+ start() {
36
+ const rl = readline.createInterface({
37
+ input: process.stdin,
38
+ output: process.stdout,
39
+ terminal: false
40
+ });
41
+
42
+ rl.on('line', (line) => {
43
+ try {
44
+ const request = JSON.parse(line);
45
+ this.handleRequest(request);
46
+ } catch (error) {
47
+ this.sendError(-32700, 'Parse error', null);
48
+ }
49
+ });
50
+
51
+ rl.on('close', () => {
52
+ process.exit(0);
53
+ });
54
+
55
+ // 发送服务就绪信号
56
+ process.stderr.write('MCP Server started\n');
57
+ }
58
+
59
+ /**
60
+ * 处理MCP请求
61
+ */
62
+ async handleRequest(request) {
63
+ const { id, method, params } = request;
64
+
65
+ try {
66
+ let result;
67
+
68
+ switch (method) {
69
+ case 'initialize':
70
+ result = this.handleInitialize(params);
71
+ break;
72
+
73
+ case 'tools/list':
74
+ result = this.handleToolsList();
75
+ break;
76
+
77
+ case 'tools/call':
78
+ result = await this.handleToolsCall(params);
79
+ break;
80
+
81
+ case 'resources/list':
82
+ result = this.handleResourcesList();
83
+ break;
84
+
85
+ default:
86
+ this.sendError(-32601, `Method not found: ${method}`, id);
87
+ return;
88
+ }
89
+
90
+ this.sendResponse(id, result);
91
+ } catch (error) {
92
+ this.sendError(-32000, error.message, id);
93
+ }
94
+ }
95
+
96
+ /**
97
+ * 处理初始化请求
98
+ */
99
+ handleInitialize(params) {
100
+ return {
101
+ protocolVersion: '2024-11-05',
102
+ capabilities: {
103
+ tools: {},
104
+ resources: {}
105
+ },
106
+ serverInfo: this.serverInfo
107
+ };
108
+ }
109
+
110
+ /**
111
+ * 处理工具列表请求
112
+ */
113
+ handleToolsList() {
114
+ const metadata = this.createMap.metadata;
115
+ const layerMetadata = this.createMap.layerMetadata;
116
+
117
+ // 合并所有图层类型的配置属性
118
+ const allConfigProperties = {};
119
+
120
+ // point 属性
121
+ for (const key in layerMetadata.point) {
122
+ const prop = layerMetadata.point[key];
123
+ allConfigProperties[key] = {
124
+ type: prop.type,
125
+ description: `[point图层] ${prop.description}`
126
+ };
127
+ if (prop.default !== undefined) allConfigProperties[key].default = prop.default;
128
+ }
129
+
130
+ // linestring 属性
131
+ for (const key in layerMetadata.linestring) {
132
+ const prop = layerMetadata.linestring[key];
133
+ allConfigProperties[key] = {
134
+ type: prop.type,
135
+ description: `[linestring图层] ${prop.description}`
136
+ };
137
+ if (prop.default !== undefined) allConfigProperties[key].default = prop.default;
138
+ }
139
+
140
+ // polygon 属性
141
+ for (const key in layerMetadata.polygon) {
142
+ const prop = layerMetadata.polygon[key];
143
+ allConfigProperties[key] = {
144
+ type: prop.type,
145
+ description: `[polygon图层] ${prop.description}`
146
+ };
147
+ if (prop.default !== undefined) allConfigProperties[key].default = prop.default;
148
+ }
149
+
150
+ return {
151
+ tools: [
152
+ {
153
+ name: 'CreateMap',
154
+ description: '根据配置生成地图图层配置信息,返回FeatureCollection格式的结果用于渲染。图层类型支持point(点)、linestring(线)、polygon(面)三种。',
155
+ inputSchema: {
156
+ type: 'object',
157
+ properties: {
158
+ title: {
159
+ type: 'string',
160
+ description: metadata.title.description
161
+ },
162
+ description: {
163
+ type: 'string',
164
+ description: metadata.description.description
165
+ },
166
+ baseStyle: {
167
+ type: 'string',
168
+ enum: metadata.baseStyle.enum,
169
+ description: metadata.baseStyle.description
170
+ },
171
+ center: {
172
+ type: 'array',
173
+ items: { type: 'number' },
174
+ description: metadata.center.description
175
+ },
176
+ zoom: {
177
+ type: 'number',
178
+ description: metadata.zoom.description
179
+ },
180
+ layers: {
181
+ type: 'array',
182
+ description: '图层配置数组。每个图层需要id和type,type决定了config中可用的属性:point类型用circle-*属性,lingestring类型用line-*属性,polygon类型用fill-*属性',
183
+ items: {
184
+ type: 'object',
185
+ properties: {
186
+ id: { type: 'string', description: '图层唯一标识符' },
187
+ type: {
188
+ type: 'string',
189
+ enum: ['point', 'linestring', 'polygon'],
190
+ description: '图层类型: point(点,使用circle-*属性), linestring(线,使用line-*属性), polygon(面,使用fill-*属性)'
191
+ },
192
+ data: { type: 'object', description: 'GeoJSON格式的地理数据' },
193
+ fileUrl: { type: 'string', description: '数据URL地址' },
194
+ config: {
195
+ type: 'object',
196
+ description: '图层样式配置,根据type选择对应属性: point用circle-*、linestring用line-*、polygon用fill-*',
197
+ properties: allConfigProperties
198
+ }
199
+ },
200
+ required: ['id', 'type']
201
+ }
202
+ }
203
+ },
204
+ required: ['title', 'description', 'layers']
205
+ }
206
+ }
207
+ ]
208
+ };
209
+ }
210
+
211
+ /**
212
+ * 格式化属性元数据
213
+ */
214
+ formatProperties(meta) {
215
+ const props = {};
216
+ for (const key in meta) {
217
+ const prop = meta[key];
218
+ props[key] = {
219
+ type: prop.type,
220
+ default: prop.default,
221
+ description: prop.description
222
+ };
223
+ if (prop.enum) {
224
+ props[key].enum = prop.enum;
225
+ }
226
+ if (prop.min !== undefined) {
227
+ props[key].minimum = prop.min;
228
+ }
229
+ if (prop.max !== undefined) {
230
+ props[key].maximum = prop.max;
231
+ }
232
+ }
233
+ return props;
234
+ }
235
+
236
+ /**
237
+ * 处理工具调用请求
238
+ */
239
+ async handleToolsCall(params) {
240
+ const { name, arguments: args } = params;
241
+
242
+ if (name !== 'CreateMap') {
243
+ throw new Error(`Unknown tool: ${name}`);
244
+ }
245
+
246
+ try {
247
+ const result = await this.createMap.create(args);
248
+ return {
249
+ content: [
250
+ {
251
+ type: 'text',
252
+ text: JSON.stringify(result, null, 2)
253
+ }
254
+ ]
255
+ };
256
+ } catch (error) {
257
+ return {
258
+ content: [
259
+ {
260
+ type: 'text',
261
+ text: `Error: ${error.message}`
262
+ }
263
+ ],
264
+ isError: true
265
+ };
266
+ }
267
+ }
268
+
269
+ /**
270
+ * 处理资源列表请求
271
+ */
272
+ handleResourcesList() {
273
+ return { resources: [] };
274
+ }
275
+
276
+ /**
277
+ * 发送响应
278
+ */
279
+ sendResponse(id, result) {
280
+ const response = {
281
+ jsonrpc: '2.0',
282
+ id,
283
+ result
284
+ };
285
+ console.log(JSON.stringify(response));
286
+ }
287
+
288
+ /**
289
+ * 发送错误
290
+ */
291
+ sendError(code, message, id) {
292
+ const response = {
293
+ jsonrpc: '2.0',
294
+ id,
295
+ error: { code, message }
296
+ };
297
+ console.log(JSON.stringify(response));
298
+ }
299
+ }
300
+
301
+ module.exports = { McpServer };