guohanghui commited on
Commit
b8dfb4e
·
verified ·
1 Parent(s): 0e6a1e4

Update pygeos/mcp_output/mcp_plugin/mcp_service.py

Browse files
pygeos/mcp_output/mcp_plugin/mcp_service.py CHANGED
@@ -1,746 +1,44 @@
1
- import os
2
- import sys
3
- from typing import List, Optional
4
-
5
  from fastmcp import FastMCP
6
- import numpy as np
7
- import pygeos
8
 
9
  # Create the FastMCP service application
10
  mcp = FastMCP("pygeos_service")
11
 
12
- # ==================== Geometry Creation ====================
13
-
14
- @mcp.tool()
15
- def create_point(x: float, y: float, z: Optional[float] = None) -> dict:
16
- """Create a point geometry from coordinates.
17
-
18
- Args:
19
- x: X coordinate
20
- y: Y coordinate
21
- z: Optional Z coordinate for 3D point
22
-
23
- Returns:
24
- dict: WKT representation of the created point
25
- """
26
- try:
27
- if z is not None:
28
- coords = [[x, y, z]]
29
- else:
30
- coords = [[x, y]]
31
- point = pygeos.points(coords)[0]
32
- wkt = pygeos.to_wkt(point)
33
- return {"success": True, "wkt": wkt, "geometry_type": "Point"}
34
- except Exception as e:
35
- return {"success": False, "error": str(e)}
36
-
37
-
38
- @mcp.tool()
39
- def create_linestring(coordinates: List[List[float]]) -> dict:
40
- """Create a linestring geometry from a list of coordinates.
41
-
42
- Args:
43
- coordinates: List of [x, y] or [x, y, z] coordinate pairs, e.g. [[0, 0], [1, 1], [2, 0]]
44
-
45
- Returns:
46
- dict: WKT representation of the created linestring
47
  """
48
- try:
49
- coords = np.array(coordinates)
50
- linestring = pygeos.linestrings([coords])[0]
51
- wkt = pygeos.to_wkt(linestring)
52
- return {"success": True, "wkt": wkt, "geometry_type": "LineString"}
53
- except Exception as e:
54
- return {"success": False, "error": str(e)}
55
-
56
 
57
- @mcp.tool()
58
- def create_polygon(shell: List[List[float]], holes: Optional[List[List[List[float]]]] = None) -> dict:
59
- """Create a polygon geometry from shell and optional holes.
60
-
61
- Args:
62
- shell: List of coordinates forming the exterior ring, e.g. [[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]
63
- holes: Optional list of hole rings
64
-
65
  Returns:
66
- dict: WKT representation of the created polygon
67
  """
68
  try:
69
- shell_ring = pygeos.linearrings([np.array(shell)])[0]
70
- if holes:
71
- hole_rings = [pygeos.linearrings([np.array(h)])[0] for h in holes]
72
- polygon = pygeos.polygons(shell_ring, hole_rings)
73
- else:
74
- polygon = pygeos.polygons(shell_ring)
75
- wkt = pygeos.to_wkt(polygon)
76
- return {"success": True, "wkt": wkt, "geometry_type": "Polygon"}
77
- except Exception as e:
78
- return {"success": False, "error": str(e)}
79
-
80
-
81
- @mcp.tool()
82
- def create_box(xmin: float, ymin: float, xmax: float, ymax: float) -> dict:
83
- """Create a rectangular polygon (box) from bounds.
84
-
85
- Args:
86
- xmin: Minimum X coordinate
87
- ymin: Minimum Y coordinate
88
- xmax: Maximum X coordinate
89
- ymax: Maximum Y coordinate
90
-
91
- Returns:
92
- dict: WKT representation of the box polygon
93
- """
94
- try:
95
- box = pygeos.box(xmin, ymin, xmax, ymax)
96
- wkt = pygeos.to_wkt(box)
97
- return {"success": True, "wkt": wkt, "geometry_type": "Polygon"}
98
- except Exception as e:
99
- return {"success": False, "error": str(e)}
100
-
101
-
102
- @mcp.tool()
103
- def from_wkt(wkt: str) -> dict:
104
- """Parse a WKT string into a geometry and return its properties.
105
-
106
- Args:
107
- wkt: Well-Known Text representation of geometry
108
-
109
- Returns:
110
- dict: Geometry properties including type, validity, and bounds
111
- """
112
- try:
113
- geom = pygeos.from_wkt(wkt)
114
- geom_type = pygeos.get_type_id(geom)
115
- type_names = {0: "Point", 1: "LineString", 2: "LinearRing", 3: "Polygon",
116
- 4: "MultiPoint", 5: "MultiLineString", 6: "MultiPolygon", 7: "GeometryCollection"}
117
- bounds = pygeos.bounds(geom).tolist()
118
  return {
119
  "success": True,
120
- "wkt": pygeos.to_wkt(geom),
121
- "geometry_type": type_names.get(int(geom_type), "Unknown"),
122
- "is_valid": bool(pygeos.is_valid(geom)),
123
- "is_empty": bool(pygeos.is_empty(geom)),
124
- "bounds": {"xmin": bounds[0], "ymin": bounds[1], "xmax": bounds[2], "ymax": bounds[3]}
125
  }
