#
tokens: 24530/50000 1/35 files (page 3/4)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 3 of 4. Use http://codebase.md/calvernaz/alphavantage?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .bumpversion.cfg
├── .github
│   ├── FUNDING.yml
│   └── workflows
│       └── publish.yml
├── .gitignore
├── .python-version
├── CONTRIBUTING.md
├── deploy
│   └── aws-stateless-mcp-lambda
│       ├── .aws-sam
│       │   └── build.toml
│       ├── deploy.sh
│       ├── lambda_function.py
│       ├── README.md
│       ├── requirements.txt
│       └── template.yaml
├── DEVELOPMENT.md
├── Dockerfile
├── LICENSE
├── pyproject.toml
├── pytest.ini
├── README.md
├── scripts
│   └── publish.py
├── smithery.yaml
├── src
│   ├── alphavantage_mcp_client
│   │   └── client.py
│   └── alphavantage_mcp_server
│       ├── __init__.py
│       ├── api.py
│       ├── oauth.py
│       ├── prompts.py
│       ├── response_utils.py
│       ├── server.py
│       ├── telemetry_bootstrap.py
│       ├── telemetry_instrument.py
│       └── tools.py
├── tests
│   ├── test_api.py
│   ├── test_http_mcp_client.py
│   ├── test_http_transport.py
│   ├── test_integration.py
│   ├── test_stdio_transport.py
│   └── test_telemetry.py
└── uv.lock
```

# Files

--------------------------------------------------------------------------------
/src/alphavantage_mcp_server/server.py:
--------------------------------------------------------------------------------

```python
   1 | import asyncio
   2 | import json
   3 | import logging
   4 | 
   5 | import mcp.server.stdio
   6 | import mcp.types as types
   7 | import toml
   8 | import uvicorn
   9 | from mcp.server import NotificationOptions, Server
  10 | from mcp.server.models import InitializationOptions
  11 | from mcp.server.streamable_http import StreamableHTTPServerTransport
  12 | from starlette.requests import Request
  13 | from starlette.responses import Response
  14 | 
  15 | from .oauth import OAuthResourceServer, create_oauth_config_from_env
  16 | from .prompts import prompts_definitions
  17 | from .tools import AlphavantageTools, tools_definitions
  18 | from .telemetry_bootstrap import init_telemetry
  19 | from .api import (
  20 |     fetch_quote,
  21 |     fetch_intraday,
  22 |     fetch_time_series_daily,
  23 |     fetch_time_series_daily_adjusted,
  24 |     fetch_time_series_weekly,
  25 |     fetch_time_series_weekly_adjusted,
  26 |     fetch_time_series_monthly,
  27 |     fetch_time_series_monthly_adjusted,
  28 |     fetch_realtime_bulk_quotes,
  29 |     search_endpoint,
  30 |     fetch_market_status,
  31 |     fetch_realtime_options,
  32 |     fetch_historical_options,
  33 |     fetch_news_sentiment,
  34 |     fetch_top_gainer_losers,
  35 |     fetch_insider_transactions,
  36 |     fetch_analytics_fixed_window,
  37 |     fetch_analytics_sliding_window,
  38 |     fetch_company_overview,
  39 |     company_dividends,
  40 |     fetch_etf_profile,
  41 |     fetch_company_splits,
  42 |     fetch_income_statement,
  43 |     fetch_balance_sheet,
  44 |     fetch_cash_flow,
  45 |     fetch_listing_status,
  46 |     fetch_earnings_calendar,
  47 |     fetch_ipo_calendar,
  48 |     fetch_exchange_rate,
  49 |     fetch_fx_intraday,
  50 |     fetch_fx_daily,
  51 |     fetch_fx_weekly,
  52 |     fetch_fx_monthly,
  53 |     fetch_digital_currency_intraday,
  54 |     fetch_digital_currency_daily,
  55 |     fetch_digital_currency_monthly,
  56 |     fetch_wti_crude,
  57 |     fetch_brent_crude,
  58 |     fetch_natural_gas,
  59 |     fetch_copper,
  60 |     fetch_aluminum,
  61 |     fetch_wheat,
  62 |     fetch_corn,
  63 |     fetch_cotton,
  64 |     fetch_sugar,
  65 |     fetch_coffee,
  66 |     fetch_all_commodities,
  67 |     fetch_real_gdp,
  68 |     fetch_real_gdp_per_capita,
  69 |     fetch_treasury_yield,
  70 |     fetch_federal_funds_rate,
  71 |     fetch_cpi,
  72 |     fetch_inflation,
  73 |     fetch_retail_sales,
  74 |     fetch_durables,
  75 |     fetch_unemployment,
  76 |     fetch_nonfarm_payrolls,
  77 |     fetch_sma,
  78 |     fetch_ema,
  79 |     fetch_wma,
  80 |     fetch_dema,
  81 |     fetch_tema,
  82 |     fetch_trima,
  83 |     fetch_kama,
  84 |     fetch_mama,
  85 |     fetch_t3,
  86 |     fetch_macd,
  87 |     fetch_macdext,
  88 |     fetch_stoch,
  89 |     fetch_stochf,
  90 |     fetch_rsi,
  91 |     fetch_stochrsi,
  92 |     fetch_willr,
  93 |     fetch_adx,
  94 |     fetch_adxr,
  95 |     fetch_apo,
  96 |     fetch_ppo,
  97 |     fetch_mom,
  98 |     fetch_bop,
  99 |     fetch_cci,
 100 |     fetch_cmo,
 101 |     fetch_roc,
 102 |     fetch_rocr,
 103 |     fetch_aroon,
 104 |     fetch_aroonosc,
 105 |     fetch_mfi,
 106 |     fetch_trix,
 107 |     fetch_ultosc,
 108 |     fetch_dx,
 109 |     fetch_minus_di,
 110 |     fetch_plus_di,
 111 |     fetch_minus_dm,
 112 |     fetch_plus_dm,
 113 |     fetch_bbands,
 114 |     fetch_midpoint,
 115 |     fetch_midprice,
 116 |     fetch_sar,
 117 |     fetch_trange,
 118 |     fetch_atr,
 119 |     fetch_natr,
 120 |     fetch_ad,
 121 |     fetch_adosc,
 122 |     fetch_obv,
 123 |     fetch_ht_trendline,
 124 |     fetch_ht_sine,
 125 |     fetch_ht_trendmode,
 126 |     fetch_ht_dcperiod,
 127 |     fetch_ht_dcphase,
 128 |     fetch_ht_phasor,
 129 |     fetch_vwap,
 130 |     fetch_earnings,
 131 |     fetch_earnings_call_transcript,
 132 | )
 133 | 
 134 | logger = logging.getLogger(__name__)
 135 | 
 136 | 
 137 | server = Server("alphavantage")
 138 | 
 139 | 
 140 | @server.list_prompts()
 141 | async def list_prompts() -> list[types.Prompt]:
 142 |     return prompts_definitions()
 143 | 
 144 | 
 145 | @server.get_prompt()
 146 | async def get_prompt(
 147 |     name: str, arguments: dict[str, str] | None = None
 148 | ) -> types.GetPromptResult:
 149 |     if name == AlphavantageTools.STOCK_QUOTE.value:
 150 |         symbol = arguments.get("symbol") if arguments else ""
 151 |         return types.GetPromptResult(
 152 |             messages=[
 153 |                 types.PromptMessage(
 154 |                     role="user",
 155 |                     content=types.TextContent(
 156 |                         type="text",
 157 |                         text=f"Fetch the stock quote for the symbol {symbol}",
 158 |                     ),
 159 |                 )
 160 |             ],
 161 |         )
 162 |     if name == AlphavantageTools.TIME_SERIES_INTRADAY.value:
 163 |         symbol = arguments.get("symbol") if arguments else ""
 164 |         interval = arguments.get("interval") if arguments else ""
 165 |         return types.GetPromptResult(
 166 |             messages=[
 167 |                 types.PromptMessage(
 168 |                     role="user",
 169 |                     content=types.TextContent(
 170 |                         type="text",
 171 |                         text=f"Fetch the time series intraday for the symbol {symbol} with interval {interval}",
 172 |                     ),
 173 |                 )
 174 |             ],
 175 |         )
 176 |     if name == AlphavantageTools.TIME_SERIES_DAILY.value:
 177 |         symbol = arguments.get("symbol") if arguments else ""
 178 |         return types.GetPromptResult(
 179 |             messages=[
 180 |                 types.PromptMessage(
 181 |                     role="user",
 182 |                     content=types.TextContent(
 183 |                         type="text",
 184 |                         text=f"Fetch the time series daily for the symbol {symbol}",
 185 |                     ),
 186 |                 )
 187 |             ],
 188 |         )
 189 |     if name == AlphavantageTools.TIME_SERIES_DAILY_ADJUSTED.value:
 190 |         symbol = arguments.get("symbol") if arguments else ""
 191 |         return types.GetPromptResult(
 192 |             messages=[
 193 |                 types.PromptMessage(
 194 |                     role="user",
 195 |                     content=types.TextContent(
 196 |                         type="text",
 197 |                         text=f"Fetch the time series daily adjusted for the symbol {symbol}",
 198 |                     ),
 199 |                 )
 200 |             ],
 201 |         )
 202 |     if name == AlphavantageTools.TIME_SERIES_WEEKLY.value:
 203 |         symbol = arguments.get("symbol") if arguments else ""
 204 |         return types.GetPromptResult(
 205 |             messages=[
 206 |                 types.PromptMessage(
 207 |                     role="user",
 208 |                     content=types.TextContent(
 209 |                         type="text",
 210 |                         text=f"Fetch the time series weekly for the symbol {symbol}",
 211 |                     ),
 212 |                 )
 213 |             ],
 214 |         )
 215 |     if name == AlphavantageTools.TIME_SERIES_WEEKLY_ADJUSTED.value:
 216 |         symbol = arguments.get("symbol") if arguments else ""
 217 |         return types.GetPromptResult(
 218 |             messages=[
 219 |                 types.PromptMessage(
 220 |                     role="user",
 221 |                     content=types.TextContent(
 222 |                         type="text",
 223 |                         text=f"Fetch the time series weekly adjusted for the symbol {symbol}",
 224 |                     ),
 225 |                 )
 226 |             ],
 227 |         )
 228 |     if name == AlphavantageTools.TIME_SERIES_MONTHLY.value:
 229 |         symbol = arguments.get("symbol") if arguments else ""
 230 |         return types.GetPromptResult(
 231 |             messages=[
 232 |                 types.PromptMessage(
 233 |                     role="user",
 234 |                     content=types.TextContent(
 235 |                         type="text",
 236 |                         text=f"Fetch the time series monthly for the symbol {symbol}",
 237 |                     ),
 238 |                 )
 239 |             ],
 240 |         )
 241 |     if name == AlphavantageTools.TIME_SERIES_MONTHLY_ADJUSTED.value:
 242 |         symbol = arguments.get("symbol") if arguments else ""
 243 |         return types.GetPromptResult(
 244 |             messages=[
 245 |                 types.PromptMessage(
 246 |                     role="user",
 247 |                     content=types.TextContent(
 248 |                         type="text",
 249 |                         text=f"Fetch the time series monthly adjusted for the symbol {symbol}",
 250 |                     ),
 251 |                 )
 252 |             ],
 253 |         )
 254 |     if name == AlphavantageTools.REALTIME_BULK_QUOTES.value:
 255 |         symbol = arguments.get("symbol") if arguments else ""
 256 |         return types.GetPromptResult(
 257 |             messages=[
 258 |                 types.PromptMessage(
 259 |                     role="user",
 260 |                     content=types.TextContent(
 261 |                         type="text",
 262 |                         text=f"Fetch real time bulk quotes for the symbols {symbol}",
 263 |                     ),
 264 |                 )
 265 |             ],
 266 |         )
 267 |     if name == AlphavantageTools.SYMBOL_SEARCH.value:
 268 |         keywords = arguments.get("keywords") if arguments else ""
 269 |         return types.GetPromptResult(
 270 |             messages=[
 271 |                 types.PromptMessage(
 272 |                     role="user",
 273 |                     content=types.TextContent(
 274 |                         type="text",
 275 |                         text=f"Search for symbols with keywords {keywords}",
 276 |                     ),
 277 |                 )
 278 |             ],
 279 |         )
 280 |     if name == AlphavantageTools.MARKET_STATUS.value:
 281 |         return types.GetPromptResult(
 282 |             messages=[
 283 |                 types.PromptMessage(
 284 |                     role="user",
 285 |                     content=types.TextContent(
 286 |                         type="text", text="Fetch the market status"
 287 |                     ),
 288 |                 )
 289 |             ],
 290 |         )
 291 |     if name == AlphavantageTools.REALTIME_OPTIONS.value:
 292 |         symbol = arguments.get("symbol") if arguments else ""
 293 |         contract = arguments.get("contract") if arguments else ""
 294 |         return types.GetPromptResult(
 295 |             messages=[
 296 |                 types.PromptMessage(
 297 |                     role="user",
 298 |                     content=types.TextContent(
 299 |                         type="text",
 300 |                         text=f"Fetch real time options for the symbol {symbol} with contract {contract}",
 301 |                     ),
 302 |                 )
 303 |             ],
 304 |         )
 305 |     if name == AlphavantageTools.HISTORICAL_OPTIONS.value:
 306 |         symbol = arguments.get("symbol") if arguments else ""
 307 |         contract = arguments.get("contract") if arguments else ""
 308 |         return types.GetPromptResult(
 309 |             messages=[
 310 |                 types.PromptMessage(
 311 |                     role="user",
 312 |                     content=types.TextContent(
 313 |                         type="text",
 314 |                         text=f"Fetch historical options for the symbol {symbol} with contract {contract}",
 315 |                     ),
 316 |                 )
 317 |             ],
 318 |         )
 319 |     if name == AlphavantageTools.NEWS_SENTIMENT.value:
 320 |         tickers = arguments.get("tickers") if arguments else ""
 321 |         topics = arguments.get("topics") if arguments else ""
 322 |         return types.GetPromptResult(
 323 |             messages=[
 324 |                 types.PromptMessage(
 325 |                     role="user",
 326 |                     content=types.TextContent(
 327 |                         type="text",
 328 |                         text=f"Fetch news sentiment for the tickers {tickers} with topics {topics}",
 329 |                     ),
 330 |                 )
 331 |             ],
 332 |         )
 333 |     if name == AlphavantageTools.TOP_GAINERS_LOSERS.value:
 334 |         return types.GetPromptResult(
 335 |             messages=[
 336 |                 types.PromptMessage(
 337 |                     role="user",
 338 |                     content=types.TextContent(
 339 |                         type="text", text="Fetch the top gainers and losers"
 340 |                     ),
 341 |                 )
 342 |             ],
 343 |         )
 344 |     if name == AlphavantageTools.INSIDER_TRANSACTIONS.value:
 345 |         symbol = arguments.get("symbol") if arguments else ""
 346 |         return types.GetPromptResult(
 347 |             messages=[
 348 |                 types.PromptMessage(
 349 |                     role="user",
 350 |                     content=types.TextContent(
 351 |                         type="text",
 352 |                         text=f"Fetch insider transactions for the symbol {symbol}",
 353 |                     ),
 354 |                 )
 355 |             ],
 356 |         )
 357 |     if name == AlphavantageTools.ANALYTICS_FIXED_WINDOW.value:
 358 |         symbol = arguments.get("symbol") if arguments else ""
 359 |         window = arguments.get("window") if arguments else ""
 360 |         return types.GetPromptResult(
 361 |             messages=[
 362 |                 types.PromptMessage(
 363 |                     role="user",
 364 |                     content=types.TextContent(
 365 |                         type="text",
 366 |                         text=f"Fetch analytics with fixed window for the symbol {symbol} with window {window}",
 367 |                     ),
 368 |                 )
 369 |             ],
 370 |         )
 371 |     if name == AlphavantageTools.ANALYTICS_SLIDING_WINDOW.value:
 372 |         symbol = arguments.get("symbol") if arguments else ""
 373 |         window = arguments.get("window") if arguments else ""
 374 |         return types.GetPromptResult(
 375 |             messages=[
 376 |                 types.PromptMessage(
 377 |                     role="user",
 378 |                     content=types.TextContent(
 379 |                         type="text",
 380 |                         text=f"Fetch analytics with sliding window for the symbol {symbol} with window {window}",
 381 |                     ),
 382 |                 )
 383 |             ],
 384 |         )
 385 |     if name == AlphavantageTools.COMPANY_OVERVIEW.value:
 386 |         symbol = arguments.get("symbol") if arguments else ""
 387 |         datatype = arguments.get("datatype") if arguments else ""
 388 |         return types.GetPromptResult(
 389 |             messages=[
 390 |                 types.PromptMessage(
 391 |                     role="user",
 392 |                     content=types.TextContent(
 393 |                         type="text",
 394 |                         text=f"Fetch the company overview for the symbol {symbol} with datatype {datatype}",
 395 |                     ),
 396 |                 )
 397 |             ],
 398 |         )
 399 |     if name == AlphavantageTools.ETF_PROFILE.value:
 400 |         symbol = arguments.get("symbol") if arguments else ""
 401 |         datatype = arguments.get("datatype") if arguments else ""
 402 |         return types.GetPromptResult(
 403 |             messages=[
 404 |                 types.PromptMessage(
 405 |                     role="user",
 406 |                     content=types.TextContent(
 407 |                         type="text",
 408 |                         text=f"Fetch the ETF profile for the symbol {symbol} with datatype {datatype}",
 409 |                     ),
 410 |                 )
 411 |             ],
 412 |         )
 413 |     if name == AlphavantageTools.COMPANY_DIVIDENDS.value:
 414 |         symbol = arguments.get("symbol") if arguments else ""
 415 |         return types.GetPromptResult(
 416 |             messages=[
 417 |                 types.PromptMessage(
 418 |                     role="user",
 419 |                     content=types.TextContent(
 420 |                         type="text",
 421 |                         text=f"Fetch the company dividends for the symbol {symbol}",
 422 |                     ),
 423 |                 )
 424 |             ],
 425 |         )
 426 |     if name == AlphavantageTools.COMPANY_SPLITS.value:
 427 |         symbol = arguments.get("symbol") if arguments else ""
 428 |         return types.GetPromptResult(
 429 |             messages=[
 430 |                 types.PromptMessage(
 431 |                     role="user",
 432 |                     content=types.TextContent(
 433 |                         type="text",
 434 |                         text=f"Fetch the company split events for the symbol {symbol}",
 435 |                     ),
 436 |                 )
 437 |             ],
 438 |         )
 439 |     if name == AlphavantageTools.INCOME_STATEMENT.value:
 440 |         symbol = arguments.get("symbol") if arguments else ""
 441 |         return types.GetPromptResult(
 442 |             messages=[
 443 |                 types.PromptMessage(
 444 |                     role="user",
 445 |                     content=types.TextContent(
 446 |                         type="text",
 447 |                         text=f"Fetch the annual and quarterly income statements for the company {symbol}",
 448 |                     ),
 449 |                 )
 450 |             ],
 451 |         )
 452 |     if name == AlphavantageTools.BALANCE_SHEET.value:
 453 |         symbol = arguments.get("symbol") if arguments else ""
 454 |         return types.GetPromptResult(
 455 |             messages=[
 456 |                 types.PromptMessage(
 457 |                     role="user",
 458 |                     content=types.TextContent(
 459 |                         type="text",
 460 |                         text=f"Fetch the annual and quarterly balance sheet for the company {symbol}",
 461 |                     ),
 462 |                 )
 463 |             ],
 464 |         )
 465 |     if name == AlphavantageTools.CASH_FLOW.value:
 466 |         symbol = arguments.get("symbol") if arguments else ""
 467 |         return types.GetPromptResult(
 468 |             messages=[
 469 |                 types.PromptMessage(
 470 |                     role="user",
 471 |                     content=types.TextContent(
 472 |                         type="text",
 473 |                         text=f"Fetch the annual and quarterly cash flow for the company {symbol}",
 474 |                     ),
 475 |                 )
 476 |             ],
 477 |         )
 478 |     if name == AlphavantageTools.COMPANY_EARNINGS.value:
 479 |         symbol = arguments.get("symbol") if arguments else ""
 480 |         return types.GetPromptResult(
 481 |             messages=[
 482 |                 types.PromptMessage(
 483 |                     role="user",
 484 |                     content=types.TextContent(
 485 |                         type="text",
 486 |                         text=f"Fetch the annual and quarterly earnings (EPS) for the company {symbol}",
 487 |                     ),
 488 |                 )
 489 |             ],
 490 |         )
 491 |     if name == AlphavantageTools.LISTING_STATUS.value:
 492 |         return types.GetPromptResult(
 493 |             messages=[
 494 |                 types.PromptMessage(
 495 |                     role="user",
 496 |                     content=types.TextContent(
 497 |                         type="text",
 498 |                         text="Fetch the list of active or delisted US stocks and ETFs",
 499 |                     ),
 500 |                 )
 501 |             ]
 502 |         )
 503 |     if name == AlphavantageTools.EARNINGS_CALENDAR.value:
 504 |         symbol = arguments.get("symbol") if arguments else ""
 505 |         return types.GetPromptResult(
 506 |             messages=[
 507 |                 types.PromptMessage(
 508 |                     role="user",
 509 |                     content=types.TextContent(
 510 |                         type="text",
 511 |                         text=f"Fetch the earnings expected in the next 3, 6, or 12 months for the {symbol}",
 512 |                     ),
 513 |                 )
 514 |             ],
 515 |         )
 516 |     if name == AlphavantageTools.EARNINGS_CALL_TRANSCRIPT.value:
 517 |         symbol = arguments.get("symbol") if arguments else ""
 518 |         quarter = arguments.get("quarter") if arguments else "2024Q1"
 519 |         return types.GetPromptResult(
 520 |             messages=[
 521 |                 types.PromptMessage(
 522 |                     role="user",
 523 |                     content=types.TextContent(
 524 |                         type="text",
 525 |                         text=f"Fetch the earnings call transcript for the {symbol} for the quarter {quarter}",
 526 |                     ),
 527 |                 )
 528 |             ],
 529 |         )
 530 | 
 531 |     if name == AlphavantageTools.IPO_CALENDAR.value:
 532 |         return types.GetPromptResult(
 533 |             messages=[
 534 |                 types.PromptMessage(
 535 |                     role="user",
 536 |                     content=types.TextContent(
 537 |                         type="text",
 538 |                         text="Fetch list of IPOs expected in the next 3 months",
 539 |                     ),
 540 |                 )
 541 |             ],
 542 |         )
 543 |     if name == AlphavantageTools.EXCHANGE_RATE.value:
 544 |         from_currency = arguments.get("from_currency") if arguments else ""
 545 |         to_currency = arguments.get("to_currency") if arguments else ""
 546 |         return types.GetPromptResult(
 547 |             messages=[
 548 |                 types.PromptMessage(
 549 |                     role="user",
 550 |                     content=types.TextContent(
 551 |                         type="text",
 552 |                         text=f"Fetch the exchange rate from {from_currency} to {to_currency}",
 553 |                     ),
 554 |                 )
 555 |             ],
 556 |         )
 557 |     if name == AlphavantageTools.FX_INTRADAY.value:
 558 |         from_symbol = arguments.get("from_symbol") if arguments else ""
 559 |         to_symbol = arguments.get("to_symbol") if arguments else ""
 560 |         interval = arguments.get("interval") if arguments else ""
 561 |         return types.GetPromptResult(
 562 |             messages=[
 563 |                 types.PromptMessage(
 564 |                     role="user",
 565 |                     content=types.TextContent(
 566 |                         type="text",
 567 |                         text=f"Fetch the intraday exchange rate from {from_symbol} to {to_symbol} with interval {interval}",
 568 |                     ),
 569 |                 )
 570 |             ],
 571 |         )
 572 |     if name == AlphavantageTools.FX_DAILY.value:
 573 |         from_symbol = arguments.get("from_symbol") if arguments else ""
 574 |         to_symbol = arguments.get("to_symbol") if arguments else ""
 575 |         return types.GetPromptResult(
 576 |             messages=[
 577 |                 types.PromptMessage(
 578 |                     role="user",
 579 |                     content=types.TextContent(
 580 |                         type="text",
 581 |                         text=f"Fetch the daily exchange rate from {from_symbol} to {to_symbol}",
 582 |                     ),
 583 |                 )
 584 |             ],
 585 |         )
 586 |     if name == AlphavantageTools.FX_WEEKLY.value:
 587 |         from_symbol = arguments.get("from_symbol") if arguments else ""
 588 |         to_symbol = arguments.get("to_symbol") if arguments else ""
 589 |         return types.GetPromptResult(
 590 |             messages=[
 591 |                 types.PromptMessage(
 592 |                     role="user",
 593 |                     content=types.TextContent(
 594 |                         type="text",
 595 |                         text=f"Fetch the weekly exchange rate from {from_symbol} to {to_symbol}",
 596 |                     ),
 597 |                 )
 598 |             ],
 599 |         )
 600 |     if name == AlphavantageTools.FX_MONTHLY.value:
 601 |         from_symbol = arguments.get("from_symbol") if arguments else ""
 602 |         to_symbol = arguments.get("to_symbol") if arguments else ""
 603 |         return types.GetPromptResult(
 604 |             messages=[
 605 |                 types.PromptMessage(
 606 |                     role="user",
 607 |                     content=types.TextContent(
 608 |                         type="text",
 609 |                         text=f"Fetch the monthly exchange rate from {from_symbol} to {to_symbol}",
 610 |                     ),
 611 |                 )
 612 |             ],
 613 |         )
 614 |     if name == AlphavantageTools.CRYPTO_INTRADAY.value:
 615 |         symbol = arguments.get("symbol") if arguments else ""
 616 |         market = arguments.get("market") if arguments else ""
 617 |         interval = arguments.get("interval") if arguments else ""
 618 | 
 619 |         return types.GetPromptResult(
 620 |             messages=[
 621 |                 types.PromptMessage(
 622 |                     role="user",
 623 |                     content=types.TextContent(
 624 |                         type="text",
 625 |                         text=f"Fetch the intraday crypto data for {symbol} in {market} with interval {interval}",
 626 |                     ),
 627 |                 )
 628 |             ],
 629 |         )
 630 |     if name == AlphavantageTools.DIGITAL_CURRENCY_DAILY.value:
 631 |         symbol = arguments.get("symbol") if arguments else ""
 632 |         market = arguments.get("market") if arguments else ""
 633 | 
 634 |         return types.GetPromptResult(
 635 |             messages=[
 636 |                 types.PromptMessage(
 637 |                     role="user",
 638 |                     content=types.TextContent(
 639 |                         type="text",
 640 |                         text=f"Fetch the daily historical time series for a digital currency (e.g., {symbol}) traded on a specific market (e.g., {market})",
 641 |                     ),
 642 |                 )
 643 |             ],
 644 |         )
 645 |     if name == AlphavantageTools.DIGITAL_CURRENCY_WEEKLY.value:
 646 |         symbol = arguments.get("symbol") if arguments else ""
 647 |         market = arguments.get("market") if arguments else ""
 648 | 
 649 |         return types.GetPromptResult(
 650 |             messages=[
 651 |                 types.PromptMessage(
 652 |                     role="user",
 653 |                     content=types.TextContent(
 654 |                         type="text",
 655 |                         text=f"Fetch the weekly historical time series for a digital currency (e.g., {symbol}) traded on a specific market, e.g., {market}",
 656 |                     ),
 657 |                 )
 658 |             ],
 659 |         )
 660 |     if name == AlphavantageTools.DIGITAL_CURRENCY_MONTHLY.value:
 661 |         symbol = arguments.get("symbol") if arguments else ""
 662 |         market = arguments.get("market") if arguments else ""
 663 | 
 664 |         return types.GetPromptResult(
 665 |             messages=[
 666 |                 types.PromptMessage(
 667 |                     role="user",
 668 |                     content=types.TextContent(
 669 |                         type="text",
 670 |                         text=f"Fetch the monthly historical time series for a digital currency (e.g., {symbol}) traded on a specific market, e.g., {market}",
 671 |                     ),
 672 |                 )
 673 |             ],
 674 |         )
 675 |     if name == AlphavantageTools.WTI_CRUDE_OIL.value:
 676 |         function = arguments.get("function") if arguments else "WTI"
 677 |         interval = arguments.get("interval") if arguments else "monthly"
 678 |         datatype = arguments.get("datatype") if arguments else "json"
 679 | 
 680 |         return types.GetPromptResult(
 681 |             messages=[
 682 |                 types.PromptMessage(
 683 |                     role="user",
 684 |                     content=types.TextContent(
 685 |                         type="text",
 686 |                         text=f"Fetch the West Texas Intermediate ({function}) crude oil prices in daily, weekly, and monthly horizons",
 687 |                     ),
 688 |                 )
 689 |             ],
 690 |         )
 691 | 
 692 |     if name == AlphavantageTools.BRENT_CRUDE_OIL.value:
 693 |         function = arguments.get("function") if arguments else "Brent"
 694 |         interval = arguments.get("interval") if arguments else "monthly"
 695 |         datatype = arguments.get("datatype") if arguments else "json"
 696 | 
 697 |         return types.GetPromptResult(
 698 |             messages=[
 699 |                 types.PromptMessage(
 700 |                     role="user",
 701 |                     content=types.TextContent(
 702 |                         type="text",
 703 |                         text=f"Fetch the {function} crude oil prices in daily, weekly, and monthly horizons",
 704 |                     ),
 705 |                 )
 706 |             ],
 707 |         )
 708 |     if name == AlphavantageTools.NATURAL_GAS.value:
 709 |         function = arguments.get("function") if arguments else "NATURAL_GAS"
 710 |         interval = arguments.get("interval") if arguments else "monthly"
 711 |         datatype = arguments.get("datatype") if arguments else "json"
 712 | 
 713 |         return types.GetPromptResult(
 714 |             messages=[
 715 |                 types.PromptMessage(
 716 |                     role="user",
 717 |                     content=types.TextContent(
 718 |                         type="text",
 719 |                         text="Fetch the Henry Hub natural gas spot prices in daily, weekly, and monthly horizons.",
 720 |                     ),
 721 |                 )
 722 |             ],
 723 |         )
 724 | 
 725 |     raise ValueError("Prompt implementation not found")
 726 | 
 727 | 
 728 | @server.list_tools()
 729 | async def handle_list_tools() -> list[types.Tool]:
 730 |     """
 731 |     Get all available tool definitions with their schemas.
 732 | 
 733 |     Returns:
 734 |         List of MCP Tool objects with input schemas
 735 |     """
 736 |     return tools_definitions()
 737 | 
 738 | 
 739 | @server.call_tool()
 740 | async def handle_call_tool(
 741 |     name: str, arguments: dict | None
 742 | ) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
 743 |     """
 744 |     Handle tool execution requests.
 745 |     Tools can modify server state and notify clients of changes.
 746 |     """
 747 |     try:
 748 |         match name:
 749 |             case AlphavantageTools.STOCK_QUOTE.value:
 750 |                 symbol = arguments.get("symbol")
 751 |                 if not symbol:
 752 |                     raise ValueError("Missing required argument: symbol")
 753 | 
 754 |                 datatype = arguments.get("datatype", "json")
 755 |                 result = await fetch_quote(symbol, datatype)
 756 | 
 757 |             case AlphavantageTools.TIME_SERIES_INTRADAY.value:
 758 |                 symbol = arguments.get("symbol")
 759 |                 interval = arguments.get("interval")
 760 |                 if not symbol or not interval:
 761 |                     raise ValueError("Missing required arguments: symbol, interval")
 762 | 
 763 |                 datatype = arguments.get("datatype", "json")
 764 |                 adjusted = arguments.get("adjusted", True)
 765 |                 extended_hours = arguments.get("extended_hours", True)
 766 |                 outputsize = arguments.get("outputsize", "compact")
 767 |                 month = arguments.get("month", None)
 768 | 
 769 |                 result = await fetch_intraday(
 770 |                     symbol,
 771 |                     interval,
 772 |                     datatype,
 773 |                     extended_hours,
 774 |                     adjusted,
 775 |                     outputsize,
 776 |                     month,
 777 |                 )
 778 |             case AlphavantageTools.TIME_SERIES_DAILY.value:
 779 |                 symbol = arguments.get("symbol")
 780 |                 if not symbol:
 781 |                     raise ValueError("Missing required argument: symbol")
 782 | 
 783 |                 datatype = arguments.get("datatype", "json")
 784 |                 outputsize = arguments.get("outputsize", "compact")
 785 | 
 786 |                 result = await fetch_time_series_daily(symbol, datatype, outputsize)
 787 |             case AlphavantageTools.TIME_SERIES_DAILY_ADJUSTED.value:
 788 |                 symbol = arguments.get("symbol")
 789 |                 if not symbol:
 790 |                     raise ValueError("Missing required argument: symbol")
 791 | 
 792 |                 datatype = arguments.get("datatype", "json")
 793 |                 outputsize = arguments.get("outputsize", "compact")
 794 | 
 795 |                 result = await fetch_time_series_daily_adjusted(
 796 |                     symbol, datatype, outputsize
 797 |                 )
 798 |             case AlphavantageTools.TIME_SERIES_WEEKLY.value:
 799 |                 symbol = arguments.get("symbol")
 800 |                 if not symbol:
 801 |                     raise ValueError("Missing required argument: symbol")
 802 | 
 803 |                 datatype = arguments.get("datatype", "json")
 804 | 
 805 |                 result = await fetch_time_series_weekly(symbol, datatype)
 806 |             case AlphavantageTools.TIME_SERIES_WEEKLY_ADJUSTED.value:
 807 |                 symbol = arguments.get("symbol")
 808 |                 if not symbol:
 809 |                     raise ValueError("Missing required argument: symbol")
 810 | 
 811 |                 datatype = arguments.get("datatype", "json")
 812 | 
 813 |                 result = await fetch_time_series_weekly_adjusted(symbol, datatype)
 814 |             case AlphavantageTools.TIME_SERIES_MONTHLY.value:
 815 |                 symbol = arguments.get("symbol")
 816 |                 if not symbol:
 817 |                     raise ValueError("Missing required argument: symbol")
 818 | 
 819 |                 datatype = arguments.get("datatype", "json")
 820 | 
 821 |                 result = await fetch_time_series_monthly(symbol, datatype)
 822 |             case AlphavantageTools.TIME_SERIES_MONTHLY_ADJUSTED.value:
 823 |                 symbol = arguments.get("symbol")
 824 |                 if not symbol:
 825 |                     raise ValueError("Missing required argument: symbol")
 826 | 
 827 |                 datatype = arguments.get("datatype", "json")
 828 | 
 829 |                 result = await fetch_time_series_monthly_adjusted(symbol, datatype)
 830 | 
 831 |             case AlphavantageTools.REALTIME_BULK_QUOTES.value:
 832 |                 symbols = arguments.get("symbols")
 833 |                 if not symbols:
 834 |                     raise ValueError("Missing required argument: symbols")
 835 | 
 836 |                 datatype = arguments.get("datatype", "json")
 837 |                 result = await fetch_realtime_bulk_quotes(symbols, datatype)
 838 | 
 839 |             case AlphavantageTools.SYMBOL_SEARCH.value:
 840 |                 keywords = arguments.get("keywords")
 841 |                 if not keywords:
 842 |                     raise ValueError("Missing required argument: keywords")
 843 | 
 844 |                 datatype = arguments.get("datatype", "json")
 845 |                 result = await search_endpoint(keywords, datatype)
 846 | 
 847 |             case AlphavantageTools.MARKET_STATUS.value:
 848 |                 result = await fetch_market_status()
 849 | 
 850 |             case AlphavantageTools.REALTIME_OPTIONS.value:
 851 |                 symbol = arguments.get("symbol")
 852 |                 if not symbol:
 853 |                     raise ValueError("Missing required argument: symbol")
 854 | 
 855 |                 datatype = arguments.get("datatype", "json")
 856 |                 contract = arguments.get("contract", "all")
 857 |                 result = await fetch_realtime_options(symbol, datatype, contract)
 858 | 
 859 |             case AlphavantageTools.HISTORICAL_OPTIONS.value:
 860 |                 symbol = arguments.get("symbol")
 861 |                 if not symbol:
 862 |                     raise ValueError("Missing required argument: symbol")
 863 | 
 864 |                 datatype = arguments.get("datatype", "json")
 865 |                 contract = arguments.get("contract", "all")
 866 |                 result = await fetch_historical_options(symbol, datatype, contract)
 867 | 
 868 |             case AlphavantageTools.NEWS_SENTIMENT.value:
 869 |                 tickers = arguments.get("tickers", [])
 870 |                 datatype = arguments.get("datatype", "json")
 871 |                 topics = arguments.get("topics", None)
 872 |                 time_from = arguments.get("time_from", None)
 873 |                 time_to = arguments.get("time_to", None)
 874 |                 sort = arguments.get("sort", "LATEST")
 875 |                 limit = arguments.get("limit", 50)
 876 | 
 877 |                 result = await fetch_news_sentiment(
 878 |                     tickers, datatype, topics, time_from, time_to, sort, limit
 879 |                 )
 880 | 
 881 |             case AlphavantageTools.TOP_GAINERS_LOSERS.value:
 882 |                 result = await fetch_top_gainer_losers()
 883 | 
 884 |             case AlphavantageTools.INSIDER_TRANSACTIONS.value:
 885 |                 symbol = arguments.get("symbol")
 886 |                 if not symbol:
 887 |                     raise ValueError("Missing required argument: symbol")
 888 | 
 889 |                 result = await fetch_insider_transactions(symbol)
 890 | 
 891 |             case AlphavantageTools.ANALYTICS_FIXED_WINDOW.value:
 892 |                 symbols = arguments.get("symbols")
 893 |                 interval = arguments.get("interval")
 894 |                 series_range = arguments.get("series_range")
 895 |                 ohlc = arguments.get("ohlc", "close")
 896 |                 calculations = arguments.get("calculations")
 897 | 
 898 |                 if not symbols or not interval or not series_range or not calculations:
 899 |                     raise ValueError(
 900 |                         "Missing required arguments: symbols, interval, series_range, calculations"
 901 |                     )
 902 |                 result = await fetch_analytics_fixed_window(
 903 |                     symbols, interval, series_range, ohlc, calculations
 904 |                 )
 905 | 
 906 |             case AlphavantageTools.ANALYTICS_SLIDING_WINDOW.value:
 907 |                 symbols = arguments.get("symbols")
 908 |                 interval = arguments.get("interval")
 909 |                 series_range = arguments.get("series_range")
 910 |                 ohlc = arguments.get("ohlc", "close")
 911 |                 window_size = arguments.get("window_size")
 912 |                 calculations = arguments.get("calculations", [])
 913 | 
 914 |                 if (
 915 |                     not symbols
 916 |                     or not interval
 917 |                     or not series_range
 918 |                     or not calculations
 919 |                     or not window_size
 920 |                 ):
 921 |                     raise ValueError(
 922 |                         "Missing required arguments: symbols, interval, series_range, calculations, window_size"
 923 |                     )
 924 |                 result = await fetch_analytics_sliding_window(
 925 |                     symbols, series_range, ohlc, interval, interval, calculations
 926 |                 )
 927 | 
 928 |             case AlphavantageTools.COMPANY_OVERVIEW.value:
 929 |                 symbol = arguments.get("symbol")
 930 |                 if not symbol:
 931 |                     raise ValueError("Missing required argument: symbol")
 932 | 
 933 |                 result = await fetch_company_overview(symbol)
 934 | 
 935 |             case AlphavantageTools.ETF_PROFILE.value:
 936 |                 symbol = arguments.get("symbol")
 937 |                 if not symbol:
 938 |                     raise ValueError("Missing required argument: symbol")
 939 | 
 940 |                 result = await fetch_etf_profile(symbol)
 941 | 
 942 |             case AlphavantageTools.COMPANY_DIVIDENDS.value:
 943 |                 symbol = arguments.get("symbol")
 944 |                 if not symbol:
 945 |                     raise ValueError("Missing required argument: symbol")
 946 | 
 947 |                 result = await company_dividends(symbol)
 948 | 
 949 |             case AlphavantageTools.COMPANY_SPLITS.value:
 950 |                 symbol = arguments.get("symbol")
 951 |                 if not symbol:
 952 |                     raise ValueError("Missing required argument: symbol")
 953 | 
 954 |                 result = await fetch_company_splits(symbol)
 955 | 
 956 |             case AlphavantageTools.INCOME_STATEMENT.value:
 957 |                 symbol = arguments.get("symbol")
 958 |                 if not symbol:
 959 |                     raise ValueError("Missing required argument: symbol")
 960 | 
 961 |                 result = await fetch_income_statement(symbol)
 962 |             case AlphavantageTools.BALANCE_SHEET.value:
 963 |                 symbol = arguments.get("symbol")
 964 |                 if not symbol:
 965 |                     raise ValueError("Missing required argument: symbol")
 966 | 
 967 |                 result = await fetch_balance_sheet(symbol)
 968 | 
 969 |             case AlphavantageTools.CASH_FLOW.value:
 970 |                 symbol = arguments.get("symbol")
 971 |                 if not symbol:
 972 |                     raise ValueError("Missing required argument: symbol")
 973 | 
 974 |                 result = await fetch_cash_flow(symbol)
 975 | 
 976 |             case AlphavantageTools.COMPANY_EARNINGS.value:
 977 |                 symbol = arguments.get("symbol")
 978 |                 if not symbol:
 979 |                     raise ValueError("Missing required argument: symbol")
 980 |                 result = await fetch_earnings(symbol)
 981 | 
 982 |             case AlphavantageTools.LISTING_STATUS.value:
 983 |                 date = arguments.get("date")
 984 |                 state = arguments.get("state")
 985 |                 result = await fetch_listing_status(date, state)
 986 | 
 987 |             case AlphavantageTools.EARNINGS_CALENDAR.value:
 988 |                 symbol = arguments.get("symbol")
 989 |                 horizon = arguments.get("horizon")
 990 | 
 991 |                 result = await fetch_earnings_calendar(symbol, horizon)
 992 | 
 993 |             case AlphavantageTools.EARNINGS_CALL_TRANSCRIPT.value:
 994 |                 symbol = arguments.get("symbol")
 995 |                 quarter = arguments.get("quarter")
 996 | 
 997 |                 result = await fetch_earnings_call_transcript(symbol, quarter)
 998 | 
 999 |             case AlphavantageTools.IPO_CALENDAR.value:
