├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── fintual_python_server ├── .python-version ├── __pycache__ │ └── main.cpython-312.pyc ├── prompts.py ├── pyproject.toml ├── server.py ├── tools.py └── uv.lock └── fintual_typescript_server └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | *.py[cod] 3 | *$py.class 4 | .DS_Store 5 | .env 6 | .env.* 7 | venv/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "CodeGPT.apiKey": "CodeGPT Plus Beta" 3 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Daniel (San) Ávila 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fintual MCP Servers 2 | This server enables LLMs to interact with Fintual's API. 3 | 4 | # API Endpoints 5 | Swagger: https://fintual.cl/api-docs/index.html 6 | 7 | # Servers list 8 | - [Python Server](https://github.com/davila7/fintual_mcp_server/tree/main/fintual_python_server) 9 | - [Typescript Server]() (coming soon) 10 | 11 | # Python Server Setup instructions 12 | 1- Clone this repository 13 | ```bash 14 | git clone https://github.com/davila7/fintual_mcp_server.git 15 | ``` 16 | 17 | 2- Install [uv](https://github.com/astral-sh/uv) 18 | ```bash 19 | curl -LsSf https://astral.sh/uv/install.sh | sh 20 | ``` 21 | 22 | # Add the server 23 | Go to the fintual_python_server folder and run the following command: 24 | ```bash 25 | cd fintual_python_server 26 | ``` 27 | 28 | Run the following command: 29 | ```bash 30 | uv run mcp install server.py 31 | ``` 32 | 33 | or Add this to your .codegpt/mcp_config.json for CodeGPT or /path/to/Claude/claude_desktop_config.json for Claude Desktop: 34 | 35 | ```json 36 | { 37 | "mcpServers": { 38 | "Fintual MCP Server": { 39 | "command": "/path_to_your_uv/.local/bin/uv", 40 | "args": [ 41 | "run", 42 | "--with", 43 | "mcp[cli]", 44 | "mcp", 45 | "run", 46 | "/fintual_mcp_server/fintual_python_server/server.py" 47 | ] 48 | } 49 | } 50 | } 51 | ``` 52 | 53 | ## Important: 54 | - Replace `/path_to_your_uv/.local/bin/uv` with the actual path to your uv executable. 55 | - Replace `/fintual_mcp_server/fintual_python_server/server.py` with the actual path to the server.py file of the Fintual MCP server. 56 | 57 | ## Configuration File Location by Tool 58 | The common JSON configuration should be placed in the following file, depending on the tool you are using: 59 | 60 | - **Claude Desktop**: `claude_desktop_config.json` 61 | - **Cursor**: `.cursor/mcp.jso` 62 | - **CodeGPT**: `~/.codegpt/mcp_config.json` 63 | 64 | # Tool list 65 | - **asset_provider**: Get the list of asset providers. 66 | - **get_asset_provider_by_id**: Get the asset provider by id. 67 | - **get_conceptual_assets**: Get the list of conceptual assets. 68 | - **banks**: Get the list of banks. 69 | 70 | # Prompt list 71 | - **assets_provider_prompt**: Prompt to use the assets_provider tool. 72 | - **conceptual_assets_prompt**: Prompt to use the conceptual_assets tool. 73 | 74 | ## Example questions to use the tools 75 | 1. Question Example: 76 | `Zurich es una administradora de activos de Fintual ?` 77 | 78 | 2. Question Example: 79 | `Cuales son los bancos integrados en Fintual ?` 80 | 81 | 1. Question Example: 82 | `Cuales son los activos conceptuales de BANCHILE?` 83 | 84 | ## Add a Prompt to use the tools from the MCP Server 85 | In Claude Desktop, you can add an speific prompt to use the tools. 86 | 87 | - Select assets_provider_prompt 88 | 89 | Screenshot 2025-05-09 at 23 35 53 90 | 91 | - Add the assets_provider 92 | 93 | Screenshot 2025-05-09 at 23 41 10 94 | 95 | ## How it works 96 | - The model will use the tools to answer the questions, but first it will ask for confirmation to use the tools. 97 | 98 | Screenshot 2025-05-09 at 23 43 17 99 | 100 | - Then the model will read the API response and answer the question. 101 | 102 | Screenshot 2025-05-09 at 23 43 53 103 | 104 | # What's next 105 | - Add more tools to the MCP Server. 106 | - Add more prompts to use the tools. 107 | - Add typescript support to the MCP Server. 108 | -------------------------------------------------------------------------------- /fintual_python_server/.python-version: -------------------------------------------------------------------------------- 1 | 3.12 2 | -------------------------------------------------------------------------------- /fintual_python_server/__pycache__/main.cpython-312.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davila7/fintual_mcp_server/ab3e8fa431b99d61f81e97a06614272cbee2811b/fintual_python_server/__pycache__/main.cpython-312.pyc -------------------------------------------------------------------------------- /fintual_python_server/prompts.py: -------------------------------------------------------------------------------- 1 | # File: prompts.py 2 | from mcp.server.fastmcp.prompts import base 3 | from typing import List 4 | 5 | class FintualMCPPrompts: 6 | """Prompts implementation for Fintual MCP server""" 7 | 8 | @staticmethod 9 | def assets_provider_prompt(assets_provider: str) -> List[base.Message]: 10 | """Prompt to check if a provider is a Fintual asset administrator.""" 11 | return [ 12 | base.UserMessage(f"{assets_provider} es administradora de activos de Fintual?"), 13 | ] 14 | 15 | @staticmethod 16 | def conceptual_asset_prompt(provider: str) -> List[base.Message]: 17 | """Prompt to get conceptual assets of a provider.""" 18 | return [ 19 | base.UserMessage(f"Cuáles son los activos conceptuales de la administradora de activos {provider}"), 20 | ] 21 | 22 | @staticmethod 23 | def very_conservative_streep_analysis(from_date: str, to_date: str) -> List[base.Message]: 24 | """ 25 | Prompt para analizar el fondo Very Conservative Streep en un rango de fechas. 26 | 27 | Args: 28 | from_date: Fecha de inicio del análisis (formato YYYY-MM-DD) 29 | to_date: Fecha de fin del análisis (formato YYYY-MM-DD) 30 | """ 31 | return [ 32 | base.UserMessage( 33 | f"""Analiza el rendimiento del fondo Very Conservative Streep (casi pura renta fija) 34 | desde {from_date} hasta {to_date}. 35 | 36 | Genera un análisis que incluya: 37 | 1. Un gráfico de la evolución del valor cuota 38 | 2. Tendencia general durante el período 39 | 3. Volatilidad observada 40 | 4. Comparación con el comportamiento esperado para un fondo conservador 41 | 5. Recomendaciones para inversionistas basadas en este análisis 42 | 43 | Usa la herramienta get_very_conservative_streep para obtener los datos. 44 | Genera todos los graficos y datos en un Interactive Artifact. """ 45 | ), 46 | ] 47 | 48 | @staticmethod 49 | def conservative_clooney_analysis(from_date: str, to_date: str) -> List[base.Message]: 50 | """ 51 | Prompt para analizar el fondo Conservative Clooney en un rango de fechas. 52 | 53 | Args: 54 | from_date: Fecha de inicio del análisis (formato YYYY-MM-DD) 55 | to_date: Fecha de fin del análisis (formato YYYY-MM-DD) 56 | """ 57 | return [ 58 | base.UserMessage( 59 | f"""Analiza el rendimiento del fondo Conservative Clooney (principalmente renta fija) 60 | desde {from_date} hasta {to_date}. 61 | 62 | Genera un análisis que incluya: 63 | 1. Un gráfico de la evolución del valor cuota 64 | 2. Tendencia general durante el período 65 | 3. Volatilidad observada 66 | 4. Comparación con el comportamiento esperado para un fondo conservador 67 | 5. Recomendaciones para inversionistas basadas en este análisis 68 | 69 | Usa la herramienta get_conservative_clooney para obtener los datos. 70 | 71 | Genera todos los graficos y datos en un Interactive Artifact. """ 72 | ), 73 | ] 74 | 75 | @staticmethod 76 | def moderate_pit_analysis(from_date: str, to_date: str) -> List[base.Message]: 77 | """ 78 | Prompt para analizar el fondo Moderate Pit en un rango de fechas. 79 | 80 | Args: 81 | from_date: Fecha de inicio del análisis (formato YYYY-MM-DD) 82 | to_date: Fecha de fin del análisis (formato YYYY-MM-DD) 83 | """ 84 | return [ 85 | base.UserMessage( 86 | f"""Analiza el rendimiento del fondo Moderate Pit (mezcla de renta fija y ETFs accionarios) 87 | desde {from_date} hasta {to_date}. 88 | 89 | Genera un análisis que incluya: 90 | 1. Un gráfico de la evolución del valor cuota 91 | 2. Tendencia general durante el período 92 | 3. Volatilidad observada 93 | 4. Comparación con el comportamiento esperado para un fondo moderado 94 | 5. Recomendaciones para inversionistas basadas en este análisis 95 | 96 | Usa la herramienta get_moderate_pit para obtener los datos. 97 | 98 | Genera todos los graficos y datos en un Interactive Artifact. """ 99 | ), 100 | ] 101 | 102 | @staticmethod 103 | def risky_norris_analysis(from_date: str, to_date: str) -> List[base.Message]: 104 | """ 105 | Prompt para analizar el fondo Risky Norris en un rango de fechas. 106 | 107 | Args: 108 | from_date: Fecha de inicio del análisis (formato YYYY-MM-DD) 109 | to_date: Fecha de fin del análisis (formato YYYY-MM-DD) 110 | """ 111 | return [ 112 | base.UserMessage( 113 | f"""Analiza el rendimiento del fondo Risky Norris (casi solamente ETFs accionarios) 114 | desde {from_date} hasta {to_date}. 115 | 116 | Genera un análisis que incluya: 117 | 1. Un gráfico de la evolución del valor cuota 118 | 2. Tendencia general durante el período 119 | 3. Volatilidad observada 120 | 4. Comparación con el comportamiento esperado para un fondo de alto riesgo 121 | 5. Recomendaciones para inversionistas basadas en este análisis 122 | 123 | Usa la herramienta get_risky_norris para obtener los datos. 124 | 125 | Genera todos los graficos y datos en un Interactive Artifact. """ 126 | ), 127 | ] 128 | 129 | @staticmethod 130 | def compare_funds_analysis(from_date: str, to_date: str) -> List[base.Message]: 131 | """ 132 | Prompt para comparar todos los fondos de Fintual en un rango de fechas. 133 | 134 | Args: 135 | from_date: Fecha de inicio del análisis (formato YYYY-MM-DD) 136 | to_date: Fecha de fin del análisis (formato YYYY-MM-DD) 137 | """ 138 | return [ 139 | base.UserMessage( 140 | f"""Compara el rendimiento de los cuatro fondos de Fintual 141 | (Very Conservative Streep, Conservative Clooney, Moderate Pit y Risky Norris) 142 | desde {from_date} hasta {to_date}. 143 | 144 | Genera un análisis comparativo que incluya: 145 | 1. Un gráfico que muestre la evolución del valor cuota de los cuatro fondos 146 | 2. Análisis de rendimiento relativo entre los fondos 147 | 3. Análisis de volatilidad comparativa 148 | 4. Correlación entre los fondos durante el período 149 | 5. Recomendaciones para diferentes perfiles de inversionistas basadas en este análisis 150 | 151 | Usa las herramientas correspondientes para obtener los datos de cada fondo. 152 | 153 | Genera todos los graficos y datos en un Interactive Artifact. """ 154 | ), 155 | ] -------------------------------------------------------------------------------- /fintual_python_server/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "fintual-python-server" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.12" 7 | dependencies = [ 8 | "mcp[cli]>=1.8.0", 9 | ] 10 | -------------------------------------------------------------------------------- /fintual_python_server/server.py: -------------------------------------------------------------------------------- 1 | # File: server.py 2 | from mcp.server.fastmcp import FastMCP 3 | import tools 4 | import prompts 5 | 6 | class FintualMCPServer: 7 | """ Main class for the Fintual MCP Server. """ 8 | def __init__(self, name: str = "Fintual Python Server"): 9 | self.name = name 10 | self.mcp = FastMCP(name) 11 | self.tools = tools.FintualMCPTools() 12 | self.prompts = prompts.FintualMCPPrompts() 13 | self._register_tools() 14 | self._register_prompts() 15 | 16 | def _register_tools(self) -> None: 17 | """ Register all tools with the MCP server. """ 18 | # Tools generales 19 | self.mcp.tool()(self.tools.login) 20 | self.mcp.tool()(self.tools.asset_providers) 21 | self.mcp.tool()(self.tools.get_asset_provider_by_id) 22 | self.mcp.tool()(self.tools.get_conceptual_asset_by_asset_provider_id) 23 | self.mcp.tool()(self.tools.banks) 24 | 25 | # Tools por fondos 26 | # Registrar las nuevas herramientas para los fondos 27 | self.mcp.tool()(self.tools.get_fund_data) 28 | self.mcp.tool()(self.tools.get_very_conservative_streep) 29 | self.mcp.tool()(self.tools.get_conservative_clooney) 30 | self.mcp.tool()(self.tools.get_moderate_pit) 31 | self.mcp.tool()(self.tools.get_risky_norris) 32 | 33 | def _register_prompts(self) -> None: 34 | """ Register all prompts with the MCP server. """ 35 | self.mcp.prompt()(self.prompts.assets_provider_prompt) 36 | self.mcp.prompt()(self.prompts.conceptual_asset_prompt) 37 | 38 | # Prompt por fondos 39 | self.mcp.prompt()(self.prompts.very_conservative_streep_analysis) 40 | self.mcp.prompt()(self.prompts.conservative_clooney_analysis) 41 | self.mcp.prompt()(self.prompts.moderate_pit_analysis) 42 | self.mcp.prompt()(self.prompts.risky_norris_analysis) 43 | self.mcp.prompt()(self.prompts.compare_funds_analysis) 44 | 45 | def run(self, transport: str = "stdio") -> None: 46 | """Runs the MCP server with the specified transport""" 47 | self.mcp.run(transport=transport) 48 | 49 | # Create a server instance at the module level 50 | server = FintualMCPServer().mcp 51 | 52 | # Main entry point 53 | if __name__ == "__main__": 54 | server.run() -------------------------------------------------------------------------------- /fintual_python_server/tools.py: -------------------------------------------------------------------------------- 1 | # File: tools.py 2 | import json 3 | from typing import Dict, Any, List 4 | from mcp.types import TextContent 5 | import urllib.request 6 | 7 | class FintualMCPTools: 8 | """A class containing tools for the Fintual agent.""" 9 | 10 | def __init__(self): 11 | self._base_url = "https://fintual.cl/api/" 12 | # Fintual funds 13 | self._fund_ids = { 14 | "very_conservative_streep": 15077, 15 | "conservative_clooney": 188, 16 | "moderate_pit": 187, 17 | "risky_norris": 186 18 | } 19 | 20 | def _fetch_fintual_data(self, endpoint: str) -> Dict[str, Any]: 21 | """Helper function to fetch data from a given Fintual API endpoint.""" 22 | response_text = "" 23 | url = f"{self._base_url}/{endpoint}" 24 | headers = { 25 | "User-Agent": "Mozilla/5.0 (compatible; FintualPythonServer/1.0)" 26 | } 27 | request = urllib.request.Request(url, headers=headers) 28 | try: 29 | response = urllib.request.urlopen(request) 30 | if response.getcode() == 200: 31 | # Leer la respuesta como texto y deserializarla 32 | response_text = response.read().decode('utf-8') 33 | response_json = json.loads(response_text) 34 | return { 35 | "content": [{ 36 | "type": "text", 37 | "text": response_json 38 | }] 39 | } 40 | else: 41 | response_text = f"Error: Unable to fetch data, HTTP Code: {response.getcode()}" 42 | except urllib.error.HTTPError as e: 43 | response_text = f"Error: {e}" 44 | except Exception as e: 45 | response_text = f"An unexpected error occurred: {e}" 46 | 47 | return { 48 | "content": [{ 49 | "type": "text", 50 | "text": response_text 51 | }] 52 | } 53 | 54 | def _post_api_data(self, endpoint: str, data: Dict[str, Any]) -> Dict[str, Any]: 55 | """Helper method to post data to the API (POST requests)""" 56 | try: 57 | data_encoded = json.dumps(data).encode('utf-8') 58 | req = urllib.request.Request( 59 | f"{self._base_url}/{endpoint}", 60 | data=data_encoded, 61 | headers = { 62 | "User-Agent": "Mozilla/5.0 (compatible; FintualPythonServer/1.0)" 63 | }, 64 | method='POST' 65 | ) 66 | with urllib.request.urlopen(req) as response: 67 | if response.getcode() == 200: 68 | return json.loads(response.read()) 69 | else: 70 | raise Exception(f"Error: Response code {response.getcode()}") 71 | except Exception as e: 72 | raise Exception(f"Error posting data to API: {str(e)}") 73 | 74 | def _format_response(self, data: Dict[str, Any]) -> Dict[str, List[TextContent]]: 75 | """Formats data for MCP response""" 76 | return { 77 | "content": [ 78 | TextContent( 79 | type="text", 80 | text=json.dumps(data, indent=4) 81 | ) 82 | ] 83 | } 84 | 85 | def login(self, email: str, password: str) -> Dict[str, List[TextContent]]: 86 | """ 87 | Authenticates a user with Fintual API and returns an access token 88 | 89 | Args: 90 | email: User's email address 91 | password: User's password 92 | 93 | Returns: 94 | Response containing the access token if successful 95 | """ 96 | data = { 97 | "user": { 98 | "email": email, 99 | "password": password 100 | } 101 | } 102 | 103 | try: 104 | response = self._post_api_data("access_tokens", data) 105 | return self._format_response(response) 106 | except Exception as e: 107 | return { 108 | "content": [ 109 | { 110 | "type": "text", 111 | "text": f"Authentication failed: {str(e)}" 112 | } 113 | ] 114 | } 115 | 116 | 117 | def asset_providers(self) -> Dict[str, List[TextContent]]: 118 | """Gets the list of asset providers from the API""" 119 | data = self._fetch_fintual_data("asset_providers") 120 | return self._format_response(data) 121 | 122 | def get_asset_provider_by_id(self, asset_provider_id: int) -> Dict[str, List[TextContent]]: 123 | """Gets the asset provider by ID from the API""" 124 | data = self._fetch_fintual_data(f"asset_providers/{asset_provider_id}") 125 | return self._format_response(data) 126 | 127 | def get_conceptual_asset_by_asset_provider_id(self, asset_provider_id: int) -> Dict[str, List[TextContent]]: 128 | """Gets the conceptual asset by asset provider ID from the API""" 129 | data = self._fetch_fintual_data(f"asset_providers/{asset_provider_id}/conceptual_assets") 130 | return self._format_response(data) 131 | 132 | def banks(self) -> Dict[str, List[TextContent]]: 133 | """Gets the list of banks from the API""" 134 | data = self._fetch_fintual_data("banks") 135 | return self._format_response(data) 136 | 137 | def get_very_conservative_streep(self, to_date: str = None, from_date: str = None) -> Dict[str, List[TextContent]]: 138 | """ 139 | Obtiene el valor cuota del fondo Very Conservative Streep (ID: 15077) 140 | 141 | Args: 142 | to_date: Fecha hasta la cual obtener datos (formato YYYY-MM-DD) 143 | from_date: Fecha desde la cual obtener datos (formato YYYY-MM-DD) 144 | """ 145 | params = [] 146 | if to_date: 147 | params.append(f"to_date={to_date}") 148 | if from_date: 149 | params.append(f"from_date={from_date}") 150 | 151 | endpoint = f"real_assets/15077/days" 152 | if params: 153 | endpoint += f"?{'&'.join(params)}" 154 | 155 | data = self._fetch_fintual_data(endpoint) 156 | return self._format_response(data) 157 | 158 | def get_conservative_clooney(self, to_date: str = None, from_date: str = None) -> Dict[str, List[TextContent]]: 159 | """ 160 | Obtiene el valor cuota del fondo Conservative Clooney (ID: 188) 161 | 162 | Args: 163 | to_date: Fecha hasta la cual obtener datos (formato YYYY-MM-DD) 164 | from_date: Fecha desde la cual obtener datos (formato YYYY-MM-DD) 165 | """ 166 | params = [] 167 | if to_date: 168 | params.append(f"to_date={to_date}") 169 | if from_date: 170 | params.append(f"from_date={from_date}") 171 | 172 | endpoint = f"real_assets/188/days" 173 | if params: 174 | endpoint += f"?{'&'.join(params)}" 175 | 176 | data = self._fetch_fintual_data(endpoint) 177 | return self._format_response(data) 178 | 179 | def get_moderate_pit(self, to_date: str = None, from_date: str = None) -> Dict[str, List[TextContent]]: 180 | """ 181 | Obtiene el valor cuota del fondo Moderate Pit (ID: 187) 182 | 183 | Args: 184 | to_date: Fecha hasta la cual obtener datos (formato YYYY-MM-DD) 185 | from_date: Fecha desde la cual obtener datos (formato YYYY-MM-DD) 186 | """ 187 | params = [] 188 | if to_date: 189 | params.append(f"to_date={to_date}") 190 | if from_date: 191 | params.append(f"from_date={from_date}") 192 | 193 | endpoint = f"real_assets/187/days" 194 | if params: 195 | endpoint += f"?{'&'.join(params)}" 196 | 197 | data = self._fetch_fintual_data(endpoint) 198 | return self._format_response(data) 199 | 200 | def get_risky_norris(self, to_date: str = None, from_date: str = None) -> Dict[str, List[TextContent]]: 201 | """ 202 | Obtiene el valor cuota del fondo Risky Norris (ID: 186) 203 | 204 | Args: 205 | to_date: Fecha hasta la cual obtener datos (formato YYYY-MM-DD) 206 | from_date: Fecha desde la cual obtener datos (formato YYYY-MM-DD) 207 | """ 208 | params = [] 209 | if to_date: 210 | params.append(f"to_date={to_date}") 211 | if from_date: 212 | params.append(f"from_date={from_date}") 213 | 214 | endpoint = f"real_assets/186/days" 215 | if params: 216 | endpoint += f"?{'&'.join(params)}" 217 | 218 | data = self._fetch_fintual_data(endpoint) 219 | return self._format_response(data) 220 | 221 | def get_fund_data(self, fund_id: int, to_date: str = None, from_date: str = None) -> Dict[str, List[TextContent]]: 222 | """ 223 | Obtiene el valor cuota de cualquier fondo por su ID 224 | 225 | Args: 226 | fund_id: ID del fondo 227 | to_date: Fecha hasta la cual obtener datos (formato YYYY-MM-DD) 228 | from_date: Fecha desde la cual obtener datos (formato YYYY-MM-DD) 229 | """ 230 | params = [] 231 | if to_date: 232 | params.append(f"to_date={to_date}") 233 | if from_date: 234 | params.append(f"from_date={from_date}") 235 | 236 | endpoint = f"real_assets/{fund_id}/days" 237 | if params: 238 | endpoint += f"?{'&'.join(params)}" 239 | 240 | raw_data = self._fetch_fintual_data(endpoint) 241 | # The data is already parsed into a dictionary by _fetch_fintual_data 242 | # Access the dictionary directly from the 'text' field 243 | try: 244 | data_json = raw_data["content"][0]["text"] 245 | # Extract only the date and price 246 | days = [ 247 | { 248 | "date": d["attributes"]["date"], 249 | "price": d["attributes"]["price"] 250 | } 251 | for d in data_json.get("data", []) 252 | ] 253 | return { 254 | "content": [ 255 | TextContent( 256 | type="text", 257 | text=json.dumps(days, indent=4) 258 | ) 259 | ] 260 | } 261 | except Exception as e: 262 | return { 263 | "content": [ 264 | TextContent( 265 | type="text", 266 | text=f"Error al procesar los datos: {str(e)}" 267 | ) 268 | ] 269 | } 270 | 271 | def get_very_conservative_streep(self, to_date: str = None, from_date: str = None) -> Dict[str, List[TextContent]]: 272 | """ 273 | Obtiene el valor cuota del fondo Very Conservative Streep 274 | 275 | Args: 276 | to_date: Fecha hasta la cual obtener datos (formato YYYY-MM-DD) 277 | from_date: Fecha desde la cual obtener datos (formato YYYY-MM-DD) 278 | """ 279 | return self.get_fund_data(self._fund_ids["very_conservative_streep"], to_date, from_date) 280 | 281 | def get_conservative_clooney(self, to_date: str = None, from_date: str = None) -> Dict[str, List[TextContent]]: 282 | """ 283 | Obtiene el valor cuota del fondo Conservative Clooney 284 | 285 | Args: 286 | to_date: Fecha hasta la cual obtener datos (formato YYYY-MM-DD) 287 | from_date: Fecha desde la cual obtener datos (formato YYYY-MM-DD) 288 | """ 289 | return self.get_fund_data(self._fund_ids["conservative_clooney"], to_date, from_date) 290 | 291 | def get_moderate_pit(self, to_date: str = None, from_date: str = None) -> Dict[str, List[TextContent]]: 292 | """ 293 | Obtiene el valor cuota del fondo Moderate Pit 294 | 295 | Args: 296 | to_date: Fecha hasta la cual obtener datos (formato YYYY-MM-DD) 297 | from_date: Fecha desde la cual obtener datos (formato YYYY-MM-DD) 298 | """ 299 | return self.get_fund_data(self._fund_ids["moderate_pit"], to_date, from_date) 300 | 301 | def get_risky_norris(self, to_date: str = None, from_date: str = None) -> Dict[str, List[TextContent]]: 302 | """ 303 | Obtiene el valor cuota del fondo Risky Norris 304 | 305 | Args: 306 | to_date: Fecha hasta la cual obtener datos (formato YYYY-MM-DD) 307 | from_date: Fecha desde la cual obtener datos (formato YYYY-MM-DD) 308 | """ 309 | return self.get_fund_data(self._fund_ids["risky_norris"], to_date, from_date) -------------------------------------------------------------------------------- /fintual_python_server/uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 2 3 | requires-python = ">=3.12" 4 | 5 | [[package]] 6 | name = "annotated-types" 7 | version = "0.7.0" 8 | source = { registry = "https://pypi.org/simple" } 9 | sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } 10 | wheels = [ 11 | { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, 12 | ] 13 | 14 | [[package]] 15 | name = "anyio" 16 | version = "4.9.0" 17 | source = { registry = "https://pypi.org/simple" } 18 | dependencies = [ 19 | { name = "idna" }, 20 | { name = "sniffio" }, 21 | { name = "typing-extensions", marker = "python_full_version < '3.13'" }, 22 | ] 23 | sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949, upload-time = "2025-03-17T00:02:54.77Z" } 24 | wheels = [ 25 | { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" }, 26 | ] 27 | 28 | [[package]] 29 | name = "certifi" 30 | version = "2025.4.26" 31 | source = { registry = "https://pypi.org/simple" } 32 | sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } 33 | wheels = [ 34 | { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, 35 | ] 36 | 37 | [[package]] 38 | name = "click" 39 | version = "8.1.8" 40 | source = { registry = "https://pypi.org/simple" } 41 | dependencies = [ 42 | { name = "colorama", marker = "sys_platform == 'win32'" }, 43 | ] 44 | sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } 45 | wheels = [ 46 | { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, 47 | ] 48 | 49 | [[package]] 50 | name = "colorama" 51 | version = "0.4.6" 52 | source = { registry = "https://pypi.org/simple" } 53 | sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } 54 | wheels = [ 55 | { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, 56 | ] 57 | 58 | [[package]] 59 | name = "fintual-python-server" 60 | version = "0.1.0" 61 | source = { virtual = "." } 62 | dependencies = [ 63 | { name = "mcp", extra = ["cli"] }, 64 | ] 65 | 66 | [package.metadata] 67 | requires-dist = [{ name = "mcp", extras = ["cli"], specifier = ">=1.8.0" }] 68 | 69 | [[package]] 70 | name = "h11" 71 | version = "0.16.0" 72 | source = { registry = "https://pypi.org/simple" } 73 | sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } 74 | wheels = [ 75 | { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, 76 | ] 77 | 78 | [[package]] 79 | name = "httpcore" 80 | version = "1.0.9" 81 | source = { registry = "https://pypi.org/simple" } 82 | dependencies = [ 83 | { name = "certifi" }, 84 | { name = "h11" }, 85 | ] 86 | sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } 87 | wheels = [ 88 | { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, 89 | ] 90 | 91 | [[package]] 92 | name = "httpx" 93 | version = "0.28.1" 94 | source = { registry = "https://pypi.org/simple" } 95 | dependencies = [ 96 | { name = "anyio" }, 97 | { name = "certifi" }, 98 | { name = "httpcore" }, 99 | { name = "idna" }, 100 | ] 101 | sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } 102 | wheels = [ 103 | { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, 104 | ] 105 | 106 | [[package]] 107 | name = "httpx-sse" 108 | version = "0.4.0" 109 | source = { registry = "https://pypi.org/simple" } 110 | sdist = { url = "https://files.pythonhosted.org/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", size = 12624, upload-time = "2023-12-22T08:01:21.083Z" } 111 | wheels = [ 112 | { url = "https://files.pythonhosted.org/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f", size = 7819, upload-time = "2023-12-22T08:01:19.89Z" }, 113 | ] 114 | 115 | [[package]] 116 | name = "idna" 117 | version = "3.10" 118 | source = { registry = "https://pypi.org/simple" } 119 | sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } 120 | wheels = [ 121 | { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, 122 | ] 123 | 124 | [[package]] 125 | name = "markdown-it-py" 126 | version = "3.0.0" 127 | source = { registry = "https://pypi.org/simple" } 128 | dependencies = [ 129 | { name = "mdurl" }, 130 | ] 131 | sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } 132 | wheels = [ 133 | { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, 134 | ] 135 | 136 | [[package]] 137 | name = "mcp" 138 | version = "1.8.0" 139 | source = { registry = "https://pypi.org/simple" } 140 | dependencies = [ 141 | { name = "anyio" }, 142 | { name = "httpx" }, 143 | { name = "httpx-sse" }, 144 | { name = "pydantic" }, 145 | { name = "pydantic-settings" }, 146 | { name = "python-multipart" }, 147 | { name = "sse-starlette" }, 148 | { name = "starlette" }, 149 | { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, 150 | ] 151 | sdist = { url = "https://files.pythonhosted.org/packages/ff/97/0a3e08559557b0ac5799f9fb535fbe5a4e4dcdd66ce9d32e7a74b4d0534d/mcp-1.8.0.tar.gz", hash = "sha256:263dfb700540b726c093f0c3e043f66aded0730d0b51f04eb0a3eb90055fe49b", size = 264641, upload-time = "2025-05-08T20:09:06.255Z" } 152 | wheels = [ 153 | { url = "https://files.pythonhosted.org/packages/b2/b2/4ac3bd17b1fdd65658f18de4eb0c703517ee0b483dc5f56467802a9197e0/mcp-1.8.0-py3-none-any.whl", hash = "sha256:889d9d3b4f12b7da59e7a3933a0acadae1fce498bfcd220defb590aa291a1334", size = 119544, upload-time = "2025-05-08T20:09:04.458Z" }, 154 | ] 155 | 156 | [package.optional-dependencies] 157 | cli = [ 158 | { name = "python-dotenv" }, 159 | { name = "typer" }, 160 | ] 161 | 162 | [[package]] 163 | name = "mdurl" 164 | version = "0.1.2" 165 | source = { registry = "https://pypi.org/simple" } 166 | sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } 167 | wheels = [ 168 | { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, 169 | ] 170 | 171 | [[package]] 172 | name = "pydantic" 173 | version = "2.11.4" 174 | source = { registry = "https://pypi.org/simple" } 175 | dependencies = [ 176 | { name = "annotated-types" }, 177 | { name = "pydantic-core" }, 178 | { name = "typing-extensions" }, 179 | { name = "typing-inspection" }, 180 | ] 181 | sdist = { url = "https://files.pythonhosted.org/packages/77/ab/5250d56ad03884ab5efd07f734203943c8a8ab40d551e208af81d0257bf2/pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d", size = 786540, upload-time = "2025-04-29T20:38:55.02Z" } 182 | wheels = [ 183 | { url = "https://files.pythonhosted.org/packages/e7/12/46b65f3534d099349e38ef6ec98b1a5a81f42536d17e0ba382c28c67ba67/pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb", size = 443900, upload-time = "2025-04-29T20:38:52.724Z" }, 184 | ] 185 | 186 | [[package]] 187 | name = "pydantic-core" 188 | version = "2.33.2" 189 | source = { registry = "https://pypi.org/simple" } 190 | dependencies = [ 191 | { name = "typing-extensions" }, 192 | ] 193 | sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } 194 | wheels = [ 195 | { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, 196 | { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, 197 | { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, 198 | { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, 199 | { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, 200 | { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, 201 | { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, 202 | { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, 203 | { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, 204 | { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, 205 | { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, 206 | { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, 207 | { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, 208 | { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, 209 | { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, 210 | { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, 211 | { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, 212 | { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, 213 | { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, 214 | { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, 215 | { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, 216 | { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, 217 | { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, 218 | { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, 219 | { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, 220 | { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, 221 | { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, 222 | { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, 223 | { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, 224 | { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, 225 | { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, 226 | ] 227 | 228 | [[package]] 229 | name = "pydantic-settings" 230 | version = "2.9.1" 231 | source = { registry = "https://pypi.org/simple" } 232 | dependencies = [ 233 | { name = "pydantic" }, 234 | { name = "python-dotenv" }, 235 | { name = "typing-inspection" }, 236 | ] 237 | sdist = { url = "https://files.pythonhosted.org/packages/67/1d/42628a2c33e93f8e9acbde0d5d735fa0850f3e6a2f8cb1eb6c40b9a732ac/pydantic_settings-2.9.1.tar.gz", hash = "sha256:c509bf79d27563add44e8446233359004ed85066cd096d8b510f715e6ef5d268", size = 163234, upload-time = "2025-04-18T16:44:48.265Z" } 238 | wheels = [ 239 | { url = "https://files.pythonhosted.org/packages/b6/5f/d6d641b490fd3ec2c4c13b4244d68deea3a1b970a97be64f34fb5504ff72/pydantic_settings-2.9.1-py3-none-any.whl", hash = "sha256:59b4f431b1defb26fe620c71a7d3968a710d719f5f4cdbbdb7926edeb770f6ef", size = 44356, upload-time = "2025-04-18T16:44:46.617Z" }, 240 | ] 241 | 242 | [[package]] 243 | name = "pygments" 244 | version = "2.19.1" 245 | source = { registry = "https://pypi.org/simple" } 246 | sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" } 247 | wheels = [ 248 | { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" }, 249 | ] 250 | 251 | [[package]] 252 | name = "python-dotenv" 253 | version = "1.1.0" 254 | source = { registry = "https://pypi.org/simple" } 255 | sdist = { url = "https://files.pythonhosted.org/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920, upload-time = "2025-03-25T10:14:56.835Z" } 256 | wheels = [ 257 | { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256, upload-time = "2025-03-25T10:14:55.034Z" }, 258 | ] 259 | 260 | [[package]] 261 | name = "python-multipart" 262 | version = "0.0.20" 263 | source = { registry = "https://pypi.org/simple" } 264 | sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158, upload-time = "2024-12-16T19:45:46.972Z" } 265 | wheels = [ 266 | { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload-time = "2024-12-16T19:45:44.423Z" }, 267 | ] 268 | 269 | [[package]] 270 | name = "rich" 271 | version = "14.0.0" 272 | source = { registry = "https://pypi.org/simple" } 273 | dependencies = [ 274 | { name = "markdown-it-py" }, 275 | { name = "pygments" }, 276 | ] 277 | sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078, upload-time = "2025-03-30T14:15:14.23Z" } 278 | wheels = [ 279 | { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" }, 280 | ] 281 | 282 | [[package]] 283 | name = "shellingham" 284 | version = "1.5.4" 285 | source = { registry = "https://pypi.org/simple" } 286 | sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } 287 | wheels = [ 288 | { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, 289 | ] 290 | 291 | [[package]] 292 | name = "sniffio" 293 | version = "1.3.1" 294 | source = { registry = "https://pypi.org/simple" } 295 | sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } 296 | wheels = [ 297 | { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, 298 | ] 299 | 300 | [[package]] 301 | name = "sse-starlette" 302 | version = "2.3.4" 303 | source = { registry = "https://pypi.org/simple" } 304 | dependencies = [ 305 | { name = "anyio" }, 306 | { name = "starlette" }, 307 | ] 308 | sdist = { url = "https://files.pythonhosted.org/packages/43/be/7e776a29b5f712b5bd13c571256a2470fcf345c562c7b2359f2ee15d9355/sse_starlette-2.3.4.tar.gz", hash = "sha256:0ffd6bed217cdbb74a84816437c609278003998b4991cd2e6872d0b35130e4d5", size = 17522, upload-time = "2025-05-04T19:28:51.44Z" } 309 | wheels = [ 310 | { url = "https://files.pythonhosted.org/packages/43/a4/ee4a20f0b5ff34c391f3685eff7cdba1178a487766e31b04efb51bbddd87/sse_starlette-2.3.4-py3-none-any.whl", hash = "sha256:b8100694f3f892b133d0f7483acb7aacfcf6ed60f863b31947664b6dc74e529f", size = 10232, upload-time = "2025-05-04T19:28:50.199Z" }, 311 | ] 312 | 313 | [[package]] 314 | name = "starlette" 315 | version = "0.46.2" 316 | source = { registry = "https://pypi.org/simple" } 317 | dependencies = [ 318 | { name = "anyio" }, 319 | ] 320 | sdist = { url = "https://files.pythonhosted.org/packages/ce/20/08dfcd9c983f6a6f4a1000d934b9e6d626cff8d2eeb77a89a68eef20a2b7/starlette-0.46.2.tar.gz", hash = "sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5", size = 2580846, upload-time = "2025-04-13T13:56:17.942Z" } 321 | wheels = [ 322 | { url = "https://files.pythonhosted.org/packages/8b/0c/9d30a4ebeb6db2b25a841afbb80f6ef9a854fc3b41be131d249a977b4959/starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35", size = 72037, upload-time = "2025-04-13T13:56:16.21Z" }, 323 | ] 324 | 325 | [[package]] 326 | name = "typer" 327 | version = "0.15.3" 328 | source = { registry = "https://pypi.org/simple" } 329 | dependencies = [ 330 | { name = "click" }, 331 | { name = "rich" }, 332 | { name = "shellingham" }, 333 | { name = "typing-extensions" }, 334 | ] 335 | sdist = { url = "https://files.pythonhosted.org/packages/98/1a/5f36851f439884bcfe8539f6a20ff7516e7b60f319bbaf69a90dc35cc2eb/typer-0.15.3.tar.gz", hash = "sha256:818873625d0569653438316567861899f7e9972f2e6e0c16dab608345ced713c", size = 101641, upload-time = "2025-04-28T21:40:59.204Z" } 336 | wheels = [ 337 | { url = "https://files.pythonhosted.org/packages/48/20/9d953de6f4367163d23ec823200eb3ecb0050a2609691e512c8b95827a9b/typer-0.15.3-py3-none-any.whl", hash = "sha256:c86a65ad77ca531f03de08d1b9cb67cd09ad02ddddf4b34745b5008f43b239bd", size = 45253, upload-time = "2025-04-28T21:40:56.269Z" }, 338 | ] 339 | 340 | [[package]] 341 | name = "typing-extensions" 342 | version = "4.13.2" 343 | source = { registry = "https://pypi.org/simple" } 344 | sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } 345 | wheels = [ 346 | { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, 347 | ] 348 | 349 | [[package]] 350 | name = "typing-inspection" 351 | version = "0.4.0" 352 | source = { registry = "https://pypi.org/simple" } 353 | dependencies = [ 354 | { name = "typing-extensions" }, 355 | ] 356 | sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222, upload-time = "2025-02-25T17:27:59.638Z" } 357 | wheels = [ 358 | { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125, upload-time = "2025-02-25T17:27:57.754Z" }, 359 | ] 360 | 361 | [[package]] 362 | name = "uvicorn" 363 | version = "0.34.2" 364 | source = { registry = "https://pypi.org/simple" } 365 | dependencies = [ 366 | { name = "click" }, 367 | { name = "h11" }, 368 | ] 369 | sdist = { url = "https://files.pythonhosted.org/packages/a6/ae/9bbb19b9e1c450cf9ecaef06463e40234d98d95bf572fab11b4f19ae5ded/uvicorn-0.34.2.tar.gz", hash = "sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328", size = 76815, upload-time = "2025-04-19T06:02:50.101Z" } 370 | wheels = [ 371 | { url = "https://files.pythonhosted.org/packages/b1/4b/4cef6ce21a2aaca9d852a6e84ef4f135d99fcd74fa75105e2fc0c8308acd/uvicorn-0.34.2-py3-none-any.whl", hash = "sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403", size = 62483, upload-time = "2025-04-19T06:02:48.42Z" }, 372 | ] 373 | -------------------------------------------------------------------------------- /fintual_typescript_server/README.md: -------------------------------------------------------------------------------- 1 | # Comming Soon --------------------------------------------------------------------------------