contree-mcp 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.
- contree_mcp/__init__.py +0 -0
- contree_mcp/__main__.py +25 -0
- contree_mcp/app.py +240 -0
- contree_mcp/arguments.py +35 -0
- contree_mcp/auth/__init__.py +2 -0
- contree_mcp/auth/registry.py +236 -0
- contree_mcp/backend_types.py +301 -0
- contree_mcp/cache.py +208 -0
- contree_mcp/client.py +711 -0
- contree_mcp/context.py +53 -0
- contree_mcp/docs.py +1203 -0
- contree_mcp/file_cache.py +381 -0
- contree_mcp/prompts.py +238 -0
- contree_mcp/py.typed +0 -0
- contree_mcp/resources/__init__.py +17 -0
- contree_mcp/resources/guide.py +715 -0
- contree_mcp/resources/image_lineage.py +46 -0
- contree_mcp/resources/image_ls.py +32 -0
- contree_mcp/resources/import_operation.py +52 -0
- contree_mcp/resources/instance_operation.py +52 -0
- contree_mcp/resources/read_file.py +33 -0
- contree_mcp/resources/static.py +12 -0
- contree_mcp/server.py +77 -0
- contree_mcp/tools/__init__.py +39 -0
- contree_mcp/tools/cancel_operation.py +36 -0
- contree_mcp/tools/download.py +128 -0
- contree_mcp/tools/get_guide.py +54 -0
- contree_mcp/tools/get_image.py +30 -0
- contree_mcp/tools/get_operation.py +26 -0
- contree_mcp/tools/import_image.py +99 -0
- contree_mcp/tools/list_files.py +80 -0
- contree_mcp/tools/list_images.py +50 -0
- contree_mcp/tools/list_operations.py +46 -0
- contree_mcp/tools/read_file.py +47 -0
- contree_mcp/tools/registry_auth.py +71 -0
- contree_mcp/tools/registry_token_obtain.py +80 -0
- contree_mcp/tools/rsync.py +46 -0
- contree_mcp/tools/run.py +97 -0
- contree_mcp/tools/set_tag.py +31 -0
- contree_mcp/tools/upload.py +50 -0
- contree_mcp/tools/wait_operations.py +79 -0
- contree_mcp-0.1.0.dist-info/METADATA +450 -0
- contree_mcp-0.1.0.dist-info/RECORD +46 -0
- contree_mcp-0.1.0.dist-info/WHEEL +4 -0
- contree_mcp-0.1.0.dist-info/entry_points.txt +2 -0
- contree_mcp-0.1.0.dist-info/licenses/LICENSE +176 -0
contree_mcp/context.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import contextvars
|
|
2
|
+
import logging
|
|
3
|
+
from contextvars import ContextVar
|
|
4
|
+
from typing import Any, Generic, TypeVar, cast
|
|
5
|
+
|
|
6
|
+
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
|
|
7
|
+
from starlette.requests import Request
|
|
8
|
+
from starlette.responses import Response
|
|
9
|
+
from starlette.types import ASGIApp
|
|
10
|
+
|
|
11
|
+
from contree_mcp.client import ContreeClient
|
|
12
|
+
from contree_mcp.file_cache import FileCache
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T")
|
|
15
|
+
log = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class StrictContextVar(Generic[T]):
|
|
19
|
+
_UNSET = object()
|
|
20
|
+
|
|
21
|
+
def __init__(self, name: str) -> None:
|
|
22
|
+
self.exception = LookupError(f"Context variable '{name}' is not set")
|
|
23
|
+
self.__var: ContextVar[T] = ContextVar(name)
|
|
24
|
+
|
|
25
|
+
def get(self) -> T:
|
|
26
|
+
value: Any = self.__var.get(self._UNSET)
|
|
27
|
+
if value is self._UNSET:
|
|
28
|
+
raise self.exception
|
|
29
|
+
return cast(T, value)
|
|
30
|
+
|
|
31
|
+
def set(self, value: T) -> None:
|
|
32
|
+
self.__var.set(value)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# Context variables for server dependencies
|
|
36
|
+
CLIENT: StrictContextVar[ContreeClient] = StrictContextVar("CLIENT")
|
|
37
|
+
FILES_CACHE: StrictContextVar[FileCache] = StrictContextVar("FILES_CACHE")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ContextMiddleware(BaseHTTPMiddleware):
|
|
41
|
+
def __init__(self, app: ASGIApp, *, ctx: contextvars.Context) -> None:
|
|
42
|
+
self.ctx = ctx
|
|
43
|
+
super().__init__(app)
|
|
44
|
+
|
|
45
|
+
async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
|
|
46
|
+
# Uvicorn cleans up contextvars between requests, so we restore them here
|
|
47
|
+
CLIENT.set(self.ctx.run(CLIENT.get))
|
|
48
|
+
FILES_CACHE.set(self.ctx.run(FILES_CACHE.get))
|
|
49
|
+
try:
|
|
50
|
+
return await call_next(request)
|
|
51
|
+
except Exception as exc:
|
|
52
|
+
log.exception("Exception while handling request")
|
|
53
|
+
raise exc
|