From 5553f22c216f08b5d2d92973517cfb6363ce74a2 Mon Sep 17 00:00:00 2001 From: Yassine Lassoued Date: Thu, 27 Mar 2025 07:33:21 +0100 Subject: [PATCH 1/3] Added support for raw request injection in RequestContext. --- .idea/.gitignore | 8 +++ .idea/deployment.xml | 56 +++++++++++++++++++ .../inspectionProfiles/profiles_settings.xml | 6 ++ .idea/misc.xml | 7 +++ .idea/modules.xml | 8 +++ .idea/python-sdk.iml | 18 ++++++ .idea/vcs.xml | 6 ++ src/mcp/client/session.py | 10 ++-- src/mcp/server/fastmcp/server.py | 11 ++-- src/mcp/server/fastmcp/tools/base.py | 2 +- src/mcp/server/fastmcp/tools/tool_manager.py | 2 +- src/mcp/server/lowlevel/server.py | 19 ++++--- src/mcp/shared/context.py | 4 +- src/mcp/shared/memory.py | 2 +- src/mcp/shared/progress.py | 3 +- tests/client/test_list_roots_callback.py | 4 +- tests/client/test_sampling_callback.py | 2 +- 17 files changed, 144 insertions(+), 24 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/deployment.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/python-sdk.iml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..13566b81 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 00000000..bdafdc14 --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 00000000..105ce2da --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..dc682e9c --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..d59171af --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/python-sdk.iml b/.idea/python-sdk.iml new file mode 100644 index 00000000..db6f33d0 --- /dev/null +++ b/.idea/python-sdk.iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/mcp/client/session.py b/src/mcp/client/session.py index 65d5e11e..155e7ecb 100644 --- a/src/mcp/client/session.py +++ b/src/mcp/client/session.py @@ -14,14 +14,14 @@ class SamplingFnT(Protocol): async def __call__( self, - context: RequestContext["ClientSession", Any], + context: RequestContext["ClientSession", Any, Any], params: types.CreateMessageRequestParams, ) -> types.CreateMessageResult | types.ErrorData: ... class ListRootsFnT(Protocol): async def __call__( - self, context: RequestContext["ClientSession", Any] + self, context: RequestContext["ClientSession", Any, Any] ) -> types.ListRootsResult | types.ErrorData: ... @@ -50,7 +50,7 @@ async def _default_message_handler( async def _default_sampling_callback( - context: RequestContext["ClientSession", Any], + context: RequestContext["ClientSession", Any, Any], params: types.CreateMessageRequestParams, ) -> types.CreateMessageResult | types.ErrorData: return types.ErrorData( @@ -60,7 +60,7 @@ async def _default_sampling_callback( async def _default_list_roots_callback( - context: RequestContext["ClientSession", Any], + context: RequestContext["ClientSession", Any, Any], ) -> types.ListRootsResult | types.ErrorData: return types.ErrorData( code=types.INVALID_REQUEST, @@ -331,7 +331,7 @@ async def send_roots_list_changed(self) -> None: async def _received_request( self, responder: RequestResponder[types.ServerRequest, types.ClientResult] ) -> None: - ctx = RequestContext[ClientSession, Any]( + ctx = RequestContext[ClientSession, Any, Any]( request_id=responder.request_id, meta=responder.request_meta, session=self, diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index bf0ce880..356103d9 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -36,7 +36,7 @@ from mcp.server.session import ServerSession, ServerSessionT from mcp.server.sse import SseServerTransport from mcp.server.stdio import stdio_server -from mcp.shared.context import LifespanContextT, RequestContext +from mcp.shared.context import LifespanContextT, RequestContext, RequestT from mcp.types import ( AnyFunction, EmbeddedResource, @@ -182,7 +182,7 @@ async def list_tools(self) -> list[MCPTool]: for info in tools ] - def get_context(self) -> Context[ServerSession, object]: + def get_context(self) -> Context[ServerSession, object, Request]: """ Returns a Context object. Note that the context will only be valid during a request; outside a request, most methods will error. @@ -491,6 +491,7 @@ async def handle_sse(request: Request) -> None: streams[0], streams[1], self._mcp_server.create_initialization_options(), + request=request, ) return Starlette( @@ -558,7 +559,7 @@ def _convert_to_content( return [TextContent(type="text", text=result)] -class Context(BaseModel, Generic[ServerSessionT, LifespanContextT]): +class Context(BaseModel, Generic[ServerSessionT, LifespanContextT, RequestT]): """Context object providing access to MCP capabilities. This provides a cleaner interface to MCP's RequestContext functionality. @@ -592,13 +593,13 @@ def my_tool(x: int, ctx: Context) -> str: The context is optional - tools that don't need it can omit the parameter. """ - _request_context: RequestContext[ServerSessionT, LifespanContextT] | None + _request_context: RequestContext[ServerSessionT, LifespanContextT, RequestT] | None _fastmcp: FastMCP | None def __init__( self, *, - request_context: RequestContext[ServerSessionT, LifespanContextT] | None = None, + request_context: RequestContext[ServerSessionT, LifespanContextT, RequestT] | None = None, fastmcp: FastMCP | None = None, **kwargs: Any, ): diff --git a/src/mcp/server/fastmcp/tools/base.py b/src/mcp/server/fastmcp/tools/base.py index e137e845..6efb3770 100644 --- a/src/mcp/server/fastmcp/tools/base.py +++ b/src/mcp/server/fastmcp/tools/base.py @@ -76,7 +76,7 @@ def from_function( async def run( self, arguments: dict[str, Any], - context: Context[ServerSessionT, LifespanContextT] | None = None, + context: Context[ServerSessionT, LifespanContextT, Any] | None = None, ) -> Any: """Run the tool with arguments.""" try: diff --git a/src/mcp/server/fastmcp/tools/tool_manager.py b/src/mcp/server/fastmcp/tools/tool_manager.py index 4d6ac268..69c2ccfa 100644 --- a/src/mcp/server/fastmcp/tools/tool_manager.py +++ b/src/mcp/server/fastmcp/tools/tool_manager.py @@ -50,7 +50,7 @@ async def call_tool( self, name: str, arguments: dict[str, Any], - context: Context[ServerSessionT, LifespanContextT] | None = None, + context: Context[ServerSessionT, LifespanContextT, Any] | None = None, ) -> Any: """Call a tool by name with arguments.""" tool = self.get_tool(name) diff --git a/src/mcp/server/lowlevel/server.py b/src/mcp/server/lowlevel/server.py index e14f73e1..cf20c30d 100644 --- a/src/mcp/server/lowlevel/server.py +++ b/src/mcp/server/lowlevel/server.py @@ -82,7 +82,7 @@ async def main(): from mcp.server.models import InitializationOptions from mcp.server.session import ServerSession from mcp.server.stdio import stdio_server as stdio_server -from mcp.shared.context import RequestContext +from mcp.shared.context import RequestContext, RequestT from mcp.shared.exceptions import McpError from mcp.shared.session import RequestResponder @@ -91,7 +91,7 @@ async def main(): LifespanResultT = TypeVar("LifespanResultT") # This will be properly typed in each Server instance's context -request_ctx: contextvars.ContextVar[RequestContext[ServerSession, Any]] = ( +request_ctx: contextvars.ContextVar[RequestContext[ServerSession, Any, RequestT]] = ( contextvars.ContextVar("request_ctx") ) @@ -109,7 +109,7 @@ def __init__( @asynccontextmanager -async def lifespan(server: Server[LifespanResultT]) -> AsyncIterator[object]: +async def lifespan(server: Server[LifespanResultT, RequestT]) -> AsyncIterator[object]: """Default lifespan context manager that does nothing. Args: @@ -121,14 +121,14 @@ async def lifespan(server: Server[LifespanResultT]) -> AsyncIterator[object]: yield {} -class Server(Generic[LifespanResultT]): +class Server(Generic[LifespanResultT, RequestT]): def __init__( self, name: str, version: str | None = None, instructions: str | None = None, lifespan: Callable[ - [Server[LifespanResultT]], AbstractAsyncContextManager[LifespanResultT] + [Server[LifespanResultT, RequestT]], AbstractAsyncContextManager[LifespanResultT] ] = lifespan, ): self.name = name @@ -213,7 +213,7 @@ def get_capabilities( ) @property - def request_context(self) -> RequestContext[ServerSession, LifespanResultT]: + def request_context(self) -> RequestContext[ServerSession, LifespanResultT, RequestT]: """If called outside of a request context, this will raise a LookupError.""" return request_ctx.get() @@ -479,6 +479,7 @@ async def run( # but also make tracing exceptions much easier during testing and when using # in-process servers. raise_exceptions: bool = False, + request: RequestT | None = None, ): async with AsyncExitStack() as stack: lifespan_context = await stack.enter_async_context(self.lifespan(self)) @@ -496,6 +497,7 @@ async def run( session, lifespan_context, raise_exceptions, + request, ) async def _handle_message( @@ -506,6 +508,7 @@ async def _handle_message( session: ServerSession, lifespan_context: LifespanResultT, raise_exceptions: bool = False, + request: RequestT | None = None, ): with warnings.catch_warnings(record=True) as w: # TODO(Marcelo): We should be checking if message is Exception here. @@ -515,7 +518,7 @@ async def _handle_message( ): with responder: await self._handle_request( - message, req, session, lifespan_context, raise_exceptions + message, req, session, lifespan_context, raise_exceptions, request ) case types.ClientNotification(root=notify): await self._handle_notification(notify) @@ -530,6 +533,7 @@ async def _handle_request( session: ServerSession, lifespan_context: LifespanResultT, raise_exceptions: bool, + request: RequestT | None, ): logger.info(f"Processing request of type {type(req).__name__}") if type(req) in self.request_handlers: @@ -546,6 +550,7 @@ async def _handle_request( message.request_meta, session, lifespan_context, + request=request, ) ) response = await handler(req) diff --git a/src/mcp/shared/context.py b/src/mcp/shared/context.py index ae85d3a1..2b673565 100644 --- a/src/mcp/shared/context.py +++ b/src/mcp/shared/context.py @@ -8,11 +8,13 @@ SessionT = TypeVar("SessionT", bound=BaseSession[Any, Any, Any, Any, Any]) LifespanContextT = TypeVar("LifespanContextT") +RequestT = TypeVar("RequestT") @dataclass -class RequestContext(Generic[SessionT, LifespanContextT]): +class RequestContext(Generic[SessionT, LifespanContextT, RequestT]): request_id: RequestId meta: RequestParams.Meta | None session: SessionT lifespan_context: LifespanContextT + request: RequestT | None = None diff --git a/src/mcp/shared/memory.py b/src/mcp/shared/memory.py index 346f6156..5ebdebdf 100644 --- a/src/mcp/shared/memory.py +++ b/src/mcp/shared/memory.py @@ -59,7 +59,7 @@ async def create_client_server_memory_streams() -> ( @asynccontextmanager async def create_connected_server_and_client_session( - server: Server[Any], + server: Server[Any, Any], read_timeout_seconds: timedelta | None = None, sampling_callback: SamplingFnT | None = None, list_roots_callback: ListRootsFnT | None = None, diff --git a/src/mcp/shared/progress.py b/src/mcp/shared/progress.py index 52e0017d..616757ea 100644 --- a/src/mcp/shared/progress.py +++ b/src/mcp/shared/progress.py @@ -1,7 +1,7 @@ from collections.abc import Generator from contextlib import contextmanager from dataclasses import dataclass, field -from typing import Generic +from typing import Generic, Any from pydantic import BaseModel @@ -62,6 +62,7 @@ def progress( ReceiveNotificationT, ], LifespanContextT, + Any, ], total: float | None = None, ) -> Generator[ diff --git a/tests/client/test_list_roots_callback.py b/tests/client/test_list_roots_callback.py index f5b59821..309242b7 100644 --- a/tests/client/test_list_roots_callback.py +++ b/tests/client/test_list_roots_callback.py @@ -1,3 +1,5 @@ +from types import NoneType + import pytest from pydantic import FileUrl @@ -30,7 +32,7 @@ async def test_list_roots_callback(): ) async def list_roots_callback( - context: RequestContext[ClientSession, None], + context: RequestContext[ClientSession, None, None], ) -> ListRootsResult: return callback_return diff --git a/tests/client/test_sampling_callback.py b/tests/client/test_sampling_callback.py index ba586d4a..ee09cc08 100644 --- a/tests/client/test_sampling_callback.py +++ b/tests/client/test_sampling_callback.py @@ -29,7 +29,7 @@ async def test_sampling_callback(): ) async def sampling_callback( - context: RequestContext[ClientSession, None], + context: RequestContext[ClientSession, None, None], params: CreateMessageRequestParams, ) -> CreateMessageResult: return callback_return From e2405770e85ceae36622b43ad6b837a55cc1e222 Mon Sep 17 00:00:00 2001 From: Yassine Lassoued Date: Thu, 27 Mar 2025 08:50:06 +0100 Subject: [PATCH 2/3] Fixed typing issues. Reverted Context generic type parameters. --- src/mcp/server/fastmcp/server.py | 21 ++++++++++++-------- src/mcp/server/fastmcp/tools/base.py | 2 +- src/mcp/server/fastmcp/tools/tool_manager.py | 2 +- src/mcp/server/lowlevel/server.py | 16 +++++++++++---- src/mcp/shared/progress.py | 2 +- tests/client/test_list_roots_callback.py | 2 -- 6 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index 356103d9..22978eb2 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -36,7 +36,7 @@ from mcp.server.session import ServerSession, ServerSessionT from mcp.server.sse import SseServerTransport from mcp.server.stdio import stdio_server -from mcp.shared.context import LifespanContextT, RequestContext, RequestT +from mcp.shared.context import LifespanContextT, RequestContext from mcp.types import ( AnyFunction, EmbeddedResource, @@ -98,9 +98,11 @@ class Settings(BaseSettings, Generic[LifespanResultT]): def lifespan_wrapper( app: FastMCP, lifespan: Callable[[FastMCP], AbstractAsyncContextManager[LifespanResultT]], -) -> Callable[[MCPServer[LifespanResultT]], AbstractAsyncContextManager[object]]: +) -> Callable[ + [MCPServer[LifespanResultT, Request]], AbstractAsyncContextManager[object] +]: @asynccontextmanager - async def wrap(s: MCPServer[LifespanResultT]) -> AsyncIterator[object]: + async def wrap(s: MCPServer[LifespanResultT, Request]) -> AsyncIterator[object]: async with lifespan(app) as context: yield context @@ -182,7 +184,7 @@ async def list_tools(self) -> list[MCPTool]: for info in tools ] - def get_context(self) -> Context[ServerSession, object, Request]: + def get_context(self) -> Context[ServerSession, object]: """ Returns a Context object. Note that the context will only be valid during a request; outside a request, most methods will error. @@ -559,7 +561,7 @@ def _convert_to_content( return [TextContent(type="text", text=result)] -class Context(BaseModel, Generic[ServerSessionT, LifespanContextT, RequestT]): +class Context(BaseModel, Generic[ServerSessionT, LifespanContextT]): """Context object providing access to MCP capabilities. This provides a cleaner interface to MCP's RequestContext functionality. @@ -593,13 +595,14 @@ def my_tool(x: int, ctx: Context) -> str: The context is optional - tools that don't need it can omit the parameter. """ - _request_context: RequestContext[ServerSessionT, LifespanContextT, RequestT] | None + _request_context: RequestContext[ServerSessionT, LifespanContextT, Request] | None _fastmcp: FastMCP | None def __init__( self, *, - request_context: RequestContext[ServerSessionT, LifespanContextT, RequestT] | None = None, + request_context: RequestContext[ServerSessionT, LifespanContextT, Request] + | None = None, fastmcp: FastMCP | None = None, **kwargs: Any, ): @@ -615,7 +618,9 @@ def fastmcp(self) -> FastMCP: return self._fastmcp @property - def request_context(self) -> RequestContext[ServerSessionT, LifespanContextT]: + def request_context( + self, + ) -> RequestContext[ServerSessionT, LifespanContextT, Request]: """Access to the underlying request context.""" if self._request_context is None: raise ValueError("Context is not available outside of a request") diff --git a/src/mcp/server/fastmcp/tools/base.py b/src/mcp/server/fastmcp/tools/base.py index 6efb3770..e137e845 100644 --- a/src/mcp/server/fastmcp/tools/base.py +++ b/src/mcp/server/fastmcp/tools/base.py @@ -76,7 +76,7 @@ def from_function( async def run( self, arguments: dict[str, Any], - context: Context[ServerSessionT, LifespanContextT, Any] | None = None, + context: Context[ServerSessionT, LifespanContextT] | None = None, ) -> Any: """Run the tool with arguments.""" try: diff --git a/src/mcp/server/fastmcp/tools/tool_manager.py b/src/mcp/server/fastmcp/tools/tool_manager.py index 69c2ccfa..4d6ac268 100644 --- a/src/mcp/server/fastmcp/tools/tool_manager.py +++ b/src/mcp/server/fastmcp/tools/tool_manager.py @@ -50,7 +50,7 @@ async def call_tool( self, name: str, arguments: dict[str, Any], - context: Context[ServerSessionT, LifespanContextT, Any] | None = None, + context: Context[ServerSessionT, LifespanContextT] | None = None, ) -> Any: """Call a tool by name with arguments.""" tool = self.get_tool(name) diff --git a/src/mcp/server/lowlevel/server.py b/src/mcp/server/lowlevel/server.py index cf20c30d..cffec77a 100644 --- a/src/mcp/server/lowlevel/server.py +++ b/src/mcp/server/lowlevel/server.py @@ -91,7 +91,7 @@ async def main(): LifespanResultT = TypeVar("LifespanResultT") # This will be properly typed in each Server instance's context -request_ctx: contextvars.ContextVar[RequestContext[ServerSession, Any, RequestT]] = ( +request_ctx: contextvars.ContextVar[RequestContext[ServerSession, Any, Any]] = ( contextvars.ContextVar("request_ctx") ) @@ -128,7 +128,8 @@ def __init__( version: str | None = None, instructions: str | None = None, lifespan: Callable[ - [Server[LifespanResultT, RequestT]], AbstractAsyncContextManager[LifespanResultT] + [Server[LifespanResultT, RequestT]], + AbstractAsyncContextManager[LifespanResultT], ] = lifespan, ): self.name = name @@ -213,7 +214,9 @@ def get_capabilities( ) @property - def request_context(self) -> RequestContext[ServerSession, LifespanResultT, RequestT]: + def request_context( + self, + ) -> RequestContext[ServerSession, LifespanResultT, RequestT]: """If called outside of a request context, this will raise a LookupError.""" return request_ctx.get() @@ -518,7 +521,12 @@ async def _handle_message( ): with responder: await self._handle_request( - message, req, session, lifespan_context, raise_exceptions, request + message, + req, + session, + lifespan_context, + raise_exceptions, + request, ) case types.ClientNotification(root=notify): await self._handle_notification(notify) diff --git a/src/mcp/shared/progress.py b/src/mcp/shared/progress.py index 616757ea..6e734869 100644 --- a/src/mcp/shared/progress.py +++ b/src/mcp/shared/progress.py @@ -1,7 +1,7 @@ from collections.abc import Generator from contextlib import contextmanager from dataclasses import dataclass, field -from typing import Generic, Any +from typing import Any, Generic from pydantic import BaseModel diff --git a/tests/client/test_list_roots_callback.py b/tests/client/test_list_roots_callback.py index 309242b7..6f3d3576 100644 --- a/tests/client/test_list_roots_callback.py +++ b/tests/client/test_list_roots_callback.py @@ -1,5 +1,3 @@ -from types import NoneType - import pytest from pydantic import FileUrl From e4e2c1b30c4a39ab87bfffa17e6d6e018ce73399 Mon Sep 17 00:00:00 2001 From: Yassine Lassoued Date: Thu, 27 Mar 2025 14:52:08 +0100 Subject: [PATCH 3/3] Deleted .idea folder. --- .idea/.gitignore | 8 --- .idea/deployment.xml | 56 ------------------- .../inspectionProfiles/profiles_settings.xml | 6 -- .idea/misc.xml | 7 --- .idea/modules.xml | 8 --- .idea/python-sdk.iml | 18 ------ .idea/vcs.xml | 6 -- 7 files changed, 109 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/deployment.xml delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/python-sdk.iml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b81..00000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/deployment.xml b/.idea/deployment.xml deleted file mode 100644 index bdafdc14..00000000 --- a/.idea/deployment.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2da..00000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index dc682e9c..00000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index d59171af..00000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/python-sdk.iml b/.idea/python-sdk.iml deleted file mode 100644 index db6f33d0..00000000 --- a/.idea/python-sdk.iml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1ddf..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file