Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a96e430e56 | |||
| 758cd5dbfb | |||
| f36f92120c | |||
| b96657c935 | |||
| b174e7f8fb | |||
| 7a7ed79d56 | |||
| 7e7d861797 | |||
| 682923dcc8 | |||
| b1a756145e | |||
| 00e72d24a6 |
@@ -4,3 +4,6 @@
|
|||||||
[submodule "third_party/oidc"]
|
[submodule "third_party/oidc"]
|
||||||
path = third_party/oidc
|
path = third_party/oidc
|
||||||
url = https://github.com/cbcoutinho/oidc
|
url = https://github.com/cbcoutinho/oidc
|
||||||
|
[submodule "third_party/notes"]
|
||||||
|
path = third_party/notes
|
||||||
|
url = https://github.com/cbcoutinho/notes
|
||||||
|
|||||||
@@ -1,3 +1,40 @@
|
|||||||
|
## v0.36.0 (2025-11-15)
|
||||||
|
|
||||||
|
### BREAKING CHANGE
|
||||||
|
|
||||||
|
- Search algorithms now require Qdrant to be populated.
|
||||||
|
Vector sync must be enabled and documents indexed for search to work.
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- Normalize hybrid search RRF scores to 0-1 range
|
||||||
|
- Enhance vector visualization UI and parallelize search verification
|
||||||
|
- Add Vector Viz tab to app home page
|
||||||
|
- Add vector visualization pane with multi-select document types
|
||||||
|
- Implement custom PCA to remove sklearn dependency
|
||||||
|
- Add multi-document Protocol with cross-app search support
|
||||||
|
- Update nc_semantic_search tool with algorithm selection
|
||||||
|
- Implement unified search algorithm module
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- Reorder tabs and fix viz pane session access
|
||||||
|
|
||||||
|
### Refactor
|
||||||
|
|
||||||
|
- Optimize Nextcloud access verification with centralized filtering
|
||||||
|
- Make all search algorithms query Qdrant payload, not Nextcloud
|
||||||
|
|
||||||
|
### Perf
|
||||||
|
|
||||||
|
- Exclude vector-sync status polling from distributed tracing
|
||||||
|
|
||||||
|
## v0.35.0 (2025-11-15)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- Enable SSE transport for mcp service and update test fixtures
|
||||||
|
|
||||||
## v0.34.2 (2025-11-13)
|
## v0.34.2 (2025-11-13)
|
||||||
|
|
||||||
### Fix
|
### Fix
|
||||||
|
|||||||
@@ -2,4 +2,30 @@
|
|||||||
|
|
||||||
set -euox pipefail
|
set -euox pipefail
|
||||||
|
|
||||||
php /var/www/html/occ app:enable notes
|
echo "Installing and configuring notes app for testing..."
|
||||||
|
|
||||||
|
# Check if development notes app is mounted at /opt/apps/notes
|
||||||
|
if [ -d /opt/apps/notes ]; then
|
||||||
|
echo "Development notes app found at /opt/apps/notes"
|
||||||
|
|
||||||
|
# Remove any existing notes app in apps (from app store or old symlink)
|
||||||
|
if [ -e /var/www/html/apps/notes ]; then
|
||||||
|
echo "Removing existing notes in apps..."
|
||||||
|
rm -rf /var/www/html/apps/notes
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create symlink from apps to the mounted development version
|
||||||
|
# Per Nextcloud docs: apps outside server root need symlinks in server root
|
||||||
|
echo "Creating symlink: apps/notes -> /opt/apps/notes"
|
||||||
|
ln -sf /opt/apps/notes /var/www/html/apps/notes
|
||||||
|
|
||||||
|
echo "Enabling notes app from /opt/apps (development mode via symlink)"
|
||||||
|
php /var/www/html/occ app:enable notes
|
||||||
|
elif [ -d /var/www/html/apps/notes ]; then
|
||||||
|
echo "notes app directory found in apps (already installed)"
|
||||||
|
php /var/www/html/occ app:enable notes
|
||||||
|
else
|
||||||
|
echo "notes app not found, installing from app store..."
|
||||||
|
php /var/www/html/occ app:install notes
|
||||||
|
php /var/www/html/occ app:enable notes
|
||||||
|
fi
|
||||||
|
|||||||
@@ -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.34.2
|
version: 0.36.0
|
||||||
appVersion: "0.34.2"
|
appVersion: "0.36.0"
|
||||||
keywords:
|
keywords:
|
||||||
- nextcloud
|
- nextcloud
|
||||||
- mcp
|
- mcp
|
||||||
|
|||||||
+12
-1
@@ -69,7 +69,6 @@ services:
|
|||||||
|
|
||||||
mcp:
|
mcp:
|
||||||
build: .
|
build: .
|
||||||
command: ["--transport", "streamable-http"]
|
|
||||||
restart: always
|
restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
app:
|
app:
|
||||||
@@ -241,6 +240,17 @@ services:
|
|||||||
profiles:
|
profiles:
|
||||||
- qdrant
|
- qdrant
|
||||||
|
|
||||||
|
open-webui:
|
||||||
|
image: ghcr.io/open-webui/open-webui:main
|
||||||
|
environment:
|
||||||
|
- OLLAMA_BASE_URL=https://ollama.internal.coutinho.io
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:3000:8080
|
||||||
|
volumes:
|
||||||
|
- open-webui:/app/backend/data
|
||||||
|
profiles:
|
||||||
|
- open-webui
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
nextcloud:
|
nextcloud:
|
||||||
db:
|
db:
|
||||||
@@ -250,3 +260,4 @@ volumes:
|
|||||||
keycloak-oauth-storage:
|
keycloak-oauth-storage:
|
||||||
qdrant-data:
|
qdrant-data:
|
||||||
mcp-data:
|
mcp-data:
|
||||||
|
open-webui:
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "nextcloud-mcp-server"
|
name = "nextcloud-mcp-server"
|
||||||
version = "0.34.2"
|
version = "0.36.0"
|
||||||
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"}
|
||||||
|
|||||||
+51
-3
@@ -9,6 +9,7 @@ import pytest
|
|||||||
from httpx import HTTPStatusError
|
from httpx import HTTPStatusError
|
||||||
from mcp import ClientSession
|
from mcp import ClientSession
|
||||||
from mcp.client.session import RequestContext
|
from mcp.client.session import RequestContext
|
||||||
|
from mcp.client.sse import sse_client
|
||||||
from mcp.client.streamable_http import streamablehttp_client
|
from mcp.client.streamable_http import streamablehttp_client
|
||||||
from mcp.types import ElicitRequestParams, ElicitResult, ErrorData
|
from mcp.types import ElicitRequestParams, ElicitResult, ErrorData
|
||||||
|
|
||||||
@@ -165,6 +166,51 @@ async def create_mcp_client_session(
|
|||||||
logger.debug(f"{client_name} client session cleaned up successfully")
|
logger.debug(f"{client_name} client session cleaned up successfully")
|
||||||
|
|
||||||
|
|
||||||
|
async def create_mcp_client_session_sse(
|
||||||
|
url: str,
|
||||||
|
token: str | None = None,
|
||||||
|
client_name: str = "MCP",
|
||||||
|
elicitation_callback: Any = None,
|
||||||
|
) -> AsyncGenerator[ClientSession, Any]:
|
||||||
|
"""
|
||||||
|
Factory function to create an MCP client session using SSE transport.
|
||||||
|
|
||||||
|
Similar to create_mcp_client_session but uses SSE transport instead of streamable-http.
|
||||||
|
Uses native async context managers to ensure correct LIFO cleanup order.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
url: MCP server URL (e.g., "http://localhost:8000/sse")
|
||||||
|
token: Optional OAuth access token for Bearer authentication
|
||||||
|
client_name: Client name for logging (e.g., "Basic MCP (SSE)")
|
||||||
|
elicitation_callback: Optional callback for handling elicitation requests
|
||||||
|
|
||||||
|
Yields:
|
||||||
|
Initialized MCP ClientSession
|
||||||
|
|
||||||
|
Note:
|
||||||
|
SSE transport is being deprecated in favor of streamable-http.
|
||||||
|
This function exists for compatibility testing only.
|
||||||
|
"""
|
||||||
|
logger.info(f"Creating SSE client for {client_name}")
|
||||||
|
|
||||||
|
# Prepare headers with OAuth token if provided
|
||||||
|
headers = {"Authorization": f"Bearer {token}"} if token else None
|
||||||
|
|
||||||
|
# Use native async with - Python ensures LIFO cleanup
|
||||||
|
# Cleanup order will be: ClientSession.__aexit__ -> sse_client.__aexit__
|
||||||
|
# Note: sse_client yields only (read_stream, write_stream), not 3 values like streamablehttp_client
|
||||||
|
async with sse_client(url, headers=headers) as (read_stream, write_stream):
|
||||||
|
async with ClientSession(
|
||||||
|
read_stream, write_stream, elicitation_callback=elicitation_callback
|
||||||
|
) as session:
|
||||||
|
await session.initialize()
|
||||||
|
logger.info(f"{client_name} client session initialized successfully")
|
||||||
|
yield session
|
||||||
|
|
||||||
|
# Cleanup happens automatically in LIFO order - no exception suppression needed
|
||||||
|
logger.debug(f"{client_name} client session cleaned up successfully")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
async def nc_client(anyio_backend) -> AsyncGenerator[NextcloudClient, Any]:
|
async def nc_client(anyio_backend) -> AsyncGenerator[NextcloudClient, Any]:
|
||||||
"""
|
"""
|
||||||
@@ -203,12 +249,14 @@ async def nc_client(anyio_backend) -> AsyncGenerator[NextcloudClient, Any]:
|
|||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
async def nc_mcp_client(anyio_backend) -> AsyncGenerator[ClientSession, Any]:
|
async def nc_mcp_client(anyio_backend) -> AsyncGenerator[ClientSession, Any]:
|
||||||
"""
|
"""
|
||||||
Fixture to create an MCP client session for integration tests using streamable-http.
|
Fixture to create an MCP client session for integration tests using SSE transport.
|
||||||
|
|
||||||
Uses anyio pytest plugin for proper async fixture handling.
|
Uses anyio pytest plugin for proper async fixture handling.
|
||||||
|
|
||||||
|
Note: SSE transport is being deprecated. This fixture uses SSE for compatibility testing.
|
||||||
"""
|
"""
|
||||||
async for session in create_mcp_client_session(
|
async for session in create_mcp_client_session_sse(
|
||||||
url="http://localhost:8000/mcp", client_name="Basic MCP"
|
url="http://localhost:8000/sse", client_name="Basic MCP (SSE)"
|
||||||
):
|
):
|
||||||
yield session
|
yield session
|
||||||
|
|
||||||
|
|||||||
+1
Submodule third_party/notes added at 0d6517e999
Vendored
+1
-1
Submodule third_party/oidc updated: 9616294911...e83dabbac1
@@ -1053,7 +1053,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nextcloud-mcp-server"
|
name = "nextcloud-mcp-server"
|
||||||
version = "0.34.2"
|
version = "0.36.0"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "aiosqlite" },
|
{ name = "aiosqlite" },
|
||||||
|
|||||||
Reference in New Issue
Block a user