awslabs.memcached-mcp-server 1.0.2__tar.gz → 1.0.4__tar.gz
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.
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/Dockerfile +33 -23
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/PKG-INFO +73 -2
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/README.md +71 -0
- awslabs_memcached_mcp_server-1.0.4/awslabs/memcached_mcp_server/context.py +39 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/awslabs/memcached_mcp_server/main.py +14 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/awslabs/memcached_mcp_server/tools/cache.py +40 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/docker-healthcheck.sh +7 -8
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/pyproject.toml +2 -2
- awslabs_memcached_mcp_server-1.0.4/tests/test_cache_readonly.py +163 -0
- awslabs_memcached_mcp_server-1.0.4/uv-requirements.txt +26 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/uv.lock +645 -445
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/.gitignore +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/.python-version +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/CHANGELOG.md +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/ELASTICACHECONNECT.md +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/LICENSE +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/NOTICE +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/awslabs/__init__.py +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/awslabs/memcached_mcp_server/__init__.py +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/awslabs/memcached_mcp_server/common/config.py +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/awslabs/memcached_mcp_server/common/connection.py +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/awslabs/memcached_mcp_server/common/server.py +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/tests/test_cache.py +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/tests/test_connection.py +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/tests/test_init.py +0 -0
- {awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/tests/test_main.py +0 -0
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
#
|
|
16
|
-
FROM public.ecr.aws/
|
|
15
|
+
# dependabot should continue to update this to the latest hash.
|
|
16
|
+
FROM public.ecr.aws/docker/library/python:3.13.5-alpine3.21@sha256:c9a09c45a4bcc618c7f7128585b8dd0d41d0c31a8a107db4c8255ffe0b69375d AS uv
|
|
17
17
|
|
|
18
18
|
# Install the project into `/app`
|
|
19
19
|
WORKDIR /app
|
|
@@ -31,40 +31,50 @@ ENV UV_PYTHON_PREFERENCE=only-system
|
|
|
31
31
|
ENV UV_FROZEN=true
|
|
32
32
|
|
|
33
33
|
# Copy the required files first
|
|
34
|
-
COPY pyproject.toml uv.lock ./
|
|
34
|
+
COPY pyproject.toml uv.lock uv-requirements.txt ./
|
|
35
|
+
|
|
36
|
+
# Python optimization and uv configuration
|
|
37
|
+
ENV PIP_NO_CACHE_DIR=1 \
|
|
38
|
+
PIP_DISABLE_PIP_VERSION_CHECK=1
|
|
39
|
+
|
|
40
|
+
# Install system dependencies and Python package manager
|
|
41
|
+
RUN apk update && \
|
|
42
|
+
apk add --no-cache --virtual .build-deps \
|
|
43
|
+
build-base \
|
|
44
|
+
gcc \
|
|
45
|
+
musl-dev \
|
|
46
|
+
libffi-dev \
|
|
47
|
+
openssl-dev \
|
|
48
|
+
cargo
|
|
35
49
|
|
|
36
50
|
# Install the project's dependencies using the lockfile and settings
|
|
37
51
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
38
|
-
pip install uv
|
|
39
|
-
uv sync --frozen --no-install-project --no-dev --no-editable
|
|
52
|
+
pip install --require-hashes --requirement uv-requirements.txt --no-cache-dir && \
|
|
53
|
+
uv sync --python 3.13 --frozen --no-install-project --no-dev --no-editable
|
|
40
54
|
|
|
41
55
|
# Then, add the rest of the project source code and install it
|
|
42
56
|
# Installing separately from its dependencies allows optimal layer caching
|
|
43
57
|
COPY . /app
|
|
44
58
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
45
|
-
uv sync --frozen --no-dev --no-editable
|
|
59
|
+
uv sync --python 3.13 --frozen --no-dev --no-editable
|
|
46
60
|
|
|
47
61
|
# Make the directory just in case it doesn't exist
|
|
48
62
|
RUN mkdir -p /root/.local
|
|
49
63
|
|
|
50
|
-
FROM public.ecr.aws/
|
|
64
|
+
FROM public.ecr.aws/docker/library/python:3.13.5-alpine3.21@sha256:c9a09c45a4bcc618c7f7128585b8dd0d41d0c31a8a107db4c8255ffe0b69375d
|
|
51
65
|
|
|
52
66
|
# Place executables in the environment at the front of the path and include other binaries
|
|
53
|
-
ENV PATH="/app/.venv/bin:$PATH
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
# Install
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
chmod o+x /root
|
|
65
|
-
|
|
66
|
-
# Get the project from the uv layer
|
|
67
|
-
COPY --from=uv --chown=app:app /root/.local /root/.local
|
|
67
|
+
ENV PATH="/app/.venv/bin:$PATH" \
|
|
68
|
+
PYTHONUNBUFFERED=1
|
|
69
|
+
|
|
70
|
+
# Install runtime dependencies and create application user
|
|
71
|
+
RUN apk update && \
|
|
72
|
+
apk add --no-cache ca-certificates && \
|
|
73
|
+
update-ca-certificates && \
|
|
74
|
+
addgroup -S app && \
|
|
75
|
+
adduser -S app -G app -h /app
|
|
76
|
+
|
|
77
|
+
# Copy application artifacts from build stage
|
|
68
78
|
COPY --from=uv --chown=app:app /app/.venv /app/.venv
|
|
69
79
|
|
|
70
80
|
# Get healthcheck script
|
|
@@ -74,5 +84,5 @@ COPY ./docker-healthcheck.sh /usr/local/bin/docker-healthcheck.sh
|
|
|
74
84
|
USER app
|
|
75
85
|
|
|
76
86
|
# When running the container, add --db-path and a bind mount to the host's db file
|
|
77
|
-
HEALTHCHECK --interval=
|
|
87
|
+
HEALTHCHECK --interval=60s --timeout=10s --start-period=10s --retries=3 CMD ["docker-healthcheck.sh"]
|
|
78
88
|
ENTRYPOINT ["awslabs.memcached-mcp-server"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: awslabs.memcached-mcp-server
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: An AWS Labs Model Context Protocol (MCP) server for Amazon ElastiCache Memcached
|
|
5
5
|
Project-URL: homepage, https://awslabs.github.io/mcp/
|
|
6
6
|
Project-URL: docs, https://awslabs.github.io/mcp/servers/memcached-mcp-server/
|
|
@@ -22,7 +22,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.13
|
|
23
23
|
Requires-Python: >=3.10
|
|
24
24
|
Requires-Dist: loguru>=0.7.0
|
|
25
|
-
Requires-Dist: mcp[cli]>=1.
|
|
25
|
+
Requires-Dist: mcp[cli]>=1.11.0
|
|
26
26
|
Requires-Dist: pydantic>=2.10.6
|
|
27
27
|
Requires-Dist: pymemcache>=4.0.0
|
|
28
28
|
Requires-Dist: python-dotenv>=0.9.9
|
|
@@ -40,6 +40,17 @@ MCP server for interacting with Amazon ElastiCache Memcached through a secure an
|
|
|
40
40
|
- Secure communication with SSL/TLS encryption
|
|
41
41
|
- Automatic connection management and pooling
|
|
42
42
|
- Built-in retry mechanism for failed operations
|
|
43
|
+
- Readonly mode to prevent write operations
|
|
44
|
+
|
|
45
|
+
### Readonly Mode
|
|
46
|
+
|
|
47
|
+
The server can be started in readonly mode, which prevents any write operations from being performed. This is useful for scenarios where you want to ensure that no data is modified, such as:
|
|
48
|
+
|
|
49
|
+
- Read-only replicas
|
|
50
|
+
- Production environments where writes should be restricted
|
|
51
|
+
- Debugging and monitoring without risk of data modification
|
|
52
|
+
|
|
53
|
+
When readonly mode is enabled, any attempt to perform a write operation (set, add, replace, delete, etc.) will return an error message.
|
|
43
54
|
|
|
44
55
|
## Prerequisites
|
|
45
56
|
|
|
@@ -51,6 +62,10 @@ MCP server for interacting with Amazon ElastiCache Memcached through a secure an
|
|
|
51
62
|
|
|
52
63
|
## Installation
|
|
53
64
|
|
|
65
|
+
| Cursor | VS Code |
|
|
66
|
+
|:------:|:-------:|
|
|
67
|
+
| [](https://cursor.com/install-mcp?name=awslabs.memcached-mcp-server&config=eyJjb21tYW5kIjoidXZ4IGF3c2xhYnMubWVtY2FjaGVkLW1jcC1zZXJ2ZXJAbGF0ZXN0IiwiZW52Ijp7IkZBU1RNQ1BfTE9HX0xFVkVMIjoiRVJST1IiLCJNRU1DQUNIRURfSE9TVCI6InlvdXItbWVtY2FjaGVkLWhvc3QiLCJNRU1DQUNIRURfUE9SVCI6IjExMjExIn0sImRpc2FibGVkIjpmYWxzZSwiYXV0b0FwcHJvdmUiOltdfQ%3D%3D) | [](https://insiders.vscode.dev/redirect/mcp/install?name=Memcached%20MCP%20Server&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22awslabs.memcached-mcp-server%40latest%22%5D%2C%22env%22%3A%7B%22FASTMCP_LOG_LEVEL%22%3A%22ERROR%22%2C%22MEMCACHED_HOST%22%3A%22your-memcached-host%22%2C%22MEMCACHED_PORT%22%3A%2211211%22%7D%2C%22disabled%22%3Afalse%2C%22autoApprove%22%3A%5B%5D%7D) |
|
|
68
|
+
|
|
54
69
|
Here are some ways you can work with MCP (e.g. for Amazon Q Developer CLI MCP, `~/.aws/amazonq/mcp.json`):
|
|
55
70
|
|
|
56
71
|
```json
|
|
@@ -71,6 +86,26 @@ Here are some ways you can work with MCP (e.g. for Amazon Q Developer CLI MCP, `
|
|
|
71
86
|
}
|
|
72
87
|
```
|
|
73
88
|
|
|
89
|
+
To run in readonly mode:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"mcpServers": {
|
|
94
|
+
"awslabs.memcached-mcp-server": {
|
|
95
|
+
"command": "uvx",
|
|
96
|
+
"args": ["awslabs.memcached-mcp-server@latest", "--readonly"],
|
|
97
|
+
"env": {
|
|
98
|
+
"FASTMCP_LOG_LEVEL": "ERROR",
|
|
99
|
+
"MEMCACHED_HOST": "your-memcached-host",
|
|
100
|
+
"MEMCACHED_PORT": "11211"
|
|
101
|
+
},
|
|
102
|
+
"disabled": false,
|
|
103
|
+
"autoApprove": []
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
74
109
|
or docker after a successful `docker build -t awslabs/memcached-mcp-server .`:
|
|
75
110
|
|
|
76
111
|
```json
|
|
@@ -98,6 +133,34 @@ or docker after a successful `docker build -t awslabs/memcached-mcp-server .`:
|
|
|
98
133
|
}
|
|
99
134
|
```
|
|
100
135
|
|
|
136
|
+
To run in readonly mode with Docker:
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"mcpServers": {
|
|
141
|
+
"awslabs.memcached-mcp-server": {
|
|
142
|
+
"command": "docker",
|
|
143
|
+
"args": [
|
|
144
|
+
"run",
|
|
145
|
+
"--rm",
|
|
146
|
+
"--interactive",
|
|
147
|
+
"--env",
|
|
148
|
+
"FASTMCP_LOG_LEVEL=ERROR",
|
|
149
|
+
"--env",
|
|
150
|
+
"MEMCACHED_HOST=your-memcached-host",
|
|
151
|
+
"--env",
|
|
152
|
+
"MEMCACHED_PORT=11211",
|
|
153
|
+
"awslabs/memcached-mcp-server:latest",
|
|
154
|
+
"--readonly"
|
|
155
|
+
],
|
|
156
|
+
"env": {},
|
|
157
|
+
"disabled": false,
|
|
158
|
+
"autoApprove": []
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
101
164
|
## Configuration
|
|
102
165
|
|
|
103
166
|
### Basic Connection Settings
|
|
@@ -155,3 +218,11 @@ docker run -p 8080:8080 \
|
|
|
155
218
|
-e MEMCACHED_PORT=11211 \
|
|
156
219
|
awslabs/memcached-mcp-server
|
|
157
220
|
```
|
|
221
|
+
|
|
222
|
+
To run in readonly mode:
|
|
223
|
+
```bash
|
|
224
|
+
docker run -p 8080:8080 \
|
|
225
|
+
-e MEMCACHED_HOST=host.docker.internal \
|
|
226
|
+
-e MEMCACHED_PORT=11211 \
|
|
227
|
+
awslabs/memcached-mcp-server --readonly
|
|
228
|
+
```
|
|
@@ -10,6 +10,17 @@ MCP server for interacting with Amazon ElastiCache Memcached through a secure an
|
|
|
10
10
|
- Secure communication with SSL/TLS encryption
|
|
11
11
|
- Automatic connection management and pooling
|
|
12
12
|
- Built-in retry mechanism for failed operations
|
|
13
|
+
- Readonly mode to prevent write operations
|
|
14
|
+
|
|
15
|
+
### Readonly Mode
|
|
16
|
+
|
|
17
|
+
The server can be started in readonly mode, which prevents any write operations from being performed. This is useful for scenarios where you want to ensure that no data is modified, such as:
|
|
18
|
+
|
|
19
|
+
- Read-only replicas
|
|
20
|
+
- Production environments where writes should be restricted
|
|
21
|
+
- Debugging and monitoring without risk of data modification
|
|
22
|
+
|
|
23
|
+
When readonly mode is enabled, any attempt to perform a write operation (set, add, replace, delete, etc.) will return an error message.
|
|
13
24
|
|
|
14
25
|
## Prerequisites
|
|
15
26
|
|
|
@@ -21,6 +32,10 @@ MCP server for interacting with Amazon ElastiCache Memcached through a secure an
|
|
|
21
32
|
|
|
22
33
|
## Installation
|
|
23
34
|
|
|
35
|
+
| Cursor | VS Code |
|
|
36
|
+
|:------:|:-------:|
|
|
37
|
+
| [](https://cursor.com/install-mcp?name=awslabs.memcached-mcp-server&config=eyJjb21tYW5kIjoidXZ4IGF3c2xhYnMubWVtY2FjaGVkLW1jcC1zZXJ2ZXJAbGF0ZXN0IiwiZW52Ijp7IkZBU1RNQ1BfTE9HX0xFVkVMIjoiRVJST1IiLCJNRU1DQUNIRURfSE9TVCI6InlvdXItbWVtY2FjaGVkLWhvc3QiLCJNRU1DQUNIRURfUE9SVCI6IjExMjExIn0sImRpc2FibGVkIjpmYWxzZSwiYXV0b0FwcHJvdmUiOltdfQ%3D%3D) | [](https://insiders.vscode.dev/redirect/mcp/install?name=Memcached%20MCP%20Server&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22awslabs.memcached-mcp-server%40latest%22%5D%2C%22env%22%3A%7B%22FASTMCP_LOG_LEVEL%22%3A%22ERROR%22%2C%22MEMCACHED_HOST%22%3A%22your-memcached-host%22%2C%22MEMCACHED_PORT%22%3A%2211211%22%7D%2C%22disabled%22%3Afalse%2C%22autoApprove%22%3A%5B%5D%7D) |
|
|
38
|
+
|
|
24
39
|
Here are some ways you can work with MCP (e.g. for Amazon Q Developer CLI MCP, `~/.aws/amazonq/mcp.json`):
|
|
25
40
|
|
|
26
41
|
```json
|
|
@@ -41,6 +56,26 @@ Here are some ways you can work with MCP (e.g. for Amazon Q Developer CLI MCP, `
|
|
|
41
56
|
}
|
|
42
57
|
```
|
|
43
58
|
|
|
59
|
+
To run in readonly mode:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"awslabs.memcached-mcp-server": {
|
|
65
|
+
"command": "uvx",
|
|
66
|
+
"args": ["awslabs.memcached-mcp-server@latest", "--readonly"],
|
|
67
|
+
"env": {
|
|
68
|
+
"FASTMCP_LOG_LEVEL": "ERROR",
|
|
69
|
+
"MEMCACHED_HOST": "your-memcached-host",
|
|
70
|
+
"MEMCACHED_PORT": "11211"
|
|
71
|
+
},
|
|
72
|
+
"disabled": false,
|
|
73
|
+
"autoApprove": []
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
44
79
|
or docker after a successful `docker build -t awslabs/memcached-mcp-server .`:
|
|
45
80
|
|
|
46
81
|
```json
|
|
@@ -68,6 +103,34 @@ or docker after a successful `docker build -t awslabs/memcached-mcp-server .`:
|
|
|
68
103
|
}
|
|
69
104
|
```
|
|
70
105
|
|
|
106
|
+
To run in readonly mode with Docker:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"mcpServers": {
|
|
111
|
+
"awslabs.memcached-mcp-server": {
|
|
112
|
+
"command": "docker",
|
|
113
|
+
"args": [
|
|
114
|
+
"run",
|
|
115
|
+
"--rm",
|
|
116
|
+
"--interactive",
|
|
117
|
+
"--env",
|
|
118
|
+
"FASTMCP_LOG_LEVEL=ERROR",
|
|
119
|
+
"--env",
|
|
120
|
+
"MEMCACHED_HOST=your-memcached-host",
|
|
121
|
+
"--env",
|
|
122
|
+
"MEMCACHED_PORT=11211",
|
|
123
|
+
"awslabs/memcached-mcp-server:latest",
|
|
124
|
+
"--readonly"
|
|
125
|
+
],
|
|
126
|
+
"env": {},
|
|
127
|
+
"disabled": false,
|
|
128
|
+
"autoApprove": []
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
71
134
|
## Configuration
|
|
72
135
|
|
|
73
136
|
### Basic Connection Settings
|
|
@@ -125,3 +188,11 @@ docker run -p 8080:8080 \
|
|
|
125
188
|
-e MEMCACHED_PORT=11211 \
|
|
126
189
|
awslabs/memcached-mcp-server
|
|
127
190
|
```
|
|
191
|
+
|
|
192
|
+
To run in readonly mode:
|
|
193
|
+
```bash
|
|
194
|
+
docker run -p 8080:8080 \
|
|
195
|
+
-e MEMCACHED_HOST=host.docker.internal \
|
|
196
|
+
-e MEMCACHED_PORT=11211 \
|
|
197
|
+
awslabs/memcached-mcp-server --readonly
|
|
198
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Context management for Memcached MCP Server."""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Context:
|
|
19
|
+
"""Context class for Memcached MCP Server."""
|
|
20
|
+
|
|
21
|
+
_readonly = False
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def initialize(cls, readonly: bool = False):
|
|
25
|
+
"""Initialize the context.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
readonly: Whether to run in readonly mode
|
|
29
|
+
"""
|
|
30
|
+
cls._readonly = readonly
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def readonly_mode(cls) -> bool:
|
|
34
|
+
"""Check if the server is running in readonly mode.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
True if readonly mode is enabled, False otherwise
|
|
38
|
+
"""
|
|
39
|
+
return cls._readonly
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
"""awslabs memcached MCP Server implementation."""
|
|
16
16
|
|
|
17
|
+
import argparse
|
|
17
18
|
from awslabs.memcached_mcp_server.common.server import mcp
|
|
19
|
+
from awslabs.memcached_mcp_server.context import Context
|
|
18
20
|
from awslabs.memcached_mcp_server.tools import cache # noqa: F401
|
|
19
21
|
from loguru import logger
|
|
20
22
|
from starlette.requests import Request # noqa: F401
|
|
@@ -41,6 +43,18 @@ class MemcachedMCPServer:
|
|
|
41
43
|
|
|
42
44
|
def main():
|
|
43
45
|
"""Run the MCP server with CLI argument support."""
|
|
46
|
+
parser = argparse.ArgumentParser(
|
|
47
|
+
description='An AWS Labs Model Context Protocol (MCP) server for interacting with Memcached'
|
|
48
|
+
)
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
'--readonly',
|
|
51
|
+
action=argparse.BooleanOptionalAction,
|
|
52
|
+
help='Prevents the MCP server from performing mutating operations',
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
args = parser.parse_args()
|
|
56
|
+
Context.initialize(args.readonly)
|
|
57
|
+
|
|
44
58
|
logger.info('Amazon ElastiCache Memcached MCP Server Started...')
|
|
45
59
|
MemcachedMCPServer().run()
|
|
46
60
|
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
from awslabs.memcached_mcp_server.common.connection import MemcachedConnectionManager
|
|
18
18
|
from awslabs.memcached_mcp_server.common.server import mcp
|
|
19
|
+
from awslabs.memcached_mcp_server.context import Context
|
|
19
20
|
from pymemcache.exceptions import MemcacheError
|
|
20
21
|
from typing import Any, Dict, List, Optional
|
|
21
22
|
|
|
@@ -106,6 +107,9 @@ async def cache_set(key: str, value: Any, expire: Optional[int] = None) -> str:
|
|
|
106
107
|
Returns:
|
|
107
108
|
Success message or error message
|
|
108
109
|
"""
|
|
110
|
+
if Context.readonly_mode():
|
|
111
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
112
|
+
|
|
109
113
|
try:
|
|
110
114
|
client = MemcachedConnectionManager.get_connection()
|
|
111
115
|
client.set(key, value, expire=expire)
|
|
@@ -128,6 +132,9 @@ async def cache_cas(key: str, value: Any, cas: int, expire: Optional[int] = None
|
|
|
128
132
|
Returns:
|
|
129
133
|
Success message or error message
|
|
130
134
|
"""
|
|
135
|
+
if Context.readonly_mode():
|
|
136
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
137
|
+
|
|
131
138
|
try:
|
|
132
139
|
client = MemcachedConnectionManager.get_connection()
|
|
133
140
|
if client.cas(key, value, cas, expire=expire):
|
|
@@ -149,6 +156,9 @@ async def cache_set_many(mapping: Dict[str, Any], expire: Optional[int] = None)
|
|
|
149
156
|
Returns:
|
|
150
157
|
Success message or error message
|
|
151
158
|
"""
|
|
159
|
+
if Context.readonly_mode():
|
|
160
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
161
|
+
|
|
152
162
|
try:
|
|
153
163
|
client = MemcachedConnectionManager.get_connection()
|
|
154
164
|
failed = client.set_many(mapping, expire=expire)
|
|
@@ -186,6 +196,9 @@ async def cache_add(key: str, value: Any, expire: Optional[int] = None) -> str:
|
|
|
186
196
|
Returns:
|
|
187
197
|
Success message or error message
|
|
188
198
|
"""
|
|
199
|
+
if Context.readonly_mode():
|
|
200
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
201
|
+
|
|
189
202
|
try:
|
|
190
203
|
client = MemcachedConnectionManager.get_connection()
|
|
191
204
|
if client.add(key, value, expire=expire):
|
|
@@ -208,6 +221,9 @@ async def cache_replace(key: str, value: Any, expire: Optional[int] = None) -> s
|
|
|
208
221
|
Returns:
|
|
209
222
|
Success message or error message
|
|
210
223
|
"""
|
|
224
|
+
if Context.readonly_mode():
|
|
225
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
226
|
+
|
|
211
227
|
try:
|
|
212
228
|
client = MemcachedConnectionManager.get_connection()
|
|
213
229
|
if client.replace(key, value, expire=expire):
|
|
@@ -229,6 +245,9 @@ async def cache_append(key: str, value: str) -> str:
|
|
|
229
245
|
Returns:
|
|
230
246
|
Success message or error message
|
|
231
247
|
"""
|
|
248
|
+
if Context.readonly_mode():
|
|
249
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
250
|
+
|
|
232
251
|
try:
|
|
233
252
|
client = MemcachedConnectionManager.get_connection()
|
|
234
253
|
if client.append(key, value):
|
|
@@ -249,6 +268,9 @@ async def cache_prepend(key: str, value: str) -> str:
|
|
|
249
268
|
Returns:
|
|
250
269
|
Success message or error message
|
|
251
270
|
"""
|
|
271
|
+
if Context.readonly_mode():
|
|
272
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
273
|
+
|
|
252
274
|
try:
|
|
253
275
|
client = MemcachedConnectionManager.get_connection()
|
|
254
276
|
if client.prepend(key, value):
|
|
@@ -268,6 +290,9 @@ async def cache_delete(key: str) -> str:
|
|
|
268
290
|
Returns:
|
|
269
291
|
Success message or error message
|
|
270
292
|
"""
|
|
293
|
+
if Context.readonly_mode():
|
|
294
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
295
|
+
|
|
271
296
|
try:
|
|
272
297
|
client = MemcachedConnectionManager.get_connection()
|
|
273
298
|
if client.delete(key):
|
|
@@ -287,6 +312,9 @@ async def cache_delete_many(keys: List[str]) -> str:
|
|
|
287
312
|
Returns:
|
|
288
313
|
Success message or error message
|
|
289
314
|
"""
|
|
315
|
+
if Context.readonly_mode():
|
|
316
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
317
|
+
|
|
290
318
|
try:
|
|
291
319
|
client = MemcachedConnectionManager.get_connection()
|
|
292
320
|
failed = client.delete_many(keys)
|
|
@@ -321,6 +349,9 @@ async def cache_incr(key: str, value: int = 1) -> str:
|
|
|
321
349
|
Returns:
|
|
322
350
|
New value or error message
|
|
323
351
|
"""
|
|
352
|
+
if Context.readonly_mode():
|
|
353
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
354
|
+
|
|
324
355
|
try:
|
|
325
356
|
client = MemcachedConnectionManager.get_connection()
|
|
326
357
|
result = client.incr(key, value)
|
|
@@ -342,6 +373,9 @@ async def cache_decr(key: str, value: int = 1) -> str:
|
|
|
342
373
|
Returns:
|
|
343
374
|
New value or error message
|
|
344
375
|
"""
|
|
376
|
+
if Context.readonly_mode():
|
|
377
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
378
|
+
|
|
345
379
|
try:
|
|
346
380
|
client = MemcachedConnectionManager.get_connection()
|
|
347
381
|
result = client.decr(key, value)
|
|
@@ -363,6 +397,9 @@ async def cache_touch(key: str, expire: int) -> str:
|
|
|
363
397
|
Returns:
|
|
364
398
|
Success message or error message
|
|
365
399
|
"""
|
|
400
|
+
if Context.readonly_mode():
|
|
401
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
402
|
+
|
|
366
403
|
try:
|
|
367
404
|
client = MemcachedConnectionManager.get_connection()
|
|
368
405
|
if client.touch(key, expire):
|
|
@@ -400,6 +437,9 @@ async def cache_flush_all(delay: int = 0) -> str:
|
|
|
400
437
|
Returns:
|
|
401
438
|
Success message or error message
|
|
402
439
|
"""
|
|
440
|
+
if Context.readonly_mode():
|
|
441
|
+
return 'Operation not permitted: Server is in readonly mode'
|
|
442
|
+
|
|
403
443
|
try:
|
|
404
444
|
client = MemcachedConnectionManager.get_connection()
|
|
405
445
|
client.flush_all(delay=delay)
|
{awslabs_memcached_mcp_server-1.0.2 → awslabs_memcached_mcp_server-1.0.4}/docker-healthcheck.sh
RENAMED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
|
-
|
|
3
2
|
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
4
3
|
#
|
|
5
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -14,13 +13,13 @@
|
|
|
14
13
|
# See the License for the specific language governing permissions and
|
|
15
14
|
# limitations under the License.
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
SERVER="memcached-mcp-server"
|
|
17
|
+
|
|
18
|
+
# Check if the server process is running
|
|
19
|
+
if pgrep -P 0 -a -l -x -f "/app/.venv/bin/python3 /app/.venv/bin/awslabs.$SERVER" > /dev/null; then
|
|
20
|
+
echo -n "$SERVER is running";
|
|
19
21
|
exit 0;
|
|
20
|
-
else
|
|
21
|
-
echo -n "Zero awslabs.* streams found";
|
|
22
|
-
exit 1;
|
|
23
22
|
fi;
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
exit
|
|
24
|
+
# Unhealthy
|
|
25
|
+
exit 1;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "awslabs.memcached-mcp-server"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.4"
|
|
4
4
|
description = "An AWS Labs Model Context Protocol (MCP) server for Amazon ElastiCache Memcached"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
7
7
|
dependencies = [
|
|
8
8
|
"loguru>=0.7.0",
|
|
9
|
-
"mcp[cli]>=1.
|
|
9
|
+
"mcp[cli]>=1.11.0",
|
|
10
10
|
"pydantic>=2.10.6",
|
|
11
11
|
"pymemcache>=4.0.0",
|
|
12
12
|
"python-dotenv>=0.9.9"
|