Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0576aa9a2 | |||
| 4a6c60113b | |||
| a0cb1ac9fe | |||
| de4f1032aa | |||
| 178be5da6d | |||
| 61d8c851c9 | |||
| a8c63c8379 | |||
| 3147180ccd | |||
| 380578dd2e | |||
| 10c5557aea | |||
| 7772b1ac2e | |||
| 0513bec105 | |||
| 4e89e92b65 |
@@ -25,7 +25,7 @@ jobs:
|
|||||||
github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
|
github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
|
||||||
changelog_increment_filename: body.md
|
changelog_increment_filename: body.md
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1
|
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2
|
||||||
with:
|
with:
|
||||||
body_path: "body.md"
|
body_path: "body.md"
|
||||||
tag_name: v${{ env.REVISION }}
|
tag_name: v${{ env.REVISION }}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ jobs:
|
|||||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||||
|
|
||||||
- name: Install Helm
|
- name: Install Helm
|
||||||
uses: azure/setup-helm@v4.3.0
|
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1
|
||||||
with:
|
with:
|
||||||
version: v3.16.0
|
version: v3.16.0
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,15 @@
|
|||||||
|
## v0.29.2 (2025-11-09)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- **helm**: Set default strategy to Recreate
|
||||||
|
|
||||||
|
## v0.29.1 (2025-11-09)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- **observability**: isolate metrics endpoint to dedicated port
|
||||||
|
|
||||||
## v0.29.0 (2025-11-09)
|
## v0.29.0 (2025-11-09)
|
||||||
|
|
||||||
### Feat
|
### Feat
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- name: qdrant
|
- name: qdrant
|
||||||
repository: https://qdrant.github.io/qdrant-helm
|
repository: https://qdrant.github.io/qdrant-helm
|
||||||
version: 0.9.0
|
version: 1.15.5
|
||||||
- name: ollama
|
- name: ollama
|
||||||
repository: https://otwld.github.io/ollama-helm
|
repository: https://otwld.github.io/ollama-helm
|
||||||
version: 1.33.0
|
version: 1.34.0
|
||||||
digest: sha256:d2a0d0e347db47dc89c607d61251aeb0b7a39eddaa2d8137526f29cf625c900c
|
digest: sha256:d51c97d05be2614b751c0dd7267ef7dc959eff5ebef859c5f895c5c554b7a874
|
||||||
generated: "2025-11-09T07:48:54.477365384+01:00"
|
generated: "2025-11-09T17:08:02.86648061Z"
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ apiVersion: v2
|
|||||||
name: nextcloud-mcp-server
|
name: nextcloud-mcp-server
|
||||||
description: A Helm chart for Nextcloud MCP Server - enables AI assistants to interact with Nextcloud
|
description: A Helm chart for Nextcloud MCP Server - enables AI assistants to interact with Nextcloud
|
||||||
type: application
|
type: application
|
||||||
version: 0.29.0
|
version: 0.29.2
|
||||||
appVersion: "0.29.0"
|
appVersion: "0.29.2"
|
||||||
keywords:
|
keywords:
|
||||||
- nextcloud
|
- nextcloud
|
||||||
- mcp
|
- mcp
|
||||||
@@ -23,10 +23,10 @@ sources:
|
|||||||
icon: https://raw.githubusercontent.com/nextcloud/server/master/core/img/logo/logo.svg
|
icon: https://raw.githubusercontent.com/nextcloud/server/master/core/img/logo/logo.svg
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: qdrant
|
- name: qdrant
|
||||||
version: "0.9.0"
|
version: "1.15.5"
|
||||||
repository: https://qdrant.github.io/qdrant-helm
|
repository: https://qdrant.github.io/qdrant-helm
|
||||||
condition: qdrant.networkMode.deploySubchart
|
condition: qdrant.networkMode.deploySubchart
|
||||||
- name: ollama
|
- name: ollama
|
||||||
version: "1.33.0"
|
version: "1.34.0"
|
||||||
repository: https://otwld.github.io/ollama-helm
|
repository: https://otwld.github.io/ollama-helm
|
||||||
condition: ollama.enabled
|
condition: ollama.enabled
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ metadata:
|
|||||||
labels:
|
labels:
|
||||||
{{- include "nextcloud-mcp-server.labels" . | nindent 4 }}
|
{{- include "nextcloud-mcp-server.labels" . | nindent 4 }}
|
||||||
spec:
|
spec:
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
{{- if not .Values.autoscaling.enabled }}
|
{{- if not .Values.autoscaling.enabled }}
|
||||||
replicas: {{ .Values.replicaCount }}
|
replicas: {{ .Values.replicaCount }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ from nextcloud_mcp_server.context import get_client as get_nextcloud_client
|
|||||||
from nextcloud_mcp_server.document_processors import get_registry
|
from nextcloud_mcp_server.document_processors import get_registry
|
||||||
from nextcloud_mcp_server.observability import (
|
from nextcloud_mcp_server.observability import (
|
||||||
ObservabilityMiddleware,
|
ObservabilityMiddleware,
|
||||||
get_metrics_handler,
|
|
||||||
get_uvicorn_logging_config,
|
get_uvicorn_logging_config,
|
||||||
setup_metrics,
|
setup_metrics,
|
||||||
setup_tracing,
|
setup_tracing,
|
||||||
@@ -786,8 +785,10 @@ def get_app(transport: str = "sse", enabled_apps: list[str] | None = None):
|
|||||||
|
|
||||||
# Setup Prometheus metrics (always enabled by default)
|
# Setup Prometheus metrics (always enabled by default)
|
||||||
if settings.metrics_enabled:
|
if settings.metrics_enabled:
|
||||||
setup_metrics()
|
setup_metrics(port=settings.metrics_port)
|
||||||
logger.info("Prometheus metrics enabled")
|
logger.info(
|
||||||
|
f"Prometheus metrics enabled on dedicated port {settings.metrics_port}"
|
||||||
|
)
|
||||||
|
|
||||||
# Setup OpenTelemetry tracing (optional)
|
# Setup OpenTelemetry tracing (optional)
|
||||||
if settings.tracing_enabled:
|
if settings.tracing_enabled:
|
||||||
@@ -1212,12 +1213,8 @@ def get_app(transport: str = "sse", enabled_apps: list[str] | None = None):
|
|||||||
routes.append(Route("/health/ready", health_ready, methods=["GET"]))
|
routes.append(Route("/health/ready", health_ready, methods=["GET"]))
|
||||||
logger.info("Health check endpoints enabled: /health/live, /health/ready")
|
logger.info("Health check endpoints enabled: /health/live, /health/ready")
|
||||||
|
|
||||||
# Add metrics endpoint (if metrics are enabled)
|
# Note: Metrics endpoint is NOT exposed on main HTTP port for security reasons.
|
||||||
if settings.metrics_enabled:
|
# Metrics are served on dedicated port via setup_metrics() (default: 9090)
|
||||||
routes.append(Route("/metrics", get_metrics_handler, methods=["GET"]))
|
|
||||||
logger.info(
|
|
||||||
f"Prometheus metrics endpoint enabled: /metrics (port: {settings.metrics_port if hasattr(settings, 'metrics_port') else 'default'})"
|
|
||||||
)
|
|
||||||
|
|
||||||
if oauth_enabled:
|
if oauth_enabled:
|
||||||
# Import OAuth routes (ADR-004 Progressive Consent)
|
# Import OAuth routes (ADR-004 Progressive Consent)
|
||||||
|
|||||||
@@ -18,10 +18,7 @@ from nextcloud_mcp_server.observability.logging_config import (
|
|||||||
get_uvicorn_logging_config,
|
get_uvicorn_logging_config,
|
||||||
setup_logging,
|
setup_logging,
|
||||||
)
|
)
|
||||||
from nextcloud_mcp_server.observability.metrics import (
|
from nextcloud_mcp_server.observability.metrics import setup_metrics
|
||||||
get_metrics_handler,
|
|
||||||
setup_metrics,
|
|
||||||
)
|
|
||||||
from nextcloud_mcp_server.observability.middleware import ObservabilityMiddleware
|
from nextcloud_mcp_server.observability.middleware import ObservabilityMiddleware
|
||||||
from nextcloud_mcp_server.observability.tracing import setup_tracing
|
from nextcloud_mcp_server.observability.tracing import setup_tracing
|
||||||
|
|
||||||
@@ -30,6 +27,5 @@ __all__ = [
|
|||||||
"get_uvicorn_logging_config",
|
"get_uvicorn_logging_config",
|
||||||
"setup_metrics",
|
"setup_metrics",
|
||||||
"setup_tracing",
|
"setup_tracing",
|
||||||
"get_metrics_handler",
|
|
||||||
"ObservabilityMiddleware",
|
"ObservabilityMiddleware",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -17,15 +17,11 @@ and resource usage. Metrics are organized by category:
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from prometheus_client import (
|
from prometheus_client import (
|
||||||
CONTENT_TYPE_LATEST,
|
|
||||||
REGISTRY,
|
|
||||||
Counter,
|
Counter,
|
||||||
Gauge,
|
Gauge,
|
||||||
Histogram,
|
Histogram,
|
||||||
generate_latest,
|
start_http_server,
|
||||||
)
|
)
|
||||||
from starlette.requests import Request
|
|
||||||
from starlette.responses import Response
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -220,29 +216,32 @@ dependency_check_duration_seconds = Histogram(
|
|||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
|
|
||||||
def setup_metrics() -> None:
|
def setup_metrics(port: int = 9090) -> None:
|
||||||
"""
|
"""
|
||||||
Initialize Prometheus metrics collection.
|
Initialize Prometheus metrics collection and start HTTP server.
|
||||||
|
|
||||||
This function should be called once during application startup.
|
Starts a dedicated HTTP server on the specified port to serve metrics.
|
||||||
It currently doesn't require any initialization beyond module-level
|
This server runs in a separate thread and is isolated from the main application.
|
||||||
metric definitions, but is provided for consistency and future extensibility.
|
|
||||||
"""
|
|
||||||
logger.info("Prometheus metrics initialized")
|
|
||||||
|
|
||||||
|
|
||||||
async def get_metrics_handler(request: Request) -> Response:
|
|
||||||
"""
|
|
||||||
HTTP handler for the /metrics endpoint.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
request: Starlette request object (unused, but required by signature)
|
port: Port to serve metrics on (default: 9090)
|
||||||
|
|
||||||
Returns:
|
Note:
|
||||||
Response containing Prometheus metrics in text format
|
Metrics endpoint (/metrics) is ONLY accessible on this dedicated port,
|
||||||
|
not on the main application HTTP port. This is a security best practice
|
||||||
|
to prevent external exposure of metrics.
|
||||||
"""
|
"""
|
||||||
metrics_data = generate_latest(REGISTRY)
|
try:
|
||||||
return Response(content=metrics_data, media_type=CONTENT_TYPE_LATEST)
|
start_http_server(port)
|
||||||
|
logger.info(f"Prometheus metrics server started on port {port}")
|
||||||
|
except OSError as e:
|
||||||
|
if "Address already in use" in str(e):
|
||||||
|
logger.warning(
|
||||||
|
f"Metrics port {port} already in use (metrics server likely already running)"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.error(f"Failed to start metrics server on port {port}: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "nextcloud-mcp-server"
|
name = "nextcloud-mcp-server"
|
||||||
version = "0.29.0"
|
version = "0.29.2"
|
||||||
description = "Model Context Protocol (MCP) server for Nextcloud integration - enables AI assistants to interact with Nextcloud data"
|
description = "Model Context Protocol (MCP) server for Nextcloud integration - enables AI assistants to interact with Nextcloud data"
|
||||||
authors = [
|
authors = [
|
||||||
{name = "Chris Coutinho", email = "chris@coutinho.io"}
|
{name = "Chris Coutinho", email = "chris@coutinho.io"}
|
||||||
|
|||||||
@@ -1059,7 +1059,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nextcloud-mcp-server"
|
name = "nextcloud-mcp-server"
|
||||||
version = "0.29.0"
|
version = "0.29.2"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "aiosqlite" },
|
{ name = "aiosqlite" },
|
||||||
|
|||||||
Reference in New Issue
Block a user