Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,12 @@
/.venv/
.coverage
docs/build

# MCP Registry tokens (security sensitive)
.mcpregistry_github_token
.mcpregistry_registry_token

# Build artifacts
dist/
*.whl
*.tar.gz
209 changes: 95 additions & 114 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,149 +1,130 @@
# python-geoservercloud
# GeoServer MCP Server

## Documentation
<!-- mcp-name: io.github.ronitjadhav/geoservercloud-mcp -->

https://camptocamp.github.io/python-geoservercloud/
A Model Context Protocol (MCP) server that exposes [GeoServer](https://geoserver.org/) REST API functionality for natural language interaction through AI assistants like Claude, VS Code Copilot, and other MCP-compatible clients.

## About

This MCP server wraps the [python-geoservercloud](docs/LIBRARY.md) library, exposing 80+ GeoServer operations as MCP tools. This enables AI assistants to manage GeoServer workspaces, datastores, layers, styles, and more through natural language commands.

### Example Interactions

Once connected, you can ask your AI assistant things like:

- *"List all workspaces in GeoServer"*
- *"Create a new workspace called 'test_data'"*
- *"What layers are available in the 'topp' workspace?"*
- *"Create a PostGIS datastore connection"*

---

## Installation

From PyPI:
### From PyPI

```shell
pip install geoservercloud
```bash
pip install geoservercloud-mcp
```

From git repository:
Or use `uvx` to run without installing (requires [uv](https://docs.astral.sh/uv/)):

```shell
git clone https://github.com/camptocamp/python-geoservercloud
cd python-geoservercloud
python3 -m venv .venv
source .venv/bin/activate
poetry install
```bash
# Install uv first (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Run the MCP server
uvx geoservercloud-mcp
```

## Quick start
### From MCP Registry

```python
from geoservercloud import GeoServerCloud
This server is published to the [MCP Registry](https://registry.modelcontextprotocol.io) as:

geoserver = GeoServerCloud(
url="http://localhost:9090/geoserver/cloud/",
user="admin",
password="geoserver",
)
geoserver.create_workspace("newworkspace")
```text
io.github.ronitjadhav/geoservercloud-mcp
```

## About
---

Lightweight Python client to interact with GeoServer Cloud REST API, GeoServer ACL and OGC services.
Intended use cases are listed below.
## Connecting to AI Clients

### Programmatic setup of a GeoServer catalog
### VS Code / Cursor

For example, creating a workspace, connecting to a PostGIS datastore and publishing a PG layer:
Add to your MCP configuration (`.vscode/mcp.json`):

```python
geoserver.create_workspace("example")
geoserver.create_pg_datastore(
workspace_name="example",
datastore_name="example_store",
pg_host="localhost",
pg_port=5432,
pg_db="database",
pg_user="user",
pg_password="password"
)
geoserver.create_feature_type(
layer_name="layer_example",
workspace_name="example",
datastore_name="example_store",
title={
"en":"Layer title",
"fr": "Titre de la couche",
"default": "Default title",
},
)
```json
{
"servers": {
"geoserver": {
"command": "uvx",
"args": ["geoservercloud-mcp"],
"env": {
"GEOSERVER_URL": "http://localhost:8080/geoserver",
"GEOSERVER_USER": "admin",
"GEOSERVER_PASSWORD": "geoserver"
}
}
}
}
```

### Testing
### Claude Desktop

Add to your Claude Desktop config:

**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
**Linux:** `~/.config/Claude/claude_desktop_config.json`

```json
{
"mcpServers": {
"geoserver": {
"command": "uvx",
"args": ["geoservercloud-mcp"],
"env": {
"GEOSERVER_URL": "http://localhost:8080/geoserver",
"GEOSERVER_USER": "admin",
"GEOSERVER_PASSWORD": "geoserver"
}
}
}
}
```

Automatic tests of GeoServer functionalities with `pytest`, for example before upgrading.
The example below tests the fallback mechanism for internationalized layer titles in the GetCapabilities document.
Restart Claude Desktop after saving the configuration.

```python
@pytest.mark.parametrize(
"language,expected_title",
[
(
"en",
"Layer title",
),
(
"fr",
"Titre de la couche",
),
(
"de,en",
"Layer title",
),
(
None,
"Default title",
),
],
)
def test_i18n_layer_title(geoserver, language, expected_title):
capabilities = geoserver.get_wms_layers(
workspace="example",
accept_languages=language,
)
layer = capabilities.get("Layer")
assert layer.get("Title") == expected_title
```
---

## Environment Variables

A test suite is provided in the directory `geoserver_acceptance_tests`.
| Variable | Default | Description |
|----------|---------|-------------|
| `GEOSERVER_URL` | `http://localhost:8080/geoserver` | GeoServer base URL |
| `GEOSERVER_USER` | `admin` | GeoServer username |
| `GEOSERVER_PASSWORD` | `geoserver` | GeoServer password |

### Syncing
---

Copying a workspace from one GeoServer instance to another, including PG datastores, layers, styles and style images.
## Python Library

#### In a Python console or script
This MCP server is built on the **python-geoservercloud** library. For programmatic access without MCP, see the [library documentation](docs/LIBRARY.md).

```python
from geoservercloud import GeoServerCloudSync
geoserversync = GeoServerCloudSync(
src_url="http://localhost:8080/geoserver",
src_user="admin",
src_password="geoserver",
dst_url="http://localhost:9099/geoserver",
dst_user="admin",
dst_password="geoserver",
from geoservercloud import GeoServerCloud

geoserver = GeoServerCloud(
url="http://localhost:8080/geoserver",
user="admin",
password="geoserver",
)
geoserversync.copy_workspace("workspace_name", deep_copy=True)
geoserver.create_workspace("my_workspace")
```

#### In a shell terminal or script

First install the package in your current virtual environment (see [Installation](#installation)), then run the script with:
Full documentation: <https://camptocamp.github.io/python-geoservercloud/>

```shell
copy-workspace --src_url "http://localhost:8080/geoserver" --src_user admin --src_password geoserver --dst_url "http://localhost:9099/geoserver" --dst_user admin --dst_password geoserver --workspace workspace_name
```

### Logging
---

Set the log level using the standard `logging` module, e.g.:
## Development

```python
import logging

gs_logger = logging.getLogger("geoservercloud")
gs_logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
gs_logger.addHandler(handler)
```
For local development, testing, and publishing, see the [Developer Guide](docs/DEVELOPER.md).
Loading
Loading