diff --git a/pyproject.toml b/pyproject.toml index 002a13b..a043d74 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,13 @@ [project] name = "mcp_massive" -version = "0.6.0" +version = "0.7.0" description = "A MCP server project" readme = "README.md" requires-python = ">=3.10" dependencies = [ "mcp[cli]>=1.15.0", - "polygon-api-client>=1.15.4", + "massive>=2.0.1", + "python-dotenv>=1.2.0", ] [[project.authors]] name = "Massive" diff --git a/src/mcp_massive/__init__.py b/src/mcp_massive/__init__.py index e828ba6..989ca37 100644 --- a/src/mcp_massive/__init__.py +++ b/src/mcp_massive/__init__.py @@ -1,7 +1,11 @@ import os from typing import Literal +from dotenv import load_dotenv from .server import run +# Load environment variables from .env file if it exists +load_dotenv() + __all__ = ["run", "main"] diff --git a/src/mcp_massive/formatters.py b/src/mcp_massive/formatters.py index bb8f49f..55fe5f3 100644 --- a/src/mcp_massive/formatters.py +++ b/src/mcp_massive/formatters.py @@ -18,18 +18,40 @@ def json_to_csv(json_input: str | dict) -> str: """ # Parse JSON if it's a string if isinstance(json_input, str): - data = json.loads(json_input) + try: + data = json.loads(json_input) + except json.JSONDecodeError: + # If JSON parsing fails, return empty CSV + return "" else: data = json_input if isinstance(data, dict) and "results" in data: - records = data["results"] + results_value = data["results"] + # Handle both list and single object responses + if isinstance(results_value, list): + records = results_value + elif isinstance(results_value, dict): + # Single object response (e.g., get_last_trade returns results as object) + records = [results_value] + else: + records = [results_value] + elif isinstance(data, dict) and "last" in data: + # Handle responses with "last" key (e.g., get_last_trade, get_last_quote) + records = [data["last"]] if isinstance(data["last"], dict) else [data] elif isinstance(data, list): records = data else: records = [data] - flattened_records = [_flatten_dict(record) for record in records] + # Only flatten dict records, skip non-dict items + flattened_records = [] + for record in records: + if isinstance(record, dict): + flattened_records.append(_flatten_dict(record)) + else: + # If it's not a dict, wrap it in a dict with a 'value' key + flattened_records.append({"value": str(record)}) if not flattened_records: return "" @@ -38,10 +60,11 @@ def json_to_csv(json_input: str | dict) -> str: all_keys = [] seen = set() for record in flattened_records: - for key in record.keys(): - if key not in seen: - all_keys.append(key) - seen.add(key) + if isinstance(record, dict): + for key in record.keys(): + if key not in seen: + all_keys.append(key) + seen.add(key) output = io.StringIO() writer = csv.DictWriter(output, fieldnames=all_keys, lineterminator="\n") diff --git a/src/mcp_massive/server.py b/src/mcp_massive/server.py index 7e798c2..6ec2528 100644 --- a/src/mcp_massive/server.py +++ b/src/mcp_massive/server.py @@ -2,15 +2,20 @@ from typing import Optional, Any, Dict, Union, List, Literal from mcp.server.fastmcp import FastMCP from mcp.types import ToolAnnotations -from polygon import RESTClient +from massive import RESTClient from importlib.metadata import version, PackageNotFoundError +from dotenv import load_dotenv from .formatters import json_to_csv from datetime import datetime, date +# Load environment variables from .env file if it exists +load_dotenv() + MASSIVE_API_KEY = os.environ.get("MASSIVE_API_KEY", "") if not MASSIVE_API_KEY: print("Warning: MASSIVE_API_KEY environment variable not set.") + print("Please set it in your environment or create a .env file with MASSIVE_API_KEY=your_key") version_number = "MCP-Massive/unknown" try: @@ -18,8 +23,8 @@ except PackageNotFoundError: pass -polygon_client = RESTClient(MASSIVE_API_KEY) -polygon_client.headers["User-Agent"] += f" {version_number}" +massive_client = RESTClient(MASSIVE_API_KEY) +massive_client.headers["User-Agent"] += f" {version_number}" poly_mcp = FastMCP("Massive") @@ -40,7 +45,7 @@ async def get_aggs( List aggregate bars for a ticker over a given date range in custom time window sizes. """ try: - results = polygon_client.get_aggs( + results = massive_client.get_aggs( ticker=ticker, multiplier=multiplier, timespan=timespan, @@ -75,7 +80,7 @@ async def list_aggs( Iterate through aggregate bars for a ticker over a given date range. """ try: - results = polygon_client.list_aggs( + results = massive_client.list_aggs( ticker=ticker, multiplier=multiplier, timespan=timespan, @@ -106,7 +111,7 @@ async def get_grouped_daily_aggs( Get grouped daily bars for entire market for a specific date. """ try: - results = polygon_client.get_grouped_daily_aggs( + results = massive_client.get_grouped_daily_aggs( date=date, adjusted=adjusted, include_otc=include_otc, @@ -132,7 +137,7 @@ async def get_daily_open_close_agg( Get daily open, close, high, and low for a specific ticker and date. """ try: - results = polygon_client.get_daily_open_close_agg( + results = massive_client.get_daily_open_close_agg( ticker=ticker, date=date, adjusted=adjusted, params=params, raw=True ) @@ -151,7 +156,7 @@ async def get_previous_close_agg( Get previous day's open, close, high, and low for a specific ticker. """ try: - results = polygon_client.get_previous_close_agg( + results = massive_client.get_previous_close_agg( ticker=ticker, adjusted=adjusted, params=params, raw=True ) @@ -177,7 +182,7 @@ async def list_trades( Get trades for a ticker symbol. """ try: - results = polygon_client.list_trades( + results = massive_client.list_trades( ticker=ticker, timestamp=timestamp, timestamp_lt=timestamp_lt, @@ -199,14 +204,12 @@ async def list_trades( @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True)) async def get_last_trade( ticker: str, - params: Optional[Dict[str, Any]] = None, ) -> str: """ Get the most recent trade for a ticker symbol. """ try: - results = polygon_client.get_last_trade(ticker=ticker, params=params, raw=True) - + results = massive_client.get_last_trade(ticker=ticker, raw=True) return json_to_csv(results.data.decode("utf-8")) except Exception as e: return f"Error: {e}" @@ -222,7 +225,7 @@ async def get_last_crypto_trade( Get the most recent trade for a crypto pair. """ try: - results = polygon_client.get_last_crypto_trade( + results = massive_client.get_last_crypto_trade( from_=from_, to=to, params=params, raw=True ) @@ -248,7 +251,7 @@ async def list_quotes( Get quotes for a ticker symbol. """ try: - results = polygon_client.list_quotes( + results = massive_client.list_quotes( ticker=ticker, timestamp=timestamp, timestamp_lt=timestamp_lt, @@ -276,7 +279,7 @@ async def get_last_quote( Get the most recent quote for a ticker symbol. """ try: - results = polygon_client.get_last_quote(ticker=ticker, params=params, raw=True) + results = massive_client.get_last_quote(ticker=ticker, params=params, raw=True) return json_to_csv(results.data.decode("utf-8")) except Exception as e: @@ -293,7 +296,7 @@ async def get_last_forex_quote( Get the most recent forex quote. """ try: - results = polygon_client.get_last_forex_quote( + results = massive_client.get_last_forex_quote( from_=from_, to=to, params=params, raw=True ) @@ -314,7 +317,7 @@ async def get_real_time_currency_conversion( Get real-time currency conversion. """ try: - results = polygon_client.get_real_time_currency_conversion( + results = massive_client.get_real_time_currency_conversion( from_=from_, to=to, amount=amount, @@ -341,7 +344,7 @@ async def list_universal_snapshots( Get universal snapshots for multiple assets of a specific type. """ try: - results = polygon_client.list_universal_snapshots( + results = massive_client.list_universal_snapshots( type=type, ticker_any_of=ticker_any_of, order=order, @@ -367,7 +370,7 @@ async def get_snapshot_all( Get a snapshot of all tickers in a market. """ try: - results = polygon_client.get_snapshot_all( + results = massive_client.get_snapshot_all( market_type=market_type, tickers=tickers, include_otc=include_otc, @@ -391,7 +394,7 @@ async def get_snapshot_direction( Get gainers or losers for a market. """ try: - results = polygon_client.get_snapshot_direction( + results = massive_client.get_snapshot_direction( market_type=market_type, direction=direction, include_otc=include_otc, @@ -414,7 +417,7 @@ async def get_snapshot_ticker( Get snapshot for a specific ticker. """ try: - results = polygon_client.get_snapshot_ticker( + results = massive_client.get_snapshot_ticker( market_type=market_type, ticker=ticker, params=params, raw=True ) @@ -433,7 +436,7 @@ async def get_snapshot_option( Get snapshot for a specific option contract. """ try: - results = polygon_client.get_snapshot_option( + results = massive_client.get_snapshot_option( underlying_asset=underlying_asset, option_contract=option_contract, params=params, @@ -454,7 +457,7 @@ async def get_snapshot_crypto_book( Get snapshot for a crypto ticker's order book. """ try: - results = polygon_client.get_snapshot_crypto_book( + results = massive_client.get_snapshot_crypto_book( ticker=ticker, params=params, raw=True ) @@ -471,7 +474,7 @@ async def get_market_holidays( Get upcoming market holidays and their open/close times. """ try: - results = polygon_client.get_market_holidays(params=params, raw=True) + results = massive_client.get_market_holidays(params=params, raw=True) return json_to_csv(results.data.decode("utf-8")) except Exception as e: @@ -486,7 +489,7 @@ async def get_market_status( Get current trading status of exchanges and financial markets. """ try: - results = polygon_client.get_market_status(params=params, raw=True) + results = massive_client.get_market_status(params=params, raw=True) return json_to_csv(results.data.decode("utf-8")) except Exception as e: @@ -513,7 +516,7 @@ async def list_tickers( Query supported ticker symbols across stocks, indices, forex, and crypto. """ try: - results = polygon_client.list_tickers( + results = massive_client.list_tickers( ticker=ticker, type=type, market=market, @@ -545,7 +548,7 @@ async def get_ticker_details( Get detailed information about a specific ticker. """ try: - results = polygon_client.get_ticker_details( + results = massive_client.get_ticker_details( ticker=ticker, date=date, params=params, raw=True ) @@ -567,7 +570,7 @@ async def list_ticker_news( Get recent news articles for a stock ticker. """ try: - results = polygon_client.list_ticker_news( + results = massive_client.list_ticker_news( ticker=ticker, published_utc=published_utc, limit=limit, @@ -592,7 +595,7 @@ async def get_ticker_types( List all ticker types supported by Massive.com. """ try: - results = polygon_client.get_ticker_types( + results = massive_client.get_ticker_types( asset_class=asset_class, locale=locale, params=params, raw=True ) @@ -613,7 +616,7 @@ async def list_splits( Get historical stock splits. """ try: - results = polygon_client.list_splits( + results = massive_client.list_splits( ticker=ticker, execution_date=execution_date, reverse_split=reverse_split, @@ -640,7 +643,7 @@ async def list_dividends( Get historical cash dividends. """ try: - results = polygon_client.list_dividends( + results = massive_client.list_dividends( ticker=ticker, ex_dividend_date=ex_dividend_date, frequency=frequency, @@ -667,7 +670,7 @@ async def list_conditions( List conditions used by Massive.com. """ try: - results = polygon_client.list_conditions( + results = massive_client.list_conditions( asset_class=asset_class, data_type=data_type, id=id, @@ -691,7 +694,7 @@ async def get_exchanges( List exchanges known by Massive.com. """ try: - results = polygon_client.get_exchanges( + results = massive_client.get_exchanges( asset_class=asset_class, locale=locale, params=params, raw=True ) @@ -728,7 +731,7 @@ async def list_stock_financials( Get fundamental financial data for companies. """ try: - results = polygon_client.vx.list_stock_financials( + results = massive_client.vx.list_stock_financials( ticker=ticker, cik=cik, company_name=company_name, @@ -776,7 +779,7 @@ async def list_ipos( Retrieve upcoming or historical IPOs. """ try: - results = polygon_client.vx.list_ipos( + results = massive_client.vx.list_ipos( ticker=ticker, listing_date=listing_date, listing_date_lt=listing_date_lt, @@ -813,7 +816,7 @@ async def list_short_interest( Retrieve short interest data for stocks. """ try: - results = polygon_client.list_short_interest( + results = massive_client.list_short_interest( ticker=ticker, settlement_date=settlement_date, settlement_date_lt=settlement_date_lt, @@ -849,7 +852,7 @@ async def list_short_volume( Retrieve short volume data for stocks. """ try: - results = polygon_client.list_short_volume( + results = massive_client.list_short_volume( ticker=ticker, date=date, date_lt=date_lt, @@ -885,7 +888,7 @@ async def list_treasury_yields( Retrieve treasury yield data. """ try: - results = polygon_client.list_treasury_yields( + results = massive_client.list_treasury_yields( date=date, date_lt=date_lt, date_lte=date_lte, @@ -919,7 +922,7 @@ async def list_inflation( Get inflation data from the Federal Reserve. """ try: - results = polygon_client.list_inflation( + results = massive_client.list_inflation( date=date, date_any_of=date_any_of, date_gt=date_gt, @@ -989,7 +992,7 @@ async def list_benzinga_analyst_insights( List Benzinga analyst insights. """ try: - results = polygon_client.list_benzinga_analyst_insights( + results = massive_client.list_benzinga_analyst_insights( date=date, date_any_of=date_any_of, date_gt=date_gt, @@ -1077,7 +1080,7 @@ async def list_benzinga_analysts( List Benzinga analysts. """ try: - results = polygon_client.list_benzinga_analysts( + results = massive_client.list_benzinga_analysts( benzinga_id=benzinga_id, benzinga_id_any_of=benzinga_id_any_of, benzinga_id_gt=benzinga_id_gt, @@ -1128,7 +1131,7 @@ async def list_benzinga_consensus_ratings( List Benzinga consensus ratings for a ticker. """ try: - results = polygon_client.list_benzinga_consensus_ratings( + results = massive_client.list_benzinga_consensus_ratings( ticker=ticker, date=date, date_gt=date_gt, @@ -1209,7 +1212,7 @@ async def list_benzinga_earnings( List Benzinga earnings. """ try: - results = polygon_client.list_benzinga_earnings( + results = massive_client.list_benzinga_earnings( date=date, date_any_of=date_any_of, date_gt=date_gt, @@ -1291,7 +1294,7 @@ async def list_benzinga_firms( List Benzinga firms. """ try: - results = polygon_client.list_benzinga_firms( + results = massive_client.list_benzinga_firms( benzinga_id=benzinga_id, benzinga_id_any_of=benzinga_id_any_of, benzinga_id_gt=benzinga_id_gt, @@ -1361,7 +1364,7 @@ async def list_benzinga_guidance( List Benzinga guidance. """ try: - results = polygon_client.list_benzinga_guidance( + results = massive_client.list_benzinga_guidance( date=date, date_any_of=date_any_of, date_gt=date_gt, @@ -1418,71 +1421,48 @@ async def list_benzinga_guidance( @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True)) async def list_benzinga_news( published: Optional[str] = None, - published_any_of: Optional[str] = None, - published_gt: Optional[str] = None, - published_gte: Optional[str] = None, - published_lt: Optional[str] = None, - published_lte: Optional[str] = None, - last_updated: Optional[str] = None, - last_updated_any_of: Optional[str] = None, - last_updated_gt: Optional[str] = None, - last_updated_gte: Optional[str] = None, - last_updated_lt: Optional[str] = None, - last_updated_lte: Optional[str] = None, - tickers: Optional[str] = None, - tickers_all_of: Optional[str] = None, - tickers_any_of: Optional[str] = None, channels: Optional[str] = None, - channels_all_of: Optional[str] = None, - channels_any_of: Optional[str] = None, tags: Optional[str] = None, - tags_all_of: Optional[str] = None, - tags_any_of: Optional[str] = None, author: Optional[str] = None, - author_any_of: Optional[str] = None, - author_gt: Optional[str] = None, - author_gte: Optional[str] = None, - author_lt: Optional[str] = None, - author_lte: Optional[str] = None, - limit: Optional[int] = 10, + stocks: Optional[str] = None, + tickers: Optional[str] = None, + limit: Optional[int] = 100, sort: Optional[str] = None, - params: Optional[Dict[str, Any]] = None, ) -> str: """ - List Benzinga news. + Retrieve real-time structured, timestamped news articles from Benzinga v2 API, including headlines, + full-text content, tickers, categories, and more. Each article entry contains metadata such as author, + publication time, and topic channels, as well as optional elements like teaser summaries, article body text, + and images. Articles can be filtered by ticker and time, and are returned in a consistent format for easy + parsing and integration. This endpoint is ideal for building alerting systems, autonomous risk analysis, + and sentiment-driven trading strategies. + + Args: + published: The timestamp (formatted as an ISO 8601 timestamp) when the news article was originally + published. Value must be an integer timestamp in seconds or formatted 'yyyy-mm-dd'. + channels: Filter for arrays that contain the value (e.g., 'News', 'Price Target'). + tags: Filter for arrays that contain the value. + author: The name of the journalist or entity that authored the news article. + stocks: Filter for arrays that contain the value. + tickers: Filter for arrays that contain the value. + limit: Limit the maximum number of results returned. Defaults to 100 if not specified. + The maximum allowed limit is 50000. + sort: A comma separated list of sort columns. For each column, append '.asc' or '.desc' to specify + the sort direction. The sort column defaults to 'published' if not specified. + The sort order defaults to 'desc' if not specified. """ try: - results = polygon_client.list_benzinga_news( + # Use the v2-specific method from the massive client library + # This calls the /benzinga/v2/news endpoint + results = massive_client.list_benzinga_news_v2( published=published, - published_any_of=published_any_of, - published_gt=published_gt, - published_gte=published_gte, - published_lt=published_lt, - published_lte=published_lte, - last_updated=last_updated, - last_updated_any_of=last_updated_any_of, - last_updated_gt=last_updated_gt, - last_updated_gte=last_updated_gte, - last_updated_lt=last_updated_lt, - last_updated_lte=last_updated_lte, - tickers=tickers, - tickers_all_of=tickers_all_of, - tickers_any_of=tickers_any_of, channels=channels, - channels_all_of=channels_all_of, - channels_any_of=channels_any_of, tags=tags, - tags_all_of=tags_all_of, - tags_any_of=tags_any_of, author=author, - author_any_of=author_any_of, - author_gt=author_gt, - author_gte=author_gte, - author_lt=author_lt, - author_lte=author_lte, + stocks=stocks, + tickers=tickers, limit=limit, sort=sort, - params=params, raw=True, ) @@ -1555,7 +1535,7 @@ async def list_benzinga_ratings( List Benzinga ratings. """ try: - results = polygon_client.list_benzinga_ratings( + results = massive_client.list_benzinga_ratings( date=date, date_any_of=date_any_of, date_gt=date_gt, @@ -1638,7 +1618,7 @@ async def list_futures_aggregates( Get aggregates for a futures contract in a given time range. """ try: - results = polygon_client.list_futures_aggregates( + results = massive_client.list_futures_aggregates( ticker=ticker, resolution=resolution, window_start=window_start, @@ -1673,7 +1653,7 @@ async def list_futures_contracts( Get a paginated list of futures contracts. """ try: - results = polygon_client.list_futures_contracts( + results = massive_client.list_futures_contracts( product_code=product_code, first_trade_date=first_trade_date, last_trade_date=last_trade_date, @@ -1701,7 +1681,7 @@ async def get_futures_contract_details( Get details for a single futures contract at a specified point in time. """ try: - results = polygon_client.get_futures_contract_details( + results = massive_client.get_futures_contract_details( ticker=ticker, as_of=as_of, params=params, @@ -1732,7 +1712,7 @@ async def list_futures_products( Get a list of futures products (including combos). """ try: - results = polygon_client.list_futures_products( + results = massive_client.list_futures_products( name=name, name_search=name_search, as_of=as_of, @@ -1764,7 +1744,7 @@ async def get_futures_product_details( Get details for a single futures product as it was at a specific day. """ try: - results = polygon_client.get_futures_product_details( + results = massive_client.get_futures_product_details( product_code=product_code, type=type, as_of=as_of, @@ -1798,7 +1778,7 @@ async def list_futures_quotes( Get quotes for a futures contract in a given time range. """ try: - results = polygon_client.list_futures_quotes( + results = massive_client.list_futures_quotes( ticker=ticker, timestamp=timestamp, timestamp_lt=timestamp_lt, @@ -1842,7 +1822,7 @@ async def list_futures_trades( Get trades for a futures contract in a given time range. """ try: - results = polygon_client.list_futures_trades( + results = massive_client.list_futures_trades( ticker=ticker, timestamp=timestamp, timestamp_lt=timestamp_lt, @@ -1877,7 +1857,7 @@ async def list_futures_schedules( Get trading schedules for multiple futures products on a specific date. """ try: - results = polygon_client.list_futures_schedules( + results = massive_client.list_futures_schedules( session_end_date=session_end_date, trading_venue=trading_venue, limit=limit, @@ -1907,7 +1887,7 @@ async def list_futures_schedules_by_product_code( Get schedule data for a single futures product across many trading dates. """ try: - results = polygon_client.list_futures_schedules_by_product_code( + results = massive_client.list_futures_schedules_by_product_code( product_code=product_code, session_end_date=session_end_date, session_end_date_lt=session_end_date_lt, @@ -1937,7 +1917,7 @@ async def list_futures_market_statuses( Get market statuses for futures products. """ try: - results = polygon_client.list_futures_market_statuses( + results = massive_client.list_futures_market_statuses( product_code_any_of=product_code_any_of, product_code=product_code, limit=limit, @@ -1973,7 +1953,7 @@ async def get_futures_snapshot( Get snapshots for futures contracts. """ try: - results = polygon_client.get_futures_snapshot( + results = massive_client.get_futures_snapshot( ticker=ticker, ticker_any_of=ticker_any_of, ticker_gt=ticker_gt, diff --git a/tests/test_formatters.py b/tests/test_formatters.py index d8885e9..5013d24 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -372,9 +372,10 @@ def test_list_with_nested_objects(self): assert "tag2" in rows[0]["tags"] def test_invalid_json_string(self): - """Test that invalid JSON string raises appropriate error.""" - with pytest.raises(json.JSONDecodeError): - json_to_csv("not valid json {") + """Test that invalid JSON string returns empty CSV gracefully.""" + # Invalid JSON should return empty string instead of raising + result = json_to_csv("not valid json {") + assert result == "" def test_csv_output_format(self): """Test that output is valid CSV with proper headers.""" diff --git a/uv.lock b/uv.lock index 4d8a107..f83188d 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" [[package]] @@ -180,6 +180,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, ] +[[package]] +name = "massive" +version = "2.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "urllib3" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d5/ee/49823c94a368173fd6b7d592b8e5e9be3a9df403cdbdada57af4d2ff6453/massive-2.0.1.tar.gz", hash = "sha256:419cd341570435b0998122919edc34cc7031f9d7a9c9ae128e1f228012160d81", size = 44064, upload-time = "2025-10-30T22:44:13.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/3e/2b02f58960029301a7b5969931efece0f0532d6efa66afcc92a4d801ba3b/massive-2.0.1-py3-none-any.whl", hash = "sha256:666d14f4401b30d7c25d8360817ef040c1a616df109775f8662f3e6078375e76", size = 61893, upload-time = "2025-10-30T22:44:12.476Z" }, +] + [[package]] name = "mcp" version = "1.15.0" @@ -210,11 +224,12 @@ cli = [ [[package]] name = "mcp-massive" -version = "0.6.0" +version = "0.7.0" source = { editable = "." } dependencies = [ + { name = "massive" }, { name = "mcp", extra = ["cli"] }, - { name = "polygon-api-client" }, + { name = "python-dotenv" }, ] [package.dev-dependencies] @@ -226,8 +241,9 @@ dev = [ [package.metadata] requires-dist = [ + { name = "massive", specifier = ">=2.0.1" }, { name = "mcp", extras = ["cli"], specifier = ">=1.15.0" }, - { name = "polygon-api-client", specifier = ">=1.15.4" }, + { name = "python-dotenv", specifier = ">=1.2.0" }, ] [package.metadata.requires-dev] @@ -264,20 +280,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] -[[package]] -name = "polygon-api-client" -version = "1.15.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "urllib3" }, - { name = "websockets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/2c/39/8f2423b65926d7f815370e83acf9b8c09d0965c7cb5b55a78eee52e679f1/polygon_api_client-1.15.4.tar.gz", hash = "sha256:2adb920dac5788732fc95a25dc8650cc843591552c8969c40f5eaaf22aaf7072", size = 37986, upload-time = "2025-09-23T23:25:14.842Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/28/b9/57a53ce17aeb46432b5df3e3ec607d9a0daece740d707798f4f7c423d5b5/polygon_api_client-1.15.4-py3-none-any.whl", hash = "sha256:561b990add5c9a251f42ba1ec85244829a15c09b02f7b08dbf149df8bb509cde", size = 54598, upload-time = "2025-09-23T23:25:13.837Z" }, -] - [[package]] name = "pydantic" version = "2.11.9" @@ -422,11 +424,11 @@ wheels = [ [[package]] name = "python-dotenv" -version = "1.0.1" +version = "1.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115, upload-time = "2024-01-23T06:33:00.505Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863, upload-time = "2024-01-23T06:32:58.246Z" }, + { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" }, ] [[package]]