126
  except Exception as e:
127
  return {"success": False, "error": str(e)}
128
 
129
-
130
- # ==================== Measurement ====================
131
-
132
- @mcp.tool()
133
- def calculate_distance(wkt1: str, wkt2: str) -> dict:
134
- """Calculate the Cartesian distance between two geometries.
135
-
136
- Args:
137
- wkt1: WKT of the first geometry
138
- wkt2: WKT of the second geometry
139
-
140
- Returns:
141
- dict: Distance between the geometries
142
- """
143
- try:
144
- geom1 = pygeos.from_wkt(wkt1)
145
- geom2 = pygeos.from_wkt(wkt2)
146
- distance = float(pygeos.distance(geom1, geom2))
147
- return {"success": True, "distance": distance}
148
- except Exception as e:
149
- return {"success": False, "error": str(e)}
150
-
151
-
152
- @mcp.tool()
153
- def calculate_area(wkt: str) -> dict:
154
- """Calculate the area of a polygon geometry.
155
-
156
- Args:
157
- wkt: WKT of the polygon geometry
158
-
159
- Returns:
160
- dict: Area of the polygon
161
- """
162
- try:
163
- geom = pygeos.from_wkt(wkt)
164
- area = float(pygeos.area(geom))
165
- return {"success": True, "area": area}
166
- except Exception as e:
167
- return {"success": False, "error": str(e)}
168
-
169
-
170
- @mcp.tool()
171
- def calculate_length(wkt: str) -> dict:
172
- """Calculate the length of a linear geometry.
173
-
174
- Args:
175
- wkt: WKT of the linear geometry (LineString, MultiLineString, or polygon boundary)
176
-
177
- Returns:
178
- dict: Length of the geometry
179
- """
180
- try:
181
- geom = pygeos.from_wkt(wkt)
182
- length = float(pygeos.length(geom))
183
- return {"success": True, "length": length}
184
- except Exception as e:
185
- return {"success": False, "error": str(e)}
186
-
187
-
188
- @mcp.tool()
189
- def get_bounds(wkt: str) -> dict:
190
- """Get the bounding box of a geometry.
191
-
192
- Args:
193
- wkt: WKT of the geometry
194
-
195
- Returns:
196
- dict: Bounding box coordinates (xmin, ymin, xmax, ymax)
197
- """
198
- try:
199
- geom = pygeos.from_wkt(wkt)
200
- bounds = pygeos.bounds(geom).tolist()
201
- return {
202
- "success": True,
203
- "xmin": bounds[0],
204
- "ymin": bounds[1],
205
- "xmax": bounds[2],
206
- "ymax": bounds[3]
207
- }
208
- except Exception as e:
209
- return {"success": False, "error": str(e)}
210
-
211
-
212
- @mcp.tool()
213
- def hausdorff_distance(wkt1: str, wkt2: str) -> dict:
214
- """Calculate the Hausdorff distance between two geometries.
215
-
216
- The Hausdorff distance is a measure of the maximum distance between
217
- the nearest points in two geometries.
218
-
219
- Args:
220
- wkt1: WKT of the first geometry
221
- wkt2: WKT of the second geometry
222
-
223
- Returns:
224
- dict: Hausdorff distance
225
- """
226
- try:
227
- geom1 = pygeos.from_wkt(wkt1)
228
- geom2 = pygeos.from_wkt(wkt2)
229
- dist = float(pygeos.hausdorff_distance(geom1, geom2))
230
- return {"success": True, "hausdorff_distance": dist}
231
- except Exception as e:
232
- return {"success": False, "error": str(e)}
233
-
234
-
235
- # ==================== Predicates ====================
236
-
237
- @mcp.tool()
238
- def check_intersects(wkt1: str, wkt2: str) -> dict:
239
- """Check if two geometries intersect.
240
-
241
- Args:
242
- wkt1: WKT of the first geometry
243
- wkt2: WKT of the second geometry
244
-
245
- Returns:
246
- dict: Boolean indicating intersection
247
- """
248
- try:
249
- geom1 = pygeos.from_wkt(wkt1)
250
- geom2 = pygeos.from_wkt(wkt2)
251
- result = bool(pygeos.intersects(geom1, geom2))
252
- return {"success": True, "intersects": result}
253
- except Exception as e:
254
- return {"success": False, "error": str(e)}
255
-
256
-
257
- @mcp.tool()
258
- def check_contains(wkt1: str, wkt2: str) -> dict:
259
- """Check if geometry 1 contains geometry 2.
260
-
261
- Args:
262
- wkt1: WKT of the container geometry
263
- wkt2: WKT of the contained geometry
264
-
265
- Returns:
266
- dict: Boolean indicating containment
267
- """
268
- try:
269
- geom1 = pygeos.from_wkt(wkt1)
270
- geom2 = pygeos.from_wkt(wkt2)
271
- result = bool(pygeos.contains(geom1, geom2))
272
- return {"success": True, "contains": result}
273
- except Exception as e:
274
- return {"success": False, "error": str(e)}
275
-
276
-
277
- @mcp.tool()
278
- def check_within(wkt1: str, wkt2: str) -> dict:
279
- """Check if geometry 1 is within geometry 2.
280
-
281
- Args:
282
- wkt1: WKT of the inner geometry
283
- wkt2: WKT of the outer geometry
284
-
285
- Returns:
286
- dict: Boolean indicating if geometry 1 is within geometry 2
287
- """
288
- try:
289
- geom1 = pygeos.from_wkt(wkt1)
290
- geom2 = pygeos.from_wkt(wkt2)
291
- result = bool(pygeos.within(geom1, geom2))
292
- return {"success": True, "within": result}
293
- except Exception as e:
294
- return {"success": False, "error": str(e)}
295
-
296
-
297
- @mcp.tool()
298
- def check_touches(wkt1: str, wkt2: str) -> dict:
299
- """Check if two geometries touch (share boundary but not interior).
300
-
301
- Args:
302
- wkt1: WKT of the first geometry
303
- wkt2: WKT of the second geometry
304
-
305
- Returns:
306
- dict: Boolean indicating if geometries touch
307
- """
308
- try:
309
- geom1 = pygeos.from_wkt(wkt1)
310
- geom2 = pygeos.from_wkt(wkt2)
311
- result = bool(pygeos.touches(geom1, geom2))
312
- return {"success": True, "touches": result}
313
- except Exception as e:
314
- return {"success": False, "error": str(e)}
315
-
316
-
317
- @mcp.tool()
318
- def check_crosses(wkt1: str, wkt2: str) -> dict:
319
- """Check if two geometries cross each other.
320
-
321
- Args:
322
- wkt1: WKT of the first geometry
323
- wkt2: WKT of the second geometry
324
-
325
- Returns:
326
- dict: Boolean indicating if geometries cross
327
- """
328
- try:
329
- geom1 = pygeos.from_wkt(wkt1)
330
- geom2 = pygeos.from_wkt(wkt2)
331
- result = bool(pygeos.crosses(geom1, geom2))
332
- return {"success": True, "crosses": result}
333
- except Exception as e:
334
- return {"success": False, "error": str(e)}
335
-
336
-
337
- @mcp.tool()
338
- def check_overlaps(wkt1: str, wkt2: str) -> dict:
339
- """Check if two geometries overlap.
340
-
341
- Args:
342
- wkt1: WKT of the first geometry
343
- wkt2: WKT of the second geometry
344
-
345
- Returns:
346
- dict: Boolean indicating if geometries overlap
347
- """
348
- try:
349
- geom1 = pygeos.from_wkt(wkt1)
350
- geom2 = pygeos.from_wkt(wkt2)
351
- result = bool(pygeos.overlaps(geom1, geom2))
352
- return {"success": True, "overlaps": result}
353
- except Exception as e:
354
- return {"success": False, "error": str(e)}
355
-
356
-
357
- @mcp.tool()
358
- def check_disjoint(wkt1: str, wkt2: str) -> dict:
359
- """Check if two geometries are disjoint (do not interact).
360
-
361
- Args:
362
- wkt1: WKT of the first geometry
363
- wkt2: WKT of the second geometry
364
-
365
- Returns:
366
- dict: Boolean indicating if geometries are disjoint
367
- """
368
- try:
369
- geom1 = pygeos.from_wkt(wkt1)
370
- geom2 = pygeos.from_wkt(wkt2)
371
- result = bool(pygeos.disjoint(geom1, geom2))
372
- return {"success": True, "disjoint": result}
373
- except Exception as e:
374
- return {"success": False, "error": str(e)}
375
-
376
-
377
- @mcp.tool()
378
- def is_valid(wkt: str) -> dict:
379
- """Check if a geometry is valid.
380
-
381
- Args:
382
- wkt: WKT of the geometry
383
-
384
- Returns:
385
- dict: Boolean indicating validity and reason if invalid
386
- """
387
- try:
388
- geom = pygeos.from_wkt(wkt)
389
- valid = bool(pygeos.is_valid(geom))
390
- reason = pygeos.is_valid_reason(geom) if not valid else None
391
- return {"success": True, "is_valid": valid, "reason": reason}
392
- except Exception as e:
393
- return {"success": False, "error": str(e)}
394
-
395
-
396
- @mcp.tool()
397
- def is_simple(wkt: str) -> dict:
398
- """Check if a geometry is simple (no self-intersection).
399
-
400
- Args:
401
- wkt: WKT of the geometry
402
-
403
- Returns:
404
- dict: Boolean indicating if geometry is simple
405
- """
406
- try:
407
- geom = pygeos.from_wkt(wkt)
408
- result = bool(pygeos.is_simple(geom))
409
- return {"success": True, "is_simple": result}
410
- except Exception as e:
411
- return {"success": False, "error": str(e)}
412
-
413
-
414
- # ==================== Constructive Operations ====================
415
-
416
- @mcp.tool()
417
- def buffer_geometry(wkt: str, distance: float, quad_segs: int = 8) -> dict:
418
- """Create a buffer around a geometry.
419
-
420
- Args:
421
- wkt: WKT of the geometry
422
- distance: Buffer distance (positive for expansion, negative for erosion)
423
- quad_segs: Number of segments for quarter circle approximation
424
-
425
- Returns:
426
- dict: WKT of the buffered geometry
427
- """
428
- try:
429
- geom = pygeos.from_wkt(wkt)
430
- buffered = pygeos.buffer(geom, distance, quadsegs=quad_segs)
431
- wkt_result = pygeos.to_wkt(buffered)
432
- return {"success": True, "wkt": wkt_result}
433
- except Exception as e:
434
- return {"success": False, "error": str(e)}
435
-
436
-
437
- @mcp.tool()
438
- def simplify_geometry(wkt: str, tolerance: float, preserve_topology: bool = True) -> dict:
439
- """Simplify a geometry using Douglas-Peucker algorithm.
440
-
441
- Args:
442
- wkt: WKT of the geometry
443
- tolerance: Simplification tolerance
444
- preserve_topology: Whether to preserve topology
445
-
446
- Returns:
447
- dict: WKT of the simplified geometry
448
- """
449
- try:
450
- geom = pygeos.from_wkt(wkt)
451
- simplified = pygeos.simplify(geom, tolerance, preserve_topology=preserve_topology)
452
- wkt_result = pygeos.to_wkt(simplified)
453
- return {"success": True, "wkt": wkt_result}
454
- except Exception as e:
455
- return {"success": False, "error": str(e)}
456
-
457
-
458
- @mcp.tool()
459
- def get_centroid(wkt: str) -> dict:
460
- """Get the centroid of a geometry.
461
-
462
- Args:
463
- wkt: WKT of the geometry
464
-
465
- Returns:
466
- dict: WKT of the centroid point
467
- """
468
- try:
469
- geom = pygeos.from_wkt(wkt)
470
- centroid = pygeos.centroid(geom)
471
- wkt_result = pygeos.to_wkt(centroid)
472
- return {"success": True, "wkt": wkt_result}
473
- except Exception as e:
474
- return {"success": False, "error": str(e)}
475
-
476
-
477
- @mcp.tool()
478
- def get_convex_hull(wkt: str) -> dict:
479
- """Get the convex hull of a geometry.
480
-
481
- Args:
482
- wkt: WKT of the geometry
483
-
484
- Returns:
485
- dict: WKT of the convex hull
486
- """
487
- try:
488
- geom = pygeos.from_wkt(wkt)
489
- hull = pygeos.convex_hull(geom)
490
- wkt_result = pygeos.to_wkt(hull)
491
- return {"success": True, "wkt": wkt_result}
492
- except Exception as e:
493
- return {"success": False, "error": str(e)}
494
-
495
-
496
- @mcp.tool()
497
- def get_envelope(wkt: str) -> dict:
498
- """Get the envelope (bounding box) of a geometry as a polygon.
499
-
500
- Args:
501
- wkt: WKT of the geometry
502
-
503
- Returns:
504
- dict: WKT of the envelope polygon
505
- """
506
- try:
507
- geom = pygeos.from_wkt(wkt)
508
- envelope = pygeos.envelope(geom)
509
- wkt_result = pygeos.to_wkt(envelope)
510
- return {"success": True, "wkt": wkt_result}
511
- except Exception as e:
512
- return {"success": False, "error": str(e)}
513
-
514
-
515
- @mcp.tool()
516
- def get_boundary(wkt: str) -> dict:
517
- """Get the boundary of a geometry.
518
-
519
- Args:
520
- wkt: WKT of the geometry
521
-
522
- Returns:
523
- dict: WKT of the boundary
524
- """
525
- try:
526
- geom = pygeos.from_wkt(wkt)
527
- boundary = pygeos.boundary(geom)
528
- wkt_result = pygeos.to_wkt(boundary)
529
- return {"success": True, "wkt": wkt_result}
530
- except Exception as e:
531
- return {"success": False, "error": str(e)}
532
-
533
-
534
- @mcp.tool()
535
- def make_valid(wkt: str) -> dict:
536
- """Make an invalid geometry valid.
537
-
538
- Args:
539
- wkt: WKT of the geometry
540
-
541
- Returns:
542
- dict: WKT of the valid geometry
543
- """
544
- try:
545
- geom = pygeos.from_wkt(wkt)
546
- valid_geom = pygeos.make_valid(geom)
547
- wkt_result = pygeos.to_wkt(valid_geom)
548
- return {"success": True, "wkt": wkt_result, "is_valid": bool(pygeos.is_valid(valid_geom))}
549
- except Exception as e:
550
- return {"success": False, "error": str(e)}
551
-
552
-
553
- # ==================== Set Operations ====================
554
-
555
- @mcp.tool()
556
- def geometry_intersection(wkt1: str, wkt2: str) -> dict:
557
- """Compute the intersection of two geometries.
558
-
559
- Args:
560
- wkt1: WKT of the first geometry
561
- wkt2: WKT of the second geometry
562
-
563
- Returns:
564
- dict: WKT of the intersection
565
- """
566
- try:
567
- geom1 = pygeos.from_wkt(wkt1)
568
- geom2 = pygeos.from_wkt(wkt2)
569
- result = pygeos.intersection(geom1, geom2)
570
- wkt_result = pygeos.to_wkt(result)
571
- return {"success": True, "wkt": wkt_result, "is_empty": bool(pygeos.is_empty(result))}
572
- except Exception as e:
573
- return {"success": False, "error": str(e)}
574
-
575
-
576
- @mcp.tool()
577
- def geometry_union(wkt1: str, wkt2: str) -> dict:
578
- """Compute the union of two geometries.
579
-
580
- Args:
581
- wkt1: WKT of the first geometry
582
- wkt2: WKT of the second geometry
583
-
584
- Returns:
585
- dict: WKT of the union
586
  """
