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
│ ├── __main__.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 | from importlib.metadata import version, PackageNotFoundError
5 |
6 | import mcp.server.stdio
7 | import mcp.types as types
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 | """Get the package version from installed metadata."""
2155 | try:
2156 | return version("alphavantage-mcp")
2157 | except PackageNotFoundError:
2158 | # Fallback version if package is not installed (e.g., during development)
2159 | return "0.0.0-dev"
2160 |
2161 |
2162 | async def run_stdio_server():
2163 | """Run the MCP stdio server"""
2164 | # Initialize telemetry for stdio transport
2165 | init_telemetry(start_metrics=True)
2166 |
2167 | async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
2168 | await server.run(
2169 | read_stream,
2170 | write_stream,
2171 | InitializationOptions(
2172 | server_name="alphavantage",
2173 | server_version=get_version(),
2174 | capabilities=server.get_capabilities(
2175 | notification_options=NotificationOptions(),
2176 | experimental_capabilities={},
2177 | ),
2178 | ),
2179 | )
2180 |
2181 |
2182 | async def run_streamable_http_server(port=8080, oauth_enabled=False):
2183 | """Run the Streamable HTTP server on the specified port"""
2184 |
2185 | # Initialize telemetry for HTTP transport
2186 | init_telemetry(start_metrics=True)
2187 |
2188 | transport = StreamableHTTPServerTransport(
2189 | mcp_session_id=None, is_json_response_enabled=True
2190 | )
2191 |
2192 | # Setup OAuth if enabled
2193 | oauth_server = None
2194 | if oauth_enabled:
2195 | oauth_config = create_oauth_config_from_env()
2196 | if oauth_config:
2197 | oauth_server = OAuthResourceServer(oauth_config)
2198 | logger.info(
2199 | f"OAuth enabled for resource server: {oauth_config.resource_server_uri}"
2200 | )
2201 | else:
2202 | logger.warning(
2203 | "OAuth requested but no configuration found. Running without OAuth."
2204 | )
2205 |
2206 | async with transport.connect() as (read_stream, write_stream):
2207 | server_task = asyncio.create_task(
2208 | server.run(
2209 | read_stream,
2210 | write_stream,
2211 | InitializationOptions(
2212 | server_name="alphavantage",
2213 | server_version=get_version(),
2214 | capabilities=server.get_capabilities(
2215 | notification_options=NotificationOptions(),
2216 | experimental_capabilities={},
2217 | ),
2218 | ),
2219 | )
2220 | )
2221 |
2222 | # Create OAuth-enhanced ASGI app wrapper for the transport
2223 | async def asgi_app(scope, receive, send):
2224 | if scope["type"] != "http":
2225 | return await send_404(send)
2226 |
2227 | path = scope["path"]
2228 | request = Request(scope, receive)
2229 |
2230 | # Handle OAuth metadata endpoint if OAuth is enabled
2231 | if oauth_server and path == oauth_server.config.resource_metadata_path:
2232 | response = await oauth_server.handle_resource_metadata_request(request)
2233 | return await send_starlette_response(response, send)
2234 |
2235 | # Handle MCP requests
2236 | elif path.startswith("/mcp"):
2237 | # OAuth authentication if enabled
2238 | if oauth_server:
2239 | # Extract session ID from request if present
2240 | session_id = request.headers.get("X-Session-ID")
2241 |
2242 | (
2243 | is_authenticated,
2244 | validation_result,
2245 | ) = await oauth_server.authenticate_request(request, session_id)
2246 |
2247 | if not is_authenticated:
2248 | # Return appropriate error response
2249 | if (
2250 | validation_result
2251 | and validation_result.error == "Insufficient scopes"
2252 | ):
2253 | response = await oauth_server.create_forbidden_response(
2254 | error="insufficient_scope",
2255 | description="Required scopes not present in token",
2256 | )
2257 | else:
2258 | error_desc = (
2259 | validation_result.error
2260 | if validation_result
2261 | else "No valid token provided"
2262 | )
2263 | response = await oauth_server.create_unauthorized_response(
2264 | error="invalid_token", description=error_desc
2265 | )
2266 | return await send_starlette_response(response, send)
2267 |
2268 | # Log successful authentication
2269 | logger.info(
2270 | f"Authenticated MCP request for user: {validation_result.subject}"
2271 | )
2272 |
2273 | # Process MCP request
2274 | try:
2275 | await transport.handle_request(scope, receive, send)
2276 | except Exception as e:
2277 | logger.error(f"Error handling MCP request: {e}")
2278 | await send_error_response(send, 500, "Internal Server Error")
2279 |
2280 | else:
2281 | # Return 404 for unknown paths
2282 | await send_404(send)
2283 |
2284 | config = uvicorn.Config(asgi_app, host="localhost", port=port)
2285 | uvicorn_server = uvicorn.Server(config)
2286 | http_task = asyncio.create_task(uvicorn_server.serve())
2287 |
2288 | try:
2289 | await asyncio.gather(server_task, http_task)
2290 | finally:
2291 | # Cleanup OAuth resources
2292 | if oauth_server:
2293 | await oauth_server.cleanup()
2294 |
2295 |
2296 | async def send_starlette_response(response: Response, send):
2297 | """Send a Starlette Response through ASGI send callable."""
2298 | await send(
2299 | {
2300 | "type": "http.response.start",
2301 | "status": response.status_code,
2302 | "headers": [
2303 | [key.encode(), value.encode()]
2304 | for key, value in response.headers.items()
2305 | ],
2306 | }
2307 | )
2308 |
2309 | # Handle different response types
2310 | if hasattr(response, "body"):
2311 | body = response.body
2312 | elif hasattr(response, "content"):
2313 | body = response.content
2314 | else:
2315 | body = b""
2316 |
2317 | await send(
2318 | {
2319 | "type": "http.response.body",
2320 | "body": body,
2321 | }
2322 | )
2323 |
2324 |
2325 | async def send_404(send):
2326 | """Send a 404 Not Found response."""
2327 | await send(
2328 | {
2329 | "type": "http.response.start",
2330 | "status": 404,
2331 | "headers": [[b"content-type", b"text/plain"]],
2332 | }
2333 | )
2334 | await send(
2335 | {
2336 | "type": "http.response.body",
2337 | "body": b"Not Found",
2338 | }
2339 | )
2340 |
2341 |
2342 | async def send_error_response(send, status_code: int, message: str):
2343 | """Send an error response."""
2344 | await send(
2345 | {
2346 | "type": "http.response.start",
2347 | "status": status_code,
2348 | "headers": [[b"content-type", b"text/plain"]],
2349 | }
2350 | )
2351 | await send(
2352 | {
2353 | "type": "http.response.body",
2354 | "body": message.encode(),
2355 | }
2356 | )
2357 |
2358 |
2359 | async def main(server_type="stdio", port=8080, oauth_enabled=False):
2360 | """Main entry point with server type selection"""
2361 | if server_type == "http":
2362 | if oauth_enabled:
2363 | logger.info(f"Starting Streamable HTTP server with OAuth on port {port}")
2364 | else:
2365 | logger.info(f"Starting Streamable HTTP server on port {port}")
2366 | await run_streamable_http_server(port=port, oauth_enabled=oauth_enabled)
2367 | else:
2368 | logger.info("Starting stdio server")
2369 | await run_stdio_server()
2370 |
```