mcp-use 1.3.12__py3-none-any.whl → 1.3.13__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.

Potentially problematic release.


This version of mcp-use might be problematic. Click here for more details.

Files changed (101) hide show
  1. mcp_use/__init__.py +1 -1
  2. mcp_use/adapters/.deprecated +0 -0
  3. mcp_use/adapters/__init__.py +18 -7
  4. mcp_use/adapters/base.py +12 -185
  5. mcp_use/adapters/langchain_adapter.py +12 -219
  6. mcp_use/agents/adapters/__init__.py +10 -0
  7. mcp_use/agents/adapters/base.py +193 -0
  8. mcp_use/agents/adapters/langchain_adapter.py +228 -0
  9. mcp_use/agents/base.py +1 -1
  10. mcp_use/agents/managers/__init__.py +19 -0
  11. mcp_use/agents/managers/base.py +36 -0
  12. mcp_use/agents/managers/server_manager.py +131 -0
  13. mcp_use/agents/managers/tools/__init__.py +15 -0
  14. mcp_use/agents/managers/tools/base_tool.py +19 -0
  15. mcp_use/agents/managers/tools/connect_server.py +69 -0
  16. mcp_use/agents/managers/tools/disconnect_server.py +43 -0
  17. mcp_use/agents/managers/tools/get_active_server.py +29 -0
  18. mcp_use/agents/managers/tools/list_servers_tool.py +53 -0
  19. mcp_use/agents/managers/tools/search_tools.py +328 -0
  20. mcp_use/agents/mcpagent.py +16 -14
  21. mcp_use/agents/remote.py +14 -1
  22. mcp_use/auth/.deprecated +0 -0
  23. mcp_use/auth/__init__.py +19 -4
  24. mcp_use/auth/bearer.py +11 -12
  25. mcp_use/auth/oauth.py +11 -620
  26. mcp_use/auth/oauth_callback.py +16 -207
  27. mcp_use/client/__init__.py +1 -0
  28. mcp_use/client/auth/__init__.py +6 -0
  29. mcp_use/client/auth/bearer.py +23 -0
  30. mcp_use/client/auth/oauth.py +629 -0
  31. mcp_use/client/auth/oauth_callback.py +214 -0
  32. mcp_use/client/client.py +356 -0
  33. mcp_use/client/config.py +106 -0
  34. mcp_use/client/connectors/__init__.py +20 -0
  35. mcp_use/client/connectors/base.py +470 -0
  36. mcp_use/client/connectors/http.py +304 -0
  37. mcp_use/client/connectors/sandbox.py +332 -0
  38. mcp_use/client/connectors/stdio.py +109 -0
  39. mcp_use/client/connectors/utils.py +13 -0
  40. mcp_use/client/connectors/websocket.py +257 -0
  41. mcp_use/client/exceptions.py +31 -0
  42. mcp_use/client/middleware/__init__.py +50 -0
  43. mcp_use/client/middleware/logging.py +31 -0
  44. mcp_use/client/middleware/metrics.py +314 -0
  45. mcp_use/client/middleware/middleware.py +266 -0
  46. mcp_use/client/session.py +162 -0
  47. mcp_use/client/task_managers/__init__.py +20 -0
  48. mcp_use/client/task_managers/base.py +145 -0
  49. mcp_use/client/task_managers/sse.py +84 -0
  50. mcp_use/client/task_managers/stdio.py +69 -0
  51. mcp_use/client/task_managers/streamable_http.py +86 -0
  52. mcp_use/client/task_managers/websocket.py +68 -0
  53. mcp_use/client.py +12 -344
  54. mcp_use/config.py +20 -97
  55. mcp_use/connectors/.deprecated +0 -0
  56. mcp_use/connectors/__init__.py +46 -20
  57. mcp_use/connectors/base.py +12 -455
  58. mcp_use/connectors/http.py +13 -300
  59. mcp_use/connectors/sandbox.py +13 -306
  60. mcp_use/connectors/stdio.py +13 -104
  61. mcp_use/connectors/utils.py +15 -8
  62. mcp_use/connectors/websocket.py +13 -252
  63. mcp_use/exceptions.py +33 -18
  64. mcp_use/managers/.deprecated +0 -0
  65. mcp_use/managers/__init__.py +56 -17
  66. mcp_use/managers/base.py +13 -31
  67. mcp_use/managers/server_manager.py +13 -119
  68. mcp_use/managers/tools/__init__.py +45 -15
  69. mcp_use/managers/tools/base_tool.py +5 -16
  70. mcp_use/managers/tools/connect_server.py +5 -67
  71. mcp_use/managers/tools/disconnect_server.py +5 -41
  72. mcp_use/managers/tools/get_active_server.py +5 -26
  73. mcp_use/managers/tools/list_servers_tool.py +5 -51
  74. mcp_use/managers/tools/search_tools.py +17 -321
  75. mcp_use/middleware/.deprecated +0 -0
  76. mcp_use/middleware/__init__.py +89 -50
  77. mcp_use/middleware/logging.py +14 -26
  78. mcp_use/middleware/metrics.py +30 -303
  79. mcp_use/middleware/middleware.py +39 -246
  80. mcp_use/session.py +13 -149
  81. mcp_use/task_managers/.deprecated +0 -0
  82. mcp_use/task_managers/__init__.py +48 -20
  83. mcp_use/task_managers/base.py +13 -140
  84. mcp_use/task_managers/sse.py +13 -79
  85. mcp_use/task_managers/stdio.py +13 -64
  86. mcp_use/task_managers/streamable_http.py +15 -81
  87. mcp_use/task_managers/websocket.py +13 -63
  88. mcp_use/telemetry/events.py +58 -0
  89. mcp_use/telemetry/telemetry.py +71 -1
  90. mcp_use/types/.deprecated +0 -0
  91. mcp_use/types/sandbox.py +13 -18
  92. {mcp_use-1.3.12.dist-info → mcp_use-1.3.13.dist-info}/METADATA +59 -34
  93. mcp_use-1.3.13.dist-info/RECORD +109 -0
  94. mcp_use-1.3.12.dist-info/RECORD +0 -64
  95. mcp_use-1.3.12.dist-info/licenses/LICENSE +0 -21
  96. /mcp_use/{observability → agents/observability}/__init__.py +0 -0
  97. /mcp_use/{observability → agents/observability}/callbacks_manager.py +0 -0
  98. /mcp_use/{observability → agents/observability}/laminar.py +0 -0
  99. /mcp_use/{observability → agents/observability}/langfuse.py +0 -0
  100. {mcp_use-1.3.12.dist-info → mcp_use-1.3.13.dist-info}/WHEEL +0 -0
  101. {mcp_use-1.3.12.dist-info → mcp_use-1.3.13.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,109 @@
1
+ """
2
+ StdIO connector for MCP implementations.
3
+
4
+ This module provides a connector for communicating with MCP implementations
5
+ through the standard input/output streams.
6
+ """
7
+
8
+ import sys
9
+
10
+ from mcp import ClientSession, StdioServerParameters
11
+ from mcp.client.session import ElicitationFnT, LoggingFnT, MessageHandlerFnT, SamplingFnT
12
+
13
+ from mcp_use.client.connectors.base import BaseConnector
14
+ from mcp_use.client.middleware import CallbackClientSession, Middleware
15
+ from mcp_use.client.task_managers import StdioConnectionManager
16
+ from mcp_use.logging import logger
17
+
18
+
19
+ class StdioConnector(BaseConnector):
20
+ """Connector for MCP implementations using stdio transport.
21
+
22
+ This connector uses the stdio transport to communicate with MCP implementations
23
+ that are executed as child processes. It uses a connection manager to handle
24
+ the proper lifecycle management of the stdio client.
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ command: str = "npx",
30
+ args: list[str] | None = None,
31
+ env: dict[str, str] | None = None,
32
+ errlog=sys.stderr,
33
+ sampling_callback: SamplingFnT | None = None,
34
+ elicitation_callback: ElicitationFnT | None = None,
35
+ message_handler: MessageHandlerFnT | None = None,
36
+ logging_callback: LoggingFnT | None = None,
37
+ middleware: list[Middleware] | None = None,
38
+ ):
39
+ """Initialize a new stdio connector.
40
+
41
+ Args:
42
+ command: The command to execute.
43
+ args: Optional command line arguments.
44
+ env: Optional environment variables.
45
+ errlog: Stream to write error output to.
46
+ sampling_callback: Optional callback to sample the client.
47
+ elicitation_callback: Optional callback to elicit the client.
48
+ """
49
+ super().__init__(
50
+ sampling_callback=sampling_callback,
51
+ elicitation_callback=elicitation_callback,
52
+ message_handler=message_handler,
53
+ logging_callback=logging_callback,
54
+ middleware=middleware,
55
+ )
56
+ self.command = command
57
+ self.args = args or [] # Ensure args is never None
58
+ self.env = env
59
+ self.errlog = errlog
60
+
61
+ async def connect(self) -> None:
62
+ """Establish a connection to the MCP implementation."""
63
+ if self._connected:
64
+ logger.debug("Already connected to MCP implementation")
65
+ return
66
+
67
+ logger.debug(f"Connecting to MCP implementation: {self.command}")
68
+ try:
69
+ # Create server parameters
70
+ server_params = StdioServerParameters(command=self.command, args=self.args, env=self.env)
71
+
72
+ # Create and start the connection manager
73
+ self._connection_manager = StdioConnectionManager(server_params, self.errlog)
74
+ read_stream, write_stream = await self._connection_manager.start()
75
+
76
+ # Create the client session
77
+ raw_client_session = ClientSession(
78
+ read_stream,
79
+ write_stream,
80
+ sampling_callback=self.sampling_callback,
81
+ elicitation_callback=self.elicitation_callback,
82
+ message_handler=self._internal_message_handler,
83
+ logging_callback=self.logging_callback,
84
+ client_info=self.client_info,
85
+ )
86
+ await raw_client_session.__aenter__()
87
+
88
+ # Wrap with middleware
89
+ self.client_session = CallbackClientSession(
90
+ raw_client_session, self.public_identifier, self.middleware_manager
91
+ )
92
+
93
+ # Mark as connected
94
+ self._connected = True
95
+ logger.debug(f"Successfully connected to MCP implementation: {self.command}")
96
+
97
+ except Exception as e:
98
+ logger.error(f"Failed to connect to MCP implementation: {e}")
99
+
100
+ # Clean up any resources if connection failed
101
+ await self._cleanup_resources()
102
+
103
+ # Re-raise the original exception
104
+ raise
105
+
106
+ @property
107
+ def public_identifier(self) -> str:
108
+ """Get the identifier for the connector."""
109
+ return f"stdio:{self.command} {' '.join(self.args)}"
@@ -0,0 +1,13 @@
1
+ from typing import Any
2
+
3
+
4
+ def is_stdio_server(server_config: dict[str, Any]) -> bool:
5
+ """Check if the server configuration is for a stdio server.
6
+
7
+ Args:
8
+ server_config: The server configuration section
9
+
10
+ Returns:
11
+ True if the server is a stdio server, False otherwise
12
+ """
13
+ return "command" in server_config and "args" in server_config
@@ -0,0 +1,257 @@
1
+ """
2
+ WebSocket connector for MCP implementations.
3
+
4
+ This module provides a connector for communicating with MCP implementations
5
+ through WebSocket connections.
6
+ """
7
+
8
+ import asyncio
9
+ import json
10
+ import uuid
11
+ from typing import Any
12
+
13
+ import httpx
14
+ from mcp.types import Tool
15
+ from websockets import ClientConnection
16
+
17
+ from mcp_use.client.connectors.base import BaseConnector
18
+ from mcp_use.client.task_managers import ConnectionManager, WebSocketConnectionManager
19
+ from mcp_use.logging import logger
20
+
21
+
22
+ class WebSocketConnector(BaseConnector):
23
+ """Connector for MCP implementations using WebSocket transport.
24
+
25
+ This connector uses WebSockets to communicate with remote MCP implementations,
26
+ using a connection manager to handle the proper lifecycle management.
27
+ """
28
+
29
+ def __init__(
30
+ self,
31
+ url: str,
32
+ headers: dict[str, str] | None = None,
33
+ auth: str | dict[str, Any] | httpx.Auth | None = None,
34
+ ):
35
+ """Initialize a new WebSocket connector.
36
+
37
+ Args:
38
+ url: The WebSocket URL to connect to.
39
+ headers: Optional additional headers.
40
+ auth: Authentication method - can be:
41
+ - A string token: Use Bearer token authentication
42
+ - A dict: Not supported for WebSocket (will log warning)
43
+ - An httpx.Auth object: Not supported for WebSocket (will log warning)
44
+ """
45
+ self.url = url
46
+ self.headers = headers or {}
47
+
48
+ # Handle authentication - WebSocket only supports bearer tokens
49
+ # An auth field it's not needed
50
+ if auth is not None:
51
+ if isinstance(auth, str):
52
+ self.headers["Authorization"] = f"Bearer {auth}"
53
+ else:
54
+ logger.warning("WebSocket connector only supports bearer token authentication")
55
+
56
+ self.ws: ClientConnection | None = None
57
+ self._connection_manager: ConnectionManager | None = None
58
+ self._receiver_task: asyncio.Task | None = None
59
+ self.pending_requests: dict[str, asyncio.Future] = {}
60
+ self._tools: list[Tool] | None = None
61
+ self._connected = False
62
+
63
+ async def connect(self) -> None:
64
+ """Establish a connection to the MCP implementation."""
65
+ if self._connected:
66
+ logger.debug("Already connected to MCP implementation")
67
+ return
68
+
69
+ logger.debug(f"Connecting to MCP implementation via WebSocket: {self.url}")
70
+ try:
71
+ # Create and start the connection manager
72
+ self._connection_manager = WebSocketConnectionManager(self.url, self.headers)
73
+ self.ws = await self._connection_manager.start()
74
+
75
+ # Start the message receiver task
76
+ self._receiver_task = asyncio.create_task(self._receive_messages(), name="websocket_receiver_task")
77
+
78
+ # Mark as connected
79
+ self._connected = True
80
+ logger.debug(f"Successfully connected to MCP implementation via WebSocket: {self.url}")
81
+
82
+ except Exception as e:
83
+ logger.error(f"Failed to connect to MCP implementation via WebSocket: {e}")
84
+
85
+ # Clean up any resources if connection failed
86
+ await self._cleanup_resources()
87
+
88
+ # Re-raise the original exception
89
+ raise
90
+
91
+ async def _receive_messages(self) -> None:
92
+ """Continuously receive and process messages from the WebSocket."""
93
+ if not self.ws:
94
+ raise RuntimeError("WebSocket is not connected")
95
+
96
+ try:
97
+ async for message in self.ws:
98
+ # Parse the message
99
+ data = json.loads(message)
100
+
101
+ # Check if this is a response to a pending request
102
+ request_id = data.get("id")
103
+ if request_id and request_id in self.pending_requests:
104
+ future = self.pending_requests.pop(request_id)
105
+ if "result" in data:
106
+ future.set_result(data["result"])
107
+ elif "error" in data:
108
+ future.set_exception(Exception(data["error"]))
109
+
110
+ logger.debug(f"Received response for request {request_id}")
111
+ else:
112
+ logger.debug(f"Received message: {data}")
113
+ except Exception as e:
114
+ logger.error(f"Error in WebSocket message receiver: {e}")
115
+ # If the websocket connection was closed or errored,
116
+ # reject all pending requests
117
+ for future in self.pending_requests.values():
118
+ if not future.done():
119
+ future.set_exception(e)
120
+
121
+ async def disconnect(self) -> None:
122
+ """Close the connection to the MCP implementation."""
123
+ if not self._connected:
124
+ logger.debug("Not connected to MCP implementation")
125
+ return
126
+
127
+ logger.debug("Disconnecting from MCP implementation")
128
+ await self._cleanup_resources()
129
+ self._connected = False
130
+ logger.debug("Disconnected from MCP implementation")
131
+
132
+ async def _cleanup_resources(self) -> None:
133
+ """Clean up all resources associated with this connector."""
134
+ errors = []
135
+
136
+ # First cancel the receiver task
137
+ if self._receiver_task and not self._receiver_task.done():
138
+ try:
139
+ logger.debug("Cancelling WebSocket receiver task")
140
+ self._receiver_task.cancel()
141
+ try:
142
+ await self._receiver_task
143
+ except asyncio.CancelledError:
144
+ logger.debug("WebSocket receiver task cancelled successfully")
145
+ except Exception as e:
146
+ logger.warning(f"Error during WebSocket receiver task cancellation: {e}")
147
+ except Exception as e:
148
+ error_msg = f"Error cancelling WebSocket receiver task: {e}"
149
+ logger.warning(error_msg)
150
+ errors.append(error_msg)
151
+ finally:
152
+ self._receiver_task = None
153
+
154
+ # Reject any pending requests
155
+ if self.pending_requests:
156
+ logger.debug(f"Rejecting {len(self.pending_requests)} pending requests")
157
+ for future in self.pending_requests.values():
158
+ if not future.done():
159
+ future.set_exception(ConnectionError("WebSocket disconnected"))
160
+ self.pending_requests.clear()
161
+
162
+ # Then stop the connection manager
163
+ if self._connection_manager:
164
+ try:
165
+ logger.debug("Stopping connection manager")
166
+ await self._connection_manager.stop()
167
+ except Exception as e:
168
+ error_msg = f"Error stopping connection manager: {e}"
169
+ logger.warning(error_msg)
170
+ errors.append(error_msg)
171
+ finally:
172
+ self._connection_manager = None
173
+ self.ws = None
174
+
175
+ # Reset tools
176
+ self._tools = None
177
+
178
+ if errors:
179
+ logger.warning(f"Encountered {len(errors)} errors during resource cleanup")
180
+
181
+ async def _send_request(self, method: str, params: dict[str, Any] | None = None) -> Any:
182
+ """Send a request and wait for a response."""
183
+ if not self.ws:
184
+ raise RuntimeError("WebSocket is not connected")
185
+
186
+ # Create a request ID
187
+ request_id = str(uuid.uuid4())
188
+
189
+ # Create a future to receive the response
190
+ future = asyncio.Future()
191
+ self.pending_requests[request_id] = future
192
+
193
+ # Send the request
194
+ await self.ws.send(json.dumps({"id": request_id, "method": method, "params": params or {}}))
195
+
196
+ logger.debug(f"Sent request {request_id} method: {method}")
197
+
198
+ # Wait for the response
199
+ try:
200
+ return await future
201
+ except Exception as e:
202
+ # Remove the request from pending requests
203
+ self.pending_requests.pop(request_id, None)
204
+ logger.error(f"Error waiting for response to request {request_id}: {e}")
205
+ raise
206
+
207
+ async def initialize(self) -> dict[str, Any]:
208
+ """Initialize the MCP session and return session information."""
209
+ logger.debug("Initializing MCP session")
210
+ result = await self._send_request("initialize")
211
+
212
+ # Get available tools
213
+ tools_result = await self.list_tools()
214
+ self._tools = [Tool(**tool) for tool in tools_result]
215
+
216
+ logger.debug(f"MCP session initialized with {len(self._tools)} tools")
217
+ return result
218
+
219
+ async def list_tools(self) -> list[dict[str, Any]]:
220
+ """List all available tools from the MCP implementation."""
221
+ logger.debug("Listing tools")
222
+ result = await self._send_request("tools/list")
223
+ return result.get("tools", [])
224
+
225
+ @property
226
+ def tools(self) -> list[Tool]:
227
+ """Get the list of available tools."""
228
+ if not self._tools:
229
+ raise RuntimeError("MCP client is not initialized")
230
+ return self._tools
231
+
232
+ async def call_tool(self, name: str, arguments: dict[str, Any]) -> Any:
233
+ """Call an MCP tool with the given arguments."""
234
+ logger.debug(f"Calling tool '{name}' with arguments: {arguments}")
235
+ return await self._send_request("tools/call", {"name": name, "arguments": arguments})
236
+
237
+ async def list_resources(self) -> list[dict[str, Any]]:
238
+ """List all available resources from the MCP implementation."""
239
+ logger.debug("Listing resources")
240
+ result = await self._send_request("resources/list")
241
+ return result
242
+
243
+ async def read_resource(self, uri: str) -> tuple[bytes, str]:
244
+ """Read a resource by URI."""
245
+ logger.debug(f"Reading resource: {uri}")
246
+ result = await self._send_request("resources/read", {"uri": uri})
247
+ return result.get("content", b""), result.get("mimeType", "")
248
+
249
+ async def request(self, method: str, params: dict[str, Any] | None = None) -> Any:
250
+ """Send a raw request to the MCP implementation."""
251
+ logger.debug(f"Sending request: {method} with params: {params}")
252
+ return await self._send_request(method, params)
253
+
254
+ @property
255
+ def public_identifier(self) -> str:
256
+ """Get the identifier for the connector."""
257
+ return f"websocket:{self.url}"
@@ -0,0 +1,31 @@
1
+ """MCP-use exceptions."""
2
+
3
+
4
+ class MCPError(Exception):
5
+ """Base exception for MCP-use."""
6
+
7
+ pass
8
+
9
+
10
+ class OAuthDiscoveryError(MCPError):
11
+ """OAuth discovery auth metadata error"""
12
+
13
+ pass
14
+
15
+
16
+ class OAuthAuthenticationError(MCPError):
17
+ """OAuth authentication-related errors"""
18
+
19
+ pass
20
+
21
+
22
+ class ConnectionError(MCPError):
23
+ """Connection-related errors."""
24
+
25
+ pass
26
+
27
+
28
+ class ConfigurationError(MCPError):
29
+ """Configuration-related errors."""
30
+
31
+ pass
@@ -0,0 +1,50 @@
1
+ """
2
+ Middleware package for MCP request interception and processing.
3
+
4
+ This package provides a flexible middleware system for intercepting MCP requests
5
+ and responses, enabling logging, metrics, caching, and custom processing.
6
+
7
+ The middleware system follows an Express.js-style pattern where middleware functions
8
+ receive a request context and a call_next function, allowing them to process both
9
+ incoming requests and outgoing responses.
10
+ """
11
+
12
+ # Core middleware implementation
13
+ # Default logging middleware
14
+ from .logging import default_logging_middleware
15
+
16
+ # Metrics middleware classes
17
+ from .metrics import (
18
+ CombinedAnalyticsMiddleware,
19
+ ErrorTrackingMiddleware,
20
+ MetricsMiddleware,
21
+ PerformanceMetricsMiddleware,
22
+ )
23
+
24
+ # Protocol types for type-safe middleware
25
+ from .middleware import (
26
+ CallbackClientSession,
27
+ MCPResponseContext,
28
+ Middleware,
29
+ MiddlewareContext,
30
+ MiddlewareManager,
31
+ NextFunctionT,
32
+ )
33
+
34
+ __all__ = [
35
+ # Core types and classes
36
+ "MiddlewareContext",
37
+ "MCPResponseContext",
38
+ "Middleware",
39
+ "MiddlewareManager",
40
+ "CallbackClientSession",
41
+ # Protocol types
42
+ "NextFunctionT",
43
+ # Default logging middleware
44
+ "default_logging_middleware",
45
+ # Metrics middleware
46
+ "MetricsMiddleware",
47
+ "PerformanceMetricsMiddleware",
48
+ "ErrorTrackingMiddleware",
49
+ "CombinedAnalyticsMiddleware",
50
+ ]
@@ -0,0 +1,31 @@
1
+ """
2
+ Default logging middleware for MCP requests.
3
+
4
+ Simple debug logging for all MCP requests and responses.
5
+ """
6
+
7
+ import time
8
+ from typing import Any
9
+
10
+ from mcp_use.client.middleware.middleware import Middleware, MiddlewareContext, NextFunctionT
11
+ from mcp_use.logging import logger
12
+
13
+
14
+ class LoggingMiddleware(Middleware):
15
+ """Default logging middleware that logs all MCP requests and responses with logger.debug."""
16
+
17
+ async def on_request(self, context: MiddlewareContext[Any], call_next: NextFunctionT) -> Any:
18
+ """Logs all MCP requests and responses with logger.debug."""
19
+ logger.debug(f"[{context.id}] {context.connection_id} -> {context.method}")
20
+ try:
21
+ result = await call_next(context)
22
+ duration = time.time() - context.timestamp
23
+ logger.debug(f"[{context.id}] {context.connection_id} <- {context.method} ({duration:.3f}s)")
24
+ return result
25
+ except Exception as e:
26
+ duration = time.time() - context.timestamp
27
+ logger.debug(f"[{context.id}] {context.connection_id} <- {context.method} FAILED ({duration:.3f}s): {e}")
28
+ raise
29
+
30
+
31
+ default_logging_middleware = LoggingMiddleware()