587
- try:
588
- geom1 = pygeos.from_wkt(wkt1)
589
- geom2 = pygeos.from_wkt(wkt2)
590
- result = pygeos.union(geom1, geom2)
591
- wkt_result = pygeos.to_wkt(result)
592
- return {"success": True, "wkt": wkt_result}
593
- except Exception as e:
594
- return {"success": False, "error": str(e)}
595
 
 
 
596
 
597
- @mcp.tool()
598
- def geometry_difference(wkt1: str, wkt2: str) -> dict:
599
- """Compute the difference of two geometries (wkt1 - wkt2).
600
-
601
- Args:
602
- wkt1: WKT of the first geometry
603
- wkt2: WKT of the geometry to subtract
604
-
605
  Returns:
606
- dict: WKT of the difference
607
- """
608
- try:
609
- geom1 = pygeos.from_wkt(wkt1)
610
- geom2 = pygeos.from_wkt(wkt2)
611
- result = pygeos.difference(geom1, geom2)
612
- wkt_result = pygeos.to_wkt(result)
613
- return {"success": True, "wkt": wkt_result, "is_empty": bool(pygeos.is_empty(result))}
614
- except Exception as e:
615
- return {"success": False, "error": str(e)}
616
-
617
-
618
- @mcp.tool()
619
- def geometry_symmetric_difference(wkt1: str, wkt2: str) -> dict:
620
- """Compute the symmetric difference of two geometries.
621
-
622
- Args:
623
- wkt1: WKT of the first geometry
624
- wkt2: WKT of the second geometry
625
-
626
- Returns:
627
- dict: WKT of the symmetric difference
628
- """
629
- try:
630
- geom1 = pygeos.from_wkt(wkt1)
631
- geom2 = pygeos.from_wkt(wkt2)
632
- result = pygeos.symmetric_difference(geom1, geom2)
633
- wkt_result = pygeos.to_wkt(result)
634
- return {"success": True, "wkt": wkt_result}
635
- except Exception as e:
636
- return {"success": False, "error": str(e)}
637
-
638
-
639
- # ==================== Linear Operations ====================
640
-
641
- @mcp.tool()
642
- def line_interpolate_point(wkt: str, distance: float, normalized: bool = False) -> dict:
643
- """Interpolate a point along a line at a given distance.
644
-
645
- Args:
646
- wkt: WKT of the line geometry
647
- distance: Distance along the line (or fraction if normalized)
648
- normalized: If True, distance is treated as fraction (0-1)
649
-
650
- Returns:
651
- dict: WKT of the interpolated point
652
- """
653
- try:
654
- geom = pygeos.from_wkt(wkt)
655
- point = pygeos.line_interpolate_point(geom, distance, normalized=normalized)
656
- wkt_result = pygeos.to_wkt(point)
657
- return {"success": True, "wkt": wkt_result}
658
- except Exception as e:
659
- return {"success": False, "error": str(e)}
660
-
661
-
662
- @mcp.tool()
663
- def line_locate_point(line_wkt: str, point_wkt: str, normalized: bool = False) -> dict:
664
- """Find the distance along a line to the nearest point.
665
-
666
- Args:
667
- line_wkt: WKT of the line geometry
668
- point_wkt: WKT of the point
669
- normalized: If True, return fraction (0-1) instead of distance
670
-
671
- Returns:
672
- dict: Distance or fraction along the line
673
- """
674
- try:
675
- line = pygeos.from_wkt(line_wkt)
676
- point = pygeos.from_wkt(point_wkt)
677
- distance = float(pygeos.line_locate_point(line, point, normalized=normalized))
678
- return {"success": True, "distance": distance, "normalized": normalized}
679
- except Exception as e:
680
- return {"success": False, "error": str(e)}
681
-
682
-
683
- # ==================== Coordinate Operations ====================
684
-
685
- @mcp.tool()
686
- def get_coordinates(wkt: str) -> dict:
687
- """Extract coordinates from a geometry.
688
-
689
- Args:
690
- wkt: WKT of the geometry
691
-
692
- Returns:
693
- dict: Array of coordinates
694
- """
695
- try:
696
- geom = pygeos.from_wkt(wkt)
697
- coords = pygeos.get_coordinates(geom).tolist()
698
- return {"success": True, "coordinates": coords, "num_coordinates": len(coords)}
699
- except Exception as e:
700
- return {"success": False, "error": str(e)}
701
-
702
-
703
- @mcp.tool()
704
- def get_num_coordinates(wkt: str) -> dict:
705
- """Get the number of coordinates in a geometry.
706
-
707
- Args:
708
- wkt: WKT of the geometry
709
-
710
- Returns:
711
- dict: Number of coordinates
712
- """
713
- try:
714
- geom = pygeos.from_wkt(wkt)
715
- num = int(pygeos.get_num_coordinates(geom))
716
- return {"success": True, "num_coordinates": num}
717
- except Exception as e:
718
- return {"success": False, "error": str(e)}
719
-
720
-
721
- # ==================== Utility ====================
722
-
723
- @mcp.tool()
724
- def get_pygeos_version() -> dict:
725
- """Get the PyGEOS library version.
726
-
727
- Returns:
728
- dict: Version information
729
  """
