From 5922090ee487c4d8495580e1d52ef725fc3c49b7 Mon Sep 17 00:00:00 2001 From: Sarmad Qadri Date: Wed, 29 Jan 2025 12:27:44 -0500 Subject: [PATCH 01/35] Add mcp-agent to list of clients --- clients.mdx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/clients.mdx b/clients.mdx index 6ca8583..2af3108 100644 --- a/clients.mdx +++ b/clients.mdx @@ -21,6 +21,7 @@ This page provides an overview of applications that support the Model Context Pr | [Superinterface][Superinterface] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools | | [5ire][5ire] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools. | | [Bee Agent Framework][Bee Agent Framework] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools in agentic workflows. | +| [mcp-agent][mcp-agent] | ❌ | ❌ | ✅ | ⚠️ | ❌ | Supports tools, server connection management, and agent workflows. | [Claude]: https://claude.ai/download @@ -35,6 +36,7 @@ This page provides an overview of applications that support the Model Context Pr [Superinterface]: https://superinterface.ai [5ire]: https://github.com/nanbingxyz/5ire [Bee Agent Framework]: https://i-am-bee.github.io/bee-agent-framework +[mcp-agent]: https://github.com/lastmile-ai/mcp-agent [Resources]: https://modelcontextprotocol.io/docs/concepts/resources [Prompts]: https://modelcontextprotocol.io/docs/concepts/prompts @@ -157,6 +159,15 @@ Theia AI and Theia IDE's MCP integration provide users with flexibility, making **Learn more:** - [Example of using MCP tools in agentic workflow](https://i-am-bee.github.io/bee-agent-framework/#/tools?id=using-the-mcptool-class) +### mcp-agent +[mcp-agent] is a simple, composable framework to build agents using Model Context Protocol. + +**Key features:** +- Automatic connection management of MCP servers. +- Expose tools from multiple servers to an LLM. +- Implements every pattern defined in [Building Effective Agents](https://www.anthropic.com/research/building-effective-agents). +- Supports workflow pause/resume signals, such as waiting for human feedback. + ## Adding MCP support to your application If you've added MCP support to your application, we encourage you to submit a pull request to add it to this list. MCP integration can provide your users with powerful contextual AI capabilities and make your application part of the growing MCP ecosystem. From fd8c702a9ed5550eec130e6bb32afc10df710108 Mon Sep 17 00:00:00 2001 From: David Soria Parra Date: Mon, 3 Feb 2025 10:45:22 +0000 Subject: [PATCH 02/35] clients: align table --- clients.mdx | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/clients.mdx b/clients.mdx index 2af3108..4e4630d 100644 --- a/clients.mdx +++ b/clients.mdx @@ -7,21 +7,21 @@ This page provides an overview of applications that support the Model Context Pr ## Feature support matrix -| Client | [Resources] | [Prompts] | [Tools] | [Sampling] | Roots | Notes | -|---------------------------|-------------|-----------|---------|------------|-------|---------------------------------------------------| -| [Claude Desktop App][Claude] | ✅ | ✅ | ✅ | ❌ | ❌ | Full support for all MCP features | -| [Zed][Zed] | ❌ | ✅ | ❌ | ❌ | ❌ | Prompts appear as slash commands | -| [Sourcegraph Cody][Cody] | ✅ | ❌ | ❌ | ❌ | ❌ | Supports resources through OpenCTX | -| [Firebase Genkit][Genkit] | ⚠️ | ✅ | ✅ | ❌ | ❌ | Supports resource list and lookup through tools. | -| [Continue][Continue] | ✅ | ✅ | ✅ | ❌ | ❌ | Full support for all MCP features | -| [GenAIScript][GenAIScript] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools. | -| [Cline][Cline] | ✅ | ❌ | ✅ | ❌ | ❌ | Supports tools and resources. | -| [LibreChat][LibreChat] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools for Agents | -| [TheiaAI/TheiaIDE][TheiaAI/TheiaIDE] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools for Agents in Theia AI and the AI-powered Theia IDE | -| [Superinterface][Superinterface] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools | -| [5ire][5ire] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools. | -| [Bee Agent Framework][Bee Agent Framework] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools in agentic workflows. | -| [mcp-agent][mcp-agent] | ❌ | ❌ | ✅ | ⚠️ | ❌ | Supports tools, server connection management, and agent workflows. | +| Client | [Resources] | [Prompts] | [Tools] | [Sampling] | Roots | Notes | +|---------------------------------------------|-------------|-----------|---------|------------|--------|------------------------------------------------------------------------------| +| [Claude Desktop App][Claude] | ✅ | ✅ | ✅ | ❌ | ❌ | Full support for all MCP features | +| [Zed][Zed] | ❌ | ✅ | ❌ | ❌ | ❌ | Prompts appear as slash commands | +| [Sourcegraph Cody][Cody] | ✅ | ❌ | ❌ | ❌ | ❌ | Supports resources through OpenCTX | +| [Firebase Genkit][Genkit] | ⚠️ | ✅ | ✅ | ❌ | ❌ | Supports resource list and lookup through tools. | +| [Continue][Continue] | ✅ | ✅ | ✅ | ❌ | ❌ | Full support for all MCP features | +| [GenAIScript][GenAIScript] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools. | +| [Cline][Cline] | ✅ | ❌ | ✅ | ❌ | ❌ | Supports tools and resources. | +| [LibreChat][LibreChat] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools for Agents | +| [TheiaAI/TheiaIDE][TheiaAI/TheiaIDE] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools for Agents in Theia AI and the AI-powered Theia IDE | +| [Superinterface][Superinterface] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools | +| [5ire][5ire] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools. | +| [Bee Agent Framework][Bee Agent Framework] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools in agentic workflows. | +| [mcp-agent][mcp-agent] | ❌ | ❌ | ✅ | ⚠️ | ❌ | Supports tools, server connection management, and agent workflows. | [Claude]: https://claude.ai/download From d1990ed74a8a0637a342f42d07e8b59019249312 Mon Sep 17 00:00:00 2001 From: David Soria Parra Date: Mon, 3 Feb 2025 10:49:20 +0000 Subject: [PATCH 03/35] clients: cursor --- clients.mdx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/clients.mdx b/clients.mdx index 4e4630d..fbd3b5c 100644 --- a/clients.mdx +++ b/clients.mdx @@ -10,6 +10,7 @@ This page provides an overview of applications that support the Model Context Pr | Client | [Resources] | [Prompts] | [Tools] | [Sampling] | Roots | Notes | |---------------------------------------------|-------------|-----------|---------|------------|--------|------------------------------------------------------------------------------| | [Claude Desktop App][Claude] | ✅ | ✅ | ✅ | ❌ | ❌ | Full support for all MCP features | +| [Cursor][Cursor] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools. | | [Zed][Zed] | ❌ | ✅ | ❌ | ❌ | ❌ | Prompts appear as slash commands | | [Sourcegraph Cody][Cody] | ✅ | ❌ | ❌ | ❌ | ❌ | Supports resources through OpenCTX | | [Firebase Genkit][Genkit] | ⚠️ | ✅ | ✅ | ❌ | ❌ | Supports resource list and lookup through tools. | @@ -25,6 +26,7 @@ This page provides an overview of applications that support the Model Context Pr [Claude]: https://claude.ai/download +[Cursor]: https://cursor.com [Zed]: https://zed.dev [Cody]: https://sourcegraph.com/cody [Genkit]: https://github.com/firebase/genkit @@ -56,6 +58,14 @@ The Claude desktop application provides comprehensive support for MCP, enabling > ⓘ Note: The Claude.ai web application does not currently support MCP. MCP features are only available in the desktop application. + +### Cursor +[Cursor](https://docs.cursor.com/advanced/model-context-protocol) is an AI code editor. + +**Key Features**: +- Support for MCP tools in Cursor Composer +- Support for both STDIO and SSE + ### Zed [Zed](https://zed.dev/docs/assistant/model-context-protocol) is a high-performance code editor with built-in MCP support, focusing on prompt templates and tool integration. From 76e729a5a0498e681aace4da8a8f61493ffc4a35 Mon Sep 17 00:00:00 2001 From: lizqwerscott Date: Sat, 1 Feb 2025 18:44:12 +0800 Subject: [PATCH 04/35] docs: add Emacs Mcp amongst the clients --- clients.mdx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/clients.mdx b/clients.mdx index fbd3b5c..b5a3ab4 100644 --- a/clients.mdx +++ b/clients.mdx @@ -23,6 +23,7 @@ This page provides an overview of applications that support the Model Context Pr | [5ire][5ire] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools. | | [Bee Agent Framework][Bee Agent Framework] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools in agentic workflows. | | [mcp-agent][mcp-agent] | ❌ | ❌ | ✅ | ⚠️ | ❌ | Supports tools, server connection management, and agent workflows. | +| [Emacs Mcp][Mcp.el] | ❌ | ❌ | ✅ | ❌ | ❌ | Supports tools in Emacs. | [Claude]: https://claude.ai/download @@ -39,6 +40,7 @@ This page provides an overview of applications that support the Model Context Pr [5ire]: https://github.com/nanbingxyz/5ire [Bee Agent Framework]: https://i-am-bee.github.io/bee-agent-framework [mcp-agent]: https://github.com/lastmile-ai/mcp-agent +[Mcp.el]: https://github.com/lizqwerscott/mcp.el [Resources]: https://modelcontextprotocol.io/docs/concepts/resources [Prompts]: https://modelcontextprotocol.io/docs/concepts/prompts @@ -178,6 +180,12 @@ Theia AI and Theia IDE's MCP integration provide users with flexibility, making - Implements every pattern defined in [Building Effective Agents](https://www.anthropic.com/research/building-effective-agents). - Supports workflow pause/resume signals, such as waiting for human feedback. +### Emacs Mcp +[Emacs Mcp](https://github.com/lizqwerscott/mcp.el) is an Emacs client designed to interface with MCP servers, enabling seamless connections and interactions. It provides MCP tool invocation support for AI plugins like [gptel](https://github.com/karthink/gptel) and [llm](https://github.com/ahyatt/llm), adhering to Emacs' standard tool invocation format. This integration enhances the functionality of AI tools within the Emacs ecosystem. + +**Key features:** +- Provides MCP tool support for Emacs. + ## Adding MCP support to your application If you've added MCP support to your application, we encourage you to submit a pull request to add it to this list. MCP integration can provide your users with powerful contextual AI capabilities and make your application part of the growing MCP ecosystem. From 71da46c7412ef39ab8ebde492231118dde1414c2 Mon Sep 17 00:00:00 2001 From: David Soria Parra Date: Fri, 7 Feb 2025 09:45:45 +0000 Subject: [PATCH 05/35] docs: move from mint.json to docs.json Mintlify moved from mint.json to a newer docs.json that is a bit more refined and in the longrun will suite us better. Let's move to docs.json Tested: * `mintlify upgrade` * `mintlify dev` and inspect website. --- docs.json | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ mint.json | 107 ----------------------------------------------- 2 files changed, 122 insertions(+), 107 deletions(-) create mode 100644 docs.json delete mode 100644 mint.json diff --git a/docs.json b/docs.json new file mode 100644 index 0000000..a9d51d4 --- /dev/null +++ b/docs.json @@ -0,0 +1,122 @@ +{ + "$schema": "https://mintlify.com/docs.json", + "theme": "willow", + "name": "Model Context Protocol", + "colors": { + "primary": "#09090b", + "light": "#FAFAFA", + "dark": "#09090b" + }, + "favicon": "/favicon.svg", + "navigation": { + "anchors": [ + { + "anchor": "Documentation", + "icon": "book-open", + "groups": [ + { + "group": "Get Started", + "pages": [ + "introduction", + { + "group": "Quickstart", + "pages": [ + "quickstart/server", + "quickstart/client", + "quickstart/user" + ] + }, + "examples", + "clients" + ] + }, + { + "group": "Tutorials", + "pages": [ + "tutorials/building-mcp-with-llms", + "docs/tools/debugging", + "docs/tools/inspector" + ] + }, + { + "group": "Concepts", + "pages": [ + "docs/concepts/architecture", + "docs/concepts/resources", + "docs/concepts/prompts", + "docs/concepts/tools", + "docs/concepts/sampling", + "docs/concepts/roots", + "docs/concepts/transports" + ] + }, + { + "group": "Development", + "pages": [ + "development/updates", + "development/roadmap", + "development/contributing" + ] + } + ] + } + ], + "global": { + "anchors": [ + { + "anchor": "Python SDK", + "href": "https://github.com/modelcontextprotocol/python-sdk", + "icon": "python" + }, + { + "anchor": "TypeScript SDK", + "href": "https://github.com/modelcontextprotocol/typescript-sdk", + "icon": "square-js" + }, + { + "anchor": "Kotlin SDK", + "href": "https://github.com/modelcontextprotocol/kotlin-sdk", + "icon": "square-k" + }, + { + "anchor": "Specification", + "href": "https://spec.modelcontextprotocol.io", + "icon": "book" + } + ] + } + }, + "logo": { + "light": "/logo/light.svg", + "dark": "/logo/dark.svg" + }, + "navbar": { + "links": [], + "primary": { + "type": "button", + "label": "GitHub", + "href": "https://github.com/modelcontextprotocol" + } + }, + "seo": { + "metatags": { + "og:image": "https://raw.githubusercontent.com/modelcontextprotocol/docs/2eb6171ddbfeefde349dc3b8d5e2b87414c26250/images/og-image.png" + }, + "indexing": "navigable" + }, + "footer": { + "socials": { + "github": "https://github.com/modelcontextprotocol" + } + }, + "redirects": [ + { + "source": "/tutorials/building-a-client", + "destination": "/quickstart/client" + }, + { + "source": "/quickstart", + "destination": "/quickstart/server" + } + ] +} diff --git a/mint.json b/mint.json deleted file mode 100644 index 265a246..0000000 --- a/mint.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "$schema": "https://mintlify.com/schema.json", - "name": "Model Context Protocol", - "logo": { - "dark": "/logo/dark.svg", - "light": "/logo/light.svg" - }, - "favicon": "/favicon.svg", - "theme": "quill", - "colors": { - "primary": "#09090b", - "light": "#FAFAFA", - "dark": "#09090b" - }, - "topbarLinks": [], - "topbarCtaButton": { - "name": "GitHub", - "url": "https://github.com/modelcontextprotocol" - }, - "search": { - "location": "top" - }, - "anchors": [ - { - "name": "Python SDK", - "icon": "python", - "url": "https://github.com/modelcontextprotocol/python-sdk" - }, - { - "name": "TypeScript SDK", - "icon": "square-js", - "url": "https://github.com/modelcontextprotocol/typescript-sdk" - }, - { - "name": "Kotlin SDK", - "icon": "square-k", - "url": "https://github.com/modelcontextprotocol/kotlin-sdk" - }, - { - "name": "Specification", - "icon": "book", - "url": "https://spec.modelcontextprotocol.io" - } - ], - "navigation": [ - { - "group": "Get Started", - "pages": [ - "introduction", - { - "group": "Quickstart", - "pages": ["quickstart/server", "quickstart/client", "quickstart/user"] - }, - "examples", - "clients" - ] - }, - - { - "group": "Tutorials", - "pages": [ - "tutorials/building-mcp-with-llms", - "docs/tools/debugging", - "docs/tools/inspector" - ] - }, - { - "group": "Concepts", - "pages": [ - "docs/concepts/architecture", - "docs/concepts/resources", - "docs/concepts/prompts", - "docs/concepts/tools", - "docs/concepts/sampling", - "docs/concepts/roots", - "docs/concepts/transports" - ] - }, - { - "group": "Development", - "pages": [ - "development/updates", - "development/roadmap", - "development/contributing" - ] - } - ], - "footerSocials": { - "github": "https://github.com/modelcontextprotocol" - }, - "feedback": { - "thumbsRating": true - }, - "redirects": [ - { - "source": "/tutorials/building-a-client", - "destination": "/quickstart/client" - }, - { - "source": "/quickstart", - "destination": "/quickstart/server" - } - ], - "metadata": { - "og:image": "https://raw.githubusercontent.com/modelcontextprotocol/docs/2eb6171ddbfeefde349dc3b8d5e2b87414c26250/images/og-image.png" - } -} From 8acb5f97a21790be81d989b41a1c8c57ce07e3f1 Mon Sep 17 00:00:00 2001 From: David Soria Parra Date: Mon, 10 Feb 2025 09:35:53 +0000 Subject: [PATCH 06/35] fix: fix client code --- quickstart/client.mdx | 51 ++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/quickstart/client.mdx b/quickstart/client.mdx index ab7866e..39b8e5a 100644 --- a/quickstart/client.mdx +++ b/quickstart/client.mdx @@ -19,7 +19,7 @@ Before starting, ensure your system meets these requirements: ## Setting Up Your Environment -First, create a new Python project with `uv`: +First, create a new Python project with `uv`: ```bash # Create project directory @@ -104,7 +104,7 @@ Next, we'll implement the method to connect to an MCP server: ```python async def connect_to_server(self, server_script_path: str): """Connect to an MCP server - + Args: server_script_path: Path to the server script (.py or .js) """ @@ -112,20 +112,20 @@ async def connect_to_server(self, server_script_path: str): is_js = server_script_path.endswith('.js') if not (is_python or is_js): raise ValueError("Server script must be a .py or .js file") - + command = "python" if is_python else "node" server_params = StdioServerParameters( command=command, args=[server_script_path], env=None ) - + stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params)) self.stdio, self.write = stdio_transport self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write)) - + await self.session.initialize() - + # List available tools response = await self.session.list_tools() tools = response.tools @@ -147,7 +147,7 @@ async def process_query(self, query: str) -> str: ] response = await self.session.list_tools() - available_tools = [{ + available_tools = [{ "name": tool.name, "description": tool.description, "input_schema": tool.inputSchema @@ -165,27 +165,34 @@ async def process_query(self, query: str) -> str: tool_results = [] final_text = [] + assistant_message_content = [] for content in response.content: if content.type == 'text': final_text.append(content.text) + assistant_message_content.append(content) elif content.type == 'tool_use': tool_name = content.name tool_args = content.input - + # Execute tool call result = await self.session.call_tool(tool_name, tool_args) tool_results.append({"call": tool_name, "result": result}) final_text.append(f"[Calling tool {tool_name} with args {tool_args}]") - # Continue conversation with tool results - if hasattr(content, 'text') and content.text: - messages.append({ - "role": "assistant", - "content": content.text - }) + assistant_message_content.append(content) messages.append({ - "role": "user", - "content": result.content + "role": "assistant", + "content": assistant_message_content + }) + messages.append({ + "role": "user", + "content": [ + { + "type": "tool_result", + "tool_use_id": content.id, + "content": result.content + } + ] }) # Get next response from Claude @@ -208,17 +215,17 @@ async def chat_loop(self): """Run an interactive chat loop""" print("\nMCP Client Started!") print("Type your queries or 'quit' to exit.") - + while True: try: query = input("\nQuery: ").strip() - + if query.lower() == 'quit': break - + response = await self.process_query(query) print("\n" + response) - + except Exception as e: print(f"\nError: {str(e)}") @@ -236,7 +243,7 @@ async def main(): if len(sys.argv) < 2: print("Usage: python client.py ") sys.exit(1) - + client = MCPClient() try: await client.connect_to_server(sys.argv[1]) @@ -427,4 +434,4 @@ If you see: > Understand how MCP connects clients, servers, and LLMs - \ No newline at end of file + From 961530d58ef22a1cc87101e393473ce59d003dea Mon Sep 17 00:00:00 2001 From: Steve Kaliski Date: Tue, 11 Feb 2025 15:18:32 -0500 Subject: [PATCH 07/35] add Stripe to Official integrations list --- examples.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/examples.mdx b/examples.mdx index 49cbd7f..6edfbcc 100644 --- a/examples.mdx +++ b/examples.mdx @@ -49,6 +49,7 @@ These MCP servers are maintained by companies for their platforms: - **[Qdrant](https://github.com/qdrant/mcp-server-qdrant/)** - Implement semantic memory using the Qdrant vector search engine - **[Raygun](https://github.com/MindscapeHQ/mcp-server-raygun)** - Access crash reporting and monitoring data - **[Search1API](https://github.com/fatwang2/search1api-mcp)** - Unified API for search, crawling, and sitemaps +- **[Stripe](https://github.com/stripe/agent-toolkit)** - Interact with the Stripe API - **[Tinybird](https://github.com/tinybirdco/mcp-tinybird)** - Interface with the Tinybird serverless ClickHouse platform ## Community highlights From 904083c681daa930698932e30a53553f71c2068c Mon Sep 17 00:00:00 2001 From: Zachary Lee Date: Fri, 14 Feb 2025 09:43:35 -0500 Subject: [PATCH 08/35] (WIP) Base for Java docs (#125) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Base for Java docs * docs(java): Migrate Java-SDK/docs Add visual documentation for Java SDK architecture: - PlantUML class diagrams showing core components and relationships - Client and server architecture diagrams - Stack architecture overview - Generated UML class diagram with detailed implementation structure * Add Java Client and Server quickstarts * reorder, redact, correct java-sdk docs Signed-off-by: Dariusz Jędrzejczyk * updated updates.mdx * fix docs.json --------- Signed-off-by: Dariusz Jędrzejczyk Co-authored-by: Christian Tzolov Co-authored-by: Dariusz Jędrzejczyk Co-authored-by: David Soria Parra --- development/updates.mdx | 14 +- docs.json | 19 +- images/java/class-diagrams.puml | 282 ++++++++++++++ images/java/java-mcp-client-architecture.jpg | Bin 0 -> 676694 bytes images/java/java-mcp-server-architecture.jpg | Bin 0 -> 859935 bytes images/java/java-mcp-uml-classdiagram.svg | 1 + images/java/mcp-stack.svg | 197 ++++++++++ introduction.mdx | 2 +- quickstart/client.mdx | 114 ++++++ quickstart/server.mdx | 299 +++++++++++++++ sdk/java/mcp-client.mdx | 322 ++++++++++++++++ sdk/java/mcp-overview.mdx | 167 +++++++++ sdk/java/mcp-server.mdx | 368 +++++++++++++++++++ 13 files changed, 1780 insertions(+), 5 deletions(-) create mode 100644 images/java/class-diagrams.puml create mode 100644 images/java/java-mcp-client-architecture.jpg create mode 100644 images/java/java-mcp-server-architecture.jpg create mode 100644 images/java/java-mcp-uml-classdiagram.svg create mode 100644 images/java/mcp-stack.svg create mode 100644 sdk/java/mcp-client.mdx create mode 100644 sdk/java/mcp-overview.mdx create mode 100644 sdk/java/mcp-server.mdx diff --git a/development/updates.mdx b/development/updates.mdx index f7fc2d4..fa12a53 100644 --- a/development/updates.mdx +++ b/development/updates.mdx @@ -3,6 +3,18 @@ title: "What's New" description: 'The latest updates and improvements to MCP' --- + + - We're excited to announce that the Java SDK developed by Spring AI at VMware Tanzu is now + the official [Java SDK](https://github.com/modelcontextprotocol/java-sdk) for MCP. + This joins our existing Kotlin SDK in our growing list of supported languages. + The Spring AI team will maintain the SDK as an integral part of the Model Context Protocol + organization. We're thrilled to welcome them to the MCP community! + + + + - Version [1.2.1](https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.2.1) of the MCP Python SDK has been released, + delivering important stability improvements and bug fixes. + - Simplified, express-like API in the [TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) - Added 8 new clients to the [clients page](https://modelcontextprotocol.io/clients) @@ -16,4 +28,4 @@ description: 'The latest updates and improvements to MCP' - Jetbrains released a Kotlin SDK for MCP! - For a sample MCP Kotlin server, check out [this repository](https://github.com/modelcontextprotocol/kotlin-sdk/tree/main/samples/kotlin-mcp-server) - \ No newline at end of file + diff --git a/docs.json b/docs.json index a9d51d4..5249334 100644 --- a/docs.json +++ b/docs.json @@ -9,10 +9,9 @@ }, "favicon": "/favicon.svg", "navigation": { - "anchors": [ + "tabs": [ { - "anchor": "Documentation", - "icon": "book-open", + "tab": "Documentation", "groups": [ { "group": "Get Started", @@ -59,6 +58,20 @@ ] } ] + }, + { + "tab": "SDKs", + "icon": "book-open", + "groups": [ + { + "group": "Java", + "pages": [ + "sdk/java/mcp-overview", + "sdk/java/mcp-client", + "sdk/java/mcp-server" + ] + } + ] } ], "global": { diff --git a/images/java/class-diagrams.puml b/images/java/class-diagrams.puml new file mode 100644 index 0000000..5b08c73 --- /dev/null +++ b/images/java/class-diagrams.puml @@ -0,0 +1,282 @@ +@startuml Core Components + +' Core Interfaces +interface McpTransport { + +Mono connect(Function, Mono> handler) + +Mono sendMessage(JSONRPCMessage message) + +void close() + +Mono closeGracefully() + + T unmarshalFrom(Object data, TypeReference typeRef) +} + +interface McpSession { + + Mono sendRequest(String method, Object requestParams, TypeReference typeRef) + +Mono sendNotification(String method, Map params) + +Mono closeGracefully() + +void close() +} + +' Core Implementation Classes +class DefaultMcpSession { + +interface RequestHandler + +interface NotificationHandler +} + +' Client Classes +class McpClient { + +{static} Builder using(ClientMcpTransport transport) +} + +class McpAsyncClient { + +Mono initialize() + +ServerCapabilities getServerCapabilities() + +Implementation getServerInfo() + +ClientCapabilities getClientCapabilities() + +Implementation getClientInfo() + +void close() + +Mono closeGracefully() + +Mono ping() + +Mono addRoot(Root root) + +Mono removeRoot(String rootUri) + +Mono rootsListChangedNotification() + +Mono callTool(CallToolRequest request) + +Mono listTools() + +Mono listResources() + +Mono readResource(ReadResourceRequest request) + +Mono listResourceTemplates() + +Mono subscribeResource(SubscribeRequest request) + +Mono unsubscribeResource(UnsubscribeRequest request) + +Mono listPrompts() + +Mono getPrompt(GetPromptRequest request) + +Mono setLoggingLevel(LoggingLevel level) +} + +class McpSyncClient { + +InitializeResult initialize() + +ServerCapabilities getServerCapabilities() + +Implementation getServerInfo() + +ClientCapabilities getClientCapabilities() + +Implementation getClientInfo() + +void close() + +boolean closeGracefully() + +Object ping() + +void addRoot(Root root) + +void removeRoot(String rootUri) + +void rootsListChangedNotification() + +CallToolResult callTool(CallToolRequest request) + +ListToolsResult listTools() + +ListResourcesResult listResources() + +ReadResourceResult readResource(ReadResourceRequest request) + +ListResourceTemplatesResult listResourceTemplates() + +void subscribeResource(SubscribeRequest request) + +void unsubscribeResource(UnsubscribeRequest request) + +ListPromptsResult listPrompts() + +GetPromptResult getPrompt(GetPromptRequest request) + +void setLoggingLevel(LoggingLevel level) +} + +' Server Classes +class McpServer { + +{static} Builder using(ServerMcpTransport transport) +} + +class McpAsyncServer { + + +ServerCapabilities getServerCapabilities() + +Implementation getServerInfo() + +ClientCapabilities getClientCapabilities() + +Implementation getClientInfo() + +void close() + +Mono closeGracefully() + + ' Tool Management + +Mono addTool(ToolRegistration toolRegistration) + +Mono removeTool(String toolName) + +Mono notifyToolsListChanged() + + ' Resource Management + +Mono addResource(ResourceRegistration resourceHandler) + +Mono removeResource(String resourceUri) + +Mono notifyResourcesListChanged() + + ' Prompt Management + +Mono addPrompt(PromptRegistration promptRegistration) + +Mono removePrompt(String promptName) + +Mono notifyPromptsListChanged() + + ' Logging + +Mono loggingNotification(LoggingMessageNotification notification) + + ' Sampling + +Mono createMessage(CreateMessageRequest request) +} + +class McpSyncServer { + +McpAsyncServer getAsyncServer() + + +ServerCapabilities getServerCapabilities() + +Implementation getServerInfo() + +ClientCapabilities getClientCapabilities() + +Implementation getClientInfo() + +void close() + +void closeGracefully() + + ' Tool Management + +void addTool(ToolRegistration toolHandler) + +void removeTool(String toolName) + +void notifyToolsListChanged() + + ' Resource Management + +void addResource(ResourceRegistration resourceHandler) + +void removeResource(String resourceUri) + +void notifyResourcesListChanged() + + ' Prompt Management + +void addPrompt(PromptRegistration promptRegistration) + +void removePrompt(String promptName) + +void notifyPromptsListChanged() + + ' Logging + +void loggingNotification(LoggingMessageNotification notification) + + ' Sampling + +CreateMessageResult createMessage(CreateMessageRequest request) +} + +' Transport Implementations +class StdioClientTransport implements ClientMcpTransport { + +void setErrorHandler(Consumer errorHandler) + +Sinks.Many getErrorSink() +} + +class StdioServerTransport implements ServerMcpTransport { +} + + +class HttpServletSseServerTransport implements ServerMcpTransport { +} + + +class HttpClientSseClientTransport implements ClientMcpTransport { +} + + +class WebFluxSseClientTransport implements ClientMcpTransport { +} + + +class WebFluxSseServerTransport implements ServerMcpTransport { + +RouterFunction getRouterFunction() +} + +class WebMvcSseServerTransport implements ServerMcpTransport { + +RouterFunction getRouterFunction() +} + + +' Schema and Error Classes +class McpSchema { + +class ErrorCodes + +interface Request + +interface JSONRPCMessage + +interface ResourceContents + +interface Content + +interface ServerCapabilities + +{static} JSONRPCMessage deserializeJsonRpcMessage() +} + +class McpError { +} + +' Relationships +McpTransport <|.. ClientMcpTransport +McpTransport <|.. ServerMcpTransport + +McpSession <|.. DefaultMcpSession +DefaultMcpSession --o McpAsyncClient +DefaultMcpSession --o McpAsyncServer + +McpClient ..> McpAsyncClient : creates +McpClient ..> McpSyncClient : creates +McpSyncClient --> McpAsyncClient : delegates to + +McpServer ..> McpAsyncServer : creates +McpServer ..> McpSyncServer : creates +McpSyncServer o-- McpAsyncServer + +DefaultMcpSession o-- McpTransport +McpSchema <.. McpSession : uses +McpError ..> McpSession : throws + +@enduml + +@startuml Message Flow + +package "MCP Schema" { + interface JSONRPCMessage { + +String jsonrpc() + } + + interface Request { + } + + class InitializeRequest + class CallToolRequest + class ListToolsRequest + class ListResourcesRequest + class ReadResourceRequest + class ListResourceTemplatesRequest + class ListPromptsRequest + class GetPromptRequest +} + +package "Resource Types" { + interface ResourceContents { + +String uri() + +String mimeType() + } + + class TextResourceContents + class BlobResourceContents + + interface Content { + +String type() + } + + class TextContent + class ImageContent + class EmbeddedResource + + interface Annotated { + +Annotations annotations() + } + + interface PromptOrResourceReference { + +String type() + } + + class PromptReference + class ResourceReference +} + +JSONRPCMessage <|.. Request +Request <|.. InitializeRequest +Request <|.. CallToolRequest +Request <|.. ListToolsRequest +Request <|.. ListResourcesRequest +Request <|.. ReadResourceRequest +Request <|.. ListResourceTemplatesRequest +Request <|.. ListPromptsRequest +Request <|.. GetPromptRequest + +ResourceContents <|.. TextResourceContents +ResourceContents <|.. BlobResourceContents + +Content <|.. TextContent +Content <|.. ImageContent +Content <|.. EmbeddedResource + +PromptOrResourceReference <|.. PromptReference +PromptOrResourceReference <|.. ResourceReference + +@enduml diff --git a/images/java/java-mcp-client-architecture.jpg b/images/java/java-mcp-client-architecture.jpg new file mode 100644 index 0000000000000000000000000000000000000000..688a2b4ad0f92090bf0033ab5eb3b20fce1a8484 GIT binary patch literal 676694 zcmeFZ2~=9=-Zx5`G-*a_osu}6YO0Be8iMoKHVzp;OAv9k(Kstca5ie&G;xYpn;5}~ zMk5F~)F>h%v5E6Y6mbGHjyT~wkC(jXeQ*8NUFUr3oVC8*bMMN-0v`4={r3Oad;e$l z`}W@hKEGvg(*khl5CCvU^aAXU9O}Dy{krRScdRXLg3bTl&;$^bBUb@{0Aw)gj^($1 zv$J>j+p+h5AMv5>t~>hvhwpz-MDwooe3%^oV5|RwKL70S@p~R1$Nr?r{ky2U|25qa(dQ?go&dlS5db)C4**EK0{~7q{#Tpm z;~!xAo2W@ngey?=@&fn+JOFT zLmx&SKJuAp;O8fgpA;Sa7t8)10P)Yng2Y&d4=DjY5kGWT{Lp?KK>owEcKFbT@;|5h z+0kRiKRt5zlMl@ypNpbo3Jmz#-9(PmdlG|Llt|C4k>NJ1!}8R!J8M zx4j!2`l`H>EpzUgwjRPRDCEbdWnJCU$~yYr-a$V~{Wa|c6=dUv`swHV(z*+l&vV~s zUAKU_Kl~~z?`^G$nHOPXY~iB$y_drto}y*tL})(wfa-rRiEe~XKRJB#(6P@%t>1}@ zK#7`85$9C-ALFTa5XrAkOjNnZnL-+|pl{rIBvO{bEUO>Wolg7UY& zK7I9eM8^&N)1u6Ud+cLhT{nBE;=VrsICWUGp7>#LfGJ=a`{$Y;Yac1_kpdqn@R0%^ zDe#d3|9_*v;RRMlZPx-y+t^ZN&_v@a^864J6#+x?f!c5z)=x@G9^0i>SGM5uno(OR z^~E|4xf)J{gi&nVQv-{VldLcQu&&ta-eXgjaw5)r5=~npu4R{`83Y?luD^MGVF4k7 znvYISAp3^+p0ia|V)Pb}y$J==b@ftpq3E1JCvHtgR3}Yn|8O+IRIjGt?zIQfO4Y_8 z&Nzan>J6fmn1iv@U@?}gH7tlaF#ogVru!1Y8meiz@Ii^#ff*uLkvhASs}BNI1>!5s z5y%zjvd4CyE_E(qOz-&G&;WiQ^fl}N=4w;@d5a;cr&#jX&al9ElDk&;X0aNdrSGETorutx_iI=c?u$M0Q<-IC5 z);HE?VAJ}*Gz&X__K(Y2&kGzVJJzribD#ayIHS|DZI_lgux_*@cVs(IXe~5!y>wt2 z7sUhpmvdGEwr#)P7_{yktz9r z#f@N=pbzZHfqhOJ-u!bz#SUy0;dX0SZVK+>*8cYu@^NcF-nIYzJp6dqez+7qK9D~? zkpIrIKk{0UF!YhveiWnrTQ2@6Mtzi!|E{ooRDM1xKOgnl|JU_e1&f8r)Xv_+-ZK$> z53aqX#wuDhGknMOBa9}CGvQ!xO#gdqTsidDUK^N1SX{eh8;&WL(=#%V+3FjZeXYpP z3wcW3>yu2XT~?N1XDH8!pyZiT9*T}9o953FG?iPsB$S7ax=s|5y5(5Mt&W{TpEjG3 zY^(JkudkTH8UR1F{r}CP_3xgKTbBI_Wzc1PRWZrQ!ylGpk`~oExRKKukd;ri6|U|BPI~TKgih7|CeybVx8bNe{B4Rgt6DX-3m} zJ)OC0Inpb;z~94!ua{Ej&od`KT{F77C*8jBT^>8`Yt7P8v4x7jw~rL?_;9OzK)%VE zv?0gnj}y;Dj`Y8(C>+@TxoY*z?Kqz6PpEwW2o`|Zwl*@#PS^)DEv@|AwEiZ2lcE*^ zj8Jg-1*foaZ6BcRVO6;P&G7BLXVkmfA8?1h|Eo~{hp%%eG03Z{BqD04J4QVy?Vvqe zcbKs&w>a;PK&$J%J2@L(yQ7}D@WPUK<_A~z2E}3jp+_f-O-&ZEMYmY=?3FNb#1B&H zzx{P*Yjp4e;D64FCH4WS<5R~|=O1b=+uBUKEg3Ptyk@-M zvFF>8Z9n($ZTjvd-`aH%Y)RoCe;w@q=#>sjjrVB+?h~sPXo5M#pqS&W zJMEAPL!r^aQmE=a;Gncne~@RC@sB;y+`7Yw`+)iq_lLg@^?&qAM=#amZ!yQ`W1$<= z2HS%yW9aex3c8V*?A%s9bbv8r861jEIUD<^EJpI;%Fg!Nu-!}Rzn2b@CIB`Se<4v1 z?7nr#a3G6kGO{C)zL}BfA2tv%JT_~+XPN#|#q#y3ns$2_Dd`};@Tw9!;kuGf5&Hld zM*EN6p1%;>sRQ!jlcIy{qUQ9_q#z~gJOk(R`T$eV3qB}FZm$14zXhAW>&}F=0Z0LV z9q>a3c0Xt4?GU~)x_(1db6H!bZ@zrFwz&_#b3j^z$sA-BtY8JnnyK5iiXT7|k$)ZN z|Lm2{9uOAKIUZydF|swCEQK}guxsq-11#bGK{0Z9{`k-eaqw+pBoTY)&cI)Hs)rA3 zzH#rP8q@pRNefo46TShZLq3AIr=_Nw2PMV-MYZJQOd4H^?Rs8l`T?~S@2^AspS=?B zK;*==ii6BzM>jSv$9UFv&V#UZfF%qclpzI!5;arS%tx42>#LvSm;ZIAdhEdNN0l7V zF1hZn*(@qCIHpIKKgCE?QGtUSVj5{{cbX8Q`uw;6?00?Gj z>;vv?rT7s1vW39HOodlF`YvhY3v+-PK!kkAKsGbu{X2-)2&)gd@npJp?IvzghP!u#s z+y>?h1<8%LBUgm{PDpMxNXKgjQ zhBE9Mu1hGOrNyP1&%oP3K!n;PE@2!9G$Ph~(ZP@jXrQuz3gJox*}rao?HdUIn5eru zbgr#shaq}b{f$9K8xd9Gp02s=nbE$v*cpUVJ+Q-5NuL$trceigy$n$Fu6_N4r?~Cs zKQH9DvLhXieXgT0(^g_Nu+9Ct=bCUJlhgM{cj1^5fd@A0)#|iqgGs=FEM|v0CxCJ~ zGJXhdR)@YVzhW&rbSVFqKd;%t>5gRt)0^_TA$|s-GG7!sHr97vyJDZ$R()x@6Vj54 z73f5;F2>In701h6AC$9x-=HxyWKcaFnIExftJah$Ed+O(LphkDDj(u2)$U;ZoQYC< z+w(vKnc#zqe~;^pi^F`W(4&$>4fJ_DbBJ}}zm`7j*L6J%DIfPnzLyb7c%f%dk)4E` z&@pq!6`;w1js!1?69m+6vp(YZ`@AYa&>) z6>F=)=iPH@?OZ@Dsm(YulYPfSQ1JpAwgjlfm|79^iyP`jZXgFdPh~^G%g5u#eahkq zdyGNVzE6^?|D?k|sC`s}{{dnC{lkBu8hkZJYf(b+k&!wtYH7BUAKYd@{33DNZ36zF zpcLFl(pAgDQ#&4<(Hk2Z^StNW+RAjES)U<~bJI8-tt$Xf#!Z@Y8J{V!POdxye*VS#f-EBp(HD{b+onVR< zV}3K3;~UmRmp?^E2SyoL&mL32er0_js>}5HdT;Wg5!E)$D0TkEuGo-^ZrxI^W7a}Z z%FR59LGrgoax474y-h7vvSX-61M*BHayIrshF3!omzVju7YqgZ8hSSNZf z#Ez`ZG{_+0f1^+Wm9VQys+AmZh4VAdBJyUliu~d-pGJ+C!!7zd*o7WY`N`6BnW?0w zdqu4}Q~Q7!7uunX6!arG2X53L5^kj-?V+=rtK?ObfKuVlu};-X!GVem@vDlK9ShGU zDrNh8^?Z|ao|(brfxzjskc!r9JJb#RCcOOLF|1e%5W(G{HSzQ2c}XFAOoBx|uQ&DlU~XJICVaMuvBJBJ1?a+t~GOF7YPU=Sb( z4l~MCGP*W8q_~mlDy_$$>lVrQmWZip`1>pxZCZR)Fc%u7%IwH+Bc+VOVI@3I*WQRY z1lc6HvbWbrd=Y;~L1$uVa7}Mu6&@jHl5>8D3C1Uns0w>up>zoS1CbRE;8s?Gw@fk= zSuoz+Fvqc{_U}C#D1IGt-Y@^_%|C~j{D|if=AbcT)rU7R37xKPS`4e=6u`z$3xD3* za8qf5R$W>qr%i{y~8lPysrPrKMwBx7$ zba92Wev5c)DBlvWY0&p!vZL8k(QCSaDM9@k^@I_h!So^b(2aF@{1XT3me)1zY~t37 z;`t~_h7&Gy2)QR%VTn3^K61TcJ8a#Q5QSm=5f{SP8x>eq<%T z9M?Al6<@sXSN-jb7d{Nfui2qJDPHvNee|B+FD=+prv#fzHm;bNBruGe_2lFWKgFC5 zUWHk)kl818q$HftsFI#y;CwQ%U=}i3BPQJ!+Ld{f#g z6YLgtikxfMk6n~p#?4zgbPvR*h@r_YnqQl!#MFk@yRbT%rhT>>Wm~cc5wLU5>Ah~G z?M2;yx^U023!W9C$7cJNg3FJ!Naxy!p7P2orqSU; z60L9_ShK=P%Ddgw(FfM*A#~P>zLgB1@$^gOH!KK0W&SC6gG2Ll@_a8K%r&kz6CU_- z%QVu%_4*6$>RoF>tXa&b-ks^Gd~J0)%dAac zT*mXkj3OvTvz)-J4d2Af_Vyv=(S+Dimn$B#;8_ge%zXW{L&Cg;M?9HH(HAH1&t^`Z((WK3RiFNF=<8oPcdvz~ujstDrMhTXqPuBg z>JlfPZC%XlW`&UTLmMw^@y1O~RK2EPcZ~ZpQa)dAhQu4l;b}(-hEx8ab!AwMMZ54&Ewv5P-K4!>iz2<-awlHNg2C*?Ff0n8MU*3weES zR9w=cY4`T|rLW72Oap_geFK-_5sHN-0H#`!25vd-5rdg_36Mtf_1~9EE$*G>SySgk|Ywqs58Og z$C_u+w5+}fY6%AJA23sRUZcEXekmMJ=coX`nec_7<(1|hmX zz|nI>llb|24|JFGX^&|SyZ$W88H*%AYxWEX z1Q*{+1HpmA*jYaXnMLb}`wv4#=XTRb9XjxmZz9_tOqZtl;SGwM^Rhw;a$LIWmP96r zgvXcB=R5=BvMgXWW}5_0T+Ype;e=gpSR%u-NZ1$Ze>Y2Mr~P zprF)y>7YVOSVC7~xG(aB4_0rI-S}>4>PDz6N?X+;EK!==Q z%Y6Xi4vbT7btyP_#KKs=2UW2)(OC>jONva)CHv(@)FI5F9hnu=7%E7<6xc&3*eWoi zTx?pNR(tZQXuN4;7?a_Z#F9N%KeMK~R$6Fe^<`g)Z0wxBA0F;!*PdHaBQq0cQFUlH z<*e%?bc~#SSrv6BxtG40%uY}7tl#xARsN3Q+Xi-|IdjtxTI>$b$Wm>vrG8H1%|8dJ z&b6py<;GKxTliq=`|Xv2_YVvvX!!w5S>5}7xQd09U4!}vdwUtxG#w#SLK|)x`Q=ii zPX_VEK*a+tF;tkHntKmv%rCw>W#D-Q&3Kv?dNEh^4HzvXljhAuCZs5(ufANAY5rU1 zebhCrJsJO`j4UV!!nA}lbOPY58#aA;ogDCn0jJZX@Y{P+Qe6`0AVHW@dkZs62Kk;} zoUIHNv}D?DE+wTasiq-(Q^=w`%uUOCCWD8A;Uk*zo6{No_MH_%%2VWA3C^uZ&obvL$uKJIyzw^Vg;I+-gsS3z5=kPth7SR*wsG{-bA!%a?izB-O zNc*me$J$z~0O^(OWvS>r>J)wwdoRkdS!Jk_4wdbV8#t4fY?QYTC`}K%%Oi4f!qga2 z(Q`Jt8~(#c2#?wCJDA@oPUh%c!7m{^;ZzS?lLM{ES68!q4KL*>T}qgHX1RDd#a!X#DoJ2$pKe+OXs#YC}o6|JiG2gCj z^$b>Pv$!xDzuaQ0v=8`>=%NpEoM~36r>3H19`lSSN*v>76Mp*gRWp zVX{E2RZ>Dif`~<9qEmaujS6-&mHi&AEskVc#vn7-H$!{fTh=hHs(+qvkHxLGo`2( zy)yb$J-vWOOR8B@$oW;T!c_@r@*Cs-rT;Ta?N zZ@liXr|44FBwclmwXJF2^Q1xN;|5;~Pk-B>o?YVQ($K^-PXuWt@dx?Z2pcm;!_B+a-iussj)^iW8_-7~FU-u!vL_O;2Wox|CSt=X+ghe@yqHd= zuT4L{wVA&`lkrV5m=DR;<`ShT1|ePA1Ay+8f1+f5w5|RV;{1C}f1Pc0!qi$pWv?Tg z9TxEYSQtdt%YNA)o=_az0e2!dk&SOARy`MRUrl;R(dJ}M>7gri=fdvzbS_YszKMco z&NU{F+h4~{Igt}%2ZBnV-Jp=@>zCo(ul$-?+nFvF=F@^~(Nn~R1BVIQ+FD=pG+a5F zh-9+fr7a-KFj9H&M+`k5Xcj~fQ!ab_Ixt8AK4Ke!31@i8wDhIH<)7kGCBSXgk&zX- zW8m18^48qrw{ugz2tWDO<%D;YbbkG5dNO5NJ^*1uvlTge^kwK^s7<(9F3&O7os;Vr z%hK)K7SbzrP*R3@Ph8xwJO+eJz-|FoyzWI-3hY-ahH1}*b$((p`SYh=Cp(xlFEu@f5=q!A*t z(vHFKfr!VVzedQ7uJY(csxj7tPH)^UVv|b?!Iol28pS9BNy&+xZdD$=F|zXkrt#Zi z-wrvr+FtRq(|J{uiZB^Rxu>I)lRFH1FaY^w4@w?_3*UsWi5)le_ zer?MDLI!+NMmobNh@sc7cxQrs$fC)jPuEMlX*UAST9={8P^sewHG6pe0o!qTa!0sr zl7i(uqh))vQ#eu2TrZ74L zzO>L@58StlHR?^kTFY}s2F<`2iVD+}|%d*^G64LlT&Id!4}Skv&@x;^ycP=){N2XbF#1-pg(iQIYV`}SV)YzuqHEd2_Z6lVf z3Ip#`?y2bkNKM5TT21#IBfTFzUG>GZE%(dg}-%=krmtanwtw=%?-RX8|D->Pt) zx!nCwipZu!$L5LZauDn z_o6SY!xZ)bZqi4SX6mob8!rhSKL@=0Fh0G*Zd6%zh=kC(zsIlcC7R#?iN* z=8n0;5RVPZ!!&|~d;R^w*NDeudP&{(DT7!HuG7b6-Uo*&NiLXW6>gJONzB3t zL`+hMwaKWb@o9?Fj!1s;Chn$Xk44;fJuLH0>!=GY4#L}+q21TAr<;N8O3hXSU2?rP z;JrOGR*g8aK+r<}`HNX=fR?PI-%p0JH>hS%-in+dP05hoGfqZ2;TxSpZcj&*)^!|K z&pYYjX^X254=U`l+LoxzPO!vqP;n=`ERd-KJk(CU0U5F;zg%?@Pm$^Oj zv%9#e5v9v-x?gE+<~Wzh2+f-W>(wQuY>kqjzUhVjG@XzwUF`$`+b$nhy+iq^2K}MgOA1Jfwh{RX?KYI%CXg)JeDALwtJOgS8CAHMRh596p6*qP`UbJ4mgqQ?3h4#7JDL5c5``JPj8EWPa}AA z_LQc3GGu&Ky^C=K_bnC2`+DRBy$qnF^=XjAa*ES^U~#;tC7fp(JoB4k-{PYUgzj)H z&K}!)_0{|^f4sL8MS-JMeR5#?098oj|E=_zgKhD3-mrH$+>T+T5 zU3hHX!q6vU?6BZ_oToUT>E7)WEsmu1Ru z3eJ3t_uFmXeGtnwIXH5RVc%Z;^R|gkc8Fhtw@G&O)i=ZYfOF)Y6@OoUpKY3KyNSTu zh?J+MmJwJNy_tx#riDHbD{0yX3`H1vB`;FdnlkQ(d7kF^J)ekx>CSe-XW%TFIAp+m z^JYZ0y1~r=mtV?-5nM(XjIH4f%H)&VGtqpd^`Pl`}>L?taj+9#7NiZWbUX) za|HTSW`yOh_wipFH+qdq<5mC1o97qCz;>6UCXq6&U++ZHmH}7kJ7ijn5Yplg<0VM z`O5g1%Lxk=qfZ{_juh_>tI%a1-bKnKgOmyq1GyM@e{-(skD+|0sbWK~bUlIGW?kJ{ zVaM4B<)~PbD^om&fv|GMa!UqPT{U|)0)HBAPmanL-z!3>4tRI0D?gz|GB)gnIzb@f zyv1vzDMAb`2aWNJ2vL_lF+-)3mXViC+JnLiJBa{dI|6rkUyL{WLh2$~KoY zm>~3a`)} z?w@;PR5wxrwqX5qWa+iY467tqz4t#A58gMTBLxy`u{C?@yD9sCu(IX*^DUc-J4tv> z`ZAnSZt1{)vlR;2SLZ-SM$^v(1i3zvO>u{tgHrKvaJvsyr6&xu%oUdDk+54nBF|D zD)6=b^BG;4VY?MyvxaqI&6sb@>^kv%bznz#%`al9r0udn{7;KDhIjUS`Eift(6HUB z>&FJ~9*?*nr#+|7Kqu)*>qAq)lU2!3Ii|d^A9mH60#QOm7T@gZmAJ*#VsQIU@s5A4kJ(0(5nGgr>in#Chd zSzc37!%-tOu2;_83N9LP?YxbVedy58G*^YpMzM3EV5arOV?4S7$M3T8 z%kqfU(M0hA6c2IV=#PY%#^7bd&J*4~z>y-6+PYC393VV-hkt%Av!Xo8m}?4er9Mgy zWcDynmATk8hNrl$d>Z^ABUU0lStTLEz>u_lf4Qu|d8l5C-T3zP4yO2gM8faX7*(&) zrDh(^1ooC(Fz;rEOC%FwyBOMajr)M>x0vCMGTu{+lb(|dO;K!sO438GGkj;egc6b{ zNYkk1k#6qSfiH2_uC)xb+o|61wz9WEGtfjlP`)I|i*axIyoPhN zuW53OdfPzCOuZ&{yjQ8?8mFbg+=gZLwqq=?0E@Adm47*0#0{%NQv)6F-=NLjknv2N zi(@0)BBo?msLAr=ZW&1Ek~sI?r`rcHC73LrCvRJ;G3kUv-))ZBhN~H0NG8`h&}EfK z80=13-|;Qj>59YSGv8d?R9?S`IpJ+foSx?Ety&H~0T;(EKXQ6(^ec17jgqN(x34LI zVRmnN)3zoFyc%FfSzKyLsjJ~J$;A^rZaJ55lL^lr*i8A}u{>VnTvHFpbZgwao%zrz zH)WNm!nV~=AfFu(g1>(tMZubm!0hT0@%3a@1*KC-{*bbv91=$uY)`N^e zn_Ay1PqzIwbm1+(uV?M_6n=nQ-+hT-+Lbtq-kZwL-;zQgF;Am3D9ou66Xp4iqh^-t zOVFH~o`cM%TJqSLae;h_ykEYyqqixLXC~V++`)~8;B}G zSj)vyR3$Bxw3eGVowj#V9!;lHE%?Hw)m_aD<9$G0LQllqzTXv<9e>ye;k!!&dPibv z@J`Sqf}2ZQjScH!Qs`vHbWY5fru6bUj)4W+J&Dmuk7-@)7~ZpPzmh}TV)hhUr3N1s z{RctKiHRLOw5qDooC}0UVRwvAPt%>YsNm&v$e+F_lQM=w7#*&)1h=k&>uJb}g!%Cj zD@xep)TK%?V^tUUyBc+`BrTxvZDRHXhO0i}=fak?K`$q=ms!RFz*! zy}2!Mmw34{Db>PmP@!aR zUQv*UhE-XRxLF<8@BAi_d-|-uF{9kiwpTyqx#-4-PWQ*l zw(dF|m^{oP&Xh~=8-?v$lK1fGaLuo2zXT-D}4#NqJ?WVak>hnq2V@+zHis!J$g4!3xE-hVvmtRd7O`5$^@ z^8ZI#uKHJE-(-ffA3h=t53;FO49|trwIGxpO>WZjIViBjhl~?QnKj0IwVje#*Jkzm zt6N!iOC}oujAB<#Wk|u`fWf2YjGZFM4vSAiLRlUXK<8rgjspRUSv`I-VOL^<|F(dU zUKn7Qk(2JJ;@e%GkVO#(hqlAb%$#WA)4k?EVbwc>CybCy%&}V<);7dni^00Q563fLr~DPBkcZ&l}`T4vEGEIepz6cvqVb- zI23FhqhhF{@)hrHslMk-Aw=e4SLH~~w9%pwp7is1660rzUCuGT-xa!&-i>&@8~rhoSq;VrNOShf5@Mp@tE6&PXbA^nn>%Kpek5q*wcSOhc%yUms^25%_w ztx&>%M$+tVYd(^Be%7(03v^{-lw&+Mg{&m&Zp7&jh5A6_#O;y?|$CSH}KpTh%{N~q|Ds))3ZhUFXs&S(7|vHekBioDdk8V zVd&4$cp8glYHs7X_92mpbT>ZRzwNE~{}R6lx{qduxo?lLO|%30(=8cu`v9+u=*f*U z6JN`H5)L>MB+>_R&MPv(ff$b}1A)x1##6&Dw!0fPCL9ZSu8-V1NfNSyB16qVf&FU} z3*sCrGUjB%j_~#-B~(F%-fq28%TtW_u_XrQq`f7($aNq}H;PskQx6n-7HZ}~jw%Aa z#~?`b79+`ajl!>7FQ`7Qd4-X>8#pT~@6XRm>sYA^?U3IjByRKf5K3*^&|W-zZY*fm z0|zsQtstY%39@qr#q5)4HMA1toHF`qKUciWsFN|Ft-nlaP&NH#oJ5n}CJs$oex*1T zy}(|xuP@AA&UP<(SPqOTqGJUTxEQtEZq&k3t|nXv(fX>MGDo`F#;0O zDss?EZv`qNiiNbM$Q7~!v%=Lfvgc-i<>Q+H!JTj5&4VlJu+BF#U%!QNG|X5Mkw0v7 zjsMHmeiJHU%W)sDNRHj>E$V!)_?4qRsEhWqzTDqNk5Y*4BVpOOkwx^!%$7?ty{2zO zwseR#oGaNb30}gK7tI;p*Y#f%cpxgYtEx%a$u>h>tLHB!7T+BjZ^dg4LlO7jmLdZZ zgDu&H>P^g&AKH=aoqng=k${%=#Vu7hzYZB0XDhy?qSMu?MVt&Sw<~G3W>WfW;;eJm z_-;x)OQ@ukW6$=03dT2Y5rkF0_ZsBOnmV0na$xxGk~RAn=B;6u5+{ojb49WNCI|=| zN{Cw#?{vO-HN*f63aLdrBhg#|jSLAKqv`sB`T~?K8 zSqot*e(}1nF{~`#F=KP9nlb}p?WP+>-LKs8>*55r8DdT3m|SEC)jNjA+-H zOu23b-nbP1m^V4vsT>hRfj0I~XZ_nxdO?AxxfiJ3I};wJbq$Gmo#^>6E10=)4IIeH z$y95(%6ML8t9cHk%RcW{FWzh|*S7aUS~y(_HFMMR(&EIgV&YUh(H-wa0=x7*Mjzbv1mTGRs zE=}_+|Ml_p*8!Om+Mbmyi`w_iW-&LC@%U^HPo6{WCEt#x53ZFY8OiVrUB%7^`iA;% zz97KBXfmpB%fOq+EjH-c2W&N?G|0ZWq}(dc3{nnELXM!?9VUNtrD-yu5LPHy40}}N z%-iwbewtc1b+(5-RnR#d6wgdo6?YQ8wKJ{#0M9d<6;@h#l;n7DyCtO#VN zJ(}VwgU^XpI#pU=#{f!=bBXWRX_kv41>?Qr ztJ=!~aVZ$6ChOa-RcFLE-G#ne8hL3%!3aX;%Dqu%GKULqe4IhTW_Zo(<~(HMU%JF4 zSjh7^kH|2j(xnnpE2?vc%S#RzrX9U0Fd487sLV_cUf?oITQCrNFzBm@eG8L1KlGWr=7e&m)&XqJVw`G5`_4w7R_sN3mf1cGm2toV9*-^3^_Y}_= zL&Z~(*nNO)1`>to&xDE(L6s-$!wpIil0U~VxrKBCqW>^!{NjI1Z{a8QlcRh zDoZdQ`t6{ORvB0)^zAX&E||(czg2sVeh+QzJtv>&?i`31N5Oa)RL!;virv z?ddNJMq<{@q3Wr@s2Qgo_2n7!tU_*DKOwf0#v)mdJn|az9`@`km@oRa`gZpSzx1JR z(lXMG53ffMd=eRKpoH8gHxBoB%<$X~^dx4O1Brbj{{1jExr~;3GQ5L=x)}f7`5$YI z6R7`=E_T!`F3+bsMpR>y(*rRbieWb9x|OwS_oajG(EQ3d>xqlq*gvm!m5S% zFhftd|Kw$@5CbI~z_#L_s8S!Z=l%(C{@td(Dtqn_f%-a*DX*(ghOZ1MRqK^o(? zwbmFkM1w+CTPCWe#~~Y{9Qn4T`1n=XXE$m`7SG9$u=<8kn_LKonJ_b zbNUAFp#tA8#u(Utl+;fZkzDS`X4Eh_)-psJ0Zz6xcXspydI=pP7v@4Xcp z{KVg<2DOe(6yLj5I4?x78+`D=E8lNTM+tsX~o8)7ZF87cMo>9FY9@U z-SiM4aWb*0he9B&=w8Oaj2Kb;Us@Up>YNGlh(uy+an+2$OlvXUW!@b!mvtJH7i>5= zPFsB$FHT>||><<9HmpQl0{U%YboWFLPB~aR|A|0 zxD~|Z9JJha)b20+heMv2^R%Pyw8J1yr638mm>NMXSuNS_*lE4fZ)3zJJg4Oh26FC= z`Rb6$p1P*LLK&>UKtQ7Ff#c2^qm;!KJqaIEuGI#BOZ_l5fBKu&;xURc%J;|7#nP=VH z+#f^xr)Lb}ShPos&{-~lL%x)ocq!3`fE|~t3(Hl0BQ|-X&K;=7G!VHLr^@Vc?EGXc zm?io=K>3=Vi_!|}Jxf}9CMq*tR=3^xR*&}CVAo|!4N*=S2X4dWP(w4KRH}%0jcDfj zdTk7bCpWA>j}2N__u5P=7#o2<3SG}QhuG>-D^8rqDVm|e6cYIo9m;sG*a}Cv+p~`~ zNg-z_w#%OD(FQ)vgsQ94!G5p1v;k(GM!Qjg-iE~6%v_|i%rQ87erc|fj$Ij~x@xQ& z_$FXj#|l=Cm2 zMip%%ae}nm*6N`JGxGs^129d1^OSi0S-mgo<&w5A6MY*Mt40YKl5m|1e=6lhkXVem^PLwH9BNb ze0vDiI_masc+3Bby)S`k^4u1swbix`lmeoREmRN?6vH5MTN$h-x2CN{=R?z``h#Wc3oMP4a)9biQk6KGFA=7#AQx+HR`)2YLXYA(#ou8fr(AV&w_sa z7)f9g>lZ!mS*PaaN)XwxWKFXmJDy-({GeaWvtqN