Skip to content

Commit 6ff20e0

Browse files
authored
Merge pull request #40 from appwrite/operator-hardening-and-ci
Introduce the Appwrite operator workflow and refresh CI
2 parents e89e4f1 + 7985188 commit 6ff20e0

27 files changed

+3051
-203
lines changed

.github/workflows/ci.yml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
7+
jobs:
8+
format:
9+
name: Format
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Check out code
13+
uses: actions/checkout@v4
14+
15+
- name: Set up Python
16+
uses: actions/setup-python@v5
17+
with:
18+
python-version: "3.12"
19+
20+
- name: Set up uv
21+
uses: astral-sh/setup-uv@v7
22+
23+
- name: Install dev dependencies
24+
run: uv sync --group dev
25+
26+
- name: Check formatting
27+
run: uv run --group dev black --check src tests
28+
29+
unit:
30+
name: Unit
31+
runs-on: ubuntu-latest
32+
steps:
33+
- name: Check out code
34+
uses: actions/checkout@v4
35+
36+
- name: Set up Python
37+
uses: actions/setup-python@v5
38+
with:
39+
python-version: "3.12"
40+
41+
- name: Set up uv
42+
uses: astral-sh/setup-uv@v7
43+
44+
- name: Install dependencies
45+
run: uv sync
46+
47+
- name: Run unit tests
48+
run: uv run python -m unittest discover -s tests/unit -v
49+
50+
integration:
51+
name: Integration
52+
runs-on: ubuntu-latest
53+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
54+
env:
55+
APPWRITE_PROJECT_ID: ${{ secrets.APPWRITE_PROJECT_ID }}
56+
APPWRITE_API_KEY: ${{ secrets.APPWRITE_API_KEY }}
57+
APPWRITE_ENDPOINT: ${{ secrets.APPWRITE_ENDPOINT }}
58+
steps:
59+
- name: Check out code
60+
uses: actions/checkout@v4
61+
62+
- name: Set up Python
63+
uses: actions/setup-python@v5
64+
with:
65+
python-version: "3.12"
66+
67+
- name: Set up uv
68+
uses: astral-sh/setup-uv@v7
69+
70+
- name: Install dependencies
71+
run: uv sync --extra integration
72+
73+
- name: Run integration tests
74+
run: uv run --extra integration python -m unittest discover -s tests/integration -v

.github/workflows/publish.yml

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
name: Publish to PyPI
1+
name: Publish
2+
23
on:
34
release:
45
types: [published]
@@ -14,7 +15,7 @@ jobs:
1415
- name: Set up Python
1516
uses: actions/setup-python@v5
1617
with:
17-
python-version: '3.12'
18+
python-version: "3.12"
1819

