mcp-server-appwrite 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,11 @@
1
+ from . import server
2
+ import asyncio
3
+
4
+
5
+ def main():
6
+ """Main entry point for the package."""
7
+ asyncio.run(server._run())
8
+
9
+
10
+ # Optionally expose other important items at package level
11
+ __all__ = ["main", "server"]
@@ -0,0 +1,4 @@
1
+ from mcp_server_appwrite import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -0,0 +1,105 @@
1
+ import asyncio
2
+ import os
3
+ import mcp.server.stdio
4
+ import mcp.types as types
5
+ from mcp.server import NotificationOptions, Server
6
+ from mcp.server.models import InitializationOptions
7
+ from mcp.shared.exceptions import McpError
8
+ from dotenv import load_dotenv
9
+ from appwrite.client import Client
10
+ from appwrite.services.databases import Databases
11
+ from appwrite.services.users import Users
12
+ from appwrite.services.teams import Teams
13
+ from appwrite.services.storage import Storage
14
+ from appwrite.services.functions import Functions
15
+ from appwrite.services.locale import Locale
16
+ from appwrite.services.avatars import Avatars
17
+ from appwrite.services.messaging import Messaging
18
+ from appwrite.exception import AppwriteException
19
+ from .tool_manager import ToolManager
20
+ from .service import Service
21
+
22
+ # Load environment variables from .env file
23
+ load_dotenv()
24
+
25
+ # Get environment variables
26
+ project_id = os.getenv('APPWRITE_PROJECT_ID')
27
+ api_key = os.getenv('APPWRITE_API_KEY')
28
+ endpoint = os.getenv('APPWRITE_ENDPOINT', 'https://cloud.appwrite.io/v1')
29
+
30
+ if not project_id or not api_key:
31
+ raise ValueError("APPWRITE_PROJECT_ID and APPWRITE_API_KEY must be set in environment variables")
32
+
33
+ # Initialize Appwrite client
34
+ client = Client()
35
+ client.set_endpoint(endpoint)
36
+ client.set_project(project_id)
37
+ client.set_key(api_key)
38
+
39
+ # Initialize tools manager and register services
40
+ tools_manager = ToolManager()
41
+ tools_manager.register_service(Service(Users(client), "users"))
42
+ tools_manager.register_service(Service(Teams(client), "teams"))
43
+ tools_manager.register_service(Service(Databases(client), "databases"))
44
+ tools_manager.register_service(Service(Storage(client), "storage"))
45
+ tools_manager.register_service(Service(Functions(client), "functions"))
46
+ tools_manager.register_service(Service(Messaging(client), "messaging"))
47
+ tools_manager.register_service(Service(Locale(client), "locale"))
48
+ tools_manager.register_service(Service(Avatars(client), "avatars"))
49
+
50
+ async def serve() -> Server:
51
+ server = Server("Appwrite MCP Server")
52
+
53
+ # @server.list_resources()
54
+ # async def handle_list_resources() -> list[types.Resource]:
55
+ # return tools_manager.get_all_resources()
56
+
57
+ # @server.read_resource()
58
+ # async def handle_read_resource(resource_id: str) -> str:
59
+ # return tools_manager.get_resource(resource_id)
60
+
61
+ @server.list_tools()
62
+ async def handle_list_tools() -> list[types.Tool]:
63
+ return tools_manager.get_all_tools()
64
+
65
+ @server.call_tool()
66
+ async def handle_call_tool(
67
+ name: str, arguments: dict | None
68
+ ) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
69
+
70
+ try:
71
+ tool_info = tools_manager.get_tool(name)
72
+ if not tool_info:
73
+ raise McpError(f"Tool {name} not found")
74
+
75
+ bound_method = tool_info["function"]
76
+ result = bound_method(**(arguments or {}))
77
+ if hasattr(result, 'to_dict'):
78
+ result_dict = result.to_dict()
79
+ return [types.TextContent(type="text", text=str(result_dict))]
80
+ return [types.TextContent(type="text", text=str(result))]
81
+ except AppwriteException as e:
82
+ return [types.TextContent(type="text", text=f"Appwrite Error: {str(e)}")]
83
+ except Exception as e:
84
+ return [types.TextContent(type="text", text=f"Error: {str(e)}")]
85
+
86
+ return server
87
+
88
+ async def _run():
89
+ async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
90
+ server = await serve()
91
+ await server.run(
92
+ read_stream,
93
+ write_stream,
94
+ InitializationOptions(
95
+ server_name="appwrite",
96
+ server_version="0.1.0",
97
+ capabilities=server.get_capabilities(
98
+ notification_options=NotificationOptions(),
99
+ experimental_capabilities={},
100
+ ),
101
+ ),
102
+ )
103
+
104
+ if __name__ == "__main__":
105
+ asyncio.run(_run())
@@ -0,0 +1,84 @@
1
+ from typing import Any, get_type_hints, Dict
2
+ import inspect
3
+ from mcp.types import Tool
4
+
5
+ class Service():
6
+ """Base class for all Appwrite services"""
7
+
8
+ def __init__(self, service_instance, service_name: str):
9
+ self.service = service_instance
10
+ self.service_name = service_name
11
+ self._method_name_overrides = self.get_method_name_overrides()
12
+
13
+ def get_method_name_overrides(self) -> Dict[str, str]:
14
+ """
15
+ Override this method to provide method name mappings.
16
+ Returns a dictionary where:
17
+ - key: original method name
18
+ - value: new method name to be used
19
+ """
20
+ return {}
21
+
22
+ def python_type_to_json_schema(self, py_type: Any) -> dict:
23
+ """Converts Python type hints to JSON Schema types."""
24
+ type_mapping = {
25
+ str: "string",
26
+ int: "integer",
27
+ float: "number",
28
+ bool: "boolean",
29
+ list: "array",
30
+ dict: "object"
31
+ }
32
+ return {"type": type_mapping.get(py_type, "string")}
33
+
34
+ def list_tools(self) -> Dict[str, Dict]:
35
+ """Lists all available tools for this service"""
36
+ tools = {}
37
+
38
+ for name, func in inspect.getmembers(self.service, predicate=inspect.ismethod):
39
+ if name.startswith('_'): # Skip private methods
40
+ continue
41
+
42
+ original_func = func.__func__
43
+
44
+ # Skip if not from the service's module
45
+ if original_func.__module__ != self.service.__class__.__module__:
46
+ continue
47
+
48
+ # Get the overridden name if it exists
49
+ tool_name = self._method_name_overrides.get(name, f"{self.service_name}_{name}")
50
+
51
+ docstring = (original_func.__doc__ or "No description available").strip()
52
+ signature = inspect.signature(original_func)
53
+ type_hints = get_type_hints(original_func)
54
+
55
+ properties = {}
56
+ required = []
57
+
58
+ for param_name, param in signature.parameters.items():
59
+ if param_name == 'self':
60
+ continue
61
+
62
+ param_type = type_hints.get(param_name, str)
63
+ properties[param_name] = self.python_type_to_json_schema(param_type)
64
+ properties[param_name]["description"] = f"Parameter '{param_name}'"
65
+
66
+ if param.default is param.empty:
67
+ required.append(param_name)
68
+
69
+ tool_definition = Tool(
70
+ name=tool_name,
71
+ description=f"{docstring}",
72
+ inputSchema={
73
+ "type": "object",
74
+ "properties": properties,
75
+ "required": required
76
+ }
77
+ )
78
+
79
+ tools[tool_name] = {
80
+ "definition": tool_definition,
81
+ "function": func
82
+ }
83
+
84
+ return tools
@@ -0,0 +1,21 @@
1
+ from typing import List, Dict
2
+ from mcp.types import Tool
3
+ from .service import Service
4
+
5
+ class ToolManager:
6
+ def __init__(self):
7
+ self.services: List[Service] = []
8
+ self.tools_registry = {}
9
+
10
+ def register_service(self, service: Service):
11
+ """Register a new service and its tools"""
12
+ self.services.append(service)
13
+ self.tools_registry.update(service.list_tools())
14
+
15
+ def get_all_tools(self) -> List[Tool]:
16
+ """Get all tool definitions"""
17
+ return [tool_info["definition"] for tool_info in self.tools_registry.values()]
18
+
19
+ def get_tool(self, name: str) -> Dict:
20
+ """Get a specific tool by name"""
21
+ return self.tools_registry.get(name)
@@ -0,0 +1,155 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-server-appwrite
3
+ Version: 0.1.0
4
+ Summary: MCP (Model Context Protocol) server for Appwrite
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.12
7
+ Requires-Dist: appwrite>=7.1.0
8
+ Requires-Dist: mcp[cli]>=1.3.0
9
+ Description-Content-Type: text/markdown
10
+
11
+ # Appwrite MCP server
12
+
13
+ ## Overview
14
+
15
+ A Model Context Protocol server for interacting with Appwrite's API. This server provides tools to manage databases, users, functions, teams, and more within your Appwrite project.
16
+
17
+ Currently the server supports the following tools:
18
+
19
+ - [x] Databases
20
+ - [x] Users
21
+ - [x] Teams
22
+ - [x] Messaging
23
+ - [x] Locale
24
+ - [x] Avatars
25
+ - [x] Storage (Beta)
26
+ - [x] Functions (Beta)
27
+
28
+ > Please note that the Storage and Functions tools are currently in beta and methods like createFile and createDeployment are not yet supported.
29
+
30
+ ## Local Development
31
+
32
+ Clone the repository
33
+
34
+ ```bash
35
+ git clone https://github.com/appwrite/mcp.git
36
+ ```
37
+
38
+ Install `uv`
39
+
40
+ ```bash
41
+ curl -LsSf https://astral.sh/uv/install.sh | sh
42
+ ```
43
+
44
+ Create virtual environment
45
+
46
+ ```bash
47
+ uv venv
48
+ source .venv/bin/activate
49
+ ```
50
+
51
+ ## Configuration
52
+
53
+ Create a `.env` file in the root directory based on `.env.example`:
54
+
55
+ ```env
56
+ APPWRITE_API_KEY=your-api-key
57
+ APPWRITE_PROJECT_ID=your-project-id
58
+ APPWRITE_ENDPOINT=your-endpoint # Optional, defaults to https://cloud.appwrite.io/v1
59
+ ```
60
+
61
+ Run the server
62
+
63
+ ```bash
64
+ uv run -v --directory ./ mcp-server-appwrite
65
+ ```
66
+
67
+ ### Usage with Claude Desktop
68
+
69
+ Add this to your `claude_desktop_config.json`:
70
+
71
+ ```json
72
+ "mcpServers": {
73
+ "appwrite": {
74
+ "command": "uv",
75
+ "args": [
76
+ "run",
77
+ "--directory",
78
+ "<path-to-repository>",
79
+ "mcp-server-appwrite"
80
+ ],
81
+ "env": {
82
+ "APPWRITE_PROJECT_ID": "your-project-id",
83
+ "APPWRITE_API_KEY": "your-api-key",
84
+ "APPWRITE_ENDPOINT": "your-endpoint" // Optional
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ Upon successful configuration, you should be able to see the server in the list of available servers in Claude Desktop.
91
+
92
+ ![Claude Desktop Config](images/claude-desktop-integration.png)
93
+
94
+ ### Usage with [Zed](https://github.com/zed-industries/zed)
95
+
96
+ Add to your Zed settings.json:
97
+
98
+ ```json
99
+ "context_servers": {
100
+ "appwrite": {
101
+ "command": "uv",
102
+ "args": [
103
+ "run",
104
+ "--directory",
105
+ "<path-to-repository>",
106
+ "mcp-server-appwrite"
107
+ ],
108
+ "env": {
109
+ "APPWRITE_PROJECT_ID": "your-project-id",
110
+ "APPWRITE_API_KEY": "your-api-key",
111
+ "APPWRITE_ENDPOINT": "your-endpoint" // Optional
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ ### Usage with [Cursor](https://www.cursor.com/)
118
+
119
+ Head to Cursor `Settings > Features > MCP Servers` and click on **Add New MCP Server**. Choose the type as `Command` and add the command below to the **Command** field.
120
+
121
+ ```bash
122
+ APPWRITE_PROJECT_ID=your-project-id APPWRITE_API_KEY=your-api-key uv run --directory <path_to_repository> mcp-server-appwrite
123
+ ```
124
+
125
+ ![Cursor Settings](./images/cursor-integration.png)
126
+
127
+ ## Debugging
128
+
129
+ You can use the MCP inspector to debug the server.
130
+
131
+ ```bash
132
+ npx @modelcontextprotocol/inspector \
133
+ uv \
134
+ --directory . \
135
+ run mcp-server-appwrite
136
+ ```
137
+
138
+ Make sure your `.env` file is properly configured before running the inspector. You can then access the inspector at `http://localhost:5173`.
139
+
140
+ ## License
141
+
142
+ This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.
143
+
144
+ ## Todos
145
+ - Add MCP server to registries
146
+ - Glama
147
+ - https://github.com/chatmcp/mcp-directory
148
+ - https://mcp.so/
149
+ - https://github.com/punkpeye/awesome-mcp-servers
150
+ - https://portkey.ai/mcp-servers
151
+ - https://www.claudemcp.com/servers
152
+ - Add support for SSE server
153
+ - Release to PIP
154
+ - ✅ Add support for env vars
155
+ - Add suppport for resources
@@ -0,0 +1,10 @@
1
+ mcp_server_appwrite/__init__.py,sha256=Od9oaUg_ckgJ4jIGa2HijocyauWDPjIC7cBRiV0P4s8,214
2
+ mcp_server_appwrite/__main__.py,sha256=bdaX6xMmFugzSR2QMdXJqanRx_Jh25jACJDqjE9cKEc,75
3
+ mcp_server_appwrite/server.py,sha256=bR_1QL9hmFeNS4aNOZbgEHkZCfQI7iBOvAnL1BYRkoU,3960
4
+ mcp_server_appwrite/service.py,sha256=WwKoh9o7W7ZOmhY0yg6k4R2cghQRe-yMTNbFtB6TFT8,2895
5
+ mcp_server_appwrite/tool_manager.py,sha256=AfRjLyMpplYjF2VJna7frXDiDUZKRN8WQu9R8j3dxPc,718
6
+ mcp_server_appwrite-0.1.0.dist-info/METADATA,sha256=f6USs_RH5GLiD_tp4IC5Q8bxbt6dOzwrBbMxAxT1J4s,3786
7
+ mcp_server_appwrite-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ mcp_server_appwrite-0.1.0.dist-info/entry_points.txt,sha256=-FBKUOp-Qmo9FldmiT3JUyF7djSeo8lLhxljOosuHkQ,74
9
+ mcp_server_appwrite-0.1.0.dist-info/licenses/LICENSE,sha256=PXzk1HbuQMAkLdHzwnBLTBIHFmgDZM0Ez2lw2gX2UQs,1096
10
+ mcp_server_appwrite-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mcp-server-appwrite = mcp_server_appwrite.__main__:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Christy Jacob
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ 1. The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ 2. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.