From f7082431e29b0eca79ff2fdd97f09af14c653b66 Mon Sep 17 00:00:00 2001 From: Hieu Tran Date: Sat, 12 Apr 2025 21:11:16 +0700 Subject: [PATCH 1/4] add section How To Work to README --- README.md | 231 ++++++++++++++++++++++++++++++------ docs/mcphub_work.mmd | 79 ++++++++++++ docs/simple_mcphub_work.mmd | 45 +++++++ docs/simple_mcphub_work.png | Bin 0 -> 65430 bytes src/mcphub/test.py | 67 +++++++++-- 5 files changed, 371 insertions(+), 51 deletions(-) create mode 100644 docs/mcphub_work.mmd create mode 100644 docs/simple_mcphub_work.mmd create mode 100644 docs/simple_mcphub_work.png diff --git a/README.md b/README.md index 817a094..55c7231 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,214 @@ # MCPHub -A hub for Model Context Protocol (MCP) servers that enables you to manage and run MCP servers locally. +MCPHub is an embeddable Model Context Protocol (MCP) solution for AI services. It enables seamless integration of MCP servers into any AI framework, allowing developers to easily configure, set up, and manage MCP servers within their applications. Whether you're using OpenAI Agents, LangChain, or Autogen, MCPHub provides a unified way to connect your AI services with MCP tools and resources. -## Installation +## Quick Start -```bash -pip install mcphub -``` +### Prerequisites -## Usage - -### Command Line Interface +Ensure you have the following tools installed: +```bash +# Install uv (Python package manager) +curl -LsSf https://astral.sh/uv/install.sh | sh -MCPHub comes with a command-line interface for common operations: +# Install git (for repository cloning) +sudo apt-get install git # Ubuntu/Debian +brew install git # macOS -```bash -# Set up all configured MCP servers -mcphub setup +# Install npx (comes with Node.js) +npm install -g npx -# List available MCP servers -mcphub list-servers +# Install MCPHub +pip install mcphub +``` -# List tools from all MCP servers -mcphub list-tools +### Configuration -# List tools from a specific server -mcphub list-tools --server azure-devops +Create a `.mcphub.json` file in your project root: -# Use the MCPHubAdapter -mcphub adapter --config mcp_config.json --server azure-devops-mcp +```json +{ + "mcpServers": { + "sequential-thinking-mcp": { + "package_name": "smithery-ai/server-sequential-thinking", + "command": "npx", + "args": [ + "-y", + "@smithery/cli@latest", + "run", + "@smithery-ai/server-sequential-thinking" + ] + } + } +} ``` -### Using in code +### Usage with OpenAI Agents ```python import asyncio -from mcphub import MCPHubAdapter, setup_all_servers, store_mcp, list_tools -from dataclasses import asdict +import json +from agents import Agent, Runner +from mcphub import MCPHub -# Initialize and set up servers -async def init(): - await setup_all_servers() - await store_mcp() +async def main(): + """ + Example of using MCPHub to integrate MCP servers with OpenAI Agents. - # List all available tools - tools = await list_tools() - print(f"Available tools: {tools}") + This example demonstrates: + 1. Initializing MCPHub + 2. Fetching and using an MCP server + 3. Listing available tools + 4. Creating and running an agent with MCP tools + """ - # Use the adapter to get a specific server - adapter = MCPHubAdapter().from_config("mcp_config.json", cache_path="cache") - server = adapter.get_server("azure-devops-mcp") + # Step 1: Initialize MCPHub + # MCPHub will automatically: + # - Find .mcphub.json in your project + # - Load server configurations + # - Set up servers (clone repos, run setup scripts if needed) + hub = MCPHub() - if server: - print(f"Server config: {server}") + # Step 2: Create an MCP server instance using async context manager + # Parameters: + # - mcp_name: The name of the server from your .mcphub.json + # - cache_tools_list: Cache the tools list for better performance + async with hub.fetch_openai_mcp_server( + mcp_name="sequential-thinking-mcp", + cache_tools_list=True + ) as server: + # Step 3: List available tools from the MCP server + # This shows what capabilities are available to your agent + tools = await server.list_tools() + + # Pretty print the tools for better readability + tools_dict = [ + dict(tool) if hasattr(tool, "__dict__") else tool for tool in tools + ] + print("Available MCP Tools:") + print(json.dumps(tools_dict, indent=2)) + + # Step 4: Create an OpenAI Agent with MCP server + # The agent can now use all tools provided by the MCP server + agent = Agent( + name="Assistant", + instructions="Use the available tools to accomplish the given task", + mcp_servers=[server] # Provide the MCP server to the agent + ) + + # Step 5: Run your agent with a complex task + # The agent will automatically have access to all MCP tools + complex_task = """Please help me analyze the following complex problem: + We need to design a new feature for our product that balances user privacy + with data collection for improving the service. Consider the ethical implications, + technical feasibility, and business impact. Break down your thinking process + step by step, and provide a detailed recommendation with clear justification + for each decision point.""" + + # Execute the task and get the result + result = await Runner.run(agent, complex_task) + print("\nAgent Response:") + print(result) + +if __name__ == "__main__": + # Run the async main function + asyncio.run(main()) +``` + +## Features + +### MCP Server Installation and Management + +- **Flexible Server Setup**: Supports both TypeScript and Python-based MCP servers +- **Multiple Installation Sources**: + - NPM packages via `npx` + - Python packages via GitHub repository URLs + - Local development servers +- **Automatic Setup**: Handles repository cloning, dependency installation, and server initialization + +### Transport Support + +- **stdio Transport**: Run MCP servers as local subprocesses +- **Automatic Path Management**: Manages server paths and working directories +- **Environment Variable Handling**: Configurable environment variables per server + +### Framework Integration + +Provides adapters for popular AI frameworks: +- OpenAI Agents +- LangChain +- Autogen + +### Server Configuration + +- **JSON-based Configuration**: Simple `.mcphub.json` configuration file +- **Environment Variable Support**: Use environment variables in configuration +- **Predefined Servers**: Access to a growing list of pre-configured MCP servers +- **Custom Server Support**: Easy integration of custom MCP servers + +### Tool Management + +- **Tool Discovery**: Automatically list and manage available tools from MCP servers +- **Tool Caching**: Optional caching of tool lists for improved performance +- **Framework-specific Adapters**: Convert MCP tools to framework-specific formats + +## MCPHub: High-Level Overview + +MCPHub simplifies the integration of Model Context Protocol (MCP) servers into AI applications through four main components: + +![MCPHub Architecture](https://raw.githubusercontent.com/Cognitive-Stacks/mcphub/refs/heads/master/docs/simple_mcphub_work.png) + +### Core Components + +1. **Params Hub** + - Manages configurations from `.mcphub.json` + - Defines which MCP servers to use and how to set them up + - Stores server parameters like commands, arguments, and environment variables + +2. **MCP Servers Manager** + - Handles server installation and setup + - Supports two types of servers: + * TypeScript-based servers (installed via npx) + * Python-based servers (installed via uv from GitHub) + - Manages server lifecycle and environment + +3. **MCP Client** + - Establishes communication with MCP servers + - Uses stdio transport for server interaction + - Handles two main operations: + * `list_tools`: Discovers available server tools + * `call_tool`: Executes server tools + +4. **Framework Adapters** + - Converts MCP tools to framework-specific formats + - Supports multiple AI frameworks: + * OpenAI Agents + * LangChain + * Autogen + +### Workflow + +1. **Configuration & Setup** + - Params Hub reads configuration + - Servers Manager sets up required servers + - Servers start and become available + +2. **Communication** + - MCP Client connects to servers via stdio + - Tools are discovered and made available + - Requests and responses flow between client and server + +3. **Integration** + - Framework adapters convert MCP tools + - AI applications use adapted tools through their preferred framework + - Tools are executed through the established communication channel + +This architecture provides a seamless way to integrate MCP capabilities into any AI application while maintaining clean separation of concerns and framework flexibility. + +## Contributing + +We welcome contributions! Please check out our [Contributing Guide](CONTRIBUTING.md) for guidelines on how to proceed. + +## License -# Run the async function -asyncio.run(init()) -``` \ No newline at end of file +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. \ No newline at end of file diff --git a/docs/mcphub_work.mmd b/docs/mcphub_work.mmd new file mode 100644 index 0000000..2118991 --- /dev/null +++ b/docs/mcphub_work.mmd @@ -0,0 +1,79 @@ +graph TB + subgraph "MCPHub Components" + PH[Params Hub] + MS[MCP Servers] + MC[MCP Clients] + FA[Framework Adapters] + end + + subgraph "Configuration" + CF[".mcphub.json"] + PS["Predefined Servers
mcphub_preconfigured_servers.json"] + end + + subgraph "Server Sources" + NPM["TypeScript-based
NPM Packages
(via npx)"] + GH["Python-based
GitHub Repos
(via uv)"] + end + + subgraph "Framework Integration" + OA["OpenAI Agents"] + LC["LangChain"] + AG["Autogen"] + end + + subgraph "MCP Server Runtime" + direction LR + ST["Server Tools"] + SE["Server Environment"] + + subgraph "Client-Server Communication" + direction TB + REQ["Request
(list_tools/call_tool)"] + RES["Response
(tools/results)"] + REQ --> |"stdio"| RES + end + end + + %% Flow for configuration and setup + CF --> PH + PS --> PH + PH --> |"Load Config"| MS + MS --> |"Install/Setup"| NPM + MS --> |"Clone & Install"| GH + + %% Flow for client and tools + MS --> |"Start Server Process"| ST + MC --> |"Send Request"| REQ + RES --> |"Return Tools/Results"| MC + SE --> ST + + %% Flow for framework integration + MC --> FA + FA --> |"Adapt"| OA + FA --> |"Adapt"| LC + FA --> |"Adapt"| AG + + %% Application usage + APP["AI Application"] --> |"Use"| OA + APP --> |"Use"| LC + APP --> |"Use"| AG + + %% Tool execution flow + OA --> |"Execute Tools"| MC + LC --> |"Execute Tools"| MC + AG --> |"Execute Tools"| MC + + classDef config fill:#f9f,stroke:#333,stroke-width:2px + classDef source fill:#bbf,stroke:#333,stroke-width:2px + classDef framework fill:#bfb,stroke:#333,stroke-width:2px + classDef runtime fill:#fbb,stroke:#333,stroke-width:2px + classDef component fill:#fff,stroke:#333,stroke-width:4px + classDef communication fill:#ff9,stroke:#333,stroke-width:2px + + class CF,PS config + class NPM,GH source + class OA,LC,AG framework + class ST,SE runtime + class PH,MS,MC,FA component + class REQ,RES communication \ No newline at end of file diff --git a/docs/simple_mcphub_work.mmd b/docs/simple_mcphub_work.mmd new file mode 100644 index 0000000..92f3f33 --- /dev/null +++ b/docs/simple_mcphub_work.mmd @@ -0,0 +1,45 @@ +graph TB + subgraph "MCPHub" + PH["Params Hub
.mcphub.json"] + MS["MCP Servers
Manager"] + MC["MCP Client"] + FA["Framework
Adapters"] + end + + subgraph "Server Sources" + NPM["TypeScript NPM
(npx)"] + GH["Python GitHub
(uv)"] + end + + subgraph "MCP Server" + ST["Server Tools"] + COM["stdio Transport
list_tools/call_tool"] + end + + subgraph "AI Application" + APP["Agent Application"] + FW["OpenAI/LangChain/
Autogen"] + end + + %% Main flows + PH --> |"Configure"| MS + MS --> |"Setup"| NPM + MS --> |"Setup"| GH + NPM & GH --> |"Start"| ST + + MC <--> |"Request/Response"| COM + COM <--> ST + + MC --> FA + FA --> FW + APP --> FW + + classDef mcphub fill:#bbf,stroke:#333,stroke-width:4px + classDef server fill:#bfb,stroke:#333,stroke-width:2px + classDef app fill:#fbb,stroke:#333,stroke-width:2px + classDef source fill:#fff,stroke:#333,stroke-width:2px + + class PH,MS,MC,FA mcphub + class ST,COM server + class APP,FW app + class NPM,GH source \ No newline at end of file diff --git a/docs/simple_mcphub_work.png b/docs/simple_mcphub_work.png new file mode 100644 index 0000000000000000000000000000000000000000..13ac4e42633ae502c04072dbc8c0bc5e286fbd50 GIT binary patch literal 65430 zcmbrm1yq#Z_dYs=pdg@vA|N54G$<(z(%m49(v8F*42^=)jr7nZAl)FM(%p^HF*FR# zJ%gXm_xJtX`(NwcweGCtVrJfV&U<2?y`TN;=lDrkQ3?--6bAx<;K@jft3n`{K@bRf z*G(+&P25jQ)E_h_RjHSd;@(GV-~*<)sDda2QW}nX{`v;^e9J*v+X(`}Z$YqQTY zfk3X9WW+_)-x+Mq;KGTP+>WnS9I%TtJHl@Uxqn&y_~e#UQO@%i3wg*V%}<&%IQOhV zDuO=U`PhOR`HCpYkDJyi0&Y}!Z-Mf=f*N53ZA(EQt-8Rc!@Tw<;z8BzDf?+FDae_W zgp@||-mTt=3oqyK+6E5(dUIFSKB4Wi(Moqr&@J%dDv9>|`&J~BM){vF{YCEny?Ps6 z;_sVhH;K@$-+iO{|8i5F_2Kwih%^zt66!~cMa9LvVIx?ev3qUgaT(#LFO~6I<|D{T zVtwxVQbRu7y?wj(_cvdRe7EasRxRI@rXp z4(F>`txnfE^KGBvQmwQ&~h*2SNH==?)5 z>4u_ZDvw6a`@W5?vXrBD2K%dh;lY)+my0p|cPwY)E|EK(ep4vGy^A8#h^?Z{zt8pXDfWMQW_0 zF2(;CcCs-Q$#@Ps2`;zEE%Gjz-%o7gZZN3#de;c<-5sl@!QO8=x$c9l&?UBEiRZ!n zqlUG^!Tr{a`#bJEr)1)D^?YN^*+-X+Q`q>dZaVF*!JML&(V5rU zj-Xe2iY^C$HL+3B!2&vKX=-FFp zxgp1gU;L`JIfiT}ntFF0w8aO@Z)EWd<{*;V1UA;Pc-~ZPj}D!XOjQrnO~-PCYj?VJ zSIpR*e&>?oJbA@Y#@h^bLPy|~p*xKh-cZ{tXf z>}C&}&6yAf`Lvf&Bj_UN2F2C$t0UtsUc^_=*h3GE&7+iW?z>B>WCyvpvrR0o`j0%# zbh;8oa3-4ADpM0W)q0b-=XCAQ6h$}OqHo0R=LAnQ32!|w(aHsPxb2v~3!ms@@SY|- z=6^9U$`Q^t71yV!c(RcC!_F|bl?iKXzfBMfeCn3NMnc>Ck=TYrXMXc4!_2J5t2&pB zr}}lyGB<(>cwdRbZ;DXYSecR1PL`X8chHj}OI#d}AG_=wcDZL03WaIB_`B22V z`F-4rZ==Lg+sH|!(`Q9O%Z2UVHO&}Uoz41t-nKs5xLFkMp6XnCj5zIb5;Q+O>Bj0& z58@#aRN=3!%3sUs5C zpLGnn;Puw&`^JQ$@5-k+yD7s!*`g$!WY&0C{mCVTFS(X)$MNA_V;K6?WlLY_NYzSk zG4VLO^BwuxQf;+v;#m4mM|+;H={`nOeetaEwy-92!@wzndAC1fOb6SMv%+*02J3Ev zOOCeHtJ|3i3TCW4O3C{t=SyC-FY;Z~lH}sMs`S0B!K2nLaCe_hLA|<>9$}ud4J9;l z`?ZJc(BU-uw5N?P=Jt7SG=ggpmd_rJH(h;Zjkm5xxO&O6wI6zP8m68! zq#vT6ZU3;Z4(&5{tzPuLnqL_YGAtp#ynMV{vd}k|Oy}bLdnUM{N~F$pn^nIaTJ-4) zHSmCpiUeYO7I2I0*~T&$(k@!%V5z>o{dME|VoG+StqjWj(KpTnr$r)J6P^|Y9^G*} zlp4&G3J>{`VKvergf8;)28Lw*L+BxeH_98*8l+fKw9XU`qocg*PjVkM?AMMIs4MF7 z$CtD&X{tX_?vd6NQv4@G5t4@|CzWt;UN_K%2zglIA*Hz6nap1Pv-jrLF1^-tz7QR& zc-}4EKLO!hQhvJnLVQjJL7v4Sh?NK@7{mv^kH0ezU82%QEj`>La^BLX8z+vVwUAxzY3D6WM+n3g zUQIna@gptoF$kr!VFuH=5h|Dvjr7vDJ~r=mcDsFg2J_iVcO7e|6?2%$pU_YY&iBbV zE_{Nf^6g5xS$@(wO}~4?@Eviv65($X%eZ@u- zJ)3W4C&mO_OYtFPYKp-gD>;D@#mV>a@A0mLN14j$m=2sk`AYEi-sp9z3gyU7(cfBP zHO)^wsxcEb&ELX;thTq)qx*>O7FVM|MvT5mlkhnBcb~~TdtavaK+w51r1R#nO$6~+ zu%1_k8t-3@(%0g3v=9R#7WM0K!0#oIAcy5Kayu#p)ys$9z5{v$f0CGGCsPHb1! zp(~GUBa7+nLLqz(ADy+1#(l@$oWs#hG|WQfd(?_fap2@4OQhDbkP4}!qmlZ9nj zT@g1L_iDOzDYX#YPJbYl6`3D`Hx9eWR1<_Ckct~%dL!svOo+g+c$Fme8TNLJyRw() z_D#g}DmjdOlKJ}Ch)X1z_6O=dv+hNIw>Q28>ECrTC*#-TN10@WCh9>2w~tpLk%3P; zKVtJN=0P>tcxKb}=api%f4Eqe=&!HXY}N^Kbp*@{eg0KSlgRy^thmaSnJe{C!46m# zqXW&XSX7@MUN<#t$f=0cjx`ZcG@0OZNv#dduHtu=eeo)5X2=?2M2nRv19r|$>QFE- z=B#8}^>&lq_7Q*V%rNy_twn~-!xwTn@$Od;$djeHAe1e3yp+5PQ74}2cap^Df8GoG zs-Y9l89T06yL#4^13UTijd5h zv>yxNtX%0TraD$obdDx+qZUgFxjn}QJKBs);dkx)V-D@AoZDaxq*SG|XIrzCLkAmI zWDQ|(9@602!5JwA>r7of%hD<_04{)FZ7@67d24#&{DpE6Snvpo_hr``9mf`|!C*h= zE7oBDBFYEczFs5^y+dMD!{0|DuLnj3P#t`-Hcas0Lq7~gr7N6S!`6RxB5Kn> z;5fBL0E}V3Y(c{cSoP`LwU@Bk4tT${i>98;f9sb^xc93PJ~wlQnFS1p&-(9T&*?kK zfs@O1dSh*?K6{Qc3)K{pVn^I_hH5hlg!JgjZ@0eFvno5I;?L1N;HMyPzM2gRa?Yf7 zJUa?2-Dl4Ln9CiWUrzVXgG=Kh7+{IpC@i|P$QlC134x4s>+jdh_dE3o(kUn?GiQGM^#zTVEZqiRQ&UdmEa3>tuQ%Hz zg=zROIeL|ERU&7>P$DeOEkK6~K6GV36NdR96POqhK}IU3!y`r|<|wB_x*`UCkLSm8 z!naibN1LeW`-scR=qIt1yOt*FDib1R+uHCf(K1td>gU>Mk#2$hqe%uvf=RIT zv#4Y6AP_70v0}l8RyH5S6s1&$XXkuTetH3$5OgT?COZ6%hazJ*%3HjC!4nrR7i^x_ ziw23f{V3WuthGL<%(xQ3ejgK>%sl1{v>O5Il)z$?Z-R|QrCpQ8!b|+ZLD0IU_!SZ{ z)u#N!e?w>NF!|5r7PzTB5VZw~Cg~ZAj3U}^1Xj>JKzQ~FvO8~zUWM7+#0s6BL$x(A z@`g;pIh+9gNAK%Pd!xf&+{1!i|Cmv{A8bxPr=!H{kV(7TOu?!NfAv^ztSE)gg?+*B zVqHrizL*cOj0TbIOVOP<41tEeIy2JiHZL!j%9b`YFMd{L(i=48+R&(NDnjVPR}b-hsWI=;%TnMGHG(~9DOi!aY1>qigD#;ih!J7) zzD!OLL&ANa0HYwS&?|?B2{j|RN5u&!AIItSjDZ~4mD9yYt*m}=uwCR!eF3X)76$i} z75?N7y1r-2SdNC2%AqAAuQ#PK=$@Dqg`c0VsGm5v>7;VhNb)Y&-gz$sZ?Da-Zw^VS ztlgM%vQ3kok~v;t^Jb`?fhGZK;n|v7%!(Fzo!dVka6BKnHz-$#h>-@ked+S-;@87^ z*KND?@gX=DBu47MJ&-%-jyRb_hZyh!5$f;Dy1wf-WN_~wK^jZ1j?m}0du``N=oM_} zs7`#yM0u2lTb6R+-%$Q0LZ&22w*y$+`^O-dLEs2(`B(-u#c;}H<{0v-R~q9@%3DVU zV>D!&&f@!-Kbw}h_C8iO)@#{U4droN7NIt31T$?tXz5WF7RmE9w}j_3FPJ0mvg>Yr zsWQ6TzjYmLQEm+6daHE)B{ia_w%U(3s;9Ie>?kisd%I@^{5nRp+-A~DN-)P=b9CKO z=e~7}K>ehK`Tj542!<0^ zU$7b5zujyzd6Hk2F9>eh4ZR0`Bd^DCLYlNv(PwCV_!1Gr0t}gTa zpb2W@O(FR@QInrHFoUgduBQM*PB4gXq;4iHvXM=#rbhPOb@?(T{VT;0G~JFaah%-l z1iHE}Nw_Zp!sD^{4Z7V2U(9004d2BGloQ@Ao!d!>bYpGJm*BSDjic1Ck0Zgz3C2}i zDzg*iJEMEijXWw>AYExU#n^ne&9vD08?Vgmr=Go%3fX^6um1>hmzg969ifT-!lQ)e zEjQlvMs=A9*ke$ytsA{E(a(>6Cz1Z7vxuDzSX*FWxp`vG#TXc5l*V&E}`&5YWQTVkt< z*@WSxO;*uygV`{RxX zQjG>rs-Y@ED_?IWREVaHO(q`j--RP+v+I_SN59kW z_e5efs`Q}RycYn51c7wIk@p=hKEL)_7^o72pRl);Y{eG-UIvp8&mAQwb&6TVZ@O#~ z`CD#KFoHZQKrX)hV-u5U)68XxZrjuaJ{hN3*vAc-o~b|~=opb@80dSkS%4$ zYfdplHhG?PdLn1&8r=`0wr1+(#)|c`)p8Y8rPe7RF?!Rru87G>$1axY@q10B#w*fd zVlb0#IL$v74!rS?Nvb;Z53yx^4aglm5EoqmnfD zgVo2V6!?Or;65;ls8D5Sti>H|V(BS-ZJKcASC(!5=P^!%pG!kuo#JU%eKx#guQG*c zzg_BnwuTjXpLo&sVDMm+-RT1-7VQ1*=uA#Cg&9Ks$vC;gnN0Qu1_VNdcDS1i!G|9WsxgMwxqG}2X+mx5M{)5!#S}b83hB!&++QA$U+Wm;|@2RCpw^$ zj-eV}tWBpHt!>LD>cU+N*2alROA~Zj?)=Y$9??2t-HtESE{r=NQA($Z(li`8!kxa; zDY=(w9md^R`%56Fvs>H3|J9|V+6TKXn_8z%dhIiBGn6N16am1lG!&JVMumoCtUouZ zxg8ZdNQCo6fJK2_59_FONYO^C9u1?H@r87St#!HdT=bJuqNWEE6;HIb8D{s1bSk^6 z-e!f`oQ{mewSO!kME9kdTfR?dGPE){GIeU3z(SBv@b3wCI8;iFm?M>z(7i#6hfq_{8((uyKA zn8Zo3tJIKXIdz(F*?9aay2?S<*Y%Q#f6!GM`yzieQBPH6lMQXTsyC8@l@=KsxQ;Za zCTOtmO;W_umVRm)F_NF7*;J$q6-#$n$+!KA%?%B(RsX|^AP``x#Ifw;Yl z1^O6tgzwQcJbRp(SNHjLl9{DWvv#6)Jv%J+s}P-Bvjt32v}$10e>?PxLD&}A99dGI zy%8Ub_~iA4DuVDs;Gj7tSSC0p%43^=HaZVDW)|%Ycw{uWxJ*i*W>Z_*NRyh!7Ht*S zF@>cYeuvR5X+yK)%bn$kOGK5gi#u+1&W=|uU?+3ihgKC44RMg7x^(9smzQ_SX~A=% zn`r73XJxL~n(br~QN>TR#%0sCu9D-sE@~XKN+BGNHe_mJT+W=t%lL?S@JsfMNf$5p z?%Efd))585MY|#Ygp!kiTV=)DcDIr~e)Q!=iD zFkx}~K3^+o?;%WfXzct4<)%D%PE5*d&@h0ME=3gl_>lYQfse_L{!ghDxhmZ@b4Mi9 zkNZ>8N<9=2Wq7$4&u%-(sr#MBZo0WchR*Z5VtS_A{|}GlE38VJs@alC#lAf6H9uhU z<|;6Qy6h7d$N1&yP^vI%Y-f%F*=T+skiSk_MjZpQoQ~Pr7i{Za1pWM2=%5}O2peC>eW#*m(+m+iU!v&M|j~^>zQVkrp zplExM>}zNw&vYFPv84)ME08?tv+HkjhI!;*V3l|G1Uqle4_Fx%dsvajnkMZEdY(4= zS^@%WP&G5^RvBHVd)| zX>6}zGDK5xO(s;FHa8s3NN-rcfT@0T9*r)Ey_mz;`JRHRl+j-jqRs-!(YcBLA_q8u_Pj$)Ik?n;bCN+e%-rI zFHu=I1d*wf=IkSdLLOP7VOz$zncQC@Tx#RU@CIKz`>GIri`&*syK2JnzWZ#|I=>!P z0N-~(IZ`g^^2(ozD{s22urzEmNlx z@u+ppx>AZg(~WdxQlYmj(hF9LZeEiID8d7x{J5A@=Qq@biMBOY&?e4S7h!=yUF}uE zCjOENgy;yCPc~Bz3`0YiGbaC=B!P&WBotWolrg*tWELyuEF!?xsr1Om&qv0qgjp13ogysNH~tHk;(W#9D$%{O zsof2IPMKF$>Gm^Ax$pIU5~<0LTJs5#8(-1#oxfRz3X~aTlN0DL>|-Esxlo9$;~5F5 z#VdaPX4s|CQ3Uiuvn<)h<>xJHVUly+W}Yf%lI=>?54}bY$^h0EtDyZy{0OnSSlCIM4;lmOOeUb(7{Qo39?t8r6SSIyA~@ge%mE(rWx_ z8ojlaI;xxmVsA#BW;i*vPf&kr1pXOvJ05_X_TChJ(_N1GrO9oV_*VSo=!QoqAImnF6dm7;$m7zgA& zG2#a8_{PNVz~PRm1NYIbjBU3ngTBklZMv!F&f?z3ttD%Rw;}hax2C7kVS-}y8Dr&( zZyQrPfZtULJ#?4+mnoQ8Ko)?>zejIn--7f29L=&|I4)6oodtaL@@$)jI2pJ%x%N$08o1Pjj6HXJD#pB)a1_7H-e%ZgO10%FSI!F zq$oYrFOTf6MnkmfRWczDl!k&fLIHF!}o|bcvhP z$}s|KzrMgaXGu2>Lkh(p9g_6*i=4`EI{uz#1F2sRF!P9M-Pz^8_YV)p;N0`P*f5Om z^H}C6T`G9{kRSTRZRTgcL60Ke8f|%#*`u{NRqTtYI;u$AJ8#o(0rG+X!}CAH z994i%EUwe8yutyN-EYuPX!N~G)*>Pob)8|uvHXa;?2Ol)$s1z;P`a&0kDL{QQ2$2i7b6We4D7Y#WY3T@l}mO z`WJ)7$<2kL>RBsNi!dfFL@U>ro^e6s(*D7aQdgkRLHf9DO*4ZiioSR=GRsBiOARJW zQboJQNJTYZ%+OoE=^&de!Sn1OSJ)O^;_Z^v>wbgoCg4Mokkm<+7iUSc-G4@1{eu)y z=}p@Ic?)Se^$MNYocv_-dhJKa!omWzLri{s?Vs$}$pB@P_ZQky7xKRJs9i58?0y00 zLa-wy+y%+_IQ0>vm8K&Fwa{*<67$$4cfn{Bp^aKrz%&L08@%{X*S4(z;Mo&pb-5gc zq^Br0i{$F0&)beYh-&Wxn};Zc_xW4?*rRV41nt#Lhb(T0%CYW>CPUI^gH&V?Dqg=a ze&FG_d@~HMPRB@mslN?~3;;e@-oZ~q<-`)cs!vG2{uq|DU6L1F>xSyT#Rvx ziVVs7*ht+H)BwIm-V(`pYw(3!XGy;NHIZn>yGe}1{h_o=&IK&7@*uyFL(anXN+c#E zkC~VXCybE(B`fRahZmdhh6dNUun~L!tCioj@SRnts3&noq@&?wYxGsbbNt|6&&ynd z&7GxMmeUjCHCV#iO^Mdd_{_Q=PO_r=;0$i0U|{2C6}wg0&)HG9j91&IX)oLLSs}O) zglWg`$q9#`YAm;~d^w+G+0I)eiG%16OW?UGwyd&J3%}dh%4IgA<8Mm@NI~Vd|3$Bt zm}@9tkWA);WyF`C$FUi*uB5o8rgSP`IJB&rb2{TeV(&LBzYW#dfQwS6Kz*snt$Iq^ zD6HGWXWuR0fi1(iI*%^FS2G_0%X+-ACx;#6-f7@2hylt6#NwsC)a*e824AgWus+>< zQz4A^U=6m3E=kIqLFNg`yWO}v;1kis>?p>9{b~5eCqgxiKCYpH2NM1gq#+Lex|%&L zpR!QYBxAci(a#$}_`+F=vrjYgtSm?9$9%XndS!z*0ilWII+N*-i$CHXA+7NFnW)!s zD`n!YFfhL5(g(Fh5rt;U6f-`1Z+)qG0pW{kuCq)3VWf(>uAfFPr$u_`v&;j|SBrJM zV^on?EA3#W_Z+K@wn*t;=oePd^_^|i_l0a68WlOV1X?)cCHmi!$@a}~ReS^lvq7ytxY zR9W=i2gb<}Q4G8mMsuB+TOCC4`dQxmW5+MRb(ZU**278q0{mho4+*Vfa(^@8+NxkZ zcz8fD8n`~7d-vZ&yLAX^r^g+%@fw%he?wAuyq`;B05nmwV=wV<9xXQHYtEYZ%R) zKNym)N`lhHFzLU~78_(H?0KO=st#v5U%xjNDl`G0C7kb{Y(yoHXcH&RCSyIT1(&xiAEdj-AsK(U^|4paEB+6y)v3orBf@%sOHyr@3}%s#8M&!jldDd@S*U%K6v$mO;=uh^ry0c_9|`9B#$%)0}} z06jgP)8f}of3L_PW+H|w-8WxA)ZbGCIFC1bH*ZdqOF_4$8G_R$SjN0c>K~03D$Z(8 zPQ{52TKGs85-}7xN^;+I9DrwF1?d^72y+-V>Tc2G)hX8@{^YI3a?lS*?(7{?K^Zdd;-0T2f z<<;ow(4;qU@;JbL3!nzxyooYI@(x zm>B(*vJ?tO;Gz(l8LTGhT|shsqlIQ9G?Vg6P)=wz2Bfo%U~-y<{nDToX~3gL=SkTt zQ(Sw&V2N}XsLEYD3%8Hq*xV02I~E}^r$9LVr944_B;$wnS0i7yVKR5pQc2igUyP=N zQwz22j*h>Cx&(#~`%O&S@4kt?>{~~{*;h%yOJ`5InbD(yQMExJDYzGy+N*5U0u4Uc zU-pXzr55e0p`T^DpM#ga*Vv>A<#v8p*pA2-gH4ez>PXn8^3cum?4P?W1Kp5Dk^IWs zreH45>9n4GLdUD1eD?=B-gN>%tk&3OTjx+O-~uxnsW~L5K`=CTH)tqz9IOi2$n|lw zVx((9UZL~}8U2zfWtfHNDu~d2WUDUhVa3Z^oLaeW30 zTBR_*Ulp&{{*&y-JamuVLYFWhOxM%H7&|@5#36;ywm_pjX{C^%CJ?+Bjy|G^G=yovp^)=r| zh03T8z+B*Wt<_)d>@Sm6V?ipa3A#$##s|1csl-2vll8e{p)`g z9VWyvKPlTKwk!*|3ZD*y=lNkl5L;q{$W;q&sY={W zwu(;+W=d+Bk5zT~q5IdDR#7HhF4o+pr~Zr_jB|$o7@IPluql=_xO! zYXgcb3vWVX;eF;ylaUt+T8FATxKk`-xz!#= zejFwX3v<=_zhPb+N?Y26G{p!SvI?F0(QTQYa?cSYZk~`CS+N03DbLz-pR{4jE&V76 zE9)N}iV8I<3lOLybAjK>^TL8;kHA*dhfFWxYFnVNtww({Fq-_ktIvnt;`C-m0P0tsV&Q`0Qwr{%sh zC73p(U(vv0SHg*9^sbE|m%g3*R(BM(^XUHp@y7yDDoa!-WTMhfE(RtLoDoY$y< zLME<`(M}#E@%bc4&rhOvCN7d)TM(`;jNxOoQcdiv0C!L7h5gwLO_-U)c#=^~jSA5+ zfY7;5{N;}r_g%)&U&Cl{&D$|=tIrTOYYSc%lRj#UO4mF83l~tF`X9YzECk_W8I%oK z`B>t9D&A1BymlJuZ%5|vTQ&GIt2tEM^k4>ph~-cYKeky7oK5Q0>c z%+$M1m3G!H#py2o4y24r7Ypn}HX#N1tIL3H(5_86SPyv&WPtzS6>b2>j;-MZ@Q5Pm zo&1BHt@`cGB>N@?e(2^$eS=SE%70Nxud%60C5YCLN?Cge)Yz^)I2CvUzWVV$yEF*L z3Cj<~j-Z1O!LmFD)*} zuE0zEHuwwbsokhb1E8cobAf7os5ZcXpf1pOKmEBiM4A-LAL>@0|A8c^&y1)VJW57# zP3|!K3%0H=p?dXCWf-FT9JM-S*Ni0u{^lRw0rFo6B=#By{jEGh;P?JlMfv~97okLB z|CD~O*>e?&qN1YP;8iM?ALB5DYA_<&wc5DNN@`Xlvi_EU!@P)9ES-}Iw^)l#Y# z75x8<1gNYYZ~f|0eAdkO|(z=L&(x%$JGkpyIs71deP_mRctte`rciYt-!Dg0rfNllx1ZYHK zroz1rXh;Cp@yPppcW`j<%?f&~hM^%_N#jvscbc$aaosv2KQT}k>cbF~d;XN?B9dW` z7=$l(!x4ILM<|<@nR)M8s3$P9E|8+_t2r&i>M0%8_@sh)eWy!Gc0 zl|oATf_=#i8wGp2LXBaFDXE$ zyl6Lxg8y>R?O7&oUdL+f93J>q&cL*T`;gZK7e8C2zzYQ1wnc z?b`RF+~g9rnnsVVsk4*rjqcipuPea->++=|*8Fwty2h963~YrA-?^O$8M+JDxjDer zmY@P<0_Pso`rblAm_dHnz0g}ksLE7?iu&{a)xVmMj8VXn7_bKo^4J3TcD-xK=47Rm z&;h|&PtQDY-&$&&3TL=M?R>>7C!;XoV|Jx0nRh4ZB=$|6T0)H%)Lprw!3nunCZ4I% zy!F$uedC&W9!8CiN?Ow>4TX$#-8zY@JhunVnvG+_b^DCti8W_o2bTn~u1kBHT4%B0 zU&aFVV3!w`_MJ&r!_Cr2rDSSA2ykI56$JrSsZ9!gQwC_uAq51!)U*nGfH{s#FW2La zoUQQOX<_AEcf3+~w_e=3I6YLC@D@^u_!fpVIg2DtoFDLw9RkTOAZvhp5C22^efo^h zj81Ch_q2dagp34=+>OeKo1*V@BVIw5bl=Y@K-xn3AGpi+LxW-{=nmf94H3j{n<^mZ z22>eP4-XcM&|AsRrk%~OU6@Uu<3fZ4pNbPCBkn%JdHfP2MZhrt#UiaWoSv1*=Zp&? z+7gnXtXwPTFM)XEigGYM-$!QgWM&J@MW;(*6}!6C#4mk>@P$E81O! z){)#?R{1F!=)W(tSuDI<(xA7P{%LJqTDJkEsP(R`W{C{6XQcf)Owk)HQB+j6 z>cKxj5f>J9mtf+p%O$m?t^T4QVHE9W6?MiZLBgP2D&K1=3`^Z$CvaCsRUQ8Etn!{V zpT^T-N~+vhc3IYVJoarmTY_!ot5NZZXFKW%UL8x+8!H_^0O*XqN8jZeeUl3{a2${b zqtu)s8JMpw$6Ki}+B(_^`=V8}f>6S1ZZmY2cnN|}w;u|suJ?r#@YOOJcj;^JaJ(;c zzOVX}IcI%>X)aPtb;Dh(Vlp{j_Q5NI_+m4&)GPFD!QCV8KQb&D^#bbcwCoNy&I@aZ7BTs9`l~T z)tFR!uxnP=?f$X*4E|M2Qj#jP7KYZLx<~no@MB1ZEba|g0d7KzKh-!m z9q+R^qR%abS2$fQif>szR9URhB$?e`m3X`1wT61EPsB-OXmbG z<;CA^)VesB(H`7qtFC056}b`Yr8WV>QjKE~A8wHfuJXtgC5Yz8e$KbjgyXSwVv$hg zN~UI9X1tx94m4GvdKPCb?6A`rsUrTqP5{NpMn6^Pd`RJWpi=J97Dis$<hl~6Nx`h5yY(nve8HZm~RSjOMc!aa1n*p<38la;9z|7haMxJdH{LuA_ZBD_SuM)LEvW1WYZ*1yqa=N40{vO*k}quSv_5Tp78u>un7D@UXop%j1UOzQ~A@U$Zf-eaBUG7LmR<@jJTvq_LsBL{0DI? zJAbOHqbC|Ylb7ZaS7RIWByW(0E0&AqD$kqy%Qw)Izt9nKe=i{55GPMiWGJ2R;?Qw{ zd^U7hjOOLc(wY8*b%~i56$4R?4xg-~Ko(6xOWLa{mGwY2Y1jM`Th7qqQ!EmPv4hXw z$Yisbu@$L@O|x6liuLO!^EaO=r84KHKoe0DN3WPJ{K7IK4^$DMIP`2+npuFI1iWCx zoDkA_d(NhXJiG_9b51ON?wzxTSri+`s&j2Osi2ag0|Jw)CrZmU+{E%jOvj&diJVSd zHF#qdVbd&qmkzPp*()}lOS=TUCa*VEQ!d0GnK?8T(KSZp#il1so2osW&F%}>-Z>ko z|6y1>^>t>q%_Td0aKP9PCCAQw`M&N;nDFIsL-XXw*w}s-1qAYfo<=ex0_2b5`R~%M z&R0x9J_5zbiveIh-+CnA4Yl(qsGFFgG~3_+kK5G+LDto0JF^KjSMsMTsmtM+3j^J$ z&izjf9-Bg3jM`vj7wxzTc^1e)-Ru=QY+1lg$xF(jke=^%kMpB~^M&42L6`~nqU<$%^v=Cr+6H76PXNZ&*byLmMu_~tz{h!6B__wzQB#^vK>o@SYdo1cKD)6Jn7i%L5D z7N|d@2qA0xI%?i7Y^sxL^a7+0J6+dmX7oO*_O{OTNHqPyg&l>eY=YH&ei&^KH7cOd ziNk=A=V(H7H@*1L#fNQBaV%G(M%8<+t4KH?Vtb1Fzx=@Mj28nKSl+kbS$U60BxH(D zHzqX;M$?tjgz|B#n=dz-<88i2kv5`3eiciG@104E1fmbZd?Rc2TE78{@4U@Q})e*P`64vZ2U*kp%@Tl ztG6p@I^+jBnXcQjTuwca)*rnnlzC6LVBR;pGXg-y0q^N_oR?RA&-ZQ*>VGt>iD(6C zN_k|(+pYr3o0s~vFED^Ac}IXy;Oa+8nw9AbuwqMwmrI6=?+Fz_cE%*Ovp-)fRzs2h z2xa}MW*rvAw&?yTv{uczWiPCNCO*L?1K-U*ThKNLHmr9b~7!6Wm)eF2v3)!F+fR)9Y%R%P(ipAQnns z1}-2sOb8n&ekW!{S+TtUHAcv!eE2PwY$0~q#pH(#c|%g_JdMwWn#=L^KBGY$t<)S4cAR$dRupfz=_3+7WC9troMg22@e_`d6_t)5_^PJrma zGz~huA1YCSD}%d-S0@HtBP-7>6s@p+g?xm1ok6R z_E_}mhKI#~pQt|(81gYGLzVHvI%kgS&%S^faM$WUCPH;?=l59GExKg0TxF&zTkFU+ ziuxYK6Ht_-$xU{YT|b@VvI^bn=MI|X3e_IkNce3xzIu3Dgmr24aPuqb90Sggd(PSY z+eB+kpxW6cd|Ar!`|PONd#Q1`7>YyQvA5*JjxHe=$DE%Z>>Czznad?0XB1dNZ-Xv85#3;%IXsT_n;V{0=>1nzQjJkfNa^5rE!6O>O0%WTYb+ z3ktbaW*ik?S)#Vq+Vk`{pbQu8D91vt4$V^<}-q7 zRzDRKmNXJnh#D-%_`bDRVg;xY4D{)74QZ`3%7Uc^**v%rmEteO98}Z2bJ`*ea`NXE z@A{_P`S>&e*NdW11J&R&A5f}+P(23`Kg)_eXu7ASUS^C8>3MdPAPT#0WJG@m7ksmp zc{W`;ufl~Le4yc0(wjz)su7`@XQ&*PR8g5(*qGWkd0F4)%Cq2ZTzq!^9hWW3Zt(Cf zJ@y!R15`J^HNiYJfz-9DK&Ehw;)e{gTRo1vZ;Jc?uAdhc?6K9J9Tf1|O*Xg#2{r&~lh@h8>FZH21I)+4Db4wC$ zVs_guV2=n}+2l#yGotX2qzi?qW-{)|0GxhQ_GChJH|<7tVS|)fQOzo_hB>YzmAX z;`|VGAdQPeVk<`vd2)fAi|_Nk+&7y*mNe-o^8d!jG~1QT}+5*tK377J(xhqE}? z?-elY>4k;-t)X<#zq}QxGQ5lOh?#@dIOKo`BO;OLSYQuA(RhI&8Jkg;+?e*Oetd4; zB3J>Acwx96tLB3@UKWHlO@e5n@p}qDI0)Q-XKQiu6@s2oIcBlCZRUNw(OqTBt@2l) zXw*`M+8qSRBV>6f5-Z{zs>>QA5(SC&odczq!oee_wafso<6-Sw=UkGY@}#aH8A&bu zK5L-Qgv*=tFgBJilU_LqWhao%0u(k=9x)|iK$jG8i=oN`RNvvQ`6r6m)_ZyOiDrM6p)pp5Q7_sQw+wn^9bQ?S8RPfo@D6v*L(fGQJxTGCb{7H)hYJ#>Q1Or(J@zG&S`i zgr&Khst!m94O}->%9j+q9=`k&p%Oy~dhdq<&R~~<+*pOpGwhx=a!T5vt=#xfZ({U? z{OQD644#^)mzsab=L%^oWYxYpI1_UEycL{VF}Wph)WbrkC+UN9Xu{=z#I*Qm=x6TgG1OZ|66f7B zd|m?_Wup@yCk&-CH#gQG|BO^VZe8F|8sv2-<*W??z}3iKE6_4&;X z?cOJ8N%>OMz&y2SF>W?dH4guPGzxaMN)==|GJDjC_skdJu zs(RKh-ZYPeqiUeuMCYxqd;&@GN^C*`{`Bh4v6NY-P=~b@?!)Qk_H{Z8Y_5+swzn{| zQsZ)1W{n+YtKu8w%H7v8iBq0haEgv{^_HIH_tmN{OAU1=naK^opLiw6^_6juH-6o( zdObLk+ZDK}2Z7uHYW$9VOB^$_wOXBku5Ut6zHA9@x0M}H%HUMjl=7_fZ&U+SMYGzC z+Z|E6L;;On7Kv0RQceX!Y@qPjqDraoO;YVC32yt1jPKF3OUbo25@ZURAcdb%MY`2|-$)~5r% zo?Z|w-kxvx8Xa;7YIVV#*!$9_8uy#Y1?h866J2}mA|H+36?@QOvhDt|VgKq}1gcn} zPg6u)-CO_kq3)tfE9!()v$Rilvm^;CMx%A&_v$GsnqGzYiPEB!#H+>4RTn_U%B$rwRTuj*@0pfa#0mQ}{Hl<#9bb zbr&%ZksQ=yDBr>~ykJ;*L|JU!i)&v9C>lPYX?gV}o9 z$d-@c>2g^ZOO%kgr_qGYau1=gpDo1SGPqwlqpVC%?lU;AIa`&e%mpeK1c1QC1kgBd z8SH1oA@d;IB*ghlyjV8QuyS+WQlsMA&oq1vb6ET<#hrM-tl&leLc46RooY~B9+OE~ ziPyXU`e);xR!6DTEzKf@14P@1sp_%w9Tapl7uqMO-T98Y)J_x5IaDds03~?7JkimSndxG$4x_it*;4bZ7h`;nr<~?6C>fo3eqK4IMifc*| zCR93whqpE#dy=hMSYxT&ewmTG&ncESk>wWXy@Y$EN*obsNtB%+9*nc?0<3O)GZA%2 zV?rIf&)^9-l!0&hTl}ZXn}J?;!^dKWfyG86CnEeW(;q9jlmO#Y!xJK3 zZ_t*arYcyo$jNfHAZ;y&XVNZeYRr!#6f1;>VSOVtD;|`c_V)Xllg1RHG!zmvI)_d> z=KI#dpF1sZm~eN;n(~s>vqm6nxmE~-mfJFI#_$GayUL_Bgp<|{!I1)r|BJTwfNHAS z-n|h7R0LEMM4F<~i*)I|s8ngvQF;kT?}>9k@YD^f(U)K`VZfGGp(a5iP= zxIwPhyuG;mhR)0p>i)W9IHts8nEH#bakGil9m8{Gcv!8*(ct(pcorGs(_s{iM@|HeG3>WG!?_DN@K}Q`uK( zTYU8lytx@DEHNC!yX?M05FDXYn5z1A|;eM)cdF}rPtKH8cj^#rm0I~(Yii`Ju-h?gtd z{1&PKbrD~atMa1sT$~F~%`Y|zc8T2$$UF`a1kt8F?xAsvFLid6mi)JPHQ zrm@`~%iPd9Svc1bbGNq=V-`?z)N6JePwUK^sz1X`Q!>sq^iVIowYtzK)w2M{U)#US zFKK28`*zp$@U;g@*7Xfn@`G_{b9ke5vY1s%M-r_ytOr+JRuPcljH}{bwF$6{@tN`J z_$unv6)GERH5lz*(6p7jH*Qh6^Oj~_JL53Ue~xY@8l)W_W7ntifM9#*lQ!$8;_U0m zMB=Dew6dwKoMK}libGObRP)SK2Q+~|m7a<)>{uJce8w?i{#RL#CkQR8?jbbH^73#V zvtQ0tIs5t#2BeBOryuRNOT+K`&z$U)HzB4*)wAvzwD?C#Z1>1}cGX&TUc*;>57tSf z`{Q$)(~nnRj0r0uynT}tUuows@h(iYR15=qy2A_abMlo;zxgJ6^%{z9qg?nmM7HNs z>iZ`Sw2l{kBMZ80!kpgM%&m=;ruy&XFx6-id{8ZCcOSqdfbvD>VsENdPZFQ!C+Gc* zHLH$jkk6_4{gwvG5hdxFnzq%OE@`ALx)3+8TZ7Wbl=x?XteSCB8&C{v%E)(}v#=hI z>V&!O^M{7Q<!PfEKgc*sFiu&7W+PPhyTE zuQyG1Mr4jq7}UKqxIMakq5j3!a0TM`_7RL!pq$DkO@3k8&)K`q!V>1=wC?Ux)ayac z>4?`(K_zg!&)m0{c7HS=0jGVtG)FmQeX)=1S+`08>*_6x|f`&G3& zv9bM-xaXAydL zg3%is6D=NLJ0iO`-RSo7*5)t!sHZ>E?KFD{aym7Cmq*(IZn@4mABP)dgGE9G%Z+$l zL?s;<)0hi1D!zTRvC2~Si)yRP;@4h}v}CmtDr4vO2s%yTz!s8k+3Hp%Lp^)DhyxG! zgv*_`y2wBLB8rT5BiW^b>`703vO02$Fl4y=8q^h3i_;gNy$zC$Uj~XSK~)ct*Y8)* zgZdpI+>1?+{M}5_>OTd|ugzK@+zA*ylLa*~vFU)Nis5@rBH~rRcXNtlt5^}-OPko2uw_~`~ zw%q3*KMT4;1&@rrFJRrVje4+DXvHr+q*lW|EU2N$It7>$Np3r%wIYrcib5>VC8&4c$brAA5E6Lv<2tp zT<^JX9^BS+rjd&+ybaK9LTt+MUa&Qj(3qKZqKJ1nVg?$dn!#t_G{6*J11Y3UOh!;; zqiNKVc{zJsVRUY{5S?#;irw#+DqTYC7;86zxWOGH7l)r=Z?O${PE>aKJ!~ki`y5I_ z?c{4bq+8?E`V8JfP9iTj>lVwE5Vk;}{dSE)bh|!vKE1}%rA<)NHA=#3(PO2^T$wi^ zm9UM1ykn}WQ!=WRcWYk_`gv|{uE!nbJfc&K`%r2NM=Kg|+H`#)t`VX+ze^r>e)Qhc7DVqNO};o9$Jliy|Rwdm#w7HbxS5-|uy?i_dVRGw<9^^L05 z^_n)p>7Tt}dCr-SvnG^ok0<>7f>Qrdf-JA!u#k@}iG%X{XF{lKUYQ*`?)4K+NaUyJ zOV|Gjbw^6rn23#W(wG;&Ca0si;CZ>Ohw_;OZQmEWo6tPtUuFBGmxTg9WEVw3%y>EB z-u=6LbSkTo1LaU^AI2OP#|EuGs35Dw4d_tQ3*CqKs?bAg>93fuvR2#RnGFy7gZjW% ziPMP1(zil&6^l0AxdwD=6z6-7u+X#~a^fmxScaR>EH#sayc2#I!F-z*UVhlZ1+8i| zKJr1N^!xe%;R{~+wL+4P^Vch5m@pHTI(ftNeZQCLL=53SMv~~;ZR0$~Vf zib!MMnz}~*<$8lg8y6nU7zlMvBv%;jYnfL7l)-b5{tHF+KM)@)^`|K9QN?RRq& z`?&y_1L8t!Y*YPd0_-!uGRd%mFjX5eQ;v>)t5HT}N1sA51uS(;jAdO5`rE5_cR%rW zmFF+!7QddLO~}Zqeq{Kkx(MU;l3b{9wsU{Pjp2^IKaUg@#|_oWqdz&2p=)gV;AU=O zp1itv%LLO}%Oaps{AQxant0+4w^4IQ&S5T*mXh&}HhNrOHa^$~!=5U@L}Xt2Kmmn6 z%0%!&&Kn-u=pa|8z4Jx9!W<_S8Juc;Nhd6_X~m&8%D&p|evV+yA}JV^NwX?`y_=xj zzsy^?2Yh}4#X441CvTVL!-u~b?ZRyWWTOs`7Mrr(Y8MK8>~gRGX7bh^Deb zKFL2!Dz(>p6PzQbzs*(wvg|-%IO{;}Pb=4)9)aD4$xX1Z^U21`U=NLie|S_oBgHrp zF4n!t;C%MB6g%+A)2zlYftzYLQft!Jpix+0fC{~<>gT7O)sq$X#jXC%Kr?g`cfCCN zC)|yWZBErg5W~B-ul6Z`yjC_2had4C2MLF66)xa}5{cvNwb_LB+roeQT?<1dQ1C%8 z)$yeqUO^6XY!7UOY8}a43LKI1&5IJ3*yj`~^W+?zT|Wi%PA)!mGARCJWqB)0a`|kU zx`f+*NX0csAa6bQ^H=6$-wlDNLq;^I!B@uw)e1t$&YNJFc&=gUnAGxfDIzr8YFQ)| zL~uw9cYWncF7mykRZBMkx+3Ax=GV9nx4w=JKHc6%$Hp9-D9{b4vwxoas8M`ef4m)} z^a~Mp?CdiZ0|&WFwsRl`E}F*GVCBi>LV(dvFWI#Fckzpf9>!ubrsGbLss=q{-shxu zr{z=AuFmSa8L_w#C2J0vBNid3Q9H|HxvuY>dnsw-=sK>l*YtOGm3=6UY86q^NCMGh zrTbbSeU=glrmL;SpNKDVnU{2DEb>|%<3zICwb0Ld^lDZEbY|SeMcJV_16oFK63W>& z{>|o6I~hekrS8e`O7fRhWlO_F7Op=(5fd982?r8J$ous;RO$YCZA@ud;di4}!vMw9 z`q&tbD4WnEjkTMf46THG9pFCMmeMnO}fN5(0tgv6PN;eUqZG{c~VGPEut;384jbwU{qaYg%en z$P94BeB>@6Gc@GCZT0sii<2+jdrPP9Wm;zcHN`1?jURrK}*w z+U>wS&ulBzOqLJt=S0fTw-O^U>NA1^^mLaw@{Rn3G=EMwW?~w@#Q8x)NMG9^(?4MR z`h9*9PpY_Q;jV9=(7RO_+ZKN(KWf6ZD4Y5zeVaT;dZqF3ZkNy%ry|tCfl<2U637Pb zDT6B4$m;QAFrxaaj`iFydou)M4Cg=?Bp#alZuAUf>3F6+%GnXeXHr{$T=>Lf;YYw3 zck%K2664uYrcQ;e;x1xe+ir8ZaSHH)KJb6@&WW@ASMnzpIkax&xDv#RE*-L!nFQVd~2YTint?wf%#F*s% z=J#X*9UsUdFS!~>7;>*g#$2;SE;3H=Z&4)Qx?paLF@);xL6iOFU&N-xSyvee-h9z5 z;j+V!-=LoYub7L!Sgq|oJQqL|@nlVSJvvN;7|GYr?#`YuN#lIVE2!JiWL3+XDBU!n ze@GpB*`81yN+(@*DcuK>U+jzf2q*Jx)vqGl>wGBBBV_?OJRV%%(Qc0MX*y27<%5PM z;#?psR=?1VYYj7yZ_Xbjnj_>+67W^Mczl3fZM}gEX`@v6jOkC=T<^bYS;qsbjMDfgXtR(8cl2aZnIK6RirJ#RkzNZ$&dzS8x1vbHU_!|sz z<|H1Q0xH~3kzD^D?6@@btD|e=GrsU0R+;=^W=JFuLlbOi$sG;1iKbm^~ zD%cvgsGVS+0iKM7IBoTdCT45L=ez!sJFp$FIH`F`?Q53!#^Kvj=A6Q2i1&BP%G@Fw zcBH1;-XF$Hiy;d_K*jj7SCD7d{eX6at#ZBd?bF2*GWisywA<)uv%3TYDz8Z}a&v?} z_q@$wE0q`x%x@tG>}5cX9t84!-Gy=syFzqf%HvELSTP@aIW+^@KZ0JESGSv1Yh|8~)#VEfmHA*xNit5?}Jjqa+Z@*Mh~_8~*Zo5L;<5Rz7US zid=csu^U3s7Jko-d^T++b(c?<#s4@<4#6n)-Iz+DTqAvSMWuejGrK|!^)k@frVXh5^7zp%y{#JVhIn%pANF;5$2 z`T63zHATdE1H|&!W*2>4VD7S~&6DBVjj+V@8&%SK^~P7gJRg^Fpk<#YNL-v@cf%Xx zR&y9A&QHp_BM4$cL^>LXV+eW@Cir1%`#T3M+^+~W8Wz#hSeBl{3*QCWe(rBOE@PKoD;bmv1ngRj=Z_l-YuG-rrPF1xj< z^B)C7mvTcN*x}?1Mn`VnEmKL{EEghFrA6;pG{CFp=^jiUeYpXd0o1O|6@D46e@nK5 zW#1Q*o%6iuB;koy1A=H?rdlEOjD&jo_zpk*F$v8RGESlRnmbfEcPr14p0ULnPkQj} zuZ0+?dWgh^qCVC~cKdJfY&<4>VJD`ySn6&XPk+ernTf;Ojxho$PRK}W6%@mzltJLJB3#*87rXU7JpZTi?ZIsa4u%kI9i$uh4!29}rnq(mmS#!z% zc9p0?ar(q|i)U&1^kRRKyZmxUkz6kFM#`*YB2bsdXVyR-!MjWxJ8|O5p$le#<+94uI^@4a^s%hDT!Q#rw2SOPOpdD&}Nl>a+`zA ziOHkGD5B@|#vpIGY)+DJEC_6Tk{w^PZeK2KNRO#;tS`cpP2ZO0EL8c#VX^1?#hR@~ zEi)i{;7Va6$^5UG&=C~*MNq55SJHuqhGp{QJT>O)iUnUAwGl&4x!X*?yH)DomtAb>ySTK~h0oI_^?WNsO}Gr!nZ5Rv}+Ixi)0?vu#i;rxmm)F{XFx zkDRkKbA&l*^3QvBC1XJn_fZ1mqKGNOLao)6KE^Fra?b}8KrwawbVe44w);$w#On2^ zWpvl_#)atZYi~m6em;P31dD&MJxe=ZMZh&NoR)=qBez!BdlN*9P?S2!!NqrzJ3V1v z$*qVE{`0wF$8j1c-5st;|O^@Mv^`hSmXj^@2&y zZnLb?I|sLALIcl{kD535Y2t>^`w^NByL`^bK+n*1V=Z2b?OY!RqNLc6+BcKe9+*rr z>U4o@wk=J5>QPU4R%Y;%nqr(xql|#Q%G|xy<2KC@>iT7&o}}lMq8{XPCX^lY!@bZ4 z@+#sB13a749^nb^;TD!%f+W~>Ohc=h?r+WEf3iL_1`Y6>k7hq?7g($;9Al-UPb?ae ztu&@Rl0N#SNT**PJO;QlFRS^En7=jolg09ru5hA-2mj|Qo^LySBft&0ZAj+Re8}KA zGxxv2jPT?sVAlX%!g^+BKN~0PjFLFmjDk5n*>5>UoB5R27pE0bOeW1Am4Z2ggK~_^ zOiDT3XYr2sf>EXA`<>O%Zhx7G}FnXP~%3*OZV9!={n?%FpX(}YHOsv*SO{4bvJHP;aW z+U38h+}V1}BR6t9aFk_6fNb?@uK+?9+}Omb@@D9-Y#^RivHI@0IAsHhkN#x``-09%@|zFD;b2%KWeOyq@v zlJ6S7MAH?i{jZ9eBK}Zg_Y|(CPa}MGfF)hgOQ`qUusSRTc z5FP@ryi$_K09SUbx>%>gDlY-gOC2@fZUyVFIk0}51GXX=n#*Y9g^+g!hK zgYButeL-NqSOjV@82Um?aXG8x{1^U z`PML~QY6U?zGZo5TqHC2S0wr0L^1#H?Ax_O71>PO+l9Oo$pP1^div7Wr5yGhR6SCp z3n@bAT`$O=3u^IFpK=Y}mzB0S^cj|&k?*}X)c-<=Z}D9hUiMr3&TZ2nwQQpnVjEp(xWdWl@jp@)5}&CJ$6}O53tQen;2kBi`j8^EDo?a4bp*XI6IZprvrS5NgyH4SUz(HTu{r z8GGsY{k1cW>R)S=k9#$cROR$(PR)MjwqSECBnFXqQ5yj;w-dbjUf4|cA-ka+QM=T6 z-ZLs{Zx?VdRDMP>IQ+DbVw8FO4+)e3c0XhnPsL$r^*iFTXmMyC7_6=q9F&BTg6E7t ztO)3-FvCmU;%^N%+ek4(lF+Yp>zhV@-Pz@z);Gg0UH?>Y;kvFQp(5MJIV!e>f%7p> zZm@|R0am5oBOq3Dn!%$Otj~vPniyvm>hX|>-6B-Pe=woqEBVaA%6}oEi$6JhD{=r& z*TFJhR@ryu;CtUWE?yZ)H;;}5gx$>Rua|D!rpSot8pfObx`L*z5y*lWpJjQfkagAE z*|X3TFA99zmS!~N6YNIr>Vin~H|1!DTJ*Noy!k7PJ&%c7(1?31$2_t=U&8A66k2S? zr^|YdfGt?Obvbj1?slqq=7o42KX!p?tv8p!Z@E$6Ks>kn-i9Hw7+Cb6w!~dD@aQij25D?>%=3H#5kHwUqYBx zJ-(k&X=YB3%_b_X!u&CQGqH)LzMToz&jMZ|lFOg93#px(cN6O2cpyvim_rF3GILbA zYbakXJ|)z7RhjWYfj(a zt8L}>LirSM-*N4{pV(1iP*t?mKxj9qSz~I`e6W~mZFstl2RJW`TSN&V1_#$-UX+y% zN-ghl$=Luj2M~>oM#)^gq>ERU;Yn8tbXZstp7z zOyG2STLhe^3wwjaA;zy%n2IO9z9n1WG&=~T_nLCql0My*_H^=a&CsWzcMUQMp2y#q zyTfZCcrmhGxhZ7n9e${e1M>V%E_rnQT%@=qKud3dU_W(*v%KkPzIvK{pO-K9?=r1A zM)q>UKDKNCufof*$F4EaesDh;jSWmM+5Mi$dVvAt0IY+}eP0TZ9~!3BEsQ=;I1OH( z*NDDAFo4=2HIQtryFCcBdh_^`T7V;+!X#PwMt;6rE3NIqD{HsEee?zFr+K#w+($dk zA>wy<1u|y3)}kh-Q06L=8iA~@D%)XmWctfXA}=oWc4U)Z`IZMLWW$;MNe zwo07?IOFZ!Y;pdzB!D@ZvpY~g7Q1pwu(0M1o0E?aMH}K0!I!oaVMxj+xt%bxqpzyK zYMqggkU&i(7@F>N^CqA)$tsXjvmYPXJ{SyuYMSoR*`Ji&2eT}GHuo+N1j^BCx3VI| zEA-dE&{jMK1nfb1B743;<)dBny|;(jh|lRv`Mk@5lO9jmKG2dDKQwTmwYw!aaT&NgZ!XlmO1r1;ihtOT?gT-nryv1Ly>dNfU2oLZ07)7e1cJ zhKX3yU|{f!lyjb~Nl6wqEZre76L_~{&16fauN(6xyX!wCX5iEB4y1Z9O!YRR#@EQD z3>0iBT_zM$>Xkkh(x16#fK?3)%FKAv&j;12kZKcJeFhaG`4q)mkv$o|P(VGoEL<7( z7|>e(6(OH3Fdoep5fC>vA;Kxiuf-_7dCJ^a*n}7OtRv0@K6pVjV45m`Eq)dW4a+kH zy54Rql<3+#GZo zvm5;JXHm>~o<xRBn>?tzoJEvwbs={9xHpv9JzR-4j>s97o%RtE)41?$0If9ydlh0}z4_Lx3 zFc42DqTm19jbI)D_t)5%ItHa9o+6tY)cA`;EY#dH#&trm?AHBDivOeZ0zr>%0`9)Y z87qL`mHmQK_H@05bD5EmQD>22NI|kNRg1Q@Y^|sQEf$-rFXCp z66oBOoT*Q>l0?|CT-D^PCY8n>Ae3nyD6(L`c^{tS9y)8T8rHmpUr4LL1Ele0Q&h7N z3U*4gBAuV=nUq4!T-BV)6EOJEoQ2j}Jraj-Rc*!`ccvOBI}i@7r{L zbk6sXgw=Fx2|KoP*h>byz+Ev#LCe2!zw5(lcn2=k#+F08RZnoz&O1wfQUQZGLrcpV z=jodAqTd!oc{FdVzZHc&vB+)OKA{$cZRi|~KU$io*E7nP zkqSOZKcVOBU-NR8tb!{0LAf#97o}kK;wRzDz9;U7KH;;zC-yPBzcZwTq>tTwOhaO= zS|@joJc(iam^Ez8(l+Uv^cnpD{Nc-JwvRa6j6_XC;_DgGw7+cQesIC=;oE;Hpp;F- zjmseY zhKS}bnRVq9nAkA}#Gq?758{)}zOP{yyieec?VK5g{Sx^$^M=ltegqyzYkA7Fct(>n zs&!g4Eda@Nl;>|m35g}{#qF6oinNVbtQn5V+ewqhC;_JX_-R;##5F>t7 zLE|Q>+DUptG=h66UwbKNXKUOwa-v1*Fm}bt0FJrd5Fldm3yqmM&i^yDN9BW!fK|CE zG`LF}Mn2r6SaI2>Md_?YbhiXJe;3bMj=O5qcd@DbDN9wV30jL~MR75!CY6F{=nXGJ-%-jZSum$9beS5K%~Z?Yrem=Xgm*HRXSb8lzZXF zj+3vPcn1_Og$U6CojJ2-KL7!J-3pjD8Hr!s3`2| z%6$Hqbhj=peV0)>8n!MWbMnb8s5LU7YM}};1FL?G^jcf-H|p#49L{oG)Uw%^TliS% zY?g=<0Qe>LtyO=wjGVx19+QSEY#{R619tnYNzNRV`nf&;fw#o-41mLJXs7F(Kc8ko537&mp-FdMS^5T%W=3pVI&pSy=UNx=YG!{$c2%Zb#~*UP|G6*G zC#$xJMZTFO&>QR_A53E{64t12f=MfNoj4Hbobh)|N=v0infm@1U)rR`Z3|$#JK++Z zex{-VW?^e8<~3i_+aD#8^=d#wa7&tbh)%BPZJ(z|#KjD=mJM{_M&+xZ6aQSV2ZGX) z$S$me`r*Ng?zPQMr&{{<%@0u6R1R(LR3zXcG#LNcp5LdpMn=YN`?&L0nzZ`&Q27ku z_i0gVJ*g0paQcZk`YN(u(SG^C9EY(~r5P=Ax5rcEr&YU{D=9Hgr?#K@%wU5285`@S zrI=8z;Ph5hep;iqZW2psm^Yr_K5U*>@=fbm5Y1ry9MI0o)XJbQ!CfiIS~LCIthLLS zbxYzCdhJcW8EX^60$d3DR(Gp;Nk3)N8Fm=v`uy8W(&m6$9^CJ9hI~73qG7^hOY#=| z{L1?Emt zNs5&w&~v5VQVZ{6^f_`leX);dJ*g=%X&ehzW^n7_JL5qDkcHjPzUdPy3TtIyMH#NrDt5?#RlPkX zoSES@o>pp1T1!6xnX1#m+nWVWy3J08E>G-WX3V4xIyF+-pYS%1NDwmom^td5N$SUa z6m{!aq9M4H*G?fB%yxW7vHvZ>cVl_=qz7%`rvS6+rDjIg;CGV&FilAr5LuH|??HI; z_lW)B%y}6i_@6N4BrEu{1UNTs21|g5aPhT1)9G64NjFcY`=5&Tl;<0>ZCjr-0=h2C zDDMqMK}Y;a7yHsUbCe<~-Ok-^1r@)J)}!v$r0w4rC{|pY=GE_`RW~f}VWI3DhS%q^ zUtnCsz}<}ooqsNkrqe2R1)z4cNNMi5ZrhLI_2s~qrn;&X;utBu{!rj(dgj=~o}frg zUOwnRY6^CG?79%IKUq%@oncx~2s$#QoRgUx)i>j&l-!A~hx%`IvZALZZ(P2l7-A0? zWBg~Yw|I^Uv9z0*sY6B^5U=-65di40n2@C#J_2YT%u!CA9Z2G{=n>RJt4nMuY?~yD zI5TGW5fBf%t=dS}nJx85yp+IqZdSd~!km%MCI18{(}AhV;1PSd)sLzW@g zJUH4${06!iW;T9*bH@_x6k2nq4-aIrrY{s?{rK|r!Meo87b4eDUHu7g{;8&O(3K}< z{7b|7W&xvp#8>9~Dm0{z1raG%Yp&gUYI*%{42+LHA8XXvqBOc3zyCjXo{`-t7cy4=nIhEIi#+^nshclC3vYRa!$c&~CGph>1ABrF|1<**4XQdGap&T|Nuy2m+orTwO zJVq)(a$>fc?@+fvst6znfo-7LK)Hi$2<(3A`p}=u7eR76GG~^qgtK+*ha|1}f9*FL z;TbG+Q>yUov`-8-N4=`Bn*kN}M)IF(hx76M!fi=!yPbXHj^zqwJlA zJiG<$)zF#9zeX9qnc#*txH8f-joKaj<^v~ZC;h|vx)s@_6>mYdTw~1+D>6H<3Hhae z9Hm(PxbY#_ko`0qV z;3vrp8s`sGi=Qg;#L+CAb`EdV&hf;HW16%vks(i(;+gY(LBV z@Rt}khreSGaTOw&LB{rM<3_p10zs9!wBn!VBqyNrAn)4rU)K8biqE{j^qJ^2ud8aHJ7^AHB>_E%d&I1h%&?jqe{OW<^M z9nn(m1i2OT)Lt7lcMg~Vb8G!HuCW#Qo(~lhZuWUfM$PqL4u3|M$S?h{1F+vPcRWD2 z5_CTp2|fimo%q@rC{i7?BtbRz?p_DsWNQob*jGH>*jMA_>ZgK9_Ir3{CBsJ)S2AOV z;|>1iz#-Y<_lket(a9VmUrCl~S4;d&eN_bVZ!)CUz{_EYB7XaO@ z*2ix_pc@p|qX5Ad_@#;GXkNQ*q{(JPY3Tw6WZr-O8L;ir+V(V5 zgNIZ8j%0Lw@YR}26E5uxiFHaw07ou!-}bgiRF0rExlXOQ#n>8Cozl92gOYaNO;~w2 zt}cyj97x}B)b$&S{g0i+m&^x~ggDqol6K(*mWRDzRyooO;)^fpbI3EWyOgSl+!+}h z8E6X|`g_f+nS5)J;FL4p>?kP_$quUCVTiK6#NOO7Z~$Iwfw#sM!;hM1!Mg>j`(vIy zt9uUf>1wFn^=52Wvs2yiiwS=0t>hN_MsEG2UCODu{Sz*kMMu`@#%|j$R>Y+?BsYWC zB2BqOOawGSS7~~YdV&waCP5NZM%*P?4h#+9C17YMyOd1ww#(#gN$D9vENYNs}B^{3I6rQ{^j1}+JXqUOagt$srW z)PbuKI+F7D4|MzWa2c4K@>suC!2zC5tLC0YmS_{2eF^1O`D10&9qkY&zJ>cb)5Fk$ zDYq1RXNQHJO`ERC`ju7Zb#ax^s>rwCOSr&e0S2b}@J#b)72fMRKkuio>#Q<%aNtKF z0?nsP(%O9+PNFn3A6rwBVL_a(n`oEOVZ4gBMZZjZm~J%nw_li}pA}k?<=MRcQoTG+ z!VlMBw1!V@m&~;tyi66u)QI^~YwI8dn}&Y3I$uLfmi7W_)5hE4mTI$pJ_UEa$6ZXL zm{;k?m6jlsXZm(a5FQ(v^9=}$GYM{882S=TMj^@r(#o&pT>gGrV=}Z}<$7tGPO?m` zosAb;eo_pk{@UI8K1Y{#+Tk#KF4MC#-80xYv1??RJEM8=#med83!m3?=J(!^c&~3r zVVHry?-S;c^(zlt5o^=6wthF9o(5R}skBtzd7BKQt+*yDn=Jg$+96;3+fH0QMJ-qG zVQ%0Z#DM$#hCGc+VB7{hG3`FHrDe@liF~6RzcS!F=IeIYogDG&PY5c)#@DU3BLU*6 zWCXktwKV4f)In3|s}q&+ADQokbdvDT#EZ|rz-)gyB3N_x>GCIqcZc;udX6Ogv{76W zb#`HCPQ^W#*)PLQm_Mn`9eUys_&MP=DdIuR5JAk^dsQO&5k=Os_hX{HeS+?}QG_F! zYLDdEf$qqVfimg}nuEUZB2@Ruwn_c*iudaMA2`puhrXI zr*P+<%Qoz})dd~|ya}C18Z$%C8uR$|22#f*Fn34O(ocbSg4sFu)=!daC4em{M_%MK z`N2t>b3jVVmaXv4pWlu%zMl;q7oO)2eZ^%QWqpf&NR`?0@4Ne9@1dt!pHdF4yCR@D zq@`WywNk>Kc|y6%jL1y%tbK(D+yN0>TLB5HRks$R%Ve%@uW;BBycOVXwt_xJU~Qcx zZVK{OlU5y({|qTM{7L*oq-!#NLm2KDTD%&Z3zik{vL+PDSOrS0gT28t1zPj*8^}BJ zB%~S}DV$q_H9Qke_sPoOwxlbAI+ZzuDV8SsxMjqi+~w`@jh)1?Mes|qI!u$py}lhE z%OGa$@XtiRhEoxSTtYlUO;)w{ za!fx`Qps}8jW?fAb&ctQdpXnR%}q=J_7^Y$rGIhDnJaV{bxQf~a26Kl+0HZP)!HJB zg6`1m_YR4yi*s63)m{RSrWD8QDMPO_ouEp)<-cKCazTgCzYyVK0V0BGRmfrr#TZF9 z_0hUcquaZvL>y>lpz%Vz_6;_}KU_Bl!>lSC+7*k}$L+;HfRvAZtP_qZFE?`zl1h;k z5xLeP3I_H$Fzi1(Z`s&UtG(z3!_>*h2yLW22^jmfw(Pa`RZXN*@mCW|1Y2o(!+ zH8Tr87-zDvyebB`0WJVy{QlD9*RZ$8UmF5`sw-p!|Ef?2e;=K3=3~PDTM@vv$h_%h zd768539RVAMxKB(T0WJUH%UuS+;3yG+Ppd1H-Lu*SjtAT;g@6JS7yW6dJ)W=;4iOM zK|{Y+!r);8lhIQUNlZcpOh-(8SME;$^}?SmIE75!j{qK|*fLhWmGv;-y%B0G3y%|W z9=v*eRI+7}T;dUSU$=Y=FdfRxiqmVVtHY2p$T6H-`t;z5{c>nuKT~I3eM*$ z9`)#RPcx3`-_{-j*7z3_43-{X*-2|J8T-@f`kjBj&kCBmB`^PN8_`i$&t9+wv1yMc z|DVs1BPmMP+AY!iw+$~`AbBr!yrO~Rvpnmo3t|8oFb2KCcf{}v?FS$UF~*!V75>KpiO^UHU#jZ4>k7W+MUAosA|Kr<|uv?ZtHbClmD;F*e#NO%TSj#h)F-OJUKcLiZ#iR z%?5=yWO!|LHMnSk|JRK50eyY{HBI|wN4Rp=)Xv1qzyU1SFR9q!j-{(v^iJ>Kpz9(ejqZ!ZepDN*0l zCohdGmzX!$V;R6V?5DUn^>*rhM~VRYPm~2|^o%^EBGqucRkne!I4PGVg_j4N9 z&N4~>PwqS2us~+=Yj&Si%*tDw=0T|bL9XA(cR2rB-!!gQv`4KLOFktVkR67K|BaPg znW@`2sX;rtt=dIw{ro91pWb+?*5W+@3axv?P|S1jfIa5aM}0F7Pj>G=KYdN}UCe!D z^sW#p!7Y|ic`CC#p3)Qjgu!O&D3@&oXI7awaY7gA$D}R^iFT}RkL>1Yoa!re+RO-< z_c!g%t8CA^)I7tdVbp=!*tmPjb1LymOcZ`vQMrBqju)Bx8QWNy@qX(LlfO|8jDGK|K_lGnoV5+Yv2E&88@)9BJq>8JJ2K-=N2E;-l`~T z7}4;jgFug(XrIgBr0^x_Nf*rNfajEjtzTD$Fmh9A2szy5q|Ews?FL*@M7qw*I{8%a z#Ct=ld+nV8MtyQpP;kJwmG-Ts%jHg}B(YiS*QrdYGpK zVz0;Dn?XccvR`V|(_PlSd3o>k8k>l8gXBVQH(WAJc>6B$A`h1FMeWkhpr}u1<%ELt z_6&9I;a*>=dg+juC1J{6t|xV^4BN|Hd5mb!OH-)TY2Hrk$x-gkihELzq<@J4t1-&R z%nRkn`*6l@BxYpqXz59W4YGCF^XWFxn*E*an>YK%(@pdS_Tr==@VN*}M-7|y=Dv|F zdgQRO$)LpKrZIBxYL!H@x^K(0)5~P3{B-H9q!dio;jqc+G2PJdSB+%1EOE+3F`C0A z458J`<)R3OjP_kZJv3;!pcq~F(pPnZg74(KrtCV4I&6MGHo3n58wI;oouLC8sbp2z zZf%t?MyW0r8dxv-3|l`qO*Vl0+kb_h6^=N#J0bP6r;_tS!&1t6Ugf z$^?<8-MtF-aQ+-IPN9DF{Zm{}@`A=nt5bcyWb5gl{5Wa5iHjorYQCrYL49sfCv^;u zxNEho4ZNk@A6ST8W6LmI?@E0H%Sx?WI3BW2Ke6cIgeCV0R2>_fNSIg`9A8~X#Ogod z^;$r`InC^Lk4#=j6yDxps?}V|>%w)L9E{L6PAw%;Li#i4ye~)Mw4nx=))CKXLRd>` zL0ei-CxPqQvaq{R14FzoYNVynW<>c|c?rpGG{&S6br^f{ZX(@;wOKO5r@Gs{%WO3& zb#NdT)U70|IxbtM`;8C>bDJwe&KFO(m$;ER{;w$Lnrz?afIcYIGYrNY9 z?juYh+s3r8$TVl_iL1C}a;R2qS!!|Bk=03#LCTAK2a5;p3`=-cC+>V(PXFe)RC*FgGV;q$REKz?rXUT z<86|;EFKC49;%3npw{s?f%|{_)3y>h8V4ly=bU=M3z$QPRqm-{FMi^#b5M2UV?C0Q zr8tZn7WI69+_X7F4j;f@Nk4Btju~4W}Vwh>7He869)00+S9hm_y$Y=mQHyD^LyNWWB{;KqITeJT!jsg zVr?0FE?1EYBo*BdNEJUn%nyr=v~X(hk#~y`Dk_gtGq6p3OuY z8Cu0WnB4)P#=Z3inb=pyJ5T>?=|&gZg8CcF>!W3c#lZ`(0|lo>v~d0Im{IS;E&LRp z$tuCHvj_pzpRHjt^am|3j}JU)icsP02ih!$?Cz~yx!$qR9R z95q=z0o!U` zuli)K-8gJ&X)15GYe&rW_ir_!{>=JDah+Be!+>RK25al{i?3CA*|1v%$BIj`S^q%f<-9+wn-#BXG)5uu!sd5(SclnA87d83eRaZgE42C`gTS zlR|fdR$KIEqz596^+^LIs4{kR%}GxtQXQ7xA2>%$+R+*JWUm>tGWjsR8XsP!Rg`V|9=X)yKqxB~m<&ylxHYn3@yl(zwAh;7BUa~&Ne?! znyI&M!|wIm|3N!xt&_L-N1}5CoeS%uJJq^9KGEUK-;3gVQi#c@lawppPbvWd@~@v6 z1RPwxTXV4n9CQofOrtsr+VkS&;|6>QQDgi$mi1{ATZzQMQBdWtooMbo(cdA`0p?)~ z(VO(B2lk&#-rf400TxmZ`dGJ_Q}2><6cCpBht}^onL62j=q{%>FJN#!QKYg8B7reV^!IJ2 zVKco19=rtD+QL_z&lZbDq^Iw(V>vAwB}O~x7AKG!cN7^S|6J4)y{qE>@?RIalI8{Y;gsB$%rZ|c z(>s=9KE!D3xW;yTapC9Rad0s_K3KYO^PYW7v)@t0>5}xDH0j4YSSK--bRC&dvgTQ7 zyX+2=^2L(HjSa+7=R+fg7lVn)U3G!U=lBDr>892=Up8(HC?tza@@|*LFjWW)wmc3< z_>I5R-_HsHW2strR_sj-iVEIFdeq{O8Q9pD$qP}ET&@dj(icV(ENt0k=RVp%y~j6p zskZb51Oij8ZoSO3->T$fO1Nq;`MvwTMe84U>eKQ9UDM`b_GWZbxqgrWYsdGWGBqpr z6T83Bd}QXVO(v9?@X7c(@{A7v4D~PZi; z5;4#5bX`7h+&6*Gw1f@wyS+KeAiw@YT!XrXXM3+3<(>;2?QMGh?4ARj8dBUb6}7=j8Jv6&8*9?XA4nAKl#uLCwm|7Q z{u?&-i|`hh-RPTW3K*XRJhtvk9aI{fLDAbspmq;Y6(R$iT46ne~%PV z=cIHW%ST^C8AyyV64h$cfV()oR!EvVH)oX02~8#;`q?6948;{Nt~12Sc)OmkLwRa= z(w*aB-@JvD9c>C$J5OC7u}W`&k8F?)^b?gAx0thZJw#Yeytu9dWiww_)m6YaK}5P>|R|8Dx={yfJt z-@elQg~DjmmoQdF2C-g@+1#UuHb9%Wn`FFdbCcxW+wb0SlDdu!{A^XimU_?0gY!ha z`4;eQxI5zB?|2W%!xB*;A5OwYLC-q>C*eVJ<2`{pxCnJR>_`*aWlbtX(5bps@d*Kw$*K z>6723ZAiN_r_E8s%)MhthM~SHJZ$jbV`N=GWa_g?U#^x_! zH_Iqex*9LVx-QRd>t*u24Ax*7L76sAr|9om&k{y#$K{}Gm&cN;jcf-}sSWA_$8rHm z6wFH$-g=!;TI8v#>21vEQ$-8UAw~By!m@oJ{XX%_KJibB{18~%pqnq^`^94M_WG^W zZo6m$z=PvBb3lV=w;FM(K{8Gi)+T>eH|Jl%(A7R- z{Zvwonu`k22a<4mBeEtmK(Cn)<{@IVX|(~3`G^fC+SV$zdg$93MFp?@M4}c(c9cvU(@`VwPwxH(A_Fa&smM22rxJcPPddc@ft@2`?734kWmVhx1hC0j2RQy_vPVBd##zALHLf%DMTP@}c!o@WSlz?-PQqSm2GqiI zB2s`NnRl5DsnK5YDQI&zFTzji>}VeHS55Ni`JwB&m_z|ydv1Gac&rRl2Zf&QAnSvLALr&kU{4b%U1O=W&51)g7XUNeDKptWz}ad>}y(6{cp9M98_-L$B*;gB;K*0*<1@DCa3I; zun{e08vXW`#(}1ElNT^k$^b(k{$VFZvb2d04X8T@LoHQbcTS5CM0c~ z5}L|?lU`cuJ2m$F>~PbRMdfyvXk%rPobr_pXs{ z35ACZQc|)@UTMoWlOC_DtS_o>)R^($S#72&K2OX;QRT^pcqOcHw8b)|rnh9U9l%$d zs|f7Kk`LKnTv0h2b*`77cWuVGd1RDMpx)1v#Ol6F05s7pIwP6v3#vwL=0*s$PHH_+ zH>ZJ2FU1XeCk_Iu-amm5;j>lxgMixVggelLWOJWy)2<;bN+N(vf3-pI%2c(zeA_;J z%LB28erb}a5T=-1qvo7dz^s2jQ~m5RMC)@9VK(xrfz{VBv{XuD8f%~TP;2ucHY$-q zIW>1UpZ11?w}Y4P1h;ya-uFtaYE#P=^~;;I1dG4vjimc3VENf&1Jk(Y#(?hsfR`cy z#$xB|l2C8ib#t#Vxo0tW;MR$UN>(2sLL*VA?Y;~2$*N+?;${K-`#`&E)8oloLsvED z8V^nq4)Mp*L+{7yW>>9*yJ=N&d*XRe029X!xb_WBPpP?rN1{fbBqQmjc4+?#A6?c# z4BlrO=@$t2kI&7Cn?V7vd+t@aOo70Ot4!FV&>5hl?#(A*2|x83Niz{NZP{Ww-(lON zy)_=pg6lcp6cP!`m{o@+W+Ip!7^Np7gf*?bcvJz&@xa9alWDVlz&c@}pl$kr@u{=V z>ad9oE}pIG!O+kmSlp3^!gTh^Ywxqy4JU*(Tz4=`x%X@tC&uF8iJO~E&yfUX);2*k z`Y{QCD=W3?Rf)v-;y1{v_8ZDc39H|WVXMhF6%I();zyp$ulgx4e2G;LkIc?>@YT`$ zM1JGm?Oz?62KfLxGj}>bv1@ny{_@AbuV&t}hv;FC1#C({t?O*#Vv8}5*fWqw*%J6s zec*U5u~%ikt3GCzw;ns~MN~WIQd25NUti@FjS&b0m8h5ZkwGHfvEQz`2zNAx7kl3h ziVXrj0~{Tp)WVxhokQ&4sb?(4X2Rhlm_!ZnB{dy>eF8n8If7c(i(UTyZXm5{u;nSSEl7AZ`4s>skJ8 zM5CbnSEAFHaLY+2Lk_a;B@zN`0w(Xj0gRmNC`xjz@DrOQ$=w`TIH#;DUFaWLNX%+oCrVH7Hl(T641;K49<=Y+OW=tsKHQH4XA8)*N~3T=T0bdFvF9nmx~;~U6WfPIhg=9D;`OWN_vK5=mtlNHIt1;>!ahB3>>LeEC{i5kq zU4t=z_?n!wNs|nbkz_qJgDnXo9$(_1LsCu6ptDGdsi585m2)_Dik^0S|8MH z?DAR8a9KvU>;;F!u0Kit?x7w~^kZvhkHwm{i@}DtVLZRXj`ewqBM%=NYLx{TwIq84 z*WW$2{^T8=_=9C8FpJa8>gUg&OU9-pfL%haHNZZ+y>-M&&$~8lVxtXE58FL-Jjr_d zS&~JcXU|kNPDf2FUZ=&!P;#?4sT(DMGgn$E*dzwn5kDWZKk@Y3l44>8PTFEa+^X+V z3s{f2&B3-2XK`r3BdvT(P%}%#3t$+|!o^oqK~L%z<&=N6Hv7vnF}nv9p+0^BN+jTM z9_gI!jOgs;2X*Ii4fWRU$UQYtmTKp}a=Ka6XId!$;Od9@*2Af&>nw)lxGPx7n&f(1 zbedN0At1i~=I5nfvp(3wfUO1|udEM#4RYBHLSMbFmr>WRB}@Lr^BNQmsI1p#E_~vs zi}u$VJ|%@=ivXNb-$_Qtb!)OT1S!8Vz^~f)6+#2cT4@@d#$B5-USv>oWt(-g>-@w} zWPP)XVPQUsa{6wgm}Ppdb3gJm!tXF>P)vOpjX?Wce({(7ZQLtsWeu&UAM|P8aBaJf+N11L^{abW%$^qJWJA+M;yL&ugyPZ}(>i z&2*mJ;t61)k$1AdBm20^MY_&&fvMw3ZJh2xR0yERP=B(EvIT_rkyms+JC5Y1$i)() zxPF;dKb-M-if%d%8pORtTHi>BWA&+MSV|oY($Q;`wV^d>#I;lH0z0(X*%|J9P5^wE z!zLOnr@TviXtoepHy5`v--Y@?Z{^ZDx%JjE>|%KNU4cFWYOj=HF|t171;oPOY{dw= z9yd0y)~$7q&kwIBOyFP#;5)qj0FYO&J>CiI+9apz+{Re~=+OHzk2+gP519KcCUQso zp7B7}=Dpb%FEz22nGnYYR;L3QM^T!JkH(6_jL*0Qlgo6Cs!}AQZPHE#VBu0}9o7s8 zDRbW=EDFJ=((U8+=Ycj~68KR))$Td5?L3}jcw#q2K4HnvMgsQU@}%Xo?*|2Q01^jE zv9QW`cX@54+kBeQgst?%1v%aA^kaaz*WCtuH%)G+md4y!{qo}8?<)F5S=Un<36g2a zkTRPneXZn*8~CrbH^?y4UfvsXwCir$#UG zLtk>-u-ECI1nu>UlT35$QYgCC*Vp@>46^RCYLY8X?;QYe;*8@nu0_kjG6qG(pgnM} zZAjCj3G#Qh_Kz_TY-iKS%sV|+;1rY9zX01c5rru{6}#TF@I$lfg|sgm$i3&J)#;TLq%673wTsqG05R! z_5Dx4!}k%R|w>pybWGC~Xx_f8q!uCok5FlNo8` z`DgPB{`R`e^AX@+y>ocw+mTk5`F?d$Gdc}}_$}|F@z=BV?f;4r0br$Sh^rA`D?sG$Lh*n>QH4(? zh0MS)`YN*{8Ceg>kfjRPV}O?a8!rA$lW-4qGWG@lVxi;huK^^!WHII>cg;czpu^7# z{(qkxn2T~#fLQD&4z9Zh4YIthSPHTjn=L8B8Nxq~LH{*iR%J#qxwwWs1Gi;<622Dj zYynCsdOJN=bdIZONgukCM){x7T#Ql;4wQMw$y5XZ+TuUsQT@Sl=MCRQCFFk_r%j%; zy4$TQWL)%styb02&|iRp+RyC|rIjc?$lhAhX^?--)WCINB5SqA1XHblm^e~_ZlI?X zwkU!c9So59u?77*RC#(4`f{#A0^Mr|wsiY`{v~*_W)CPK{3GuT_D3M=(?pJ(L86$ zsV`*pxfSVe=fs56y=*7TQL&k{V(CZR>PIjh4U{+7CJ4+p@H89OZtvFP1@@TRcL_&m z@wN8f70+~^YRYz>ls*glY2VCz<5*)#rQljdq7o( znetop=jfnheOVCyg9g@5&kzqoBM^^`){JMSI^Sryo`#wWp|$S`oNjowi;48~b}Fsf z@suR~`wRt!JM9<0G(|{a0}5w9+IrGUfgV<)ohypqnf5lo2TquR7G1ePgN_k|x4D)}>_#RLTBp znm!p$$CpXW)h?--49N@6kI%RV`;_>F2=vr5jAzB11Ig4-$oFXh?FyHq&~^LXyQiB1 zIS6yNW$NK=;uHvA81*mSdCK7b!>z*Yy%b9yyJV&1nsu~ln(Z$dQ=3UY#>tWg|4heh z4?`(Oq#d4Oy zQ6n6Hrg{?>V>n?D@;r_^aglt9JHV*BqO1 zMf@#QCk~CAqBIt?60H!e`i4QgwCYJZbxXQ==*qVqT^DcZXN>Pd{~m1qXqOVCizyCk z2)b3qQ08qd1<9Of5iHJrV6}yNJK%+QaQ=7#J6^%J7`kGgqiA{7!V)!y^dXuDM{G?|)Dcp07VUppf+NF%e$ql70F4BRW zZXUMQ&3VJ=V28HzBUMk6GaL$>L;vZa6jFmj99l> zg=(fCdxt8yMu&{ivjju(hr-FKL0Np0alcMM!o|Crbrha-F7ZryIBm9+mRA`Th2AQt z@qOoB&v)sf?2MmHct~2&hN7>va(w=N{)ewD)$HMiL@J}6p5V3|k$xJ=EM&#ut)~q# zY-0-1*8x;d(UDE4<0G3heomXJl3{%OZ4MvoDy3%4jnCp`T@&(Hd{PifmgcipQbEaE zP1bQPlzW~F=1si0?358pngFLw%FGmNdp1^R4=Ez1!=f1?Gm&GqkqkHK?jAKx%+7K}%I?&;P1Ww;B&L}F z9m1JTI-HSV?%5G+7`O3j_>a>ER?vZFrm2_9nL@@=rG{h8er!WGGZlkxenTZqatcBwTv;KEJYf$Qmel9}9Qh`FEbPoay*b1LYE`RSnbRf8xJnn;`TN596 zy&zmkVfWY&dyD-6lW3iHThlkuj-NjEbM>17(~Eca;Jv3M*UfQF4S|X)GX8sLV_)c* z#9Z|_-83&>PEy%bSWKM@h)1j7>jTN}bY)8tB! zg*XcJ1(D&gd3ej@XrXcPkVmuR`_#}|ppRFsVoWWyK685xRu+F(tWf``HSGPNesx!K z+dPyUw~5po4m3cF?im3B5dT?r8EO=eEx)DHC%eFx%}yy%c*d{Y-XS$RCMLD!A@`E~ zx)iaub1D*UvsK<<@b0dbea_=P_q+jC6OhDdvz@`2i^V1P6#x9;p0*!<+nDn0UrZC~ zBRI~zW10jd=($+ipHd$JY_~M(JVsyFQrM5H#!n%hVw1bYT1CgfC1vr3-0X(m*JYrE zHwXNNK9PiE^J-1#v@$nm3#VSFpL^KU+g-Z?>zPQa9^EZvTnGh^m`K}OY|cvMyH>R< zAGNFDh{8O7eCjbO>uma>H9O;P+xmM}K&d3}iVN&vLg*k&1EUoDiAwzQ&0Mi<%K$$9 z-1EDjy<-Z;)_`&;d;9yrH%$ypzV7!?A5XP7j^uOUr1&wZmQkDZO?Mg_s&Xc0uNDWfH9>QTNHgW*&};- zyp3sV)Ao^0f#LqMP=p1QkHgCv-2~s@zatmzj~yQMKz&U?#eq{!)@J1N%|X!vcdp_? z1c#r9u=H&sg<XDt7BjmxfJ35BZl%F@=g)p$|cfHarm z79SVs$GgrU)N`dMqP3z-P_Fj&)4?mA<%i@#MNU@0qVS3Kq}%`g)m9-k$AsW75D}Fe zpO@>Dxi{dm47NISdD3*FouD>2Nd5xNzyvVoxChekqNlo`UMB|&B z1nq%E_dy+GYNagpLAO(tE$rN#_kR18z`kV-%-AjgYkW9`FEOzTjLyD6xTV;JK4>Z& z)5d&*E(>TMAOzcZk6Y5&`SDG3nAg57>C93xQo<8pqaRliNQw`(25^HV<;O;ISz6CV zPCT2$y+04yB;W0&u*k+VzIYGY9G((!6X{T@GTQ9r80?Ie2@?}JZ59)N(AObk+}*9f z)0S#gIMYpN%*|+L<)RxGA%B+jlUMtA(0mi)n+YdM!iNQl(lzQgNBb3-b#5p|l!UPFDfEC%VXK#K^R^ ztOXC2*;1RWkeRncU~}&3G#?NI9V*_&lBo{#iL?P;K?Kp@p4ZkJc}J`)Qc#4Km4}gh z#5%r@smd_gBe>DnRAXDUx`;6}Lw_d7HIY51@Y6AVHQr>F|GV9_#Uhx^wB(H&HQKa{ zm&b;7ACDE)q#Ad6*I2OQbZ(b&-2Gy>wrh)e)N?8w|eElr!-GE&oD)On2Uy4emhr zxpZF0qs=OI!t}O9_Yp>^aaNo9s;9}h51@N8)L)V75j~xXk2i~=sHL(k8O}bQLKKAadqLO4PtvS$381>2hktbh1^~jk*>S?Su7NYU>n>_bTNp;hG2^3J?Da; zXb1iOIra9Anou^o__?9AM9AFj$4aL|bCrFyi}N-VD#OR!LvvRh>x0;%9n}j@g&;wTp6r5AWiN`JlDcfhT-i?P(Sr zb`H!2q3;c z1n>{gxX0g7<8N$Ee?T?f^Y!rr<@B{((F$K)mfWfB4;l_?l<^uJV`fP`SA)yP#VcSc zc2EYc`5cQ@d+W;vakW9r6FMFuFKlb_%mR}at6v!&zo-N}Uu=pSY$;$>drWl$fpAZ* z!2umyJ7{EIjc((imMF>qVpfQ|mSVCJFy=~RH2}~424AF|K)x&7Z8UPjwnqe2+$65v z_L97X^VO%b5Zgi@^1B=NUAjVOe$-rAV7?#H2I_8lbMruQNgB6cTSegHv~d92&|XRT zRG?!$bkN`_Vz$k%@CApmGZB-pU@0Rc5vm07slCL;SP^E&S5u)j#!d>&lop$PVrngc zPqV~%F&_?;U1N4A2`u1sGvq}6r!+`gSvJ*{E0BnEvDtj(&t$uH%|--b&Kuvn95KvV zrbm4T18UT^pEObV8i>7$^I$o}+#-gT4LDZ0)Ic)jm`oUKMVxu{I)}XdU^vDCEqL_X zNb@eAc?4Q5@j;XC+>w-Y`rU6v^3LK&<$7!YHkq-^d&y(D==XrJ4Q;InkW&3> z{7QqoI@)DG3@_;vaq-P5{p^TJE&mzP&NZ7!E%P4fWzx>WElbX$Y!uT!^Rc8gZ|o;y zRBs$B+lY7EEyhxbb-l7-q!xEQK{(Ckh-u1dKU+-vf`K2>cW>OO7JX$VfZ>ka^p={X`{Y~*R-QO4O7pA;T4EvsKLTdy5I>w3-US1f@-$WD;`i5 zQL(VdVBpL1y0F!b@YMKM)_tlC=$esSwfS4&g)sjgpS4C<&rl3veT%TAT;)2i$6YYYqrH&A+|!l zt%KBw!&H9Sip{yLt?6YS?TCV< zu|);iF-hymo`qT1R5PvQ>lHKX>eCNY%vj1BmKgnh0q$Q^R!471yp?o)ym<~5!IiFG z#|C<8Dm(e0X{$-gKZ@CW`!Eft{K-{ojD5`}|nqm}Y+Z0O%evJlW+280cP!S#PpZ`KeKXvH@&e@!IoU$0}Gk`X_6ElY)ZD?m^|d2%#)SRUieQj zvv>*!;FB2)4K_>Z5-*y38v-e=O}Jag>dT{-e6UxhEaU@{@+k$_i%YQ1aKtc4s4*sXm`eYaoVCw@Q4PdJa0rr1a2JSb*^Q7`6 z$S0F;E09!aC27w7Q-S@z)HdZ-(R%+W%mUhuy;}b!zn67@(DQZfrHkt3KYzbO7FSwh z|JOh;P~-*5usdQ>fX`M6$2mOU@G`ri7tirIWyd2qbBjSmhG#!~{0aM}ISY(v=?-Ei?fDDchAY><%Klg)YB&`EP)D z>Ayc)eEfG`8?0bpwS22+t0;9fv#9(Gwy#q$GB&0;R#eW`CMmjmusG~s|6_t(7`*SF zn}`Hb_e&OK@^n$@_ozxOG24JX9 zPpDdC)nBFw$oho#HDF!atKNe+4;ouGKb|s7$JJSU2$l&i?zoX6u`A{G)c`VFl>*wG zp(JcZ+%Wz<&v7Fv<2yiS`(o4#xS&Se6I2j?7}o&*Dr{}KvmI#S)D_GQxhOdsu4hgi zzI6lR^OKL)R4!8xIfde+=HZ3;6soTw-IlE=K6RprLZIu{R!&y(XmDJqZo#~$7{b)&zAZU z?|L&9^4dxYX8)X2W%S7mCxKyke=tsz#!)Z`T1T((^UxeJel#pGW%(K@G~gIymfBze ziIS@KN|W*>-fZwp6o-y*5E@gKjfX~$Q~cG<@&#OG@6}`GGi%m$9y?4`)S&yt&<>mX=%Jd?$oHx6A~|~uBenw+l}ZwZzfdqSS@$!%|2bm zvf6Xcu0zH)J^~A$DS= zV(h1HjO@8o^7Y3nHVj~!qP_>hm+uyCyZxe3Zv0c~mY5Xp@@knA%JXwsymZorvxn=$ zY5?w%GUY5EmGRDPxyYB)Y|wK~ld78rKT-bli2B*-BTbamL-kj)uyNyoHc#Y?%r_>M zN0ynNr8NhzSSDSQEvBiViC5yv=>QKltDlwF;@iEF+YeT5+VUK3# z1pClLvI=q_ao%?JGWE^HGZEM4Agei z0d<0J3HDPJi*-Yc1!60MCDkilw`c2u)^|`gE8w~wb7E>Iu_6J}Jik=cWqe>f^O^RgjVq%KXmXQ`|H% zEx?pMO=5elr>wb6uEjtN@=>*R%{Wy?^;@s!z3kC%;MuwzZ!@mzJyRk)W~SY-CMqIz zJqvQN-X3V68zU{vOoYfOF^=d#w*IK0FkKO9AE7uU>ZlXm0Ly#FIjW!;u#l9ka8&l_ z^#!L&yTgy99b;45Z=yf64S(=~E6|{%4ChVrn zlLln!dUg>6jLl`I&_fAVW+6OIAg-W~W|P-z5Vo(I;Dk!*)??sPrkJkhUDIYGp^AV<`Jf3ExOGneEAO#W+%Q4wF-Wg?;we96>1x@)C*uVVqU;MxvFdlI1E`z#la8U-)-VdW%((t-Ohf`iA6!^)8ikHPL zU#^4wsM8z|TA;qQhO_X$LY-JC_{KWKAcVMV8Tv`m6#mH!{(MpN1s*{DxU$IZIaZfa zxyZ=+r&<=t>aT7Cxb+f8rEl7}2t)5_=Y|G1yI!%2-}m=bM6A>9wtP3FNU!qo9tz zJr}(THT@+V8{UzU;Pj_joR=!VLZh z;FvEn+NkDReUZb;Q0;fU&Ji#f*@<{RdaXI^mlEmy+A?dSHkDc48t)zFgW_dv$1{F03G(T?Oqltk8b+{VB8N z6a19SJ4yL3kQ)>O*`x9SgUYwRU4_aDvz#x@dMDjI9~WcSJh_=i7Jy0t)n%nrJ_2Se zkn4bqnpaQ%V14vd>(+JTXH1(Iu(`Htm5D?88sIf<9>Hw8N>&VkG2%xK9+qEw(62x# zN=VsUuQU(%e(I+CG0lEzl#(C#ysR&N_-STV=(AzcP3F2AV0Vw2k#H$F@&VDfwRQOX z8uY8T$K0lMyIFhos3S@zW&6mtsP6PSBw!A_`iX(=+9P~&aH@nM?>$@SPVZdtlJF^A zqGm8;SgXDTvO~IhdE$_=ZfXil2Ox)5ZJquU8uQvk`baHy&%ne+JWnudNa5NoNJXMk zR~bZ(p3mF7roSmaK<1DSIy+6#BO_m?%bLE0bwBvti#atLG?kVg?5K>tXG7aw=he_R z_NIUP<*yWJ<;d+@4!GQ-e739QxC+?;a&3h@OZZ~kZ-P>e)(%4I03TK@{;|y0w{=3} zW^xhF3XN%-Y;NcS8XLCv=V9;9tPfh)zK4juu?3e~HnQVliBvUrHb%%>mNw!xac2h zCQHIf51Yi!50cseL#r^&v`QK#LvNtu22&T%e4JqwXdsB+!#B#7T}dHP`RpLZ&M`RF=` zm~@se>^vckj`VoeDZ9n`9zm_QK$#FOdFII=`yIy>5J~|vhd;HGM$%-}9)CFcoAWSd z^!i}ewl)GeXNjJSRzHqjAX?h zDK=FJ;j>kA+T83*W!NjF8)B;Y(S<;~bUWT1Aw{2e>(B6{eCNox%HwDG=>=kAC<4u_ zp!HmXW~+>Q?x+3U8P3c{+OECJSlH6_md#S#Of$yecF`E$mtBgU*7=c%5A2V-2D#V}RqLD_ zct-GM5UDKqC@&o}((2x8?0tP(BNFasq9h#S7sQsGw!>(~PnC1vFnpn?fRo@4AO4m zHD(!B2gSC|p4c4$iW#;5P;IGBq4;6iszqP;Osl(*qwp|3`>3zZ)~RSBO)f_{T8xO_ zUmaOoh}RxC8802hy8BBx4DFS(-eC*e4wm2^&54%b3!yZY&r}bHqN+w?xkI2Pe^pDy z^_wboMWupl!$~G5yOGd91;NG@4iBv{k4RQo)h7k6r^CLEQ?2^mXD5HI292+DcZoA7 z@`g~P6fryvHXHGrn|ToV9{N#1@!#c=`^_#Q&%v=Vy~p7>p9fB8&g-c;|5mG}&Gcw- z{h;EF#MO&T#H7l;9f*C8d7m=eOf>N)n*JOYaphO%f!tZS$U_(=#7to2Ee}dmdJb~* z6~zRSCGKMtUH>|bU(jJ(gitv+#=RJgc1>Hs4b=LS$pzzrwU0X$tU53c^Zv|rCUvH#1I1bO=JBmXmsp?``AzcVUG-*Ejm z{JNq8BMpxWsDxgmG-Net|9!#d0*a*T5uD9XG&~}R|g-lKa8svTBie^-@n(xwLQ}Zwfg(#bFzJb#i$V9E`>U}XcqLK2|x`= zoNe+!k-+AA=sHx^N9q15d)H}WEkd|#<}+8!;l`9TG6*nK-|dIOMg+ji(6i2)!D_p^ zU|jbxfRg+jA(TY&I`GG@Jpkr=LTW0b$K{RQ_!oOfw2gC{uts(D`ox49u8qMCS%E}~ z-NuCNkBDJwiJF?4RUXS)e!Ghq?!U^s^vpPi_xCSdOyGiLF6n};$x4MKG(w0*_T($G z|Na-yc407*d$7UM|LDOKwC!{OpjO2J1QT_j6nNq0=!45l^$zHgj#!L{fOGWYPi=6$ z62k@BYouFXM7W)^cjVX2G%3HTKtQn6 zeL!M)(p2uHw$#qMDJZ~}xX*(KbpLUl_F)7ZX(gobVj;40=+&C~kJp+jIwqauFJg1d>Ig~4b4ir1ET z40n{vO9R%AspQ${8LsqZGmWej4HizFcY{diOTkR?p?JUPbe2}g7)MdpM;2MaNsTQ2|LFFu?5x=8lj=RUnvKs)?9?h)ot5Nv6 zbXNYv&J3T~$HZS@Y`xz<-r3a4lDdGro^-SVYZXB`s1~n2pJz+dnj-9}=N_8mpa22y z#2DRN9(A9gZGcSFOD#V0V##r6@je@a3bW5or=j@$?pRLYV2(rU))MVG8`>`=4Pw#) zI-@yCHa>4JD{gUY%?02ReXv2|%jvmSS8lfNg(sO*+by1uzZ+0jZ?b?eD7Is_gzX0w z>YyJ0v6~<1JfXK(_$XOCV=~NI%z+y5yAf^K*(>31gRLJXa{KnJJ^sR=2$*h!NhrGers$BV!-**g9Hzd_Ymg=aySn4{(8**J&H%O2Dm+f0E#_+aa>O7DJ9c!=7Hj zxo(stw`zxmLY~7%8&_(?q_!4j$Eax-6jz+u#bjl55&%5*A`+cpJS(Bv<(1hKL`BPHhz5lAU4I+vpJ5uYwPptWs8UY8*76sceb7v9$0hq0mJ7WDbP*^ z2ynerLd`FhzxBw%W@=3*cXIMdAcSGx+o15kE#*2G1?1)~(^ca)x$cyu&M(Ygt3M!wn2u zv2Nt<#6Z1w;k2XoJGO-(&Esa>p{g;O^=p399G@WuMu!{yJ{3Ql<~ zVT47H!ytS7`>^pDw=Z3)Up$=jqS!#;muG@2B14?nXX?!;3@%H*wjf_%yf40$jKP%K|S#LxI$-)TNQ!0dK&Mt6%&m|HKi^GyhbWf%{S+Zn5~De_Hr zI{d1G)&pCv>3D^ekjL^sq6b=fVxY`&>+?h$mi4=YQXH?ZM*X~en5#_JvzNy)A%H}2 z@BJ`l4rnVOKO^GN)}-4H7KL`}k`f?Qctcc?9Q{*Dwb54Y!8I{Zxx@T?l9%Ykz?#aJ zOLOgLi+)P*ma?-3rLI=MPo4LKGW>sq`I=)&A2`Z7s28Pz!VSJ^l19WCEu|-O^pl)G zK*I&G$K!Rt^QDtItGyCUEnfP}waurCtm~O4jnwv=6QGfh!wfjBEV0??dE$?#7ro_|IIPwGb2ZMjsgq9I+p2H7ZWY$`vlBh{WO7*eqpxJ9DV#<91#|nBq& zRt8|^Bm=Fnldz1-y{E*)f6?9lL?Ut$eJR4qBr4Ekk#D&4ed@7L89-`p?7xGW7=w+J zM9A(!&n^)9zfV%QCGmZfFolNEHJ$)}5Jd%F1f%}|$+Zgp3AFlpk!Tqrt-x#(QPyg0 zZS85Y^Cd~j|KCwr;=<`6w$7SNhvolqzy67Y`Gx>~nnM@aLI7a-)E_g?^}iiOW;lm@ zla#MV;zf9CEC8=#wKZ9c>;DWet9CPimXFa5S1@_DoBY@vttag_b*KJ2Vgs5!z$3tt zL}Y=J2#F|=l{vMj#jBJIn8_A?z(mfkqs1o*EmTXxdhN`k;w+F#}sJ%ywbiJz0WS4F@azB}raEpqj$ z@!YnTivg|lG6oLnlRbkv*Gl(yxn>bvQT8jPOG|cBEdg~K)3xd{=YdVkf%0W02Ys5v z-mEiG(~^Gu9FsYJfYv%;w|>_O8hltQgtkZ`&b^;lpWr`eJp)x(Zt+EqS414QHVW9h z?@h}fHjd-Jkv=`k>@62s*o-}?hzEsscX&ongmj$Y>_D?Z&0} z%$eL-7+`{m&r38Xr`T0@Y$lBOOAjHjj>KbOE8o*?^qnBHs*32kQzT5a75xqI5(7tY zR0SoA%nEDzXGlz^QwAJtOfA)#rUi3I--qq|xK$*JHH&QU4Exv3#Kdt?6@edg2IgXgl?`oZIzmMlf8ru*^IhIVSzL zJg{vWPng%m3N^`qD}L_WAF;JxqcX+EAE8*0Ad_F1QM++h-LlEtn%Ve2p^ zdvwK_-|(jefsylmOs(k_4ZgWV!vZXViYP;CEIyn#o>RfBQwi?TP70RA`IYhPF%o4O z*7s^s5r?MLt$+K!T^F`)x6L$KuT-#zhN-al$G78GKB3R{8&6jE#;RV91PZs6FUx}# z25~4DkvYC8^XKv95yHAhTSTAKUO|AxoWE3l<~c~a``FV#Z4~dfyJSC60B`i0+9|{= zhHjc63dREA4&(EuzbdrXrx#7FltC4H$pi)MO1$loS74B-V%SupD=Zcd5T%bjrGwF{ zOZJvbeoY(h7KoG^CeZ`kCWxw$+Y<#H4+G8}I^k^rAuf(*@y+!fktbHrmB8vlx81{* z=>C8V3+3N?E>j#5PC)nVuHSQQU_c4@tb1Ji zbcJ*BI^y8RS-pvC#Q*olRru478^^oJ#0O0?8h#^lgT#(=ZTso>p@MY}s%I*2z&Ssg zxOVotgS)Igryv-P)rC=~*{Bdj{uK`6E(DYt&^^N-ehHDTRu+9$P?K@(Y+G=An=GRp zD}2d7+$U-6o{!eZp82-Hd@#%A(>lc<|kA8$*rmTxckYv{h zj&2QjUzS!8OYbE|gVUV5W~EpjR}3NPd_L>qR#B|_MA&RLYjwutbk zh-|dYauc^aJ{e=mg^0Tw$Dliw)WVNMPp6h-GxAWEe^hKv?C>8cG=0~o_mdn|lyo{9 zF=-Ug*#PaeS+)0x3(sf>qqR~AlImS2jqP{`Y5k5qan2=Kc)7(&Qi>|ekcp&_&dHDb zOuAEr<#qFF1LfJlnxgl!m3+GY*!uz;jvBa6S>?HWBBU z`F8o?vRgu^a_!~1?(^9_W&I?auR1I7)qAPdp!X*ydp~y1Pu;$lBR7}b=aS%w>UFaZ zN1Au5(aF6+b!`dP|2$PZ3|gF)1)B|Q1-UE*?b8HV?S;v{vTyWr)l>FN(yEygH0vJ_ z|6k30cRbbY|NjX`A}iyhZX@00WE^GQ$vD)Bl$E`co$T!FNMuEX>`^kakC`NUZw?Z& z_jZim^``DmeIDQM@AvPoKYHYJT-W=3U9Y{K{4FK1bM&(WH)ev3d&m9NGsn|3j4Gqd zjG|NR6IH{(06c@)H~-u1*}V_DK3){0JH*KsmYuXy)4L+wx_gg5cFI?1^iVD;QT>P9 zPW}d^<%>hs8%-4w<+hRT6l6NdSiLtEBmOuuUfkE|s<$R89YKs`2E%FEMp^*}8U7hv zn}!c`VpWzR4CSyt+9W=Ya&PftiW^kyLW>@1_G(+A-F~xxcTrfWB3#okuhJeV{j4j$y`Q&nbM9GYcGeP08*eg@=_*40mZDgia>OKdUv}B}K^huEw9{g_`F8f)MN5oLJme;EF`X!UBb^ac0}ltZm_b*?MxY zKx3LrV4m~FQuF!;uUZ5L3C?q zizp{6jG7>%%fN@0%9WZiuy^5^ zKE&kUIRt0pq4s>l#W*k=p~;_)qZyNTezyD}#q|j)Fue3pHq1$BKK3%i4?Wm73*5KpVyj)jqOxQ zE}B|S#xDuL2{slAR*!zMm?o+V-Kajv{3hW0WK(2}DP!r11ck`DyzK>H=Yqp< z9>!AZ1df@5%qQ{o_#)E9(S<~OdFMV3{_M$g5WM&=lYkpl@SLXaIvI4QX|EJZJlsZGh?eGXY&wK1_SM&+Z_#nc#IwG2yjQpf)|4R>cfPRTC1I{DUq)u+5Sm#-BPZPPk}&nhrX=GdYjGAtdADnk z2+l3D*6;+JP(s5)x;<`9I};5ir{B5HDSzv>f-^N(ak3F9&EXKrSYBc=M=+#~EE^B; zppur^x+C}mpEjhb{i121c;^H&qThg-m;{XfW>@=&21r*k7(g~9Xob73Re6B**&XyM z9#j+XzC1&9-}zb=qFv~3mS^`#h+S4K;kK7hh;?gx1}hnf9{}TpB|M}?evk!c1ZTh; zV2X)7aa{Tegc6IaL)s5$XeItaeH!-?L6J;sRw40vXNxUMlSl|oOad~6$$tdE&TJ6r z;9O}hy(nYp)3n7oY9huLKM%q^>(5BgmRe#j6nmY3o(_E5AMQV$jI1D`z2MJhM2jV} z-ldkfUb26e41A?0@aR$K$Y?_q!gZhj6xN#*-C>u4ShOuyx0elii54K`gIdd?umgQMbSW_F^$TI$f3j;dHS9u3)i{A?_!- zNJ;t-4u8#RFj)U+NmhBKSm^cc8_~`j{6OuE6Fn=K#t83|q~5&Ruh_`RGU@f)pOXcq zef+jR4<6&Pi?k7k?NWb0?QYHcYVeUvd{vh8LRTk|oFjNo^zTcH`gaCEOcS9{0Pt>T zPMgSyNubueJ>(6oPB3##meV!EJ!tW84`~2q{KpY|hWm^DlPeq1_K%F{!M48BOlqV7 zV6~##dd}6%r%A96V6ST6j#|0z!i&A&0njP-`2Kz!Y_U&XVM)ptOXns)5WLV%iiG=Z7?ala_} zl!05(%FkxM6Tq!4&Y$Nq327khc;K-qmvVDBxP8Z~I?e`1`h!3e+yrdl_t(h*4s`>V znl71uoYeZ1P!Sx@yxm~2Gsot}UDxA|t&tPCIfNUHB-^y&I15uk5rCd}f8}57CCyCE zX~I%HEI`l3l5#VW3*fVti27^H;xTTs3;=o_4Q)4byd6Z^2xKQ&!&JQcNGs-&mAFr< zq#WD<~AEssQz;CKhQyg8G)PB2r0 z-ZXs)M7S`3mkv-Rbf;ldbiYV2DL84p^D%1+dnZ|^-CXYgHuWQzdDRTJSM6%+OO~X( zp)3S&DGK!&i}mX$cyR#MngPt@Q5M~qpyAcI2a?38Sgg8$`Jhq}TVU$-WaKdypwp=V z#DY@hLkNAZGXv+DBsk(&BWsrhjmP2iOoHZI<+1mxNI zF>wEARe)~|d#_eYfB~uh$Pu1#Ci861r29G(XOOePJ@iPM6HJKXZ{GiXrxxuAGiFR` z`6XYp!qm)L@Ygy(21B2lzamL5fAw1p;64wVi@z;B^sU;vrM6gXU|fRVKQ7(4d-UE_iMeRJ1G5qq-~EjUj1s&nupb;{^XPCB?yt2h zL3mE+G?@XEowk_>m2}qEoQz`D<*M3ik6$|fxA9@W`(Y-(%~G&n1A|k1nTXe@vN0T@ z8y_Ru$&;>61_LvKh&)#bMNuTT=&4`{XQ-gV=On=N04VkK&t>7k^=+UOs6;ib*;Tnx zXe0YAtUcOEaUw{yl06b<7kavjLEsG^OO8(2n=M@Uscu>_TC9h!=t^T?FU3BgWCY^BAXc$0#v}bgXnM^N2jy0Ds2el6n5){zejhyVpsn=I znphCOoEm<)hSG3-731`*ju@j6Z}kYLuZvPX$ToP}QpG z6L7|~mWmt2Rk{xlV$Stjow%Tkyo;=NMJz^?@71-%i2CbP*0^vt5SJ6I65hN+N{fXB zQxukDvTVgZ0heSAcn@|YwlaaN24YLbn`lrjl-)I9`ubr+rY8t0z+zm(sOwu-c!QhY zb5BL^lMC!iQ(QOm*jv5ky3fMk5MBTMUA`ceTxgEi=^)Lrk@;|2@&?;mHwy%=o|1$v z$uo&OSeHvxOn`+?KK!-2nZ~!Gg1xplhooo#R;t<5`E7TkC5VaGDXNBT2t>cX$^)JCYwnQw5= z7Tnfx!c1i7QjVnY-wP7yJ^vW@ceN^|(A-Pb0by2EZM)Yq?svQsqxn$aXr zn+D0Z604KS7E7Br1nUPjDbmS*}g=Y+r_>srVS6sFVh&^?666b5g_|)%oZn7Ro)kc60 zJ$Vpewtd$SjX-G8lUt zqAQ98L-)97ggb_s3M^Td>>^EWD|k(wtQ8R6lgzbU*d*=!(_BzHz7r+`09r}_V&8AXs6w0 zylv0t48x+jdNw!meRZ%GQ@B~h^xs=a4iQd-cvmd_c!7Qg;-6;t2ZJngVJjyHp{fXv z5=UWCU_@erENhs8M?q3pFt{#D zbIQ>wM$BgMuHkM6b3k2s}*Kq zhI!cktIG=cS!Do#_2-m3VG|&>&s&^06P72$$|m1k8w5r`@|^T9?e#p#gaoM81TYrs zl8w`_5a~S*sSRY)f-wNRQT9J3Cc5`b&SmQF#P(0qc|qA0KVX*~5!nZnq0=tI{RE#P z0B`i>m?M-pb2RPs>|VjgYu1eu z!q`0EZ0Sx!Z7YoIK1@FB?A52kNJ6-m5rL1n|sbNr1j zi~Hgacj6-_SGF~a9)HxY^z|ji&ZNaOZ-cS2lVGS5&v@*Z2VtYb%T>pxFxcSpBUJ!w z@19;iK46pzIS)kb zF@RU!Rt=d=QNM-y=L=1{KN<0h^&58;LjbN*0W)Oiu!nNUS7_;CqSd>jT)LUcXy!4)iKx)*Q7wnJPh^)GW0^E z4X6|H@$AwzSEVflZN*v1-zrOnNOeep1+5{=CgqGek-T=Oa(KZ|D>R=E3(zi`OWc^x zp#kJ4^4amdvwDyk(V42qT;SrG!Rhk_NO>Db=lgZ;KjQ`bM+)(FIsk_ID^fgJoF-D8 zW*tBX)#vKf%qtB=$Hd$uybBeeG1#lz4t1%LSYIox`v$BT{G|_~Q0fq^_3!Uj3^&3p z*9ABo$Ohf_``jA<+!wnpez33ki4s)A0)|3rgFCx?lF2b)uSa+P^;-bqyE>g596h;I zu@#4Vy4GT|HSEw-Ln+1?fZ&b*zI_w0SuG+W8wIO&WSjtM?YvSpfGQMou_Jy#3#z4H zRI0@h1wS+hVfW?a^fVw;(f_5K=kkYGV%haxUh*^Ac0J0gV3t}vG-0kx$zY;B6iVZ^ zfOT0T}E#2+E3OW4$*6!XI9Vu_(O)lFyavsoVn}P285f znfpJQq{+r=bh3mRoiPoOnlW|(O?1sA#4o&}Zmr+BWq;x4O~caDTuEol^`P8-Y*(~V z%$I8*#)AFkMK-Tw4W@;MYFbwG$iDu1-m+Y;?&;_@08av`;AR7vE97UC+w_;o5<%G+ z?E5c;kO1Xm>p`;Ja(C^@WsBRP{?W=$nz)Lk05ryel4&NGIUi(b+WTt6H?2U9)$5l3 z?}CK&y#+Zr`D(E{zW9fIKERFbZsp1p@nmhG-5uGgG=BG4+j%CH$8FCMxCc877;*i& zApUqpfUhRg+A_78;QEK@;WcjGW3r*~v~8h3j#dsjgJ! z19`QwK49+P)V+jRQ0Vm0_5)~L0(LDuQbOerx#D*8JBjsesW_#@U^UBKZO9RL9uhfan@gNZnlMluD%z}Ei)b#W_ z_KUbHa+T$ZsPaNt=Wf4ww_TVf&EyX^S*7o7{_ox*dS40KJ|BBk@?Vs2O&jB z=tap!0K$Fm`eMoWd}lWGd~Vrau@1$3K`!)72*ly7=sA4D$ZOksVoG*)pd3$=13b7~ zcM$5>M6A(qg3b+yY0J5=NF+;t@bGT*7e_?0_xYJo1yZu6n&p${wq9C#RSh^%V7u zLo3)>iPIyjt}hgHO>iH4=e8lZt=&TTv+V82f?+*&7*S_IZ-1W^!>!$YkR+BwRqfe0 zft38heWfsW0LUH*#>L8m*5S}opP$&V_(JG;|50qA3Q9WFOFG`*ciop^Orxe(Ag=0(szMwP%jdGf`pd~U}fgF3*N ze8-GQFFtiail`QdJhag9FGOa>2Cx7Gz+XQDL3l(;+s86sj~+I7rkx&kOu0Y@V_@ix zUq8ZNDfE!w`~qDI40Z)`q!FQ52BZ;T2}hy~I(Nvn1z+&^xhN-KC>V<<Xdi-G>TNe)8g(tg&bY9(@A~^^#^(Ceitbrnlt_mfG~v z-dQ8m|8|(p^ZjlZaC-6eUv6rPy|C676gk6T-1JzLiJ3bl=gkG%#hehU`h*T1u9E%Y z(_2QpP1|*ZYbvrKiEifM$6D;CJi>$!obRpw;4o{r7nq!y6Ki<-9M@>H3U{Dw9Qz%5 zAOvA~zr-i4TCu{p1(V83#67cEpD_1;KK|;fui|41mJc4s`Z%E0eQgbPh&5}~)7A)! zz38-aDu(BxCyn;?nv%^ze5$ujRWNc%$HLas2{y2xXa-i`d3-2HY0q)VdMnd#jPdP~ zmV4gUjZtT!1cpZ%`L)01#E!CG&2w&LXVA0UiC)%r-_M9^({`xI&%k^QT=tfy?&AnR zG<>*L)EYc!O%rwMc1vW>_~n7ED6X)tSrI!~1S;mB?~SE{E{3qU#Ayf>F!9y?WF9;9 zA0j!N_@?3K#yd$OyL_N8Dukg+=xV3c7OUxBJUW$jo@IBka$Z(imv>j?OU04eKNVSg z!XQ!~3!<`g*TSdS4MpP~{BS~bh1rQ&mrj!O;!$Oc$ffKr|DnM5r|aZMa5j@N+-~ge+!Jw`7r6u*lN{zh zOUy5rAAq$DS~|bZn;WZ?^$t<&h-Y3^m^FCwE^CKDJtN0zh^doJvGF%!y_Ugw#W6kd z_CQH%>vFg8E_EYUm;cBa`uh57a_UVZ_CE?ND^~ckdo*h$i1MIzF1q@99`TC{Yw3X$ zxr#o2>iVakMcHKhiuMMNRW1d->C**0aoWREdgjCSlNMqwvx~}|Z?FsZ>>gKiY`i{@ zbR=AIwGqpx*l01J#-w*eB=U?|ljoX8v?zxu9~-v6*jPz4jDKBrTe0+BU29ZOy7|ej zfT<~AM!!1-B@1^R#Vilz{Ykm?~$(>oX`gI`m zfpjMA%5zxKF@5ytRqPFi#{cd*QFydlAt)%=1e#b3`m(j5Q0C6TRu#8p#YV*2t1Cnd zE)8m$G^T|!!!kB_F`UI$1g9DcP{o}Ys@&41*t4?)NAe-WfTfsma0H!J`Hop~_W$}dj>h#2(KpYj~S zZl(I4MJJK~G^_vSp}^z|;Qz|%bTEbhED7lV7+U&I8|e=P@Q17p0K37C5V+2f$xyvzXvvqztH^`iNmzImPm(=bMe9zr8S`1$#@nfz7=F~w4MU3CW_ z#pY4}uM59}B{OF%{RB%D3OLv=`xX!}ajfGYB_{u|9yu$tSk{-B1Z<(0JhMKO;<`N_ zS7~z(#+k_bW^`;nPvVI(9(8ho=4Ok#$oj3iatbfrN(ECuB(`KyiS)@Sk>A2(ZKE zO5&-j6VFTT!lBUYnJWn7qx2;J3k!o?TkZzW-fn?HfAiPzD06#+oIzDrO??v$;d{n) z0_Jz*Mo;HHNbtBHdnu~i928l?Sk4{m`hWy8ANU#M4EyWEKY|;82>-PQ{)@)`RR8l5 zztq1+`0Np4^tFGv!f}@2|8piG9WHf3JS#$ismCB?q*Vsqda(Dugw?NF&bX&e@3fY~ zG}5!E8J@~JgvqqGlqvB=zR($-FHkM#O`v!!WXG?>j@ ztP{FXQW~{jHP?`Va1pV`W<`p{;)MjOHt>k2+SAVEowK$jrkYjL_%hR+0u4DUCzoED zBH`uT@{OGhucal*@vJ(IsJ;QGow<)S0*7u3n+8+xDM{^M)zxCQ0-eN}d11q}ixt_f zbEa-vH-Xq=YsopZoEa`F?(XS^_bWO?YHk-`wh=&XsaTpShSFrzYN@TfxLBm>VE0JBC$Dx?7Ss)5M=Aj7&C__~rB zo4ewF+rl5oIV?&j8h))f9KMvSqa|b^Y8mRdu@0T_u48!Q%k%Cw_-;OLW|x~B=$h$tj=)rcY+~ADH9zo=$mt%oo%oF!TQ8g zS>?x0b6ZMAx6cO z6N-T-8u4@I&H1P>nG~Quo*ns7CeG)&zI$O%4<^12n+A0;$}?&eh0wP!btauidJy9G z7>FLyqc1u-vv(y`vm&nAbXi>Ym>na)psv!MrosY_|9q756Lw(l(sQ$3JE260AR#68 z^#Xg)-iBNV(&{dT6RfamkC5|hQh=C-j?8MGu5%twiTr>X3WDNw(4W(B Date: Sat, 12 Apr 2025 21:12:16 +0700 Subject: [PATCH 2/4] add section How To Work to README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 55c7231..35d8fec 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ Provides adapters for popular AI frameworks: MCPHub simplifies the integration of Model Context Protocol (MCP) servers into AI applications through four main components: -![MCPHub Architecture](https://raw.githubusercontent.com/Cognitive-Stacks/mcphub/refs/heads/master/docs/simple_mcphub_work.png) +![MCPHub Architecture](https://raw.githubusercontent.com/Cognitive-Stacks/mcphub/refs/heads/write_docs/docs/simple_mcphub_work.png) ### Core Components From 515becd866d72e3f545fa152d26629858422de51 Mon Sep 17 00:00:00 2001 From: Hieu Tran Date: Sat, 12 Apr 2025 21:31:40 +0700 Subject: [PATCH 3/4] add guideline to readme --- README.md | 100 ++++++++++++++++++++++++++++-- src/mcphub/mcp_servers/servers.py | 13 ++++ src/mcphub/mcphub.py | 14 ++++- 3 files changed, 120 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 35d8fec..31c093c 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,46 @@ if __name__ == "__main__": ## Features +### Server Configuration + +- **JSON-based Configuration**: Simple `.mcphub.json` configuration file +- **Environment Variable Support**: Use environment variables in configuration +- **Predefined Servers**: Access to a growing list of pre-configured MCP servers +- **Custom Server Support**: Easy integration of custom MCP servers + +Configure your MCP servers in `.mcphub.json`: + +```json +{ + "mcpServers": { + // TypeScript-based MCP server using NPX + "sequential-thinking-mcp": { + "package_name": "smithery-ai/server-sequential-thinking", // NPM package name + "command": "npx", // Command to run server + "args": [ // Command arguments + "-y", + "@smithery/cli@latest", + "run", + "@smithery-ai/server-sequential-thinking" + ] + }, + // Python-based MCP server from GitHub + "azure-storage-mcp": { + "package_name": "mashriram/azure_mcp_server", // Package identifier + "repo_url": "https://github.com/mashriram/azure_mcp_server", // GitHub repository + "command": "uv", // Python package manager + "args": ["run", "mcp_server_azure_cmd"], // Run command + "setup_script": "uv pip install -e .", // Installation script + "env": { // Environment variables + "AZURE_STORAGE_CONNECTION_STRING": "${AZURE_STORAGE_CONNECTION_STRING}", + "AZURE_STORAGE_CONTAINER_NAME": "${AZURE_STORAGE_CONTAINER_NAME}", + "AZURE_STORAGE_BLOB_NAME": "${AZURE_STORAGE_BLOB_NAME}" + } + } + } +} +``` + ### MCP Server Installation and Management - **Flexible Server Setup**: Supports both TypeScript and Python-based MCP servers @@ -139,12 +179,36 @@ Provides adapters for popular AI frameworks: - LangChain - Autogen -### Server Configuration +```python +from mcphub import MCPHub -- **JSON-based Configuration**: Simple `.mcphub.json` configuration file -- **Environment Variable Support**: Use environment variables in configuration -- **Predefined Servers**: Access to a growing list of pre-configured MCP servers -- **Custom Server Support**: Easy integration of custom MCP servers +async def framework_examples(): + hub = MCPHub() + + # 1. OpenAI Agents Integration + async with hub.fetch_openai_mcp_server( + mcp_name="sequential-thinking-mcp", + cache_tools_list=True + ) as server: + # Use server with OpenAI agents + agent = Agent( + name="Assistant", + mcp_servers=[server] + ) + + # 2. LangChain Tools Integration + langchain_tools = await hub.fetch_langchain_mcp_tools( + mcp_name="sequential-thinking-mcp", + cache_tools_list=True + ) + # Use tools with LangChain + + # 3. Autogen Adapters Integration + autogen_adapters = await hub.fetch_autogen_mcp_adapters( + mcp_name="sequential-thinking-mcp" + ) + # Use adapters with Autogen +``` ### Tool Management @@ -152,11 +216,35 @@ Provides adapters for popular AI frameworks: - **Tool Caching**: Optional caching of tool lists for improved performance - **Framework-specific Adapters**: Convert MCP tools to framework-specific formats +Discover and manage MCP server tools: + +```python +from mcphub import MCPHub + +async def tool_management(): + hub = MCPHub() + + # List all tools from a specific MCP server + tools = await hub.list_tools(mcp_name="sequential-thinking-mcp") + + # Print tool information + for tool in tools: + print(f"Tool Name: {tool.name}") + print(f"Description: {tool.description}") + print(f"Parameters: {tool.parameters}") + print("---") + + # Tools can be: + # - Cached for better performance using cache_tools_list=True + # - Converted to framework-specific formats automatically + # - Used directly with AI frameworks through adapters +``` + ## MCPHub: High-Level Overview MCPHub simplifies the integration of Model Context Protocol (MCP) servers into AI applications through four main components: -![MCPHub Architecture](https://raw.githubusercontent.com/Cognitive-Stacks/mcphub/refs/heads/write_docs/docs/simple_mcphub_work.png) +![MCPHub Architecture](./docs/simple_mcphub_work.png) ### Core Components diff --git a/src/mcphub/mcp_servers/servers.py b/src/mcphub/mcp_servers/servers.py index 6f9a146..8f454cb 100644 --- a/src/mcphub/mcp_servers/servers.py +++ b/src/mcphub/mcp_servers/servers.py @@ -192,3 +192,16 @@ async def make_autogen_mcp_adapters(self, mcp_name: str) -> List[StdioMcpToolAda adapter = await StdioMcpToolAdapter.from_server_params(server_params, tool.name) adapters.append(adapter) return adapters + + async def list_tools(self, mcp_name: str) -> List[BaseTool]: + """ + List all tools from an MCP server. + + Args: + mcp_name: The name of the MCP server configuration to use + + Returns: + List[BaseTool]: List of tools provided by the MCP server + """ + async with self.make_openai_mcp_server(mcp_name, cache_tools_list=True) as server: + return await server.list_tools() diff --git a/src/mcphub/mcphub.py b/src/mcphub/mcphub.py index 0a55125..2f0c5b6 100644 --- a/src/mcphub/mcphub.py +++ b/src/mcphub/mcphub.py @@ -68,4 +68,16 @@ async def fetch_autogen_mcp_adapters(self, mcp_name: str) -> List[StdioMcpToolAd Returns: StdioMcpToolAdapter: The configured MCP adapter """ - return await self.servers.make_autogen_mcp_adapters(mcp_name) \ No newline at end of file + return await self.servers.make_autogen_mcp_adapters(mcp_name) + + async def list_tools(self, mcp_name: str) -> List[BaseTool]: + """ + List all tools from an MCP server. + + Args: + mcp_name: The name of the MCP server configuration to use + + Returns: + List[BaseTool]: List of tools provided by the MCP server + """ + return await self.servers.list_tools(mcp_name) \ No newline at end of file From a6cfb31f58f35f4f0ab4447d5cbd5b599119a21f Mon Sep 17 00:00:00 2001 From: Hieu Tran Date: Sat, 12 Apr 2025 21:32:37 +0700 Subject: [PATCH 4/4] add title of Features and Guidelines --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 31c093c..9081d59 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ if __name__ == "__main__": asyncio.run(main()) ``` -## Features +## Features and Guidelines ### Server Configuration