awnode 0.3.3__tar.gz → 0.3.4__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.
- {awnode-0.3.3 → awnode-0.3.4}/PKG-INFO +3 -3
- {awnode-0.3.3 → awnode-0.3.4}/README.md +1 -1
- {awnode-0.3.3 → awnode-0.3.4}/awnode/__init__.py +1 -1
- {awnode-0.3.3 → awnode-0.3.4}/awnode/mcp_server.py +71 -29
- {awnode-0.3.3 → awnode-0.3.4}/docs/aither-manifest.json +4 -4
- {awnode-0.3.3 → awnode-0.3.4}/docs/index.html +2 -2
- {awnode-0.3.3 → awnode-0.3.4}/pyproject.toml +9 -12
- awnode-0.3.4/tests/test_mcp_api_compat.py +60 -0
- {awnode-0.3.3 → awnode-0.3.4}/.github/workflows/publish.yml +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/.gitignore +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/CLAUDE.md +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/Dockerfile +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/LICENSE +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/_smoke_check.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/aither-constellation.js +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/aither-manifest.json +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/__main__.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/_doctor.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/cli.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/comfyui_setup.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/components/__init__.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/components/autorig.yaml +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/components/canvas.yaml +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/components/comfyui-3d.yaml +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/components/comfyui.yaml +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/components/design.yaml +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/components/iris.yaml +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/components/muse.yaml +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/components/ollama.yaml +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/components/sd-webui.yaml +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/extensions.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/hub.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/license.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/proxy.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/server.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/service_install.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/sync.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/__init__.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/_http.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/_scopes.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/commands.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/context.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/documents.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/embeddings.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/extensions.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/filesystem.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/fleet_host.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/fleet_verbs.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/generation.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/git_tools.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/http_client.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/knowledge.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/memory.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/mermaid.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/notebooks.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/ollama.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/orchestrator.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/tools/search.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/awnode/update_check.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/dist_validate/aithernode-0.1.0-py3-none-any.whl +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/docker-entrypoint.sh +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/docs/aither-constellation.js +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/docs/llms.txt +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/packaging/aithernode-stub/README.md +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/packaging/aithernode-stub/pyproject.toml +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_awnix_host_install.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_chat_endpoint_auth.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_component_image_env.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_custom_backend.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_extension_contract.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_fleet_host_tools.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_fleet_verbs_tools.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_hub_error_cooldown.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_mcp_mode_reprobe.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_mcp_server_auth.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_mcp_sse_transport.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_pair_mode_route.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_proxy_plane.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_server_route_hygiene.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_server_security_hardening.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_sync_enrollment_lifecycle.py +0 -0
- {awnode-0.3.3 → awnode-0.3.4}/tests/test_update_check.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: awnode
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: awnode — lightweight local gateway for AitherOS
|
|
5
5
|
Project-URL: Homepage, https://aitherium.com
|
|
6
6
|
Author-email: Aitherium <hello@aitherium.com>
|
|
@@ -11,7 +11,7 @@ Requires-Python: >=3.10
|
|
|
11
11
|
Requires-Dist: awdk>=1.3.0
|
|
12
12
|
Requires-Dist: fastapi>=0.109.0
|
|
13
13
|
Requires-Dist: httpx>=0.26.0
|
|
14
|
-
Requires-Dist: mcp<
|
|
14
|
+
Requires-Dist: mcp<3.0.0,>=1.0.0
|
|
15
15
|
Requires-Dist: pyyaml>=6.0
|
|
16
16
|
Requires-Dist: uvicorn[standard]>=0.27.0
|
|
17
17
|
Provides-Extra: all
|
|
@@ -282,7 +282,7 @@ Every repository here is public. Each publishes an `aither-manifest.json` beside
|
|
|
282
282
|
| [awsettings](https://github.com/Aitherium/awsettings) | Your agent's permissions and config, following you to the next machine | [docs](https://aitherium.github.io/awsettings/) |
|
|
283
283
|
| [awavatar](https://github.com/Aitherium/awavatar) | One character spec in, a rigged, animated, multi-style avatar pack out | [docs](https://aitherium.github.io/awavatar/) |
|
|
284
284
|
|
|
285
|
-
**Built on** [llama.cpp](https://github.com/ggml-org/llama.cpp) · [vLLM](https://github.com/vllm-project/vllm) · [ComfyUI](https://github.com/comfyanonymous/ComfyUI) · [CentOS Stream](https://www.centos.org/centos-stream/) · [Podman](https://github.com/containers/podman) · [Docker](https://github.com/moby/moby) · [LanceDB](https://github.com/lancedb/lancedb) · [WireGuard](https://www.wireguard.com/) · [FFmpeg](https://ffmpeg.org/) · [Blender + Rigify](https://www.blender.org/) · [headroom](https://github.com/headroomlabs-ai/headroom) · [SANA](https://github.com/NVlabs/Sana) · [Hunyuan3D](https://github.com/Tencent-Hunyuan/Hunyuan3D-2.1) · [repowise](https://github.com/repowise-dev/repowise) · [Playwright](https://github.com/microsoft/playwright) · [Chromium](https://www.chromium.org/) · [Next.js](https://github.com/vercel/next.js) · [React](https://github.com/facebook/react).
|
|
285
|
+
**Built on** [REA (Reverse Engineer Anything)](https://github.com/morluto/rea) · [llama.cpp](https://github.com/ggml-org/llama.cpp) · [vLLM](https://github.com/vllm-project/vllm) · [ComfyUI](https://github.com/comfyanonymous/ComfyUI) · [CentOS Stream](https://www.centos.org/centos-stream/) · [Podman](https://github.com/containers/podman) · [Docker](https://github.com/moby/moby) · [LanceDB](https://github.com/lancedb/lancedb) · [WireGuard](https://www.wireguard.com/) · [FFmpeg](https://ffmpeg.org/) · [Blender + Rigify](https://www.blender.org/) · [headroom](https://github.com/headroomlabs-ai/headroom) · [SANA](https://github.com/NVlabs/Sana) · [Hunyuan3D](https://github.com/Tencent-Hunyuan/Hunyuan3D-2.1) · [repowise](https://github.com/repowise-dev/repowise) · [Playwright](https://github.com/microsoft/playwright) · [Chromium](https://www.chromium.org/) · [Next.js](https://github.com/vercel/next.js) · [React](https://github.com/facebook/react).
|
|
286
286
|
|
|
287
287
|
<div id="aither-constellation" data-self="awnode"></div>
|
|
288
288
|
<script src="aither-constellation.js"></script>
|
|
@@ -254,7 +254,7 @@ Every repository here is public. Each publishes an `aither-manifest.json` beside
|
|
|
254
254
|
| [awsettings](https://github.com/Aitherium/awsettings) | Your agent's permissions and config, following you to the next machine | [docs](https://aitherium.github.io/awsettings/) |
|
|
255
255
|
| [awavatar](https://github.com/Aitherium/awavatar) | One character spec in, a rigged, animated, multi-style avatar pack out | [docs](https://aitherium.github.io/awavatar/) |
|
|
256
256
|
|
|
257
|
-
**Built on** [llama.cpp](https://github.com/ggml-org/llama.cpp) · [vLLM](https://github.com/vllm-project/vllm) · [ComfyUI](https://github.com/comfyanonymous/ComfyUI) · [CentOS Stream](https://www.centos.org/centos-stream/) · [Podman](https://github.com/containers/podman) · [Docker](https://github.com/moby/moby) · [LanceDB](https://github.com/lancedb/lancedb) · [WireGuard](https://www.wireguard.com/) · [FFmpeg](https://ffmpeg.org/) · [Blender + Rigify](https://www.blender.org/) · [headroom](https://github.com/headroomlabs-ai/headroom) · [SANA](https://github.com/NVlabs/Sana) · [Hunyuan3D](https://github.com/Tencent-Hunyuan/Hunyuan3D-2.1) · [repowise](https://github.com/repowise-dev/repowise) · [Playwright](https://github.com/microsoft/playwright) · [Chromium](https://www.chromium.org/) · [Next.js](https://github.com/vercel/next.js) · [React](https://github.com/facebook/react).
|
|
257
|
+
**Built on** [REA (Reverse Engineer Anything)](https://github.com/morluto/rea) · [llama.cpp](https://github.com/ggml-org/llama.cpp) · [vLLM](https://github.com/vllm-project/vllm) · [ComfyUI](https://github.com/comfyanonymous/ComfyUI) · [CentOS Stream](https://www.centos.org/centos-stream/) · [Podman](https://github.com/containers/podman) · [Docker](https://github.com/moby/moby) · [LanceDB](https://github.com/lancedb/lancedb) · [WireGuard](https://www.wireguard.com/) · [FFmpeg](https://ffmpeg.org/) · [Blender + Rigify](https://www.blender.org/) · [headroom](https://github.com/headroomlabs-ai/headroom) · [SANA](https://github.com/NVlabs/Sana) · [Hunyuan3D](https://github.com/Tencent-Hunyuan/Hunyuan3D-2.1) · [repowise](https://github.com/repowise-dev/repowise) · [Playwright](https://github.com/microsoft/playwright) · [Chromium](https://www.chromium.org/) · [Next.js](https://github.com/vercel/next.js) · [React](https://github.com/facebook/react).
|
|
258
258
|
|
|
259
259
|
<div id="aither-constellation" data-self="awnode"></div>
|
|
260
260
|
<script src="aither-constellation.js"></script>
|
|
@@ -43,6 +43,7 @@ import sys
|
|
|
43
43
|
from enum import Enum
|
|
44
44
|
from typing import Any, Callable, Dict, List, get_type_hints
|
|
45
45
|
|
|
46
|
+
from mcp import types as mcp_types
|
|
46
47
|
from mcp.server import Server
|
|
47
48
|
from mcp.server.lowlevel import NotificationOptions
|
|
48
49
|
from mcp.server.stdio import stdio_server
|
|
@@ -113,7 +114,7 @@ async def detect_mode() -> RuntimeMode:
|
|
|
113
114
|
# Scopes — which tool modules are available in which mode
|
|
114
115
|
# ---------------------------------------------------------------------------
|
|
115
116
|
|
|
116
|
-
from awnode.tools._scopes import
|
|
117
|
+
from awnode.tools._scopes import PLATFORM_ONLY, SHELL_CLOUD, SHELL_LOCAL # noqa: E402
|
|
117
118
|
|
|
118
119
|
|
|
119
120
|
def _scope_for_module(module_name: str) -> str:
|
|
@@ -281,7 +282,6 @@ def _discover_tools() -> Dict[str, Dict[str, Any]]:
|
|
|
281
282
|
# MCP Server
|
|
282
283
|
# ---------------------------------------------------------------------------
|
|
283
284
|
|
|
284
|
-
server = Server("awnode")
|
|
285
285
|
_current_mode: RuntimeMode = RuntimeMode.STANDALONE
|
|
286
286
|
|
|
287
287
|
|
|
@@ -321,14 +321,8 @@ async def _reprobe_loop() -> None:
|
|
|
321
321
|
logger.debug("mode re-probe failed: %s", exc)
|
|
322
322
|
|
|
323
323
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
"""Return tools available for the current runtime mode."""
|
|
327
|
-
global _session
|
|
328
|
-
try:
|
|
329
|
-
_session = server.request_context.session
|
|
330
|
-
except LookupError:
|
|
331
|
-
pass
|
|
324
|
+
def visible_tools() -> list[Tool]:
|
|
325
|
+
"""Tools available for the current runtime mode."""
|
|
332
326
|
tools: list[Tool] = []
|
|
333
327
|
for name, info in _TOOL_REGISTRY.items():
|
|
334
328
|
if not _mode_allows_scope(_current_mode, info["scope"]):
|
|
@@ -341,15 +335,15 @@ async def list_tools() -> list[Tool]:
|
|
|
341
335
|
return tools
|
|
342
336
|
|
|
343
337
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
338
|
+
async def dispatch_tool(name: str, arguments: dict) -> "tuple[str, bool]":
|
|
339
|
+
"""Invoke a registered tool by name, applying the runtime-mode scope rule.
|
|
340
|
+
|
|
341
|
+
Returns ``(text, is_error)``. Transport-neutral: both mcp API generations
|
|
342
|
+
below wrap this one function, so the two can never disagree on a verdict.
|
|
343
|
+
"""
|
|
347
344
|
info = _TOOL_REGISTRY.get(name)
|
|
348
345
|
if info is None:
|
|
349
|
-
return
|
|
350
|
-
type="text",
|
|
351
|
-
text=json.dumps({"error": f"Unknown tool: {name}"}, indent=2),
|
|
352
|
-
)]
|
|
346
|
+
return json.dumps({"error": f"Unknown tool: {name}"}, indent=2), True
|
|
353
347
|
|
|
354
348
|
# Scope check
|
|
355
349
|
if not _mode_allows_scope(_current_mode, info["scope"]):
|
|
@@ -366,13 +360,60 @@ async def call_tool(name: str, arguments: dict) -> list[TextContent]:
|
|
|
366
360
|
)
|
|
367
361
|
else:
|
|
368
362
|
msg = f"Tool '{name}' is not available in {_current_mode.value} mode."
|
|
369
|
-
return
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
363
|
+
return json.dumps({"error": msg, "scope": scope}, indent=2), True
|
|
364
|
+
|
|
365
|
+
return await invoke_registered_tool(name, info, arguments)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
# -- mcp 2.x: handlers are constructor arguments on the low-level Server -------------
|
|
369
|
+
|
|
370
|
+
async def _on_list_tools(ctx: Any, _params: Any) -> Any:
|
|
371
|
+
global _session
|
|
372
|
+
_session = getattr(ctx, "session", None) or _session
|
|
373
|
+
return mcp_types.ListToolsResult(tools=visible_tools())
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
async def _on_call_tool(_ctx: Any, params: Any) -> Any:
|
|
377
|
+
text, is_error = await dispatch_tool(params.name, dict(params.arguments or {}))
|
|
378
|
+
return mcp_types.CallToolResult(
|
|
379
|
+
content=[TextContent(type="text", text=text)], is_error=is_error,
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def _build_server() -> Server:
|
|
384
|
+
"""Construct the low-level Server against whichever mcp generation is installed.
|
|
373
385
|
|
|
374
|
-
|
|
375
|
-
|
|
386
|
+
mcp 2.x removed the 1.x ``@server.list_tools()`` / ``@server.call_tool()``
|
|
387
|
+
decorators (``awnode mcp`` died at import with AttributeError once a sibling aw
|
|
388
|
+
brick pulled mcp 2.2 into the shared env, 2026-10-14) and takes the handlers as
|
|
389
|
+
``on_list_tools=`` / ``on_call_tool=`` instead. awdk[node] still pins mcp<2, so
|
|
390
|
+
awnode supports BOTH rather than forcing a resolver conflict on a shared env.
|
|
391
|
+
"""
|
|
392
|
+
try:
|
|
393
|
+
return Server("awnode", on_list_tools=_on_list_tools, on_call_tool=_on_call_tool)
|
|
394
|
+
except TypeError as exc:
|
|
395
|
+
# mcp 1.x: no handler kwargs -- register through the decorators below.
|
|
396
|
+
logger.debug("mcp 1.x Server API (%s); using the decorator registration", exc)
|
|
397
|
+
srv = Server("awnode")
|
|
398
|
+
|
|
399
|
+
@srv.list_tools()
|
|
400
|
+
async def list_tools() -> list[Tool]:
|
|
401
|
+
global _session
|
|
402
|
+
try:
|
|
403
|
+
_session = srv.request_context.session
|
|
404
|
+
except LookupError:
|
|
405
|
+
logger.debug("tools/list outside a request context; keeping the last session")
|
|
406
|
+
return visible_tools()
|
|
407
|
+
|
|
408
|
+
@srv.call_tool()
|
|
409
|
+
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
|
|
410
|
+
text, _is_error = await dispatch_tool(name, arguments)
|
|
411
|
+
return [TextContent(type="text", text=text)]
|
|
412
|
+
|
|
413
|
+
return srv
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
server = _build_server()
|
|
376
417
|
|
|
377
418
|
|
|
378
419
|
async def invoke_registered_tool(
|
|
@@ -390,8 +431,9 @@ async def invoke_registered_tool(
|
|
|
390
431
|
denial = get_license_manager().check_tool(info["module"])
|
|
391
432
|
if denial:
|
|
392
433
|
return json.dumps({"error": denial, "scope": "subscription"}, indent=2), True
|
|
393
|
-
except ImportError:
|
|
394
|
-
|
|
434
|
+
except ImportError as exc:
|
|
435
|
+
# License check failure should never block tools.
|
|
436
|
+
logger.debug("license module unavailable; tool %s not gated: %s", name, exc)
|
|
395
437
|
|
|
396
438
|
func = info["func"]
|
|
397
439
|
|
|
@@ -473,7 +515,7 @@ def _host_is_loopback(host_header: str) -> bool:
|
|
|
473
515
|
def build_sse_app(mcp_key: str = "", loopback_only: bool = True):
|
|
474
516
|
"""The Starlette app behind ``awnode mcp --transport sse``.
|
|
475
517
|
|
|
476
|
-
Routes (the standard MCP HTTP+SSE transport,
|
|
518
|
+
Routes (the standard MCP HTTP+SSE transport, ``SseServerTransport``):
|
|
477
519
|
GET /health liveness (never behind auth)
|
|
478
520
|
GET /sse opens the event stream; its first event names the
|
|
479
521
|
per-session POST endpoint (``/messages/?session_id=...``)
|
|
@@ -490,9 +532,9 @@ def build_sse_app(mcp_key: str = "", loopback_only: bool = True):
|
|
|
490
532
|
rebinding page reaches 127.0.0.1 as same-origin under its own Host name, so
|
|
491
533
|
every request carrying an Origin is refused (MCP clients are not browsers --
|
|
492
534
|
the same rule as aw-hub), and with ``loopback_only`` any Host that is not
|
|
493
|
-
127.0.0.1 / localhost / [::1] is refused too. The pin is ``mcp>=1.0,<
|
|
494
|
-
TransportSecuritySettings exists only in later 1.x, so it is layered on
|
|
495
|
-
importable but never relied on alone.
|
|
535
|
+
127.0.0.1 / localhost / [::1] is refused too. The pin is ``mcp>=1.0,<3`` and
|
|
536
|
+
TransportSecuritySettings exists only in later 1.x and 2.x, so it is layered on
|
|
537
|
+
when importable but never relied on alone.
|
|
496
538
|
"""
|
|
497
539
|
from mcp.server.sse import SseServerTransport
|
|
498
540
|
from starlette.applications import Starlette
|
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
"includes": [],
|
|
16
16
|
"metrics": {
|
|
17
17
|
"files": {
|
|
18
|
-
"value":
|
|
19
|
-
"as_of": "2026-10-
|
|
18
|
+
"value": 80,
|
|
19
|
+
"as_of": "2026-10-13T18:27:40+00:00"
|
|
20
20
|
},
|
|
21
21
|
"tests": {
|
|
22
|
-
"value":
|
|
23
|
-
"as_of": "2026-10-
|
|
22
|
+
"value": 17,
|
|
23
|
+
"as_of": "2026-10-13T18:27:40+00:00"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -1179,7 +1179,7 @@ the read-only set; for full tool access from an IDE use <code>awnode mcp</code>.
|
|
|
1179
1179
|
</tr>
|
|
1180
1180
|
</tbody>
|
|
1181
1181
|
</table>
|
|
1182
|
-
<p><strong>Built on</strong> <a href="https://github.com/ggml-org/llama.cpp">llama.cpp</a> · <a href="https://github.com/vllm-project/vllm">vLLM</a> · <a href="https://github.com/comfyanonymous/ComfyUI">ComfyUI</a> · <a href="https://www.centos.org/centos-stream/">CentOS Stream</a> · <a href="https://github.com/containers/podman">Podman</a> · <a href="https://github.com/moby/moby">Docker</a> · <a href="https://github.com/lancedb/lancedb">LanceDB</a> · <a href="https://www.wireguard.com/">WireGuard</a> · <a href="https://ffmpeg.org/">FFmpeg</a> · <a href="https://www.blender.org/">Blender + Rigify</a> · <a href="https://github.com/headroomlabs-ai/headroom">headroom</a> · <a href="https://github.com/NVlabs/Sana">SANA</a> · <a href="https://github.com/Tencent-Hunyuan/Hunyuan3D-2.1">Hunyuan3D</a> · <a href="https://github.com/repowise-dev/repowise">repowise</a> · <a href="https://github.com/microsoft/playwright">Playwright</a> · <a href="https://www.chromium.org/">Chromium</a> · <a href="https://github.com/vercel/next.js">Next.js</a> · <a href="https://github.com/facebook/react">React</a>.</p>
|
|
1182
|
+
<p><strong>Built on</strong> <a href="https://github.com/morluto/rea">REA (Reverse Engineer Anything)</a> · <a href="https://github.com/ggml-org/llama.cpp">llama.cpp</a> · <a href="https://github.com/vllm-project/vllm">vLLM</a> · <a href="https://github.com/comfyanonymous/ComfyUI">ComfyUI</a> · <a href="https://www.centos.org/centos-stream/">CentOS Stream</a> · <a href="https://github.com/containers/podman">Podman</a> · <a href="https://github.com/moby/moby">Docker</a> · <a href="https://github.com/lancedb/lancedb">LanceDB</a> · <a href="https://www.wireguard.com/">WireGuard</a> · <a href="https://ffmpeg.org/">FFmpeg</a> · <a href="https://www.blender.org/">Blender + Rigify</a> · <a href="https://github.com/headroomlabs-ai/headroom">headroom</a> · <a href="https://github.com/NVlabs/Sana">SANA</a> · <a href="https://github.com/Tencent-Hunyuan/Hunyuan3D-2.1">Hunyuan3D</a> · <a href="https://github.com/repowise-dev/repowise">repowise</a> · <a href="https://github.com/microsoft/playwright">Playwright</a> · <a href="https://www.chromium.org/">Chromium</a> · <a href="https://github.com/vercel/next.js">Next.js</a> · <a href="https://github.com/facebook/react">React</a>.</p>
|
|
1183
1183
|
<div id="aither-constellation" data-self="awnode"></div>
|
|
1184
1184
|
<script src="aither-constellation.js"></script>
|
|
1185
1185
|
|
|
@@ -1257,7 +1257,7 @@ the read-only set; for full tool access from an IDE use <code>awnode mcp</code>.
|
|
|
1257
1257
|
<div class="fk-element" aria-label="Aitherium, element 0, symbol Ai, the element of creation"><span class="fk-el-no">0</span><span class="fk-el-sy">Ai</span><span class="fk-el-nm">aitherium</span></div>
|
|
1258
1258
|
<p class="fk-brandlines"><span>Aitherium · the element of creation</span><span>Aither — the medium creation moves through</span></p>
|
|
1259
1259
|
<div class="fk-family"><a href="https://aitherium.com/about"><span class="n">Aitherium</span><span class="r">the company</span></a><a href="https://aitherium.com/"><span class="n">AitherOS</span><span class="r">the OS</span></a><a href="https://aitherium.github.io/awnix/"><span class="n m">awnix</span><span class="r">the base</span></a><a href="https://aitherium.github.io/awdk/"><span class="n m">awdk</span><span class="r">the SDK</span></a><a href="https://aitherium.github.io/awsh/"><span class="n m">awsh</span><span class="r">the shell</span></a><a href="https://aitherium.github.io/"><span class="n m">aw* bricks</span><span class="r">the frameworks</span></a><a href="https://aitherium.com/studio"><span class="n">The Studio</span><span class="r">build apps, agents, workflows</span></a></div>
|
|
1260
|
-
<p class="fk-colophon fk-built-on">Built on <a href="https://www.blender.org/" rel="noopener">Blender + Rigify</a> · <a href="https://www.centos.org/centos-stream/" rel="noopener">CentOS Stream</a> · <a href="https://www.chromium.org/" rel="noopener">Chromium</a> · <a href="https://github.com/comfyanonymous/ComfyUI" rel="noopener">ComfyUI</a> · <a href="https://github.com/moby/moby" rel="noopener">Docker</a> · <a href="https://ffmpeg.org/" rel="noopener">FFmpeg</a> · <a href="https://github.com/headroomlabs-ai/headroom" rel="noopener">headroom</a> · <a href="https://github.com/Tencent-Hunyuan/Hunyuan3D-2.1" rel="noopener">Hunyuan3D</a> · <a href="https://github.com/lancedb/lancedb" rel="noopener">LanceDB</a> · <a href="https://github.com/ggml-org/llama.cpp" rel="noopener">llama.cpp</a> · <a href="https://github.com/vercel/next.js" rel="noopener">Next.js</a> · <a href="https://github.com/microsoft/playwright" rel="noopener">Playwright</a> · <a href="https://github.com/containers/podman" rel="noopener">Podman</a> · <a href="https://github.com/facebook/react" rel="noopener">React</a> · <a href="https://github.com/repowise-dev/repowise" rel="noopener">repowise</a> · <a href="https://github.com/NVlabs/Sana" rel="noopener">SANA</a> · <a href="https://github.com/vllm-project/vllm" rel="noopener">vLLM</a> · <a href="https://www.wireguard.com/" rel="noopener">WireGuard</a></p>
|
|
1260
|
+
<p class="fk-colophon fk-built-on">Built on <a href="https://www.blender.org/" rel="noopener">Blender + Rigify</a> · <a href="https://www.centos.org/centos-stream/" rel="noopener">CentOS Stream</a> · <a href="https://www.chromium.org/" rel="noopener">Chromium</a> · <a href="https://github.com/comfyanonymous/ComfyUI" rel="noopener">ComfyUI</a> · <a href="https://github.com/moby/moby" rel="noopener">Docker</a> · <a href="https://ffmpeg.org/" rel="noopener">FFmpeg</a> · <a href="https://github.com/headroomlabs-ai/headroom" rel="noopener">headroom</a> · <a href="https://github.com/Tencent-Hunyuan/Hunyuan3D-2.1" rel="noopener">Hunyuan3D</a> · <a href="https://github.com/lancedb/lancedb" rel="noopener">LanceDB</a> · <a href="https://github.com/ggml-org/llama.cpp" rel="noopener">llama.cpp</a> · <a href="https://github.com/vercel/next.js" rel="noopener">Next.js</a> · <a href="https://github.com/microsoft/playwright" rel="noopener">Playwright</a> · <a href="https://github.com/containers/podman" rel="noopener">Podman</a> · <a href="https://github.com/morluto/rea" rel="noopener">REA (Reverse Engineer Anything)</a> · <a href="https://github.com/facebook/react" rel="noopener">React</a> · <a href="https://github.com/repowise-dev/repowise" rel="noopener">repowise</a> · <a href="https://github.com/NVlabs/Sana" rel="noopener">SANA</a> · <a href="https://github.com/vllm-project/vllm" rel="noopener">vLLM</a> · <a href="https://www.wireguard.com/" rel="noopener">WireGuard</a></p>
|
|
1261
1261
|
<p class="fk-colophon">Part of the <strong>aw family</strong> — Aither World tools, each one <em>adoptable alone</em>. Generated from the brick README and the ecosystem registry.</p>
|
|
1262
1262
|
</footer>
|
|
1263
1263
|
<nav class="fk-dock" aria-label="The family"><a href="https://aitherium.com/" aria-label="AitherOS"><svg class="fk-mark" viewBox="0 0 512 512" fill="none" aria-hidden="true"><g transform="translate(256 256) scale(0.86) translate(-256 -256)"><polygon points="256,96 400,360 112,360" stroke="currentColor" stroke-width="26" stroke-linejoin="round"/><circle cx="256" cy="262" r="52" fill="currentColor"/><circle cx="256" cy="262" r="26" fill="#050507"/><circle cx="256" cy="262" r="10" fill="currentColor"/></g></svg></a><span class="fk-sep" aria-hidden="true"></span><a href="https://aitherium.github.io/" aria-current="page">bricks</a><a href="https://aitherium.github.io/awdk/">awdk</a><a href="https://aitherium.github.io/awsh/">awsh</a><a href="https://aitherium.github.io/awnix/">awnix</a><a href="https://aitherium.github.io/awknowledge/">guide</a><a href="https://blog.aitherium.com/">journal</a></nav>
|
|
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
|
|
|
8
8
|
# [project.scripts]). The old `aithernode` distribution name is kept resolving by
|
|
9
9
|
# the redirect stub in `packaging/aithernode-stub/`.
|
|
10
10
|
name = "awnode"
|
|
11
|
-
version = "0.3.
|
|
11
|
+
version = "0.3.4"
|
|
12
12
|
description = "awnode — lightweight local gateway for AitherOS"
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
requires-python = ">=3.10"
|
|
@@ -23,17 +23,14 @@ dependencies = [
|
|
|
23
23
|
"pyyaml>=6.0",
|
|
24
24
|
"fastapi>=0.109.0",
|
|
25
25
|
"uvicorn[standard]>=0.27.0",
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
# failure had been hiding, not something this pin causes. Migrating to
|
|
35
|
-
# the 2.x API is real follow-up work, not a version-string fix.
|
|
36
|
-
"mcp>=1.0.0,<2.0.0",
|
|
26
|
+
# mcp 1.x AND 2.x are both supported (mcp_server._build_server picks the
|
|
27
|
+
# API at import): 2.x moved the low-level handlers from the
|
|
28
|
+
# @server.list_tools()/@server.call_tool() decorators to on_list_tools= /
|
|
29
|
+
# on_call_tool= constructor kwargs. The old <2 pin broke `awnode mcp` the
|
|
30
|
+
# moment a sibling aw brick (awrelay/awgraph/awdelphi need >=2) pulled
|
|
31
|
+
# 2.2 into the same env (2026-10-14); widening to <3 instead of >=2 keeps
|
|
32
|
+
# awdk[node] (still mcp<2) co-installable in one env.
|
|
33
|
+
"mcp>=1.0.0,<3.0.0",
|
|
37
34
|
]
|
|
38
35
|
|
|
39
36
|
# No Repository/Documentation entry: Aitherium/awnode is a PRIVATE
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""`awnode mcp` must import and serve on whichever mcp generation is installed.
|
|
2
|
+
|
|
3
|
+
2026-10-14: a sibling aw brick pulled mcp 2.2 into the shared env and `awnode mcp`
|
|
4
|
+
died at import (`'Server' object has no attribute 'list_tools'`). The live SSE test
|
|
5
|
+
proves list+call end to end; these pin the transport-neutral core both API paths wrap.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import json
|
|
11
|
+
|
|
12
|
+
import awnode.mcp_server as ms
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_module_builds_a_server_on_the_installed_mcp():
|
|
16
|
+
assert ms.server is not None
|
|
17
|
+
# 2.x registers on_list_tools via the constructor; 1.x via decorators. Either
|
|
18
|
+
# way a tools/list handler must exist, or the server answers nothing.
|
|
19
|
+
handlers = getattr(ms.server, "request_handlers", None)
|
|
20
|
+
if handlers is not None: # mcp 1.x
|
|
21
|
+
assert any("ListTools" in getattr(k, "__name__", "") for k in handlers)
|
|
22
|
+
else: # mcp 2.x
|
|
23
|
+
assert ms.server.get_request_handler("tools/list") is not None
|
|
24
|
+
assert ms.server.get_request_handler("tools/call") is not None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_unknown_tool_is_an_error(monkeypatch):
|
|
28
|
+
monkeypatch.setattr(ms, "_TOOL_REGISTRY", {})
|
|
29
|
+
text, is_error = asyncio.run(ms.dispatch_tool("nope", {}))
|
|
30
|
+
assert is_error is True
|
|
31
|
+
assert "Unknown tool" in json.loads(text)["error"]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_scope_refusal_is_an_error_and_hidden_from_the_list(monkeypatch):
|
|
35
|
+
def _f():
|
|
36
|
+
return "ran"
|
|
37
|
+
|
|
38
|
+
monkeypatch.setattr(ms, "_TOOL_REGISTRY", {"plat": {
|
|
39
|
+
"func": _f, "scope": "platform_only", "module": "x",
|
|
40
|
+
"description": "d", "schema": {"type": "object", "properties": {}},
|
|
41
|
+
}})
|
|
42
|
+
monkeypatch.setattr(ms, "_current_mode", ms.RuntimeMode.STANDALONE)
|
|
43
|
+
assert [t.name for t in ms.visible_tools()] == []
|
|
44
|
+
text, is_error = asyncio.run(ms.dispatch_tool("plat", {}))
|
|
45
|
+
assert is_error is True and json.loads(text)["scope"] == "platform_only"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_allowed_tool_runs(monkeypatch):
|
|
49
|
+
def _f(x: str = "") -> str:
|
|
50
|
+
return f"got {x}"
|
|
51
|
+
|
|
52
|
+
# "filesystem" is a free-plan module, so the subscription gate passes.
|
|
53
|
+
monkeypatch.setattr(ms, "_TOOL_REGISTRY", {"echo": {
|
|
54
|
+
"func": _f, "scope": "shell_local", "module": "filesystem",
|
|
55
|
+
"description": "d", "schema": {"type": "object", "properties": {}},
|
|
56
|
+
}})
|
|
57
|
+
monkeypatch.setattr(ms, "_current_mode", ms.RuntimeMode.STANDALONE)
|
|
58
|
+
assert [t.name for t in ms.visible_tools()] == ["echo"]
|
|
59
|
+
text, is_error = asyncio.run(ms.dispatch_tool("echo", {"x": "hi", "junk": 1}))
|
|
60
|
+
assert (text, is_error) == ("got hi", False)
|
|
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
|
|
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
|
|
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
|