mcp-server-appwrite 2.1.0__tar.gz → 2.1.2__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.
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/PKG-INFO +1 -1
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/apps/resource.py +22 -1
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/apps/views.py +11 -5
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/assets/view.html +47 -2
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/data/docs_index.npz +1 -1
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/operator.py +1 -2
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/test_apps.py +32 -10
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/.dockerignore +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/.env.example +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/.github/workflows/ci.yml +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/.github/workflows/production.yml +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/.github/workflows/publish.yml +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/.github/workflows/staging.yml +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/.github/workflows/update-docs-index.yml +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/.gitignore +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/.python-version +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/AGENTS.md +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/CLAUDE.md +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/Dockerfile +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/LICENSE +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/README.md +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/compose.yaml +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/apps.md +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/appwrite-mcp-flow.png +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/appwrite-mcp-flow.svg +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/authentication.md +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/development.md +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/documentation-search.md +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/events.md +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/flags.md +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/images/claude-desktop-local-mcp-servers.png +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/images/codex-mcp.png +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/images/cursor-mcp.png +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/self-hosted.md +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/docs/tool-surface.md +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/glama.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/pyproject.toml +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/scripts/build_docs_index.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/scripts/docs_release_notes.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/scripts/render_server_json.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/server.template.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/__init__.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/__main__.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/apps/__init__.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/apps/protocol.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/assets/__init__.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/assets/favicon.svg +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/assets/instructions.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/auth.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/catalog_policy.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/constants.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/context.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/docs.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/docs_index.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/docs_search.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/docs_source.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/error_classification.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/error_monitoring.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/__init__.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/bus.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/catalog.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/delivery.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/egress.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/envelope.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/errors.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/ingress.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/projection.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/protocol.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/streams.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/subscriptions.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/webhooks.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/flags.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/http_app.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/instructions.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/legacy.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/server.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/service.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/telemetry.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/tool_manager.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/deployment_function_duplicate.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/deployment_function_failed.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/deployment_function_ready.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/deployment_site_ready.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/execution_async_failed.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/execution_async_waiting.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/execution_sync_failed.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/file_created.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/function_activation.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/row_created.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/user_created.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/support.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/test_events_ingress.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/test_events_protocol.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/test_events_stream.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/test_events_subscribe.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/test_stdio.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/test_tools.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/support.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_avatars.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_console_sdk_oauth.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_docs_index.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_docs_source.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_functions.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_locale.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_messaging.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_oauth_discovery.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_operator.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_sites.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_storage.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_tables_db.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_teams.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_users.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/test_all.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/fixtures/jwe-v1.json +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_auth.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_context.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_docs.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_docs_search.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_error_classification.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_error_monitoring.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_events_delivery.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_events_egress.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_events_envelope.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_events_protocol.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_http_app.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_instructions.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_operator.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_release_metadata.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_server.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_service.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_telemetry.py +0 -0
- {mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: mcp-server-appwrite
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: Build and deploy application backends. Add authentication, PostgreSQL/MySQL databases, vector databases, storage, serverless functions, realtime, messaging, hosting, domains, CDN and firewall.
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.12
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/apps/resource.py
RENAMED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
One HTML document (``assets/view.html``, plain JavaScript with no build step)
|
|
4
4
|
renders every view; it picks one from the tool result's ``structuredContent``.
|
|
5
|
+
Hosts cache UI resources by URI, so the tools point at
|
|
6
|
+
``ui://appwrite/view/<hash of the HTML>``: a release that changes the view
|
|
7
|
+
changes the URI, and hosts fetch it again. The bare ``ui://appwrite/view``
|
|
8
|
+
still serves the current HTML for tool lists cached before versioning.
|
|
5
9
|
It declares no CSP domains, so hosts apply SEP-1865's restrictive default: no
|
|
6
10
|
network access and no external scripts. Every Appwrite read and write it makes
|
|
7
11
|
is a ``tools/call`` the host proxies to this server under the user's own
|
|
@@ -11,6 +15,7 @@ credentials.
|
|
|
11
15
|
from __future__ import annotations
|
|
12
16
|
|
|
13
17
|
from functools import cache
|
|
18
|
+
from hashlib import sha256
|
|
14
19
|
from importlib.resources import files
|
|
15
20
|
from typing import Any
|
|
16
21
|
|
|
@@ -23,14 +28,30 @@ from .protocol import MIME_TYPE
|
|
|
23
28
|
META: dict[str, Any] = {"ui": {"csp": {}, "prefersBorder": True}}
|
|
24
29
|
|
|
25
30
|
|
|
31
|
+
VERSION_LENGTH = 12
|
|
32
|
+
"""Hex digits of the HTML's SHA-256 in the URI: enough that two releases
|
|
33
|
+
never collide."""
|
|
34
|
+
|
|
35
|
+
|
|
26
36
|
@cache
|
|
27
37
|
def html() -> str:
|
|
28
38
|
return files("mcp_server_appwrite.assets").joinpath("view.html").read_text()
|
|
29
39
|
|
|
30
40
|
|
|
41
|
+
@cache
|
|
42
|
+
def uri() -> str:
|
|
43
|
+
"""The URI the tools point at, versioned by the HTML it serves."""
|
|
44
|
+
digest = sha256(html().encode("utf-8")).hexdigest()[:VERSION_LENGTH]
|
|
45
|
+
return f"{VIEW_URI}/{digest}"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def serves(requested: str) -> bool:
|
|
49
|
+
return requested in (uri(), VIEW_URI)
|
|
50
|
+
|
|
51
|
+
|
|
31
52
|
def resource() -> types.Resource:
|
|
32
53
|
return types.Resource(
|
|
33
|
-
uri=
|
|
54
|
+
uri=uri(),
|
|
34
55
|
name="Appwrite view",
|
|
35
56
|
description=(
|
|
36
57
|
"Interactive Appwrite view: table rows and deployment build logs."
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/apps/views.py
RENAMED
|
@@ -19,6 +19,7 @@ what such a script could do.
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
21
|
import json
|
|
22
|
+
import re
|
|
22
23
|
from collections.abc import Callable
|
|
23
24
|
from enum import StrEnum
|
|
24
25
|
from typing import Any
|
|
@@ -26,7 +27,8 @@ from typing import Any
|
|
|
26
27
|
import mcp.types as types
|
|
27
28
|
from appwrite_console.query import Query
|
|
28
29
|
|
|
29
|
-
from ..constants import SHOW_TOOL_NAME,
|
|
30
|
+
from ..constants import SHOW_TOOL_NAME, VIEW_WRITE_TOOL_NAME
|
|
31
|
+
from . import resource
|
|
30
32
|
|
|
31
33
|
Run = Callable[[dict[str, Any], bool], list[Any]]
|
|
32
34
|
"""Runs a hidden catalog tool from raw call arguments (``tool_name``,
|
|
@@ -46,6 +48,10 @@ SUMMARY_ROWS = 10
|
|
|
46
48
|
SUMMARY_COLUMNS = 4
|
|
47
49
|
SUMMARY_CELL = 24
|
|
48
50
|
|
|
51
|
+
ANSI = re.compile(r"\x1b\[[0-9;?]*[ -/]*[@-~]")
|
|
52
|
+
"""Terminal escape sequences (colors, cursor moves) in build logs: the view
|
|
53
|
+
renders the colors, the model's summary drops them."""
|
|
54
|
+
|
|
49
55
|
TERMINAL_STATUSES = frozenset({"ready", "failed", "canceled"})
|
|
50
56
|
|
|
51
57
|
WRITES = (
|
|
@@ -273,10 +279,10 @@ def _show_tool() -> types.Tool:
|
|
|
273
279
|
"additionalProperties": False,
|
|
274
280
|
},
|
|
275
281
|
_meta={
|
|
276
|
-
"ui": {"resourceUri":
|
|
282
|
+
"ui": {"resourceUri": resource.uri(), "visibility": ["model", "app"]},
|
|
277
283
|
# The flat key hosts read before ``ui.resourceUri``; SEP-1865 drops
|
|
278
284
|
# it at GA.
|
|
279
|
-
"ui/resourceUri":
|
|
285
|
+
"ui/resourceUri": resource.uri(),
|
|
280
286
|
},
|
|
281
287
|
)
|
|
282
288
|
|
|
@@ -302,7 +308,7 @@ def _write_tool() -> types.Tool:
|
|
|
302
308
|
"required": ["tool_name", "arguments", "confirm_write"],
|
|
303
309
|
"additionalProperties": False,
|
|
304
310
|
},
|
|
305
|
-
_meta={"ui": {"resourceUri":
|
|
311
|
+
_meta={"ui": {"resourceUri": resource.uri(), "visibility": ["app"]}},
|
|
306
312
|
)
|
|
307
313
|
|
|
308
314
|
|
|
@@ -387,5 +393,5 @@ def _deployment_summary(data: dict[str, Any]) -> str:
|
|
|
387
393
|
logs = deployment["logs"][-SUMMARY_LOG_LINES:]
|
|
388
394
|
if logs:
|
|
389
395
|
lines.append("Last build log lines:")
|
|
390
|
-
lines.extend(logs)
|
|
396
|
+
lines.extend(ANSI.sub("", line) for line in logs)
|
|
391
397
|
return "\n".join(lines)
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/assets/view.html
RENAMED
|
@@ -183,6 +183,14 @@ pre.logs {
|
|
|
183
183
|
.status { padding: 32px 18px; text-align: center; color: var(--color-text-secondary); }
|
|
184
184
|
.status.error { color: var(--color-text-danger); text-align: left; white-space: pre-wrap; }
|
|
185
185
|
:root[data-display="fullscreen"] pre.logs { height: 60vh; }
|
|
186
|
+
.ansi-bold { font-weight: var(--font-weight-semibold); }
|
|
187
|
+
.ansi-dim, .ansi-gray, .ansi-black { color: var(--color-text-secondary); }
|
|
188
|
+
.ansi-red { color: var(--color-text-danger); }
|
|
189
|
+
.ansi-green { color: var(--color-text-success); }
|
|
190
|
+
.ansi-yellow { color: var(--color-text-warning); }
|
|
191
|
+
.ansi-blue, .ansi-cyan { color: light-dark(#1d5fb4, #8ab4f8); }
|
|
192
|
+
.ansi-magenta { color: var(--accent); }
|
|
193
|
+
.ansi-white, .ansi-bright { color: var(--color-text-primary); }
|
|
186
194
|
@media (max-width: 560px) {
|
|
187
195
|
.fields { grid-template-columns: minmax(0, 1fr); }
|
|
188
196
|
.steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
@@ -199,6 +207,11 @@ pre.logs {
|
|
|
199
207
|
const WRITE_TOOL = "appwrite_view_write";
|
|
200
208
|
const POLL_MS = 3000;
|
|
201
209
|
const PAGE_SIZE = 25;
|
|
210
|
+
const ESCAPE = /\x1b\[[0-9;?]*[ -\/]*[@-~]/g;
|
|
211
|
+
const ANSI_COLORS = {
|
|
212
|
+
30: "black", 31: "red", 32: "green", 33: "yellow", 34: "blue", 35: "magenta", 36: "cyan", 37: "white",
|
|
213
|
+
90: "gray", 91: "red", 92: "green", 93: "yellow", 94: "blue", 95: "magenta", 96: "cyan", 97: "bright",
|
|
214
|
+
};
|
|
202
215
|
const TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/;
|
|
203
216
|
const EDITABLE = {
|
|
204
217
|
string: "text", varchar: "text", text: "text", mediumtext: "text", longtext: "text",
|
|
@@ -619,6 +632,36 @@ pre.logs {
|
|
|
619
632
|
request("ui/update-model-context", { content: [{ type: "text", text }] }).catch(() => {});
|
|
620
633
|
}
|
|
621
634
|
|
|
635
|
+
// Build logs carry terminal color codes (SGR, "ESC[31m"). Each run of text
|
|
636
|
+
// becomes a span whose classes carry its color and weight; other escape
|
|
637
|
+
// sequences are dropped. Text only ever goes in as a text node.
|
|
638
|
+
function ansi(line) {
|
|
639
|
+
const parts = [];
|
|
640
|
+
const style = { color: null, bold: false, dim: false };
|
|
641
|
+
let last = 0;
|
|
642
|
+
const push = (text) => {
|
|
643
|
+
if (!text) return;
|
|
644
|
+
const classes = [style.color, style.bold && "ansi-bold", style.dim && "ansi-dim"].filter(Boolean);
|
|
645
|
+
parts.push(classes.length ? el("span", { className: classes.join(" ") }, text) : text);
|
|
646
|
+
};
|
|
647
|
+
for (const match of line.matchAll(ESCAPE)) {
|
|
648
|
+
push(line.slice(last, match.index));
|
|
649
|
+
last = match.index + match[0].length;
|
|
650
|
+
if (!match[0].endsWith("m")) continue;
|
|
651
|
+
const codes = match[0].slice(2, -1).split(";").map(Number);
|
|
652
|
+
for (const code of codes) {
|
|
653
|
+
if (code === 0) Object.assign(style, { color: null, bold: false, dim: false });
|
|
654
|
+
else if (code === 1) style.bold = true;
|
|
655
|
+
else if (code === 2) style.dim = true;
|
|
656
|
+
else if (code === 22) Object.assign(style, { bold: false, dim: false });
|
|
657
|
+
else if (code === 39) style.color = null;
|
|
658
|
+
else if (ANSI_COLORS[code]) style.color = "ansi-" + ANSI_COLORS[code];
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
push(line.slice(last));
|
|
662
|
+
return parts;
|
|
663
|
+
}
|
|
664
|
+
|
|
622
665
|
function pill(status) {
|
|
623
666
|
const tone = status === "ready" ? "ready"
|
|
624
667
|
: status === "failed" || status === "canceled" ? "failed"
|
|
@@ -671,8 +714,10 @@ pre.logs {
|
|
|
671
714
|
deployment.activate ? el("span", {}, "Activates when ready") : null);
|
|
672
715
|
|
|
673
716
|
const logs = el("pre", { className: "logs", tabindex: "0", "aria-label": "Build logs" },
|
|
674
|
-
|
|
675
|
-
|
|
717
|
+
deployment.truncated ? el("span", { className: "ansi-dim" }, "… earlier lines omitted\n") : null,
|
|
718
|
+
deployment.logs.length
|
|
719
|
+
? deployment.logs.flatMap((line) => [...ansi(line), "\n"])
|
|
720
|
+
: data.done ? "No build logs." : "Waiting for build output…");
|
|
676
721
|
|
|
677
722
|
const footer = el("footer", { className: "bar" },
|
|
678
723
|
el("span", { className: "muted", style: "font-size: var(--font-text-xs-size)" },
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/data/docs_index.npz
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
|
-
name: mcp_server_appwrite-2.1.
|
|
2
|
+
name: mcp_server_appwrite-2.1.2/src/mcp_server_appwrite/data/docs_index.npz
|
|
3
3
|
size: 35543664 bytes
|
|
4
4
|
sha256: 61d266fdb9a958b272d1b351cc6ebd6e824b0d0fe294483703e0795e4b0580df
|
|
@@ -33,7 +33,6 @@ from .constants import (
|
|
|
33
33
|
SEARCH_TOOL_NAME,
|
|
34
34
|
UPDATE_HINTS,
|
|
35
35
|
VERBS,
|
|
36
|
-
VIEW_URI,
|
|
37
36
|
WRITE_TOOL_NAME,
|
|
38
37
|
)
|
|
39
38
|
from .docs_search import DocsSearch
|
|
@@ -437,7 +436,7 @@ class Operator:
|
|
|
437
436
|
if uri == CATALOG_URI:
|
|
438
437
|
return [ReadResourceContents(self._cached_catalog_json, "application/json")]
|
|
439
438
|
|
|
440
|
-
if apps and uri
|
|
439
|
+
if apps and view_resource.serves(uri):
|
|
441
440
|
return [view_resource.read()]
|
|
442
441
|
|
|
443
442
|
if (
|
|
@@ -8,7 +8,9 @@ the view pages, refreshes, follows a build and saves an edit.
|
|
|
8
8
|
checked to have reached no Appwrite write at all.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
import hashlib
|
|
11
12
|
import json
|
|
13
|
+
import re
|
|
12
14
|
import unittest
|
|
13
15
|
from typing import Any
|
|
14
16
|
|
|
@@ -36,6 +38,11 @@ UI = {"extensions": {EXTENSION: {"mimeTypes": [MIME_TYPE]}}}
|
|
|
36
38
|
ROWS = 30
|
|
37
39
|
PAGE = 25
|
|
38
40
|
LOG_LINES = 250
|
|
41
|
+
# How open-runtimes colors a build log line.
|
|
42
|
+
ANSI_LINE = (
|
|
43
|
+
"\x1b[90m[13:23:45] \x1b[31m[\x1b[0mopen-runtimes\x1b[31m] "
|
|
44
|
+
"\x1b[32mBuild finished. \x1b[0m"
|
|
45
|
+
)
|
|
39
46
|
|
|
40
47
|
cloud: Cloud
|
|
41
48
|
|
|
@@ -71,7 +78,8 @@ def setUpModule() -> None:
|
|
|
71
78
|
"dep_new",
|
|
72
79
|
FUNCTION,
|
|
73
80
|
"building",
|
|
74
|
-
"\n".join(f"line {index}" for index in range(1, LOG_LINES
|
|
81
|
+
"\n".join(f"line {index}" for index in range(1, LOG_LINES))
|
|
82
|
+
+ f"\n{ANSI_LINE}",
|
|
75
83
|
providerBranch="main",
|
|
76
84
|
providerCommitHash="a91c3e0f00",
|
|
77
85
|
),
|
|
@@ -158,15 +166,18 @@ class AppsFlow(unittest.TestCase):
|
|
|
158
166
|
|
|
159
167
|
listed = tools(self.host)
|
|
160
168
|
show = listed["appwrite_show"]
|
|
169
|
+
# Hosts cache UI resources by URI, so the URI carries the HTML's hash:
|
|
170
|
+
# a release that changes the view makes hosts fetch it again.
|
|
171
|
+
uri = show["_meta"]["ui"]["resourceUri"]
|
|
172
|
+
self.assertRegex(uri, rf"^{re.escape(VIEW_URI)}/[0-9a-f]{{12}}$")
|
|
161
173
|
self.assertEqual(
|
|
162
|
-
show["_meta"]["ui"],
|
|
163
|
-
{"resourceUri": VIEW_URI, "visibility": ["model", "app"]},
|
|
174
|
+
show["_meta"]["ui"], {"resourceUri": uri, "visibility": ["model", "app"]}
|
|
164
175
|
)
|
|
165
|
-
self.assertEqual(show["_meta"]["ui/resourceUri"],
|
|
176
|
+
self.assertEqual(show["_meta"]["ui/resourceUri"], uri)
|
|
166
177
|
self.assertTrue(show["annotations"]["readOnlyHint"])
|
|
167
178
|
write = listed["appwrite_view_write"]
|
|
168
179
|
self.assertEqual(
|
|
169
|
-
write["_meta"]["ui"], {"resourceUri":
|
|
180
|
+
write["_meta"]["ui"], {"resourceUri": uri, "visibility": ["app"]}
|
|
170
181
|
)
|
|
171
182
|
self.assertTrue(write["annotations"]["destructiveHint"])
|
|
172
183
|
# The operator tools are unchanged.
|
|
@@ -176,12 +187,13 @@ class AppsFlow(unittest.TestCase):
|
|
|
176
187
|
|
|
177
188
|
_, response = self.host.call("resources/list")
|
|
178
189
|
view = next(
|
|
179
|
-
each for each in response["result"]["resources"] if each["uri"] ==
|
|
190
|
+
each for each in response["result"]["resources"] if each["uri"] == uri
|
|
180
191
|
)
|
|
181
192
|
self.assertEqual(view["mimeType"], MIME_TYPE)
|
|
182
193
|
|
|
183
|
-
_, response = self.host.call("resources/read", {"uri":
|
|
194
|
+
_, response = self.host.call("resources/read", {"uri": uri})
|
|
184
195
|
(contents,) = response["result"]["contents"]
|
|
196
|
+
self.assertEqual(contents["uri"], uri)
|
|
185
197
|
self.assertEqual(contents["mimeType"], MIME_TYPE)
|
|
186
198
|
# No CSP domains: the host's restrictive default, no network access.
|
|
187
199
|
self.assertEqual(contents["_meta"]["ui"], {"csp": {}, "prefersBorder": True})
|
|
@@ -191,6 +203,12 @@ class AppsFlow(unittest.TestCase):
|
|
|
191
203
|
# Appwrite data reaches the DOM as text only.
|
|
192
204
|
self.assertNotIn("innerHTML", html)
|
|
193
205
|
self.assertNotIn("insertAdjacentHTML", html)
|
|
206
|
+
digest = hashlib.sha256(html.encode("utf-8")).hexdigest()[:12]
|
|
207
|
+
self.assertEqual(uri, f"{VIEW_URI}/{digest}")
|
|
208
|
+
|
|
209
|
+
# Tool lists cached before the URI was versioned still resolve.
|
|
210
|
+
_, response = self.host.call("resources/read", {"uri": VIEW_URI})
|
|
211
|
+
self.assertEqual(response["result"]["contents"][0]["text"], html)
|
|
194
212
|
|
|
195
213
|
def test_hosts_without_apps_are_not_offered_the_view(self):
|
|
196
214
|
with self.server.client() as plain:
|
|
@@ -199,7 +217,7 @@ class AppsFlow(unittest.TestCase):
|
|
|
199
217
|
self.assertNotIn("appwrite_view_write", listed)
|
|
200
218
|
_, response = plain.call("resources/list")
|
|
201
219
|
uris = {each["uri"] for each in response["result"]["resources"]}
|
|
202
|
-
self.
|
|
220
|
+
self.assertFalse(any(each.startswith(VIEW_URI) for each in uris))
|
|
203
221
|
|
|
204
222
|
# A 2025-era client on the stateless transport lists tools without a
|
|
205
223
|
# session, so its capabilities are unknown and the view is offered.
|
|
@@ -310,12 +328,16 @@ class AppsFlow(unittest.TestCase):
|
|
|
310
328
|
self.assertFalse(data["done"])
|
|
311
329
|
# Only the end of a long log is carried.
|
|
312
330
|
self.assertEqual(len(build["logs"]), 200)
|
|
313
|
-
|
|
331
|
+
# The view gets the colors; the model's summary gets plain text.
|
|
332
|
+
self.assertEqual(build["logs"][-1], ANSI_LINE)
|
|
314
333
|
self.assertTrue(build["truncated"])
|
|
315
334
|
text = result["content"][0]["text"]
|
|
316
335
|
self.assertIn(f"Deployment dep_new of function {FUNCTION} is building.", text)
|
|
317
336
|
self.assertIn("Source: main @ a91c3e0.", text)
|
|
318
|
-
self.assertTrue(
|
|
337
|
+
self.assertTrue(
|
|
338
|
+
text.endswith("[13:23:45] [open-runtimes] Build finished. "), text
|
|
339
|
+
)
|
|
340
|
+
self.assertNotIn("\x1b", text)
|
|
319
341
|
|
|
320
342
|
status_path = rf"/v1/functions/{FUNCTION}/deployments/dep_new/status"
|
|
321
343
|
result = self.call(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/.github/workflows/update-docs-index.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/apps/__init__.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/apps/protocol.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/assets/__init__.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/assets/favicon.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/catalog_policy.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/docs_index.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/docs_search.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/docs_source.py
RENAMED
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/error_monitoring.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/__init__.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/bus.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/catalog.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/delivery.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/egress.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/envelope.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/errors.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/ingress.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/projection.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/protocol.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/streams.py
RENAMED
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/events/webhooks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/instructions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/telemetry.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/src/mcp_server_appwrite/tool_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/e2e/fixtures/appwrite/row_created.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_console_sdk_oauth.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_docs_index.py
RENAMED
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_docs_source.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/integration/test_oauth_discovery.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mcp_server_appwrite-2.1.0 → mcp_server_appwrite-2.1.2}/tests/unit/test_error_classification.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|