1920
- name: Install build dependencies
2021
run: |
@@ -29,28 +30,3 @@ jobs:
2930
TWINE_USERNAME: __token__
3031
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
3132
run: twine upload dist/*
32-
33-
publish-mcp:
34-
name: Publish to MCP Registry
35-
runs-on: ubuntu-latest
36-
needs: publish
37-
permissions:
38-
id-token: write
39-
contents: read
40-
steps:
41-
- name: Check out code
42-
uses: actions/checkout@v4
43-
44-
- name: Wait for PyPI propagation
45-
run: sleep 10
46-
47-
- name: Install MCP Publisher
48-
run: |
49-
curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.1.0/mcp-publisher_1.1.0_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
50-
chmod +x mcp-publisher
51-
52-
- name: Login to MCP Registry
53-
run: ./mcp-publisher login github-oidc
54-
55-
- name: Publish to MCP Registry
56-
run: ./mcp-publisher publish

README.md

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
mcp-name: io.github.appwrite/mcp-for-api
44

5-
[![Install MCP Server](https://cursor.com/deeplink/mcp-install-light.svg)](https://cursor.com/install-mcp?name=appwrite&config=eyJjb21tYW5kIjoidXZ4IG1jcC1zZXJ2ZXItYXBwd3JpdGUgLS11c2VycyIsImVudiI6eyJBUFBXUklURV9BUElfS0VZIjoiPHlvdXItYXBpLWtleT4iLCJBUFBXUklURV9QUk9KRUNUX0lEIjoiPHlvdXItcHJvamVjdC1pZD4iLCJBUFBXUklURV9FTkRQT0lOVCI6Imh0dHBzOi8vPFJFR0lPTj4uY2xvdWQuYXBwd3JpdGUuaW8vdjEifX0%3D)
5+
[![Install MCP Server](https://cursor.com/deeplink/mcp-install-light.svg)](https://cursor.com/install-mcp?name=appwrite&config=%7B%22command%22%3A%22uvx%20mcp-server-appwrite%22%2C%22env%22%3A%7B%22APPWRITE_API_KEY%22%3A%22%3Cyour-api-key%3E%22%2C%22APPWRITE_PROJECT_ID%22%3A%22%3Cyour-project-id%3E%22%2C%22APPWRITE_ENDPOINT%22%3A%22https%3A//%3CREGION%3E.cloud.appwrite.io/v1%22%7D%7D)
66

77
## Overview
88

@@ -23,6 +23,8 @@ A Model Context Protocol server for interacting with Appwrite's API. This server
2323

2424
> Before launching the MCP server, you must setup an [Appwrite project](https://cloud.appwrite.io/) and create an API key with the necessary scopes enabled.
2525
26+
The server validates the credentials and scopes required for its built-in Appwrite service set during startup. If the endpoint, project ID, API key, or scopes are wrong, the MCP server will fail to start instead of waiting for the first tool call to fail.
27+
2628
Create a `.env` file in your working directory and add the following:
2729

2830
```env
@@ -64,7 +66,7 @@ When using [`uv`](https://docs.astral.sh/uv/) no specific installation is needed
6466
use [`uvx`](https://docs.astral.sh/uv/guides/tools/) to directly run *mcp-server-appwrite*.
6567

6668
```bash
67-
uvx mcp-server-appwrite [args]
69+
uvx mcp-server-appwrite
6870
```
6971

7072
### Using pip
@@ -75,30 +77,22 @@ pip install mcp-server-appwrite
7577
Then run the server using
7678

7779
```bash
78-
python -m mcp_server_appwrite [args]
80+
python -m mcp_server_appwrite
7981
```
8082

81-
### Command-line arguments
83+
### Tool surface
8284

83-
Both the `uv` and `pip` setup processes require certain arguments to enable MCP tools for various Appwrite APIs.
85+
The server no longer accepts service-selection or mode flags. It always starts in a compact workflow so the MCP client only sees a small operator-style surface while the full Appwrite catalog stays internal.
8486

85-
> When an MCP tool is enabled, the tool's definition is passed to the LLM, using up tokens from the model's available context window. As a result, the effective context window is reduced.
86-
>
87-
> The default Appwrite MCP server ships with only the Databases tools (our most commonly used API) enabled to stay within these limits. Additional tools can be enabled by using the flags below.
87+
- Only 2 MCP tools are exposed to the model:
88+
- `appwrite_search_tools`
89+
- `appwrite_call_tool`
90+
- The full Appwrite tool catalog stays internal and is searched at runtime.
91+
- Large tool outputs are stored as MCP resources and returned as preview text plus a resource URI.
92+
- Mutating hidden tools require `confirm_write=true`.
93+
- The server automatically registers all supported Appwrite services except the legacy Databases API.
8894

89-
| Argument | Description |
90-
| --- | --- |
91-
| `--tablesdb` | Enables the TablesDB API |
92-
| `--users` | Enables the Users API |
93-
| `--teams` | Enables the Teams API |
94-
| `--storage` | Enables the Storage API |
95-
| `--functions` | Enables the Functions API |
96-
| `--messaging` | Enables the Messaging API |
97-
| `--locale` | Enables the Locale API |
98-
| `--avatars` | Enables the Avatars API |
99-
| `--sites` | Enables the Sites API |
100-
| `--all` | Enables all Appwrite APIs |
101-
| `--databases` | Enables the Legacy Databases API |
95+
If you still have older MCP configs that pass flags such as `--mode` or `--users`, remove them.
10296

10397
## Usage with Claude Desktop
10498

@@ -184,7 +178,7 @@ Head to Windsurf `Settings > Cascade > Model Context Protocol (MCP) Servers` and
184178
"servers": {
185179
"appwrite": {
186180
"command": "uvx",
187-
"args": ["mcp-server-appwrite", "--users"],
181+
"args": ["mcp-server-appwrite"],
188182
"env": {
189183
"APPWRITE_PROJECT_ID": "<YOUR_PROJECT_ID>",
190184
"APPWRITE_API_KEY": "<YOUR_API_KEY>",
@@ -206,7 +200,7 @@ Head to Windsurf `Settings > Cascade > Model Context Protocol (MCP) Servers` and
206200
### Clone the repository
207201

208202
```bash
209-
git clone https://github.com/appwrite/mcp.git
203+
git clone https://github.com/appwrite/mcp-for-api.git
210204
```
211205

212206
### Install `uv`
@@ -251,6 +245,22 @@ source .venv/bin/activate
251245
uv run -v --directory ./ mcp-server-appwrite
252246
```
253247

248+
## Testing
249+
250+
### Unit tests
251+
252+
```bash
253+
uv run python -m unittest discover -s tests/unit -v
254+
```
255+
256+
### Live integration tests
257+
258+
These tests create and delete real Appwrite resources against a real Appwrite project. They run automatically when valid Appwrite credentials are available in the environment or `.env`.
259+
260+
```bash
261+
uv run --extra integration python -m unittest discover -s tests/integration -v
262+
```
263+
254264
## Debugging
255265

256266
You can use the MCP inspector to debug the server.

pyproject.toml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,35 @@
11
[project]
22
name = "mcp-server-appwrite"
3-
version = "0.3.3"
3+
version = "0.4"
44
description = "MCP (Model Context Protocol) server for Appwrite"
55
readme = "README.md"
66
requires-python = ">=3.12"
77
dependencies = [
88
"appwrite>=13.4.1",
99
"docstring-parser>=0.16",
1010
"mcp[cli]>=1.3.0",
11+
"python-dotenv>=1.0.1",
12+
]
13+
14+
[project.optional-dependencies]
15+
integration = [
16+
"argon2-cffi>=23.1.0",
17+
"bcrypt>=4.1.2",
18+
"passlib>=1.7.4",
19+
"pycryptodome>=3.20.0",
20+
]
21+
22+
[dependency-groups]
23+
dev = [
24+
"black>=25.1.0",
1125
]
1226

1327
[project.scripts]
1428
mcp-server-appwrite = "mcp_server_appwrite.__main__:main"
1529

30+
[tool.black]
31+
target-version = ["py312"]
32+
1633
[build-system]
1734
requires = ["hatchling"]
1835
build-backend = "hatchling.build"

server.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
33
"name": "io.github.appwrite/mcp-for-api",
44
"description": "MCP (Model Context Protocol) server for Appwrite",
5-
"version": "0.3.3",
5+
"version": "0.4",
66
"repository": {
77
"url": "https://github.com/appwrite/mcp-for-api",
88
"source": "github"
99
},
1010
"packages": [
1111
{
12-
"version": "0.3.3",
12+
"version": "0.4",
1313
"registryType": "pypi",
1414
"identifier": "mcp-server-appwrite",
1515
"transport": {
Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
from . import server
21
import asyncio
2+
import sys
33

44

55
def main():
66
"""Main entry point for the package."""
7-
asyncio.run(server._run())
7+
from .server import _run
88

9+
try:
10+
asyncio.run(_run())
11+
except KeyboardInterrupt:
12+
print("[appwrite-mcp] Shutdown requested", file=sys.stderr, flush=True)
13+
return 0
914

10-
# Optionally expose other important items at package level
11-
__all__ = ["main", "server"]
15+
16+
__all__ = ["main"]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from mcp_server_appwrite import main
22

33
if __name__ == "__main__":
4-
main()
4+
main()

0 commit comments

Comments
 (0)