Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 84106a059e | |||
| c1c5a61952 |
@@ -1,3 +1,9 @@
|
||||
## v0.12.0 (2025-09-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- **server**: Add support for `streamable-http` transport type
|
||||
|
||||
## v0.11.1 (2025-09-11)
|
||||
|
||||
### Fix
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ services:
|
||||
|
||||
mcp:
|
||||
build: .
|
||||
command: ["--host", "0.0.0.0"]
|
||||
command: ["--host", "0.0.0.0", "--transport", "streamable-http"]
|
||||
ports:
|
||||
- 8000:8000
|
||||
environment:
|
||||
|
||||
@@ -2,7 +2,7 @@ import click
|
||||
import logging
|
||||
import uvicorn
|
||||
from collections.abc import AsyncIterator
|
||||
from contextlib import asynccontextmanager
|
||||
from contextlib import asynccontextmanager, AsyncExitStack
|
||||
from dataclasses import dataclass
|
||||
|
||||
from starlette.applications import Starlette
|
||||
@@ -83,9 +83,19 @@ def get_app(transport: str = "sse", enabled_apps: list[str] | None = None):
|
||||
f"Unknown app: {app_name}. Available apps: {list(available_apps.keys())}"
|
||||
)
|
||||
|
||||
mcp_app = mcp.sse_app() if transport == "sse" else mcp.streamable_http_app()
|
||||
if transport == "sse":
|
||||
mcp_app = mcp.sse_app()
|
||||
lifespan = None
|
||||
else:
|
||||
mcp_app = mcp.streamable_http_app()
|
||||
|
||||
app = Starlette(routes=[Mount("/", app=mcp_app)])
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: Starlette):
|
||||
async with AsyncExitStack() as stack:
|
||||
await stack.enter_async_context(mcp.session_manager.run())
|
||||
yield
|
||||
|
||||
app = Starlette(routes=[Mount("/", app=mcp_app)], lifespan=lifespan)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "nextcloud-mcp-server"
|
||||
version = "0.11.1"
|
||||
version = "0.12.0"
|
||||
description = ""
|
||||
authors = [
|
||||
{name = "Chris Coutinho",email = "chris@coutinho.io"}
|
||||
|
||||
+10
-10
@@ -6,7 +6,7 @@ from typing import Any, AsyncGenerator
|
||||
import pytest
|
||||
from httpx import HTTPStatusError
|
||||
from mcp import ClientSession
|
||||
from mcp.client.sse import sse_client
|
||||
from mcp.client.streamable_http import streamablehttp_client
|
||||
|
||||
from nextcloud_mcp_server.client import NextcloudClient
|
||||
|
||||
@@ -39,18 +39,18 @@ async def nc_client() -> AsyncGenerator[NextcloudClient, Any]:
|
||||
await client.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@pytest.fixture(scope="session")
|
||||
async def nc_mcp_client() -> AsyncGenerator[ClientSession, Any]:
|
||||
"""
|
||||
Fixture to create an MCP client session for integration tests.
|
||||
Fixture to create an MCP client session for integration tests using streamable-http.
|
||||
"""
|
||||
logger.info("Creating SSE client")
|
||||
sse_context = sse_client(url="http://127.0.0.1:8000/sse")
|
||||
logger.info("Creating Streamable HTTP client")
|
||||
streamable_context = streamablehttp_client("http://127.0.0.1:8000/mcp")
|
||||
session_context = None
|
||||
|
||||
try:
|
||||
read, write = await sse_context.__aenter__()
|
||||
session_context = ClientSession(read, write)
|
||||
read_stream, write_stream, _ = await streamable_context.__aenter__()
|
||||
session_context = ClientSession(read_stream, write_stream)
|
||||
session = await session_context.__aenter__()
|
||||
await session.initialize()
|
||||
logger.info("MCP client session initialized successfully")
|
||||
@@ -71,14 +71,14 @@ async def nc_mcp_client() -> AsyncGenerator[ClientSession, Any]:
|
||||
logger.warning(f"Error closing session: {e}")
|
||||
|
||||
try:
|
||||
await sse_context.__aexit__(None, None, None)
|
||||
await streamable_context.__aexit__(None, None, None)
|
||||
except RuntimeError as e:
|
||||
if "cancel scope" in str(e):
|
||||
logger.debug(f"Ignoring cancel scope teardown issue: {e}")
|
||||
else:
|
||||
logger.warning(f"Error closing SSE client: {e}")
|
||||
logger.warning(f"Error closing streamable HTTP client: {e}")
|
||||
except Exception as e:
|
||||
logger.warning(f"Error closing SSE client: {e}")
|
||||
logger.warning(f"Error closing streamable HTTP client: {e}")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
Reference in New Issue
Block a user