1000 |                 result = await fetch_ipo_calendar()
1001 | 
1002 |             case AlphavantageTools.EXCHANGE_RATE.value:
1003 |                 from_currency = arguments.get("from_currency")
1004 |                 to_currency = arguments.get("to_currency")
1005 | 
1006 |                 if not from_currency or not to_currency:
1007 |                     raise ValueError(
1008 |                         "Missing required arguments: from_currency, to_currency"
1009 |                     )
1010 | 
1011 |                 result = await fetch_exchange_rate(from_currency, to_currency)
1012 | 
1013 |             case AlphavantageTools.FX_INTRADAY.value:
1014 |                 from_symbol = arguments.get("from_symbol")
1015 |                 to_symbol = arguments.get("to_symbol")
1016 |                 interval = arguments.get("interval")
1017 |                 outputsize = arguments.get("outputsize", "compact")
1018 |                 datatype = arguments.get("datatype", "json")
1019 | 
1020 |                 if not from_symbol or not to_symbol or not interval:
1021 |                     raise ValueError(
1022 |                         "Missing required arguments: from_symbol, to_symbol, interval"
1023 |                     )
1024 | 
1025 |                 result = await fetch_fx_intraday(
1026 |                     from_symbol, to_symbol, interval, outputsize, datatype
1027 |                 )
1028 | 
1029 |             case AlphavantageTools.FX_DAILY.value:
1030 |                 from_symbol = arguments.get("from_symbol")
1031 |                 to_symbol = arguments.get("to_symbol")
1032 |                 datatype = arguments.get("datatype", "json")
1033 |                 outputsize = arguments.get("outputsize", "compact")
1034 | 
1035 |                 if not from_symbol or not to_symbol:
1036 |                     raise ValueError(
1037 |                         "Missing required arguments: from_symbol, to_symbol"
1038 |                     )
1039 | 
1040 |                 result = await fetch_fx_daily(
1041 |                     from_symbol, to_symbol, datatype, outputsize
1042 |                 )
1043 | 
1044 |             case AlphavantageTools.FX_WEEKLY.value:
1045 |                 from_symbol = arguments.get("from_symbol")
1046 |                 to_symbol = arguments.get("to_symbol")
1047 |                 datatype = arguments.get("datatype", "json")
1048 | 
1049 |                 if not from_symbol or not to_symbol:
1050 |                     raise ValueError(
1051 |                         "Missing required arguments: from_symbol, to_symbol"
1052 |                     )
1053 | 
1054 |                 result = await fetch_fx_weekly(from_symbol, to_symbol, datatype)
1055 | 
1056 |             case AlphavantageTools.FX_MONTHLY.value:
1057 |                 from_symbol = arguments.get("from_symbol")
1058 |                 to_symbol = arguments.get("to_symbol")
1059 |                 datatype = arguments.get("datatype", "json")
1060 | 
1061 |                 if not from_symbol or not to_symbol:
1062 |                     raise ValueError(
1063 |                         "Missing required arguments: from_symbol, to_symbol"
1064 |                     )
1065 | 
1066 |                 result = await fetch_fx_monthly(from_symbol, to_symbol, datatype)
1067 | 
1068 |             case AlphavantageTools.CRYPTO_INTRADAY.value:
1069 |                 symbol = arguments.get("symbol")
1070 |                 market = arguments.get("market")
1071 |                 interval = arguments.get("interval")
1072 |                 outputsize = arguments.get("outputsize", "compact")
1073 |                 datatype = arguments.get("datatype", "json")
1074 | 
1075 |                 if not symbol or not market or not interval:
1076 |                     raise ValueError(
1077 |                         "Missing required arguments: symbol, market, interval"
1078 |                     )
1079 | 
1080 |                 result = await fetch_digital_currency_intraday(
1081 |                     symbol, market, interval, datatype, outputsize
1082 |                 )
1083 | 
1084 |             case AlphavantageTools.DIGITAL_CURRENCY_DAILY.value:
1085 |                 symbol = arguments.get("symbol")
1086 |                 market = arguments.get("market")
1087 | 
1088 |                 if not symbol or not market:
1089 |                     raise ValueError("Missing required arguments: symbol, market")
1090 | 
1091 |                 result = await fetch_digital_currency_daily(symbol, market)
1092 | 
1093 |             case AlphavantageTools.DIGITAL_CURRENCY_WEEKLY.value:
1094 |                 symbol = arguments.get("symbol")
1095 |                 market = arguments.get("market")
1096 | 
1097 |                 if not symbol or not market:
1098 |                     raise ValueError("Missing required arguments: symbol, market")
1099 | 
1100 |                 result = await fetch_digital_currency_daily(symbol, market)
1101 | 
1102 |             case AlphavantageTools.DIGITAL_CURRENCY_MONTHLY.value:
1103 |                 symbol = arguments.get("symbol")
1104 |                 market = arguments.get("market")
1105 | 
1106 |                 if not symbol or not market:
1107 |                     raise ValueError("Missing required arguments: symbol, market")
1108 | 
1109 |                 result = await fetch_digital_currency_monthly(symbol, market)
1110 | 
1111 |             case AlphavantageTools.WTI_CRUDE_OIL.value:
1112 |                 interval = arguments.get("interval", "montHly")
1113 |                 datatype = arguments.get("datatype", "json")
1114 | 
1115 |                 result = await fetch_wti_crude(interval, datatype)
1116 | 
1117 |             case AlphavantageTools.BRENT_CRUDE_OIL.value:
1118 |                 interval = arguments.get("interval", "monthly")
1119 |                 datatype = arguments.get("datatype", "json")
1120 | 
1121 |                 result = await fetch_brent_crude(interval, datatype)
1122 | 
1123 |             case AlphavantageTools.NATURAL_GAS.value:
1124 |                 interval = arguments.get("interval", "monthly")
1125 |                 datatype = arguments.get("datatype", "json")
1126 | 
1127 |                 result = await fetch_natural_gas(interval, datatype)
1128 | 
1129 |             case AlphavantageTools.COPPER.value:
1130 |                 interval = arguments.get("interval", "monthly")
1131 |                 datatype = arguments.get("datatype", "json")
1132 | 
1133 |                 result = await fetch_copper(interval, datatype)
1134 | 
1135 |             case AlphavantageTools.ALUMINUM.value:
1136 |                 interval = arguments.get("interval", "monthly")
1137 |                 datatype = arguments.get("datatype", "json")
1138 | 
1139 |                 result = await fetch_aluminum(interval, datatype)
1140 | 
1141 |             case AlphavantageTools.WHEAT.value:
1142 |                 interval = arguments.get("interval", "monthly")
1143 |                 datatype = arguments.get("datatype", "json")
1144 | 
1145 |                 result = await fetch_wheat(interval, datatype)
1146 | 
1147 |             case AlphavantageTools.CORN.value:
1148 |                 interval = arguments.get("interval", "monthly")
1149 |                 datatype = arguments.get("datatype", "json")
1150 | 
1151 |                 result = await fetch_corn(interval, datatype)
1152 | 
1153 |             case AlphavantageTools.COTTON.value:
1154 |                 interval = arguments.get("interval", "monthly")
1155 |                 datatype = arguments.get("datatype", "json")
1156 | 
1157 |                 result = await fetch_cotton(interval, datatype)
1158 | 
1159 |             case AlphavantageTools.SUGAR.value:
1160 |                 interval = arguments.get("interval", "monthly")
1161 |                 datatype = arguments.get("datatype", "json")
1162 | 
1163 |                 result = await fetch_sugar(interval, datatype)
1164 | 
1165 |             case AlphavantageTools.COFFEE.value:
1166 |                 interval = arguments.get("interval", "monthly")
1167 |                 datatype = arguments.get("datatype", "json")
1168 | 
1169 |                 result = await fetch_coffee(interval, datatype)
1170 | 
1171 |             case AlphavantageTools.ALL_COMMODITIES.value:
1172 |                 interval = arguments.get("interval", "monthly")
1173 |                 datatype = arguments.get("datatype", "json")
1174 | 
1175 |                 result = await fetch_all_commodities(interval, datatype)
1176 | 
1177 |             case AlphavantageTools.REAL_GDP.value:
1178 |                 interval = arguments.get("interval", "monthly")
1179 |                 datatype = arguments.get("datatype", "json")
1180 | 
1181 |                 result = await fetch_real_gdp(interval, datatype)
1182 | 
1183 |             case AlphavantageTools.REAL_GDP_PER_CAPITA.value:
1184 |                 datatype = arguments.get("datatype", "json")
1185 | 
1186 |                 result = await fetch_real_gdp_per_capita(datatype)
1187 | 
1188 |             case AlphavantageTools.TREASURY_YIELD.value:
1189 |                 interval = arguments.get("interval", "monthly")
1190 |                 maturity = arguments.get("maturity", "10year")
1191 |                 datatype = arguments.get("datatype", "json")
1192 | 
1193 |                 result = await fetch_treasury_yield(interval, maturity, datatype)
1194 | 
1195 |             case AlphavantageTools.FEDERAL_FUNDS_RATE.value:
1196 |                 interval = arguments.get("interval", "monthly")
1197 |                 datatype = arguments.get("datatype", "json")
1198 | 
1199 |                 result = await fetch_federal_funds_rate(interval, datatype)
1200 | 
1201 |             case AlphavantageTools.CPI.value:
1202 |                 interval = arguments.get("interval", "monthly")
1203 |                 datatype = arguments.get("datatype", "json")
1204 | 
1205 |                 result = await fetch_cpi(interval, datatype)
1206 | 
1207 |             case AlphavantageTools.INFLATION.value:
1208 |                 datatype = arguments.get("datatype", "json")
1209 | 
1210 |                 result = await fetch_inflation(datatype)
1211 | 
1212 |             case AlphavantageTools.RETAIL_SALES.value:
1213 |                 datatype = arguments.get("datatype", "json")
1214 | 
1215 |                 result = await fetch_retail_sales(datatype)
1216 | 
1217 |             case AlphavantageTools.DURABLES.value:
1218 |                 datatype = arguments.get("datatype", "json")
1219 | 
1220 |                 result = await fetch_durables(datatype)
1221 | 
1222 |             case AlphavantageTools.UNEMPLOYMENT.value:
1223 |                 datatype = arguments.get("datatype", "json")
1224 | 
1225 |                 result = await fetch_unemployment(datatype)
1226 | 
1227 |             case AlphavantageTools.NONFARM_PAYROLL.value:
1228 |                 datatype = arguments.get("datatype", "json")
1229 | 
1230 |                 result = await fetch_nonfarm_payrolls(datatype)
1231 | 
1232 |             case AlphavantageTools.SMA.value:
1233 |                 symbol = arguments.get("symbol")
1234 |                 interval = arguments.get("interval")
1235 |                 month = arguments.get("month")
1236 |                 time_period = arguments.get("time_period")
1237 |                 series_type = arguments.get("series_type")
1238 |                 datatype = arguments.get("datatype", "json")
1239 |                 max_data_points = arguments.get("max_data_points", 100)
1240 | 
1241 |                 if not symbol or not interval or not time_period or not series_type:
1242 |                     raise ValueError(
1243 |                         "Missing required arguments: symbol, interval, time_period, series_type"
1244 |                     )
1245 | 
1246 |                 result = await fetch_sma(
1247 |                     symbol,
1248 |                     interval,
1249 |                     month,
1250 |                     time_period,
1251 |                     series_type,
1252 |                     datatype,
1253 |                     max_data_points,
1254 |                 )
1255 | 
1256 |             case AlphavantageTools.EMA.value:
1257 |                 symbol = arguments.get("symbol")
1258 |                 interval = arguments.get("interval")
1259 |                 month = arguments.get("month")
1260 |                 time_period = arguments.get("time_period")
1261 |                 series_type = arguments.get("series_type")
1262 |                 datatype = arguments.get("datatype", "json")
1263 | 
1264 |                 if not symbol or not interval or not time_period or not series_type:
1265 |                     raise ValueError(
1266 |                         "Missing required arguments: symbol, interval, time_period, series_type"
1267 |                     )
1268 | 
1269 |                 result = await fetch_ema(
1270 |                     symbol, interval, month, time_period, series_type, datatype
1271 |                 )
1272 | 
1273 |             case AlphavantageTools.WMA.value:
1274 |                 symbol = arguments.get("symbol")
1275 |                 interval = arguments.get("interval")
1276 |                 month = arguments.get("month")
1277 |                 time_period = arguments.get("time_period")
1278 |                 series_type = arguments.get("series_type")
1279 |                 datatype = arguments.get("datatype", "json")
1280 | 
1281 |                 if not symbol or not interval or not time_period or not series_type:
1282 |                     raise ValueError(
1283 |                         "Missing required arguments: symbol, interval, time_period, series_type"
1284 |                     )
1285 | 
1286 |                 result = await fetch_wma(
1287 |                     symbol, interval, month, time_period, series_type, datatype
1288 |                 )
1289 | 
1290 |             case AlphavantageTools.DEMA.value:
1291 |                 symbol = arguments.get("symbol")
1292 |                 interval = arguments.get("interval")
1293 |                 month = arguments.get("month")
1294 |                 time_period = arguments.get("time_period")
1295 |                 series_type = arguments.get("series_type")
1296 |                 datatype = arguments.get("datatype", "json")
1297 | 
1298 |                 if not symbol or not interval or not time_period or not series_type:
1299 |                     raise ValueError(
1300 |                         "Missing required arguments: symbol, interval, time_period, series_type"
1301 |                     )
1302 | 
1303 |                 result = await fetch_dema(
1304 |                     symbol, interval, month, time_period, series_type, datatype
1305 |                 )
1306 | 
1307 |             case AlphavantageTools.TEMA.value:
1308 |                 symbol = arguments.get("symbol")
1309 |                 interval = arguments.get("interval")
1310 |                 month = arguments.get("month")
1311 |                 time_period = arguments.get("time_period")
1312 |                 series_type = arguments.get("series_type")
1313 |                 datatype = arguments.get("datatype", "json")
1314 | 
1315 |                 if not symbol or not interval or not time_period or not series_type:
1316 |                     raise ValueError(
1317 |                         "Missing required arguments: symbol, interval, time_period, series_type"
1318 |                     )
1319 | 
1320 |                 result = await fetch_tema(
1321 |                     symbol, interval, month, time_period, series_type, datatype
1322 |                 )
1323 | 
1324 |             case AlphavantageTools.TRIMA.value:
1325 |                 symbol = arguments.get("symbol")
1326 |                 interval = arguments.get("interval")
1327 |                 month = arguments.get("month")
1328 |                 time_period = arguments.get("time_period")
1329 |                 series_type = arguments.get("series_type")
1330 |                 datatype = arguments.get("datatype", "json")
1331 | 
1332 |                 if not symbol or not interval or not time_period or not series_type:
1333 |                     raise ValueError(
1334 |                         "Missing required arguments: symbol, interval, time_period, series_type"
1335 |                     )
1336 | 
1337 |                 result = await fetch_trima(
1338 |                     symbol, interval, month, time_period, series_type, datatype
1339 |                 )
1340 | 
1341 |             case AlphavantageTools.KAMA.value:
1342 |                 symbol = arguments.get("symbol")
1343 |                 interval = arguments.get("interval")
1344 |                 month = arguments.get("month")
1345 |                 time_period = arguments.get("time_period")
1346 |                 series_type = arguments.get("series_type")
1347 |                 datatype = arguments.get("datatype", "json")
1348 | 
1349 |                 if not symbol or not interval or not time_period or not series_type:
1350 |                     raise ValueError(
1351 |                         "Missing required arguments: symbol, interval, time_period, series_type"
1352 |                     )
1353 | 
1354 |                 result = await fetch_kama(
1355 |                     symbol, interval, month, time_period, series_type, datatype
1356 |                 )
1357 | 
1358 |             case AlphavantageTools.MAMA.value:
1359 |                 symbol = arguments.get("symbol")
1360 |                 interval = arguments.get("interval")
1361 |                 month = arguments.get("month")
1362 |                 series_type = arguments.get("series_type")
1363 |                 fastlimit = arguments.get("fastlimit")
1364 |                 slowlimit = arguments.get("slowlimit")
1365 |                 datatype = arguments.get("datatype", "json")
1366 | 
1367 |                 if (
1368 |                     not symbol
1369 |                     or not interval
1370 |                     or not series_type
1371 |                     or not fastlimit
1372 |                     or not slowlimit
1373 |                 ):
1374 |                     raise ValueError(
1375 |                         "Missing required arguments: symbol, interval, series_type, fastlimit, slowlimit"
1376 |                     )
1377 | 
1378 |                 result = await fetch_mama(
1379 |                     symbol, interval, month, series_type, fastlimit, slowlimit, datatype
1380 |                 )
1381 | 
1382 |             case AlphavantageTools.VWAP.value:
1383 |                 symbol = arguments.get("symbol")
1384 |                 interval = arguments.get("interval")
1385 |                 month = arguments.get("month")
1386 |                 datatype = arguments.get("datatype", "json")
1387 | 
1388 |                 if not symbol or not interval:
1389 |                     raise ValueError("Missing required arguments: symbol, interval")
1390 | 
1391 |                 result = await fetch_vwap(symbol, interval, month, datatype)
1392 | 
1393 |             case AlphavantageTools.T3.value:
1394 |                 symbol = arguments.get("symbol")
1395 |                 interval = arguments.get("interval")
1396 |                 month = arguments.get("month")
1397 |                 time_period = arguments.get("time_period")
1398 |                 series_type = arguments.get("series_type")
1399 |                 datatype = arguments.get("datatype", "json")
1400 | 
1401 |                 if not symbol or not interval or not time_period or not series_type:
1402 |                     raise ValueError(
1403 |                         "Missing required arguments: symbol, interval, time_period, series_type"
1404 |                     )
1405 | 
1406 |                 result = await fetch_t3(
1407 |                     symbol, interval, month, time_period, series_type, datatype
1408 |                 )
1409 | 
1410 |             case AlphavantageTools.MACD.value:
1411 |                 symbol = arguments.get("symbol")
1412 |                 interval = arguments.get("interval")
1413 |                 month = arguments.get("month")
1414 |                 series_type = arguments.get("series_type")
1415 |                 fastperiod = arguments.get("fastperiod", 12)
1416 |                 slowperiod = arguments.get("slowperiod", 26)
1417 |                 signalperiod = arguments.get("signalperiod", 9)
1418 |                 datatype = arguments.get("datatype", "json")
1419 | 
1420 |                 if not symbol or not interval or not series_type:
1421 |                     raise ValueError(
1422 |                         "Missing required arguments: symbol, interval, series_type"
1423 |                     )
1424 | 
1425 |                 result = await fetch_macd(
1426 |                     symbol,
1427 |                     interval,
1428 |                     month,
1429 |                     series_type,
1430 |                     fastperiod,
1431 |                     slowperiod,
1432 |                     signalperiod,
1433 |                     datatype,
1434 |                 )
1435 |             case AlphavantageTools.MACDEXT.value:
1436 |                 symbol = arguments.get("symbol")
1437 |                 interval = arguments.get("interval")
1438 |                 month = arguments.get("month")
1439 |                 series_type = arguments.get("series_type")
1440 |                 fastperiod = arguments.get("fastperiod", 12)
1441 |                 slowperiod = arguments.get("slowperiod", 26)
1442 |                 signalperiod = arguments.get("signalperiod", 9)
1443 |                 fastmatype = arguments.get("fastmatype", 0)
1444 |                 slowmatype = arguments.get("slowmatype", 0)
1445 |                 signalmatype = arguments.get("signalmatype", 0)
1446 |                 datatype = arguments.get("datatype", "json")
1447 | 
1448 |                 if not symbol or not interval or not series_type:
1449 |                     raise ValueError(
1450 |                         "Missing required arguments: symbol, interval, series_type"
1451 |                     )
1452 | 
1453 |                 result = await fetch_macdext(
1454 |                     symbol,
1455 |                     interval,
1456 |                     month,
1457 |                     series_type,
1458 |                     fastperiod,
1459 |                     slowperiod,
1460 |                     signalperiod,
1461 |                     fastmatype,
1462 |                     slowmatype,
1463 |                     signalmatype,
1464 |                     datatype,
1465 |                 )
1466 | 
1467 |             case AlphavantageTools.STOCH.value:
1468 |                 symbol = arguments.get("symbol")
1469 |                 interval = arguments.get("interval")
1470 |                 month = arguments.get("month")
1471 |                 fastkperiod = arguments.get("fastkperiod", 5)
1472 |                 slowkperiod = arguments.get("slowkperiod", 3)
1473 |                 slowdperiod = arguments.get("slowdperiod", 3)
1474 |                 slowkmatype = arguments.get("slowkmatype", 0)
1475 |                 slowdmatype = arguments.get("slowdmatype", 0)
1476 |                 datatype = arguments.get("datatype", "json")
1477 | 
1478 |                 if not symbol or not interval:
1479 |                     raise ValueError("Missing required arguments: symbol, interval")
1480 | 
1481 |                 result = await fetch_stoch(
1482 |                     symbol,
1483 |                     interval,
1484 |                     month,
1485 |                     fastkperiod,
1486 |                     slowkperiod,
1487 |                     slowdperiod,
1488 |                     slowkmatype,
1489 |                     slowdmatype,
1490 |                     datatype,
1491 |                 )
1492 | 
1493 |             case AlphavantageTools.STOCHF.value:
1494 |                 symbol = arguments.get("symbol")
1495 |                 interval = arguments.get("interval")
1496 |                 month = arguments.get("month")
1497 |                 fastkperiod = arguments.get("fastkperiod", 5)
1498 |                 fastdperiod = arguments.get("fastdperiod", 3)
1499 |                 fastdmatype = arguments.get("fastdmatype", 0)
1500 |                 datatype = arguments.get("datatype", "json")
1501 | 
1502 |                 if not symbol or not interval:
1503 |                     raise ValueError("Missing required arguments: symbol, interval")
1504 | 
1505 |                 result = await fetch_stochf(
1506 |                     symbol,
1507 |                     interval,
1508 |                     month,
1509 |                     fastkperiod,
1510 |                     fastdperiod,
1511 |                     fastdmatype,
1512 |                     datatype,
1513 |                 )
1514 | 
1515 |             case AlphavantageTools.RSI.value:
1516 |                 symbol = arguments.get("symbol")
1517 |                 interval = arguments.get("interval")
1518 |                 month = arguments.get("month")
1519 |                 time_period = arguments.get("time_period", 14)
1520 |                 series_type = arguments.get("series_type")
1521 |                 datatype = arguments.get("datatype", "json")
1522 | 
1523 |                 if not symbol or not interval or not series_type:
1524 |                     raise ValueError(
1525 |                         "Missing required arguments: symbol, interval, series_type"
1526 |                     )
1527 | 
1528 |                 result = await fetch_rsi(
1529 |                     symbol, interval, month, time_period, series_type, datatype
1530 |                 )
1531 | 
1532 |             case AlphavantageTools.STOCHRSI.value:
1533 |                 symbol = arguments.get("symbol")
1534 |                 interval = arguments.get("interval")
1535 |                 month = arguments.get("month")
1536 |                 time_period = arguments.get("time_period", 14)
1537 |                 series_type = arguments.get("series_type")
1538 |                 fastkperiod = arguments.get("fastkperiod", 5)
1539 |                 fastdperiod = arguments.get("fastdperiod", 3)
1540 |                 fastdmatype = arguments.get("fastdmatype", 0)
1541 |                 datatype = arguments.get("datatype", "json")
1542 | 
1543 |                 if not symbol or not interval or not time_period or not series_type:
1544 |                     raise ValueError(
1545 |                         "Missing required arguments: symbol, interval, time_period, series_type"
1546 |                     )
1547 | 
1548 |                 result = await fetch_stochrsi(
1549 |                     symbol,
1550 |                     interval,
1551 |                     month,
1552 |                     time_period,
1553 |                     series_type,
1554 |                     fastkperiod,
1555 |                     fastdperiod,
1556 |                     fastdmatype,
1557 |                     datatype,
1558 |                 )
1559 | 
1560 |             case AlphavantageTools.WILLR.value:
1561 |                 symbol = arguments.get("symbol")
1562 |                 interval = arguments.get("interval")
1563 |                 month = arguments.get("month")
1564 |                 time_period = arguments.get("time_period", 14)
1565 |                 datatype = arguments.get("datatype", "json")
1566 | 
1567 |                 if not symbol or not interval:
1568 |                     raise ValueError(
1569 |                         "Missing required arguments: symbol, interval, time_period"
1570 |                     )
1571 | 
1572 |                 result = await fetch_willr(
1573 |                     symbol, interval, month, time_period, datatype
1574 |                 )
1575 | 
1576 |             case AlphavantageTools.ADX.value:
1577 |                 symbol = arguments.get("symbol")
1578 |                 interval = arguments.get("interval")
1579 |                 month = arguments.get("month")
1580 |                 time_period = arguments.get("time_period", 14)
1581 |                 datatype = arguments.get("datatype", "json")
1582 | 
1583 |                 if not symbol or not interval:
1584 |                     raise ValueError(
1585 |                         "Missing required arguments: symbol, interval, time_period"
1586 |                     )
1587 | 
1588 |                 result = await fetch_adx(symbol, interval, month, time_period, datatype)
1589 | 
1590 |             case AlphavantageTools.ADXR.value:
1591 |                 symbol = arguments.get("symbol")
1592 |                 interval = arguments.get("interval")
1593 |                 month = arguments.get("month")
1594 |                 time_period = arguments.get("time_period", 14)
1595 |                 datatype = arguments.get("datatype", "json")
1596 | 
1597 |                 if not symbol or not interval:
1598 |                     raise ValueError(
1599 |                         "Missing required arguments: symbol, interval, time_period"
1600 |                     )
1601 | 
1602 |                 result = await fetch_adxr(
1603 |                     symbol, interval, month, time_period, datatype
1604 |                 )
1605 | 
1606 |             case AlphavantageTools.APO.value:
1607 |                 symbol = arguments.get("symbol")
1608 |                 interval = arguments.get("interval")
1609 |                 month = arguments.get("month")
1610 |                 series_type = arguments.get("series_type")
1611 |                 fastperiod = arguments.get("fastperiod", 12)
1612 |                 slowperiod = arguments.get("slowperiod", 26)
1613 |                 matype = arguments.get("matype", 0)
1614 |                 datatype = arguments.get("datatype", "json")
1615 | 
1616 |                 if not symbol or not interval or not series_type:
1617 |                     raise ValueError(
1618 |                         "Missing required arguments: symbol, interval, series_type"
1619 |                     )
1620 | 
1621 |                 result = await fetch_apo(
1622 |                     symbol,
1623 |                     interval,
1624 |                     month,
1625 |                     series_type,
1626 |                     fastperiod,
1627 |                     slowperiod,
1628 |                     matype,
1629 |                     datatype,
1630 |                 )
1631 | 
1632 |             case AlphavantageTools.PPO.value:
1633 |                 symbol = arguments.get("symbol")
1634 |                 interval = arguments.get("interval")
1635 |                 month = arguments.get("month")
1636 |                 series_type = arguments.get("series_type")
1637 |                 fastperiod = arguments.get("fastperiod", 12)
1638 |                 slowperiod = arguments.get("slowperiod", 26)
1639 |                 matype = arguments.get("matype", 0)
1640 |                 datatype = arguments.get("datatype", "json")
1641 | 
1642 |                 if not symbol or not interval or not series_type:
1643 |                     raise ValueError(
1644 |                         "Missing required arguments: symbol, interval, series_type"
1645 |                     )
1646 | 
1647 |                 result = await fetch_ppo(
1648 |                     symbol,
1649 |                     interval,
1650 |                     month,
1651 |                     series_type,
1652 |                     fastperiod,
1653 |                     slowperiod,
1654 |                     matype,
1655 |                     datatype,
1656 |                 )
1657 | 
1658 |             case AlphavantageTools.MOM.value:
1659 |                 symbol = arguments.get("symbol")
1660 |                 interval = arguments.get("interval")
1661 |                 month = arguments.get("month")
1662 |                 time_period = arguments.get("time_period", 10)
1663 |                 series_type = arguments.get("series_type")
1664 |                 datatype = arguments.get("datatype", "json")
1665 | 
1666 |                 if not symbol or not interval or not series_type:
1667 |                     raise ValueError(
1668 |                         "Missing required arguments: symbol, interval, series_type"
1669 |                     )
1670 | 
1671 |                 result = await fetch_mom(
1672 |                     symbol, interval, month, time_period, series_type, datatype
1673 |                 )
1674 | 
1675 |             case AlphavantageTools.BOP.value:
1676 |                 symbol = arguments.get("symbol")
1677 |                 interval = arguments.get("interval")
1678 |                 month = arguments.get("month")
1679 |                 datatype = arguments.get("datatype", "json")
1680 | 
1681 |                 if not symbol or not interval:
1682 |                     raise ValueError("Missing required arguments: symbol, interval")
1683 | 
1684 |                 result = await fetch_bop(symbol, interval, month, datatype)
1685 | 
1686 |             case AlphavantageTools.CCI.value:
1687 |                 symbol = arguments.get("symbol")
1688 |                 interval = arguments.get("interval")
1689 |                 month = arguments.get("month")
1690 |                 time_period = arguments.get("time_period", 20)
1691 |                 datatype = arguments.get("datatype", "json")
1692 | 
1693 |                 if not symbol or not interval:
1694 |                     raise ValueError("Missing required arguments: symbol, interval")
1695 | 
1696 |                 result = await fetch_cci(symbol, interval, month, time_period, datatype)
1697 | 
1698 |             case AlphavantageTools.CMO.value:
1699 |                 symbol = arguments.get("symbol")
1700 |                 interval = arguments.get("interval")
1701 |                 month = arguments.get("month")
1702 |                 time_period = arguments.get("time_period", 14)
1703 |                 datatype = arguments.get("datatype", "json")
1704 | 
1705 |                 if not symbol or not interval:
1706 |                     raise ValueError("Missing required arguments: symbol, interval")
1707 | 
1708 |                 result = await fetch_cmo(symbol, interval, month, time_period, datatype)
1709 | 
1710 |             case AlphavantageTools.ROC.value:
1711 |                 symbol = arguments.get("symbol")
1712 |                 interval = arguments.get("interval")
1713 |                 month = arguments.get("month")
1714 |                 time_period = arguments.get("time_period", 10)
1715 |                 series_type = arguments.get("series_type")
1716 |                 datatype = arguments.get("datatype", "json")
1717 | 
1718 |                 if not symbol or not interval or not series_type:
1719 |                     raise ValueError(
1720 |                         "Missing required arguments: symbol, interval, series_type"
1721 |                     )
1722 | 
1723 |                 result = await fetch_roc(
1724 |                     symbol, interval, month, time_period, series_type, datatype
1725 |                 )
1726 | 
1727 |             case AlphavantageTools.ROCR.value:
1728 |                 symbol = arguments.get("symbol")
1729 |                 interval = arguments.get("interval")
1730 |                 month = arguments.get("month")
1731 |                 time_period = arguments.get("time_period", 10)
1732 |                 series_type = arguments.get("series_type")
1733 |                 datatype = arguments.get("datatype", "json")
1734 | 
1735 |                 if not symbol or not interval or not series_type:
1736 |                     raise ValueError(
1737 |                         "Missing required arguments: symbol, interval, series_type"
1738 |                     )
1739 | 
1740 |                 result = await fetch_rocr(
1741 |                     symbol, interval, month, time_period, series_type, datatype
1742 |                 )
1743 | 
1744 |             case AlphavantageTools.AROON.value:
1745 |                 symbol = arguments.get("symbol")
1746 |                 interval = arguments.get("interval")
1747 |                 month = arguments.get("month")
1748 |                 time_period = arguments.get("time_period", 14)
1749 |                 datatype = arguments.get("datatype", "json")
1750 | 
1751 |                 if not symbol or not interval:
1752 |                     raise ValueError("Missing required arguments: symbol, interval")
1753 | 
1754 |                 result = await fetch_aroon(
1755 |                     symbol, interval, month, time_period, datatype
1756 |                 )
1757 | 
1758 |             case AlphavantageTools.AROONOSC.value:
1759 |                 symbol = arguments.get("symbol")
1760 |                 interval = arguments.get("interval")
1761 |                 month = arguments.get("month")
1762 |                 time_period = arguments.get("time_period", 14)
1763 |                 datatype = arguments.get("datatype", "json")
1764 | 
1765 |                 if not symbol or not interval:
1766 |                     raise ValueError("Missing required arguments: symbol, interval")
1767 | 
1768 |                 result = await fetch_aroonosc(
1769 |                     symbol, interval, month, time_period, datatype
1770 |                 )
1771 | 
1772 |             case AlphavantageTools.MFI.value:
1773 |                 symbol = arguments.get("symbol")
1774 |                 interval = arguments.get("interval")
1775 |                 month = arguments.get("month")
1776 |                 time_period = arguments.get("time_period", 14)
1777 |                 datatype = arguments.get("datatype", "json")
1778 | 
1779 |                 if not symbol or not interval:
1780 |                     raise ValueError("Missing required arguments: symbol, interval")
1781 | 
1782 |                 result = await fetch_mfi(symbol, interval, month, time_period, datatype)
1783 | 
1784 |             case AlphavantageTools.TRIX.value:
1785 |                 symbol = arguments.get("symbol")
1786 |                 interval = arguments.get("interval")
1787 |                 month = arguments.get("month")
1788 |                 time_period = arguments.get("time_period", 30)
1789 |                 series_type = arguments.get("series_type")
1790 |                 datatype = arguments.get("datatype", "json")
1791 | 
1792 |                 if not symbol or not interval or not series_type:
1793 |                     raise ValueError(
1794 |                         "Missing required arguments: symbol, interval, series_type"
1795 |                     )
1796 | 
1797 |                 result = await fetch_trix(
1798 |                     symbol, interval, month, time_period, series_type, datatype
1799 |                 )
1800 | 
1801 |             case AlphavantageTools.ULTOSC.value:
1802 |                 symbol = arguments.get("symbol")
1803 |                 interval = arguments.get("interval")
1804 |                 month = arguments.get("month")
1805 |                 time_period1 = arguments.get("time_period1", 7)
1806 |                 time_period2 = arguments.get("time_period2", 14)
1807 |                 time_period3 = arguments.get("time_period3", 28)
1808 |                 datatype = arguments.get("datatype", "json")
1809 | 
1810 |                 if not symbol or not interval:
1811 |                     raise ValueError("Missing required arguments: symbol, interval")
1812 | 
1813 |                 result = await fetch_ultosc(
1814 |                     symbol,
1815 |                     interval,
1816 |                     month,
1817 |                     time_period1,
1818 |                     time_period2,
1819 |                     time_period3,
1820 |                     datatype,
1821 |                 )
1822 | 
1823 |             case AlphavantageTools.DX.value:
1824 |                 symbol = arguments.get("symbol")
1825 |                 interval = arguments.get("interval")
1826 |                 month = arguments.get("month")
1827 |                 time_period = arguments.get("time_period", 14)
1828 |                 datatype = arguments.get("datatype", "json")
1829 | 
1830 |                 if not symbol or not interval or not time_period:
1831 |                     raise ValueError(
1832 |                         "Missing required arguments: symbol, interval, time_period"
1833 |                     )
1834 | 
1835 |                 result = await fetch_dx(symbol, interval, month, time_period, datatype)
1836 | 
1837 |             case AlphavantageTools.MINUS_DI.value:
1838 |                 symbol = arguments.get("symbol")
1839 |                 interval = arguments.get("interval")
1840 |                 month = arguments.get("month")
1841 |                 time_period = arguments.get("time_period", 14)
1842 |                 datatype = arguments.get("datatype", "json")
1843 | 
1844 |                 if not symbol or not interval or not time_period:
1845 |                     raise ValueError(
1846 |                         "Missing required arguments: symbol, interval, time_period"
1847 |                     )
1848 | 
1849 |                 result = await fetch_minus_di(
1850 |                     symbol, interval, month, time_period, datatype
1851 |                 )
1852 | 
1853 |             case AlphavantageTools.PLUS_DI.value:
1854 |                 symbol = arguments.get("symbol")
1855 |                 interval = arguments.get("interval")
1856 |                 month = arguments.get("month")
1857 |                 time_period = arguments.get("time_period", 14)
1858 |                 datatype = arguments.get("datatype", "json")
1859 | 
1860 |                 if not symbol or not interval or not time_period:
1861 |                     raise ValueError(
1862 |                         "Missing required arguments: symbol, interval, time_period"
1863 |                     )
1864 | 
1865 |                 result = await fetch_plus_di(
1866 |                     symbol, interval, month, time_period, datatype
1867 |                 )
1868 |             case AlphavantageTools.MINUS_DM.value:
1869 |                 symbol = arguments.get("symbol")
1870 |                 interval = arguments.get("interval")
1871 |                 month = arguments.get("month")
1872 |                 time_period = arguments.get("time_period", 14)
1873 |                 datatype = arguments.get("datatype", "json")
1874 | 
1875 |                 if not symbol or not interval or not time_period:
1876 |                     raise ValueError(
1877 |                         "Missing required arguments: symbol, interval, time_period"
1878 |                     )
1879 | 
1880 |                 result = await fetch_minus_dm(
1881 |                     symbol, interval, month, time_period, datatype
1882 |                 )
1883 | 
1884 |             case AlphavantageTools.PLUS_DM.value:
1885 |                 symbol = arguments.get("symbol")
1886 |                 interval = arguments.get("interval")
1887 |                 month = arguments.get("month")
1888 |                 time_period = arguments.get("time_period", 14)
1889 |                 datatype = arguments.get("datatype", "json")
1890 | 
1891 |                 if not symbol or not interval or not time_period:
1892 |                     raise ValueError(
1893 |                         "Missing required arguments: symbol, interval, time_period"
1894 |                     )
1895 | 
1896 |                 result = await fetch_plus_dm(
1897 |                     symbol, interval, month, time_period, datatype
1898 |                 )
1899 | 
1900 |             case AlphavantageTools.BBANDS.value:
1901 |                 symbol = arguments.get("symbol")
1902 |                 interval = arguments.get("interval")
1903 |                 month = arguments.get("month")
1904 |                 time_period = arguments.get("time_period", 20)
1905 |                 series_type = arguments.get("series_type")
1906 |                 nbdevup = arguments.get("nbdevup", 2)
1907 |                 nbdevdn = arguments.get("nbdevdn", 2)
1908 |                 matype = arguments.get("matype", 0)
1909 |                 datatype = arguments.get("datatype", "json")
1910 | 
1911 |                 if not symbol or not interval or not series_type:
1912 |                     raise ValueError(
1913 |                         "Missing required arguments: symbol, interval, series_type"
1914 |                     )
1915 | 
1916 |                 result = await fetch_bbands(
1917 |                     symbol,
1918 |                     interval,
1919 |                     month,
1920 |                     time_period,
1921 |                     series_type,
1922 |                     nbdevup,
1923 |                     nbdevdn,
1924 |                     matype,
1925 |                     datatype,
1926 |                 )
1927 | 
1928 |             case AlphavantageTools.MIDPOINT.value:
1929 |                 symbol = arguments.get("symbol")
1930 |                 interval = arguments.get("interval")
1931 |                 month = arguments.get("month")
1932 |                 time_period = arguments.get("time_period", 14)
1933 |                 series_type = arguments.get("series_type")
1934 |                 datatype = arguments.get("datatype", "json")
1935 | 
1936 |                 if not symbol or not interval or not time_period or not series_type:
1937 |                     raise ValueError(
1938 |                         "Missing required arguments: symbol, interval, time_period, series_type"
1939 |                     )
1940 | 
1941 |                 result = await fetch_midpoint(
1942 |                     symbol, interval, month, time_period, series_type, datatype
1943 |                 )
1944 | 
1945 |             case AlphavantageTools.MIDPRICE.value:
1946 |                 symbol = arguments.get("symbol")
1947 |                 interval = arguments.get("interval")
1948 |                 month = arguments.get("month")
1949 |                 time_period = arguments.get("time_period", 14)
1950 |                 datatype = arguments.get("datatype", "json")
1951 | 
1952 |                 if not symbol or not interval or not time_period:
1953 |                     raise ValueError(
1954 |                         "Missing required arguments: symbol, interval, time_period"
1955 |                     )
1956 | 
1957 |                 result = await fetch_midprice(
1958 |                     symbol, interval, month, time_period, datatype
1959 |                 )
1960 | 
1961 |             case AlphavantageTools.SAR.value:
1962 |                 symbol = arguments.get("symbol")
1963 |                 interval = arguments.get("interval")
1964 |                 month = arguments.get("month")
1965 |                 acceleration = arguments.get("acceleration", 0.02)
1966 |                 maximum = arguments.get("maximum", 0.2)
1967 |                 datatype = arguments.get("datatype", "json")
1968 | 
1969 |                 if not symbol or not interval:
1970 |                     raise ValueError("Missing required arguments: symbol, interval")
1971 | 
1972 |                 result = await fetch_sar(
1973 |                     symbol, interval, month, acceleration, maximum, datatype
1974 |                 )
1975 | 
1976 |             case AlphavantageTools.TRANGE.value:
1977 |                 symbol = arguments.get("symbol")
1978 |                 interval = arguments.get("interval")
1979 |                 month = arguments.get("month")
1980 |                 datatype = arguments.get("datatype", "json")
1981 | 
1982 |                 if not symbol or not interval:
1983 |                     raise ValueError("Missing required arguments: symbol, interval")
1984 | 
1985 |                 result = await fetch_trange(symbol, interval, month, datatype)
1986 | 
1987 |             case AlphavantageTools.ATR.value:
1988 |                 symbol = arguments.get("symbol")
1989 |                 interval = arguments.get("interval")
1990 |                 month = arguments.get("month")
1991 |                 time_period = arguments.get("time_period", 14)
1992 |                 datatype = arguments.get("datatype", "json")
1993 | 
1994 |                 if not symbol or not interval or not time_period:
1995 |                     raise ValueError(
1996 |                         "Missing required arguments: symbol, interval, time_period"
1997 |                     )
1998 | 
1999 |                 result = await fetch_atr(symbol, interval, month, time_period, datatype)
2000 | 
2001 |             case AlphavantageTools.NATR.value:
2002 |                 symbol = arguments.get("symbol")
2003 |                 interval = arguments.get("interval")
2004 |                 month = arguments.get("month")
2005 |                 time_period = arguments.get("time_period", 14)
2006 |                 datatype = arguments.get("datatype", "json")
2007 | 
2008 |                 if not symbol or not interval or not time_period:
2009 |                     raise ValueError(
2010 |                         "Missing required arguments: symbol, interval, time_period"
2011 |                     )
2012 | 
2013 |                 result = await fetch_natr(
2014 |                     symbol, interval, month, time_period, datatype
2015 |                 )
2016 | 
2017 |             case AlphavantageTools.AD.value:
2018 |                 symbol = arguments.get("symbol")
2019 |                 interval = arguments.get("interval")
2020 |                 month = arguments.get("month")
2021 |                 datatype = arguments.get("datatype", "json")
2022 | 
2023 |                 if not symbol or not interval:
2024 |                     raise ValueError("Missing required arguments: symbol, interval")
2025 | 
2026 |                 result = await fetch_ad(symbol, interval, month, datatype)
2027 | 
2028 |             case AlphavantageTools.ADOSC.value:
2029 |                 symbol = arguments.get("symbol")
2030 |                 interval = arguments.get("interval")
2031 |                 month = arguments.get("month")
2032 |                 fastperiod = arguments.get("fastperiod", 3)
2033 |                 slowperiod = arguments.get("slowperiod", 10)
2034 |                 datatype = arguments.get("datatype", "json")
2035 | 
2036 |                 if not symbol or not interval:
2037 |                     raise ValueError("Missing required arguments: symbol, interval")
2038 | 
2039 |                 result = await fetch_adosc(
2040 |                     symbol, interval, month, fastperiod, slowperiod, datatype
2041 |                 )
2042 | 
2043 |             case AlphavantageTools.OBV.value:
2044 |                 symbol = arguments.get("symbol")
2045 |                 interval = arguments.get("interval")
2046 |                 month = arguments.get("month")
2047 |                 datatype = arguments.get("datatype", "json")
2048 | 
2049 |                 if not symbol or not interval:
2050 |                     raise ValueError("Missing required arguments: symbol, interval")
2051 | 
2052 |                 result = await fetch_obv(symbol, interval, month, datatype)
2053 | 
2054 |             case AlphavantageTools.HT_TRENDLINE.value:
2055 |                 symbol = arguments.get("symbol")
2056 |                 interval = arguments.get("interval")
2057 |                 month = arguments.get("month")
2058 |                 series_type = arguments.get("series_type")
2059 |                 datatype = arguments.get("datatype", "json")
2060 | 
2061 |                 if not symbol or not interval or not series_type:
2062 |                     raise ValueError(
2063 |                         "Missing required arguments: symbol, interval, series_type"
2064 |                     )
2065 | 
2066 |                 result = await fetch_ht_trendline(
2067 |                     symbol, interval, month, series_type, datatype
2068 |                 )
2069 | 
2070 |             case AlphavantageTools.HT_SINE.value:
2071 |                 symbol = arguments.get("symbol")
2072 |                 interval = arguments.get("interval")
2073 |                 month = arguments.get("month")
2074 |                 series_type = arguments.get("series_type")
2075 |                 datatype = arguments.get("datatype", "json")
2076 | 
2077 |                 if not symbol or not interval or not series_type:
2078 |                     raise ValueError(
2079 |                         "Missing required arguments: symbol, interval, series_type"
2080 |                     )
2081 | 
2082 |                 result = await fetch_ht_sine(
2083 |                     symbol, interval, month, series_type, datatype
2084 |                 )
2085 | 
2086 |             case AlphavantageTools.HT_TRENDMODE.value:
2087 |                 symbol = arguments.get("symbol")
2088 |                 interval = arguments.get("interval")
2089 |                 month = arguments.get("month")
2090 |                 datatype = arguments.get("datatype", "json")
2091 | 
2092 |                 if not symbol or not interval:
2093 |                     raise ValueError("Missing required arguments: symbol, interval")
2094 | 
2095 |                 result = await fetch_ht_trendmode(symbol, interval, month, datatype)
2096 | 
2097 |             case AlphavantageTools.HT_DCPERIOD.value:
2098 |                 symbol = arguments.get("symbol")
2099 |                 interval = arguments.get("interval")
2100 |                 month = arguments.get("month")
2101 |                 series_types = arguments.get("series_types")
2102 |                 datatype = arguments.get("datatype", "json")
2103 | 
2104 |                 if not symbol or not interval or not series_types:
2105 |                     raise ValueError(
2106 |                         "Missing required arguments: symbol, interval, series_types"
2107 |                     )
2108 | 
2109 |                 result = await fetch_ht_dcperiod(
2110 |                     symbol, interval, month, series_types, datatype
2111 |                 )
2112 | 
2113 |             case AlphavantageTools.HT_DCPHASE.value:
2114 |                 symbol = arguments.get("symbol")
2115 |                 interval = arguments.get("interval")
2116 |                 month = arguments.get("month")
2117 |                 series_types = arguments.get("series_types")
2118 |                 datatype = arguments.get("datatype", "json")
2119 | 
2120 |                 if not symbol or not interval or not series_types:
2121 |                     raise ValueError(
2122 |                         "Missing required arguments: symbol, interval, series_types"
2123 |                     )
2124 | 
2125 |                 result = await fetch_ht_dcphase(
2126 |                     symbol, interval, month, series_types, datatype
2127 |                 )
2128 | 
2129 |             case AlphavantageTools.HT_PHASOR.value:
2130 |                 symbol = arguments.get("symbol")
2131 |                 interval = arguments.get("interval")
2132 |                 month = arguments.get("month")
2133 |                 series_types = arguments.get("series_types")
2134 |                 datatype = arguments.get("datatype", "json")
2135 | 
2136 |                 if not symbol or not interval or not series_types:
2137 |                     raise ValueError(
2138 |                         "Missing required arguments: symbol, interval, series_types"
2139 |                     )
2140 | 
2141 |                 result = await fetch_ht_phasor(
2142 |                     symbol, interval, month, series_types, datatype
2143 |                 )
2144 |             case _:
2145 |                 raise ValueError(f"Unknown tool: {name}")
2146 | 
2147 |         return [types.TextContent(type="text", text=json.dumps(result, indent=2))]
2148 | 
2149 |     except Exception as e:
2150 |         raise ValueError(f"Error processing alphavantage query: {str(e)}") from e
2151 | 
2152 | 
2153 | def get_version():
2154 |     with open("pyproject.toml", "r") as f:
2155 |         pyproject = toml.load(f)
2156 |         return pyproject["project"]["version"]
2157 | 
2158 | 
2159 | async def run_stdio_server():
2160 |     """Run the MCP stdio server"""
2161 |     # Initialize telemetry for stdio transport
2162 |     init_telemetry(start_metrics=True)
2163 | 
2164 |     async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
2165 |         await server.run(
2166 |             read_stream,
2167 |             write_stream,
2168 |             InitializationOptions(
2169 |                 server_name="alphavantage",
2170 |                 server_version=get_version(),
2171 |                 capabilities=server.get_capabilities(
2172 |                     notification_options=NotificationOptions(),
2173 |                     experimental_capabilities={},
2174 |                 ),
2175 |             ),
2176 |         )
2177 | 
2178 | 
2179 | async def run_streamable_http_server(port=8080, oauth_enabled=False):
2180 |     """Run the Streamable HTTP server on the specified port"""
2181 | 
2182 |     # Initialize telemetry for HTTP transport
2183 |     init_telemetry(start_metrics=True)
2184 | 
2185 |     transport = StreamableHTTPServerTransport(
2186 |         mcp_session_id=None, is_json_response_enabled=True
2187 |     )
2188 | 
2189 |     # Setup OAuth if enabled
2190 |     oauth_server = None
2191 |     if oauth_enabled:
2192 |         oauth_config = create_oauth_config_from_env()
2193 |         if oauth_config:
2194 |             oauth_server = OAuthResourceServer(oauth_config)
2195 |             logger.info(
2196 |                 f"OAuth enabled for resource server: {oauth_config.resource_server_uri}"
2197 |             )
2198 |         else:
2199 |             logger.warning(
2200 |                 "OAuth requested but no configuration found. Running without OAuth."
2201 |             )
2202 | 
2203 |     async with transport.connect() as (read_stream, write_stream):
2204 |         server_task = asyncio.create_task(
2205 |             server.run(
2206 |                 read_stream,
2207 |                 write_stream,
2208 |                 InitializationOptions(
2209 |                     server_name="alphavantage",
2210 |                     server_version=get_version(),
2211 |                     capabilities=server.get_capabilities(
2212 |                         notification_options=NotificationOptions(),
2213 |                         experimental_capabilities={},
2214 |                     ),
2215 |                 ),
2216 |             )
2217 |         )
2218 | 
2219 |         # Create OAuth-enhanced ASGI app wrapper for the transport
2220 |         async def asgi_app(scope, receive, send):
2221 |             if scope["type"] != "http":
2222 |                 return await send_404(send)
2223 | 
2224 |             path = scope["path"]
2225 |             request = Request(scope, receive)
2226 | 
2227 |             # Handle OAuth metadata endpoint if OAuth is enabled
2228 |             if oauth_server and path == oauth_server.config.resource_metadata_path:
2229 |                 response = await oauth_server.handle_resource_metadata_request(request)
2230 |                 return await send_starlette_response(response, send)
2231 | 
2232 |             # Handle MCP requests
2233 |             elif path.startswith("/mcp"):
2234 |                 # OAuth authentication if enabled
2235 |                 if oauth_server:
2236 |                     # Extract session ID from request if present
2237 |                     session_id = request.headers.get("X-Session-ID")
2238 | 
2239 |                     (
2240 |                         is_authenticated,
2241 |                         validation_result,
2242 |                     ) = await oauth_server.authenticate_request(request, session_id)
2243 | 
2244 |                     if not is_authenticated:
2245 |                         # Return appropriate error response
2246 |                         if (
2247 |                             validation_result
2248 |                             and validation_result.error == "Insufficient scopes"
2249 |                         ):
2250 |                             response = await oauth_server.create_forbidden_response(
2251 |                                 error="insufficient_scope",
2252 |                                 description="Required scopes not present in token",
2253 |                             )
2254 |                         else:
2255 |                             error_desc = (
2256 |                                 validation_result.error
2257 |                                 if validation_result
2258 |                                 else "No valid token provided"
2259 |                             )
2260 |                             response = await oauth_server.create_unauthorized_response(
2261 |                                 error="invalid_token", description=error_desc
2262 |                             )
2263 |                         return await send_starlette_response(response, send)
2264 | 
2265 |                     # Log successful authentication
2266 |                     logger.info(
2267 |                         f"Authenticated MCP request for user: {validation_result.subject}"
2268 |                     )
2269 | 
2270 |                 # Process MCP request
2271 |                 try:
2272 |                     await transport.handle_request(scope, receive, send)
2273 |                 except Exception as e:
2274 |                     logger.error(f"Error handling MCP request: {e}")
2275 |                     await send_error_response(send, 500, "Internal Server Error")
2276 | 
2277 |             else:
2278 |                 # Return 404 for unknown paths
2279 |                 await send_404(send)
2280 | 
2281 |         config = uvicorn.Config(asgi_app, host="localhost", port=port)
2282 |         uvicorn_server = uvicorn.Server(config)
2283 |         http_task = asyncio.create_task(uvicorn_server.serve())
2284 | 
2285 |         try:
2286 |             await asyncio.gather(server_task, http_task)
2287 |         finally:
2288 |             # Cleanup OAuth resources
2289 |             if oauth_server:
2290 |                 await oauth_server.cleanup()
2291 | 
2292 | 
2293 | async def send_starlette_response(response: Response, send):
2294 |     """Send a Starlette Response through ASGI send callable."""
2295 |     await send(
2296 |         {
2297 |             "type": "http.response.start",
2298 |             "status": response.status_code,
2299 |             "headers": [
2300 |                 [key.encode(), value.encode()]
2301 |                 for key, value in response.headers.items()
2302 |             ],
2303 |         }
2304 |     )
2305 | 
2306 |     # Handle different response types
2307 |     if hasattr(response, "body"):
2308 |         body = response.body
2309 |     elif hasattr(response, "content"):
2310 |         body = response.content
2311 |     else:
2312 |         body = b""
2313 | 
2314 |     await send(
2315 |         {
2316 |             "type": "http.response.body",
2317 |             "body": body,
2318 |         }
2319 |     )
2320 | 
2321 | 
2322 | async def send_404(send):
2323 |     """Send a 404 Not Found response."""
2324 |     await send(
2325 |         {
2326 |             "type": "http.response.start",
2327 |             "status": 404,
2328 |             "headers": [[b"content-type", b"text/plain"]],
2329 |         }
2330 |     )
2331 |     await send(
2332 |         {
2333 |             "type": "http.response.body",
2334 |             "body": b"Not Found",
2335 |         }
2336 |     )
2337 | 
2338 | 
2339 | async def send_error_response(send, status_code: int, message: str):
2340 |     """Send an error response."""
2341 |     await send(
2342 |         {
2343 |             "type": "http.response.start",
2344 |             "status": status_code,
2345 |             "headers": [[b"content-type", b"text/plain"]],
2346 |         }
2347 |     )
2348 |     await send(
2349 |         {
2350 |             "type": "http.response.body",
2351 |             "body": message.encode(),
2352 |         }
2353 |     )
2354 | 
2355 | 
2356 | async def main(server_type="stdio", port=8080, oauth_enabled=False):
2357 |     """Main entry point with server type selection"""
2358 |     if server_type == "http":
2359 |         if oauth_enabled:
2360 |             logger.info(f"Starting Streamable HTTP server with OAuth on port {port}")
2361 |         else:
2362 |             logger.info(f"Starting Streamable HTTP server on port {port}")
2363 |         await run_streamable_http_server(port=port, oauth_enabled=oauth_enabled)
2364 |     else:
2365 |         logger.info("Starting stdio server")
2366 |         await run_stdio_server()
2367 | 
```
Page 3/4FirstPrevNextLast