Skip to content

Commit 10414a9

Browse files
committed
Harden the Appwrite operator and CI workflow
1 parent e89e4f1 commit 10414a9

26 files changed

Lines changed: 3044 additions & 228 deletions

.github/workflows/ci.yml

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
release:
7+
types: [published]
8+
9+
jobs:
10+
format:
11+
name: Format
12+
if: github.event_name != 'release'
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Check out code
16+
uses: actions/checkout@v4
17+
18+
- name: Set up Python
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: "3.12"
22+
23+
- name: Set up uv
24+
uses: astral-sh/setup-uv@v7
25+
26+
- name: Install dev dependencies
27+
run: uv sync --group dev
28+
29+
- name: Check formatting
30+
run: uv run --group dev black --check src tests
31+
32+
unit:
33+
name: Unit
34+
if: github.event_name != 'release'
35+
runs-on: ubuntu-latest
36+
steps:
37+
- name: Check out code
38+
uses: actions/checkout@v4
39+
40+
- name: Set up Python
41+
uses: actions/setup-python@v5
42+
with:
43+
python-version: "3.12"
44+
45+
- name: Set up uv
46+
uses: astral-sh/setup-uv@v7
47+
48+
- name: Install dependencies
49+
run: uv sync
50+
51+
- name: Run unit tests
52+
run: uv run python -m unittest discover -s tests/unit -v
53+
54+
integration:
55+
name: Integration
56+
if: github.event_name != 'release'
57+
runs-on: ubuntu-latest
58+
env:
59+
APPWRITE_PROJECT_ID: ${{ secrets.APPWRITE_PROJECT_ID }}
60+
APPWRITE_API_KEY: ${{ secrets.APPWRITE_API_KEY }}
61+
APPWRITE_ENDPOINT: ${{ secrets.APPWRITE_ENDPOINT }}
62+
steps:
63+
- name: Check out code
64+
uses: actions/checkout@v4
65+
66+
- name: Set up Python
67+
uses: actions/setup-python@v5
68+
with:
69+
python-version: "3.12"
70+
71+
- name: Set up uv
72+
uses: astral-sh/setup-uv@v7
73+
74+
- name: Install dependencies
75+
run: uv sync --extra integration
76+
77+
- name: Run integration tests
78+
run: uv run --extra integration python -m unittest discover -s tests/integration -v
79+
80+
publish:
81+
name: Release build and publish
82+
if: github.event_name == 'release'
83+
runs-on: ubuntu-latest
84+
steps:
85+
- name: Check out code
86+
uses: actions/checkout@v4
87+
88+
- name: Set up Python
89+
uses: actions/setup-python@v5
90+
with:
91+
python-version: "3.12"
92+
93+
- name: Install build dependencies
94+
run: |
95+
python -m pip install --upgrade pip
96+
pip install build twine
97+
98+
- name: Build package
99+
run: python -m build
100+
101+
- name: Publish to PyPI
102+
env:
103+
TWINE_USERNAME: __token__
104+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
105+
run: twine upload dist/*

.github/workflows/publish.yml

Lines changed: 0 additions & 56 deletions
This file was deleted.

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: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,28 @@ 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"
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)