730
  try:
 
 
731
  return {
732
  "success": True,
733
- "pygeos_version": pygeos.__version__,
734
- "geos_version": pygeos.geos_version_string
735
  }
736
  except Exception as e:
737
- return {"success": False, "error": str(e)}
738
-
739
-
740
- def create_app() -> FastMCP:
741
- """Create and return the FastMCP application instance.
742
-
743
- Returns:
744
- FastMCP: The application instance
745
- """
746
- return mcp
 
 
 
 
 
1
  from fastmcp import FastMCP
 
 
2
 
3
  # Create the FastMCP service application
4
  mcp = FastMCP("pygeos_service")
5
 
6
+ @mcp.tool(name="list_geometries", description="List all available geometry types in PyGEOS")
7
+ def list_geometries() -> dict:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  """
9
+ List all available geometry types in PyGEOS.
 
 
 
 
 
 
 
10
 
 
 
 
 
 
 
 
 
11
  Returns:
12
+ - dict: A dictionary with success status and list of geometry types.
13
  """
14
  try:
15
+ from pygeos import GeometryType
16
+ geometries = [g.name for g in GeometryType]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  return {
18
  "success": True,
19
+ "geometries": geometries,
20
+ "count": len(geometries)
 
 
 
21
  }
22
  except Exception as e:
23
  return {"success": False, "error": str(e)}
24
 
25
+ @mcp.tool(name="create_geometry", description="Create a geometry object in PyGEOS")
26
+ def create_geometry(wkt: str) -> dict:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  """
28
+ Create a geometry object from a WKT string.
 
 
 
 
 
 
 
29
 
30
+ Parameters:
31
+ - wkt: Well-Known Text representation of the geometry
32
 
 
 
 
 
 
 
 
 
33
  Returns:
34
+ - dict: Information about the created geometry
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  """
36
  try:
37
+ from pygeos import from_wkt
38
+ geometry = from_wkt(wkt)
39
  return {
40
  "success": True,
41
+ "geometry": str(geometry)
 
42
  }
43
  except Exception as e:
44
+ return {"success": False, "error": str(e)}