#
tokens: 27540/50000 12/12 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .github
│   └── workflows
│       └── ci.yml
├── .gitignore
├── .python-version
├── assets
│   ├── polygon_banner_darkmode.png
│   └── polygon_banner_lightmode.png
├── docker-compose.yml
├── Dockerfile
├── entrypoint.py
├── glama.json
├── justfile
├── LICENSE
├── manifest.json
├── pyproject.toml
├── README.md
├── src
│   └── mcp_polygon
│       ├── __init__.py
│       └── server.py
└── uv.lock
```

# Files

--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------

```
1 | 3.13
2 | 
```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
 1 | # Python-generated files
 2 | __pycache__/
 3 | *.py[oc]
 4 | build/
 5 | dist/
 6 | wheels/
 7 | *.egg-info
 8 | .ruff-cache/
 9 | 
10 | # Virtual environments
11 | .venv
12 | .env
13 | venv/
14 | env/
15 | ENV/
16 | .python-version
17 | 
18 | # IDE-specific files
19 | .idea/
20 | .vscode/
21 | *.swp
22 | *.swo
23 | 
24 | # OS-specific files
25 | .DS_Store
26 | Thumbs.db
27 | 
28 | # Environment and secrets
29 | .env.local
30 | 
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | <a href="https://polygon.io">
  2 |   <div align="center">
  3 |     <picture>
  4 |         <source media="(prefers-color-scheme: light)" srcset="assets/polygon_banner_lightmode.png">
  5 |         <source media="(prefers-color-scheme: dark)" srcset="assets/polygon_banner_darkmode.png">
  6 |         <img alt="Polygon.io logo" src="assets/polygon_banner_lightmode.png" height="100">
  7 |     </picture>
  8 |   </div>
  9 | </a>
 10 | <br>
 11 | 
 12 | > [!IMPORTANT]
 13 | > :test_tube: This project is experimental and could be subject to breaking changes.
 14 | 
 15 | # Polygon.io MCP Server
 16 | 
 17 |  [![GitHub release](https://img.shields.io/github/v/release/polygon-io/mcp_polygon)](https://github.com/polygon-io/mcp_polygon/releases)
 18 | 
 19 | A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that provides access to [Polygon.io](https://polygon.io?utm_campaign=mcp&utm_medium=referral&utm_source=github) financial market data API through an LLM-friendly interface.
 20 | 
 21 | ## Overview
 22 | 
 23 | This server exposes all Polygon.io API endpoints as MCP tools, providing access to comprehensive financial market data including:
 24 | 
 25 | - Stock, options, forex, and crypto aggregates and bars
 26 | - Real-time and historical trades and quotes
 27 | - Market snapshots
 28 | - Ticker details and reference data
 29 | - Dividends and splits data
 30 | - Financial fundamentals
 31 | - Market status and holidays
 32 | 
 33 | ## Installation
 34 | 
 35 | ### Prerequisites
 36 | 
 37 | - Python 3.10+
 38 | - A Polygon.io API key <br> [![Button]][Link]
 39 | - [Astral UV](https://docs.astral.sh/uv/getting-started/installation/)
 40 |   - For existing installs, check that you have a version that supports the `uvx` command.
 41 | 
 42 | ### Claude Code
 43 | First, install [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview)
 44 | 
 45 | ```bash
 46 | npm install -g @anthropic-ai/claude-code
 47 | ```
 48 | 
 49 | Use the following command to add the Polygon MCP server to your local environment.
 50 | This assumes `uvx` is in your $PATH; if not, then you need to provide the full
 51 | path to `uvx`.
 52 | 
 53 | ```bash
 54 | # Claude CLI
 55 | claude mcp add polygon -e POLYGON_API_KEY=your_api_key_here -- uvx --from git+https://github.com/polygon-io/[email protected] mcp_polygon
 56 | ```
 57 | 
 58 | This command will install the MCP server in your current project.
 59 | If you want to install it globally, you can run the command with `-s <scope>` flag.
 60 | See `claude mcp add --help` for more options.
 61 | 
 62 | To start Claude Code, run `claude` in your terminal.
 63 | - If this is your first time using, follow the setup prompts to authenticate
 64 | 
 65 | You can also run `claude mcp add-from-claude-desktop` if the MCP server is installed already for Claude Desktop.
 66 | 
 67 | ### Claude Desktop
 68 | 
 69 | 1. Follow the [Claude Desktop MCP installation instructions](https://modelcontextprotocol.io/quickstart/user) to complete the initial installation and find your configuration file.
 70 | 1. Use the following example as reference to add Polygon's MCP server.
 71 | Make sure you complete the various fields.
 72 |     1. Path find your path to `uvx`, run `which uvx` in your terminal.
 73 |     2. Replace `<your_api_key_here>` with your actual Polygon.io API key.
 74 |     3. Replace `<your_home_directory>` with your home directory path, e.g., `/home/username` (Mac/Linux) or `C:\Users\username` (Windows).
 75 | 
 76 | <details>
 77 |   <summary>claude_desktop_config.json</summary>
 78 | 
 79 | ```json
 80 | {
 81 |     "mcpServers": {
 82 |         "polygon": {
 83 |             "command": "<path_to_your_uvx_install>/uvx",
 84 |             "args": [
 85 |                 "--from",
 86 |                 "git+https://github.com/polygon-io/[email protected]",
 87 |                 "mcp_polygon"
 88 |             ],
 89 |             "env": {
 90 |                 "POLYGON_API_KEY": "<your_api_key_here>",
 91 |                 "HOME": "<your_home_directory>"
 92 |             }
 93 |         }
 94 |     }
 95 | }
 96 | ```
 97 | </details>
 98 | 
 99 | ## Transport Configuration
100 | 
101 | By default, STDIO transport is used.
102 | 
103 | To configure [SSE](https://modelcontextprotocol.io/specification/2024-11-05/basic/transports#http-with-sse) or [Streamable HTTP](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http), set the `MCP_TRANSPORT` environment variable.
104 | 
105 | Example:
106 | 
107 | ```bash
108 | MCP_TRANSPORT=streamable-http \
109 | POLYGON_API_KEY=<your_api_key_here> \
110 | uv run entrypoint.py
111 | ```
112 | 
113 | ## Usage Examples
114 | 
115 | Once integrated, you can prompt Claude to access Polygon.io data:
116 | 
117 | ```
118 | Get the latest price for AAPL stock
119 | Show me yesterday's trading volume for MSFT
120 | What were the biggest stock market gainers today?
121 | Get me the latest crypto market data for BTC-USD
122 | ```
123 | 
124 | ## Available Tools
125 | 
126 | This MCP server implements all Polygon.io API endpoints as tools, including:
127 | 
128 | - `get_aggs` - Stock aggregates (OHLC) data for a specific ticker
129 | - `list_trades` - Historical trade data
130 | - `get_last_trade` - Latest trade for a symbol
131 | - `list_ticker_news` - Recent news articles for tickers
132 | - `get_snapshot_ticker` - Current market snapshot for a ticker
133 | - `get_market_status` - Current market status and trading hours
134 | - `list_stock_financials` - Fundamental financial data
135 | - And many more...
136 | 
137 | Each tool follows the Polygon.io SDK parameter structure while converting responses to standard JSON that LLMs can easily process.
138 | 
139 | ## Development
140 | 
141 | ### Running Locally
142 | 
143 | Check to ensure you have the [Prerequisites](#prerequisites) installed.
144 | 
145 | ```bash
146 | # Sync dependencies
147 | uv sync
148 | 
149 | # Run the server
150 | POLYGON_API_KEY=your_api_key_here uv run mcp_polygon
151 | ```
152 | 
153 | <details>
154 |   <summary>Local Dev Config for claude_desktop_config.json</summary>
155 | 
156 | ```json
157 | 
158 |   "mcpServers": {
159 |     "polygon": {
160 |       "command": "/your/path/.cargo/bin/uv",
161 |       "args": [
162 |         "run",
163 |         "--with",
164 |         "/your/path/mcp_polygon",
165 |         "mcp_polygon"
166 |       ],
167 |       "env": {
168 |         "POLYGON_API_KEY": "your_api_key_here",
169 |         "HOME": "/Users/danny"
170 |       }
171 |     }
172 |   }
173 | ```
174 | </details>
175 | 
176 | ### Debugging
177 | 
178 | For debugging and testing, we recommend using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector):
179 | 
180 | ```bash
181 | npx @modelcontextprotocol/inspector uv --directory /path/to/mcp_polygon run mcp_polygon
182 | ```
183 | 
184 | This will launch a browser interface where you can interact with your MCP server directly and see input/output for each tool.
185 | 
186 | ### Code Linting
187 | 
188 | This project uses [just](https://github.com/casey/just) for common development tasks. To lint your code before submitting a PR:
189 | 
190 | ```bash
191 | just lint
192 | ```
193 | 
194 | This will run `ruff format` and `ruff check --fix` to automatically format your code and fix linting issues.
195 | 
196 | ## Links
197 | - [Polygon.io Documentation](https://polygon.io/docs?utm_campaign=mcp&utm_medium=referral&utm_source=github)
198 | - [Model Context Protocol](https://modelcontextprotocol.io)
199 | - [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)
200 | 
201 | ## Privacy Policy
202 | 
203 | This MCP server interacts with Polygon.io's API to fetch market data. All data requests are subject to Polygon.io's privacy policy and terms of service.
204 | 
205 | - **Polygon.io Privacy Policy**: https://polygon.io/legal/privacy
206 | - **Data Handling**: This server does not store or cache any user data. All requests are proxied directly to Polygon.io's API.
207 | - **API Key**: Your Polygon.io API key is used only for authenticating requests to their API.
208 | 
209 | ## Contributing
210 | If you found a bug or have an idea for a new feature, please first discuss it with us by submitting a new issue.
211 | We will respond to issues within at most 3 weeks.
212 | We're also open to volunteers if you want to submit a PR for any open issues but please discuss it with us beforehand.
213 | PRs that aren't linked to an existing issue or discussed with us ahead of time will generally be declined.
214 | 
215 | <!----------------------------------------------------------------------------->
216 | [Link]: https://polygon.io/?utm_campaign=mcp&utm_medium=referral&utm_source=github 'Polygon.io Home Page'
217 | <!---------------------------------[ Buttons ]--------------------------------->
218 | [Button]: https://img.shields.io/badge/Get_One_For_Free-5F5CFF?style=for-the-badge&logoColor=white
219 | 
```

--------------------------------------------------------------------------------
/src/mcp_polygon/__init__.py:
--------------------------------------------------------------------------------

```python
1 | from .server import run
2 | 
3 | __all__ = ["run"]
4 | 
```

--------------------------------------------------------------------------------
/glama.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "$schema": "https://glama.ai/mcp/schemas/server.json",
 3 |   "maintainers": [
 4 |     "DanStough",
 5 |     "joedursun",
 6 |     "penelopus",
 7 |     "qrpike"
 8 |   ]
 9 | }
10 | 
```

--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------

```yaml
 1 | services:
 2 |   mcp_polygon:
 3 |     build: .
 4 |     volumes:
 5 |       - .:/app
 6 |     container_name: mcp_polygon_server
 7 |     environment:
 8 |       - POLYGON_API_KEY=${POLYGON_API_KEY}
 9 |     stdin_open: true
10 |     tty: true
11 | 
```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
 1 | FROM python:3.13-slim
 2 | 
 3 | WORKDIR /app
 4 | 
 5 | # Install uv for dependency management
 6 | RUN pip install uv
 7 | 
 8 | COPY . ./
 9 | 
10 | RUN uv pip install --system -e .
11 | RUN chmod +x entrypoint.py
12 | 
13 | ENV PYTHONPATH=/app/src:$PYTHONPATH
14 | 
15 | ENTRYPOINT ["uv", "run", "./entrypoint.py"]
16 | 
```

--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------

```toml
 1 | [project]
 2 | name = "mcp_polygon"
 3 | version = "0.4.1"
 4 | description = "A MCP server project"
 5 | readme = "README.md"
 6 | requires-python = ">=3.10"
 7 | dependencies = [
 8 |     "mcp[cli]>=1.9.3",
 9 |  "polygon-api-client>=1.15.3",
10 | ]
11 | [[project.authors]]
12 | name = "Polygon"
13 | email = "[email protected]"
14 | 
15 | [build-system]
16 | requires = [ "hatchling",]
17 | build-backend = "hatchling.build"
18 | 
19 | [dependency-groups]
20 | dev = [
21 |     "ruff>=0.12.4",
22 | ]
23 | 
24 | [project.scripts]
25 | mcp_polygon = "mcp_polygon:run"
26 | 
```

--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------

```yaml
 1 | name: Validate Code Quality
 2 | 
 3 | permissions:
 4 |   contents: read
 5 | 
 6 | on:
 7 |   pull_request:
 8 |     branches:
 9 |       - 'master'
10 | 
11 | jobs:
12 |   lint:
13 |     name: Code Quality & Testing
14 |     runs-on: ubuntu-latest
15 |     steps:
16 |       - uses: actions/checkout@v4
17 | 
18 |       - name: Install UV
19 |         uses: astral-sh/setup-uv@v4
20 |         with:
21 |           enable-cache: true
22 | 
23 |       - name: Set up Python
24 |         uses: actions/setup-python@v5
25 |         with:
26 |           python-version-file: "pyproject.toml"
27 | 
28 |       - name: Install dependencies
29 |         run: uv sync
30 | 
31 |       - name: Run Ruff check
32 |         run: uv run ruff check
33 | 
34 |       - name: Run Ruff format
35 |         run: uv run ruff format --check
36 | 
```

--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "manifest_version": "0.2",
 3 |   "name": "mcp_polygon",
 4 |   "version": "0.4.1",
 5 |   "description": "MCP server providing access to Polygon.io financial market data API",
 6 |   "author": {
 7 |     "name": "Polygon.io",
 8 |     "email": "[email protected]",
 9 |     "url": "https://polygon.io"
10 |   },
11 |   "privacy_policies": [
12 |     "https://polygon.io/legal/privacy"
13 |   ],
14 |   "server": {
15 |     "type": "python",
16 |     "entry_point": "mcp_polygon",
17 |     "mcp_config": {
18 |       "command": "uvx",
19 |       "args": [
20 |         "--from",
21 |         "git+https://github.com/polygon-io/mcp_polygon",
22 |         "mcp_polygon"
23 |       ]
24 |     }
25 |   },
26 |   "user_config": {
27 |     "POLYGON_API_KEY": {
28 |       "type": "string",
29 |       "description": "Your Polygon.io API key for accessing market data",
30 |       "required": true,
31 |       "sensitive": true
32 |     }
33 |   },
34 |   "compatibility": {
35 |     "python": ">=3.10"
36 |   },
37 |   "repository": "https://github.com/polygon-io/mcp_polygon",
38 |   "license": "MIT"
39 | }
40 | 
```

--------------------------------------------------------------------------------
/entrypoint.py:
--------------------------------------------------------------------------------

```python
 1 | #!/usr/bin/env python
 2 | import os
 3 | from typing import Literal
 4 | from mcp_polygon import server
 5 | 
 6 | 
 7 | def transport() -> Literal["stdio", "sse", "streamable-http"]:
 8 |     """
 9 |     Determine the transport type for the MCP server.
10 |     Defaults to 'stdio' if not set in environment variables.
11 |     """
12 |     mcp_transport_str = os.environ.get("MCP_TRANSPORT", "stdio")
13 | 
14 |     # These are currently the only supported transports
15 |     supported_transports: dict[str, Literal["stdio", "sse", "streamable-http"]] = {
16 |         "stdio": "stdio",
17 |         "sse": "sse",
18 |         "streamable-http": "streamable-http",
19 |     }
20 | 
21 |     return supported_transports.get(mcp_transport_str, "stdio")
22 | 
23 | 
24 | # Ensure the server process doesn't exit immediately when run as an MCP server
25 | def start_server():
26 |     polygon_api_key = os.environ.get("POLYGON_API_KEY", "")
27 |     if not polygon_api_key:
28 |         print("Warning: POLYGON_API_KEY environment variable not set.")
29 |     else:
30 |         print("Starting Polygon MCP server with API key configured.")
31 | 
32 |     server.run(transport=transport())
33 | 
34 | 
35 | if __name__ == "__main__":
36 |     start_server()
37 | 
```

--------------------------------------------------------------------------------
/src/mcp_polygon/server.py:
--------------------------------------------------------------------------------

```python
   1 | import os
   2 | import json
   3 | from typing import Optional, Any, Dict, Union, List, Literal
   4 | from mcp.server.fastmcp import FastMCP
   5 | from mcp.types import ToolAnnotations
   6 | from polygon import RESTClient
   7 | from importlib.metadata import version, PackageNotFoundError
   8 | 
   9 | from datetime import datetime, date
  10 | 
  11 | POLYGON_API_KEY = os.environ.get("POLYGON_API_KEY", "")
  12 | if not POLYGON_API_KEY:
  13 |     print("Warning: POLYGON_API_KEY environment variable not set.")
  14 | 
  15 | version_number = "MCP-Polygon/unknown"
  16 | try:
  17 |     version_number = f"MCP-Polygon/{version('mcp_polygon')}"
  18 | except PackageNotFoundError:
  19 |     pass
  20 | 
  21 | polygon_client = RESTClient(POLYGON_API_KEY)
  22 | polygon_client.headers["User-Agent"] += f" {version_number}"
  23 | 
  24 | poly_mcp = FastMCP("Polygon", dependencies=["polygon"])
  25 | 
  26 | 
  27 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
  28 | async def get_aggs(
  29 |     ticker: str,
  30 |     multiplier: int,
  31 |     timespan: str,
  32 |     from_: Union[str, int, datetime, date],
  33 |     to: Union[str, int, datetime, date],
  34 |     adjusted: Optional[bool] = None,
  35 |     sort: Optional[str] = None,
  36 |     limit: Optional[int] = None,
  37 |     params: Optional[Dict[str, Any]] = None,
  38 | ) -> Dict[str, Any]:
  39 |     """
  40 |     List aggregate bars for a ticker over a given date range in custom time window sizes.
  41 |     """
  42 |     try:
  43 |         results = polygon_client.get_aggs(
  44 |             ticker=ticker,
  45 |             multiplier=multiplier,
  46 |             timespan=timespan,
  47 |             from_=from_,
  48 |             to=to,
  49 |             adjusted=adjusted,
  50 |             sort=sort,
  51 |             limit=limit,
  52 |             params=params,
  53 |             raw=True,
  54 |         )
  55 | 
  56 |         # Parse the binary data to string and then to JSON
  57 |         data_str = results.data.decode("utf-8")
  58 |         return json.loads(data_str)
  59 |     except Exception as e:
  60 |         return {"error": str(e)}
  61 | 
  62 | 
  63 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
  64 | async def list_aggs(
  65 |     ticker: str,
  66 |     multiplier: int,
  67 |     timespan: str,
  68 |     from_: Union[str, int, datetime, date],
  69 |     to: Union[str, int, datetime, date],
  70 |     adjusted: Optional[bool] = None,
  71 |     sort: Optional[str] = None,
  72 |     limit: Optional[int] = None,
  73 |     params: Optional[Dict[str, Any]] = None,
  74 | ) -> Dict[str, Any]:
  75 |     """
  76 |     Iterate through aggregate bars for a ticker over a given date range.
  77 |     """
  78 |     try:
  79 |         results = polygon_client.list_aggs(
  80 |             ticker=ticker,
  81 |             multiplier=multiplier,
  82 |             timespan=timespan,
  83 |             from_=from_,
  84 |             to=to,
  85 |             adjusted=adjusted,
  86 |             sort=sort,
  87 |             limit=limit,
  88 |             params=params,
  89 |             raw=True,
  90 |         )
  91 | 
  92 |         data_str = results.data.decode("utf-8")
  93 |         return json.loads(data_str)
  94 |     except Exception as e:
  95 |         return {"error": str(e)}
  96 | 
  97 | 
  98 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
  99 | async def get_grouped_daily_aggs(
 100 |     date: str,
 101 |     adjusted: Optional[bool] = None,
 102 |     include_otc: Optional[bool] = None,
 103 |     locale: Optional[str] = None,
 104 |     market_type: Optional[str] = None,
 105 |     params: Optional[Dict[str, Any]] = None,
 106 | ) -> Dict[str, Any]:
 107 |     """
 108 |     Get grouped daily bars for entire market for a specific date.
 109 |     """
 110 |     try:
 111 |         results = polygon_client.get_grouped_daily_aggs(
 112 |             date=date,
 113 |             adjusted=adjusted,
 114 |             include_otc=include_otc,
 115 |             locale=locale,
 116 |             market_type=market_type,
 117 |             params=params,
 118 |             raw=True,
 119 |         )
 120 | 
 121 |         data_str = results.data.decode("utf-8")
 122 |         return json.loads(data_str)
 123 |     except Exception as e:
 124 |         return {"error": str(e)}
 125 | 
 126 | 
 127 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 128 | async def get_daily_open_close_agg(
 129 |     ticker: str,
 130 |     date: str,
 131 |     adjusted: Optional[bool] = None,
 132 |     params: Optional[Dict[str, Any]] = None,
 133 | ) -> Dict[str, Any]:
 134 |     """
 135 |     Get daily open, close, high, and low for a specific ticker and date.
 136 |     """
 137 |     try:
 138 |         results = polygon_client.get_daily_open_close_agg(
 139 |             ticker=ticker, date=date, adjusted=adjusted, params=params, raw=True
 140 |         )
 141 | 
 142 |         data_str = results.data.decode("utf-8")
 143 |         return json.loads(data_str)
 144 |     except Exception as e:
 145 |         return {"error": str(e)}
 146 | 
 147 | 
 148 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 149 | async def get_previous_close_agg(
 150 |     ticker: str,
 151 |     adjusted: Optional[bool] = None,
 152 |     params: Optional[Dict[str, Any]] = None,
 153 | ) -> Dict[str, Any]:
 154 |     """
 155 |     Get previous day's open, close, high, and low for a specific ticker.
 156 |     """
 157 |     try:
 158 |         results = polygon_client.get_previous_close_agg(
 159 |             ticker=ticker, adjusted=adjusted, params=params, raw=True
 160 |         )
 161 | 
 162 |         data_str = results.data.decode("utf-8")
 163 |         return json.loads(data_str)
 164 |     except Exception as e:
 165 |         return {"error": str(e)}
 166 | 
 167 | 
 168 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 169 | async def list_trades(
 170 |     ticker: str,
 171 |     timestamp: Optional[Union[str, int, datetime, date]] = None,
 172 |     timestamp_lt: Optional[Union[str, int, datetime, date]] = None,
 173 |     timestamp_lte: Optional[Union[str, int, datetime, date]] = None,
 174 |     timestamp_gt: Optional[Union[str, int, datetime, date]] = None,
 175 |     timestamp_gte: Optional[Union[str, int, datetime, date]] = None,
 176 |     limit: Optional[int] = None,
 177 |     sort: Optional[str] = None,
 178 |     order: Optional[str] = None,
 179 |     params: Optional[Dict[str, Any]] = None,
 180 | ) -> Dict[str, Any]:
 181 |     """
 182 |     Get trades for a ticker symbol.
 183 |     """
 184 |     try:
 185 |         results = polygon_client.list_trades(
 186 |             ticker=ticker,
 187 |             timestamp=timestamp,
 188 |             timestamp_lt=timestamp_lt,
 189 |             timestamp_lte=timestamp_lte,
 190 |             timestamp_gt=timestamp_gt,
 191 |             timestamp_gte=timestamp_gte,
 192 |             limit=limit,
 193 |             sort=sort,
 194 |             order=order,
 195 |             params=params,
 196 |             raw=True,
 197 |         )
 198 | 
 199 |         data_str = results.data.decode("utf-8")
 200 |         return json.loads(data_str)
 201 |     except Exception as e:
 202 |         return {"error": str(e)}
 203 | 
 204 | 
 205 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 206 | async def get_last_trade(
 207 |     ticker: str,
 208 |     params: Optional[Dict[str, Any]] = None,
 209 | ) -> Dict[str, Any]:
 210 |     """
 211 |     Get the most recent trade for a ticker symbol.
 212 |     """
 213 |     try:
 214 |         results = polygon_client.get_last_trade(ticker=ticker, params=params, raw=True)
 215 | 
 216 |         data_str = results.data.decode("utf-8")
 217 |         return json.loads(data_str)
 218 |     except Exception as e:
 219 |         return {"error": str(e)}
 220 | 
 221 | 
 222 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 223 | async def get_last_crypto_trade(
 224 |     from_: str,
 225 |     to: str,
 226 |     params: Optional[Dict[str, Any]] = None,
 227 | ) -> Dict[str, Any]:
 228 |     """
 229 |     Get the most recent trade for a crypto pair.
 230 |     """
 231 |     try:
 232 |         results = polygon_client.get_last_crypto_trade(
 233 |             from_=from_, to=to, params=params, raw=True
 234 |         )
 235 | 
 236 |         data_str = results.data.decode("utf-8")
 237 |         return json.loads(data_str)
 238 |     except Exception as e:
 239 |         return {"error": str(e)}
 240 | 
 241 | 
 242 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 243 | async def list_quotes(
 244 |     ticker: str,
 245 |     timestamp: Optional[Union[str, int, datetime, date]] = None,
 246 |     timestamp_lt: Optional[Union[str, int, datetime, date]] = None,
 247 |     timestamp_lte: Optional[Union[str, int, datetime, date]] = None,
 248 |     timestamp_gt: Optional[Union[str, int, datetime, date]] = None,
 249 |     timestamp_gte: Optional[Union[str, int, datetime, date]] = None,
 250 |     limit: Optional[int] = None,
 251 |     sort: Optional[str] = None,
 252 |     order: Optional[str] = None,
 253 |     params: Optional[Dict[str, Any]] = None,
 254 | ) -> Dict[str, Any]:
 255 |     """
 256 |     Get quotes for a ticker symbol.
 257 |     """
 258 |     try:
 259 |         results = polygon_client.list_quotes(
 260 |             ticker=ticker,
 261 |             timestamp=timestamp,
 262 |             timestamp_lt=timestamp_lt,
 263 |             timestamp_lte=timestamp_lte,
 264 |             timestamp_gt=timestamp_gt,
 265 |             timestamp_gte=timestamp_gte,
 266 |             limit=limit,
 267 |             sort=sort,
 268 |             order=order,
 269 |             params=params,
 270 |             raw=True,
 271 |         )
 272 | 
 273 |         data_str = results.data.decode("utf-8")
 274 |         return json.loads(data_str)
 275 |     except Exception as e:
 276 |         return {"error": str(e)}
 277 | 
 278 | 
 279 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 280 | async def get_last_quote(
 281 |     ticker: str,
 282 |     params: Optional[Dict[str, Any]] = None,
 283 | ) -> Dict[str, Any]:
 284 |     """
 285 |     Get the most recent quote for a ticker symbol.
 286 |     """
 287 |     try:
 288 |         results = polygon_client.get_last_quote(ticker=ticker, params=params, raw=True)
 289 | 
 290 |         data_str = results.data.decode("utf-8")
 291 |         return json.loads(data_str)
 292 |     except Exception as e:
 293 |         return {"error": str(e)}
 294 | 
 295 | 
 296 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 297 | async def get_last_forex_quote(
 298 |     from_: str,
 299 |     to: str,
 300 |     params: Optional[Dict[str, Any]] = None,
 301 | ) -> Dict[str, Any]:
 302 |     """
 303 |     Get the most recent forex quote.
 304 |     """
 305 |     try:
 306 |         results = polygon_client.get_last_forex_quote(
 307 |             from_=from_, to=to, params=params, raw=True
 308 |         )
 309 | 
 310 |         data_str = results.data.decode("utf-8")
 311 |         return json.loads(data_str)
 312 |     except Exception as e:
 313 |         return {"error": str(e)}
 314 | 
 315 | 
 316 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 317 | async def get_real_time_currency_conversion(
 318 |     from_: str,
 319 |     to: str,
 320 |     amount: Optional[float] = None,
 321 |     precision: Optional[int] = None,
 322 |     params: Optional[Dict[str, Any]] = None,
 323 | ) -> Dict[str, Any]:
 324 |     """
 325 |     Get real-time currency conversion.
 326 |     """
 327 |     try:
 328 |         results = polygon_client.get_real_time_currency_conversion(
 329 |             from_=from_,
 330 |             to=to,
 331 |             amount=amount,
 332 |             precision=precision,
 333 |             params=params,
 334 |             raw=True,
 335 |         )
 336 | 
 337 |         data_str = results.data.decode("utf-8")
 338 |         return json.loads(data_str)
 339 |     except Exception as e:
 340 |         return {"error": str(e)}
 341 | 
 342 | 
 343 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 344 | async def list_universal_snapshots(
 345 |     type: str,
 346 |     ticker_any_of: Optional[List[str]] = None,
 347 |     order: Optional[str] = None,
 348 |     limit: Optional[int] = None,
 349 |     sort: Optional[str] = None,
 350 |     params: Optional[Dict[str, Any]] = None,
 351 | ) -> Dict[str, Any]:
 352 |     """
 353 |     Get universal snapshots for multiple assets of a specific type.
 354 |     """
 355 |     try:
 356 |         results = polygon_client.list_universal_snapshots(
 357 |             type=type,
 358 |             ticker_any_of=ticker_any_of,
 359 |             order=order,
 360 |             limit=limit,
 361 |             sort=sort,
 362 |             params=params,
 363 |             raw=True,
 364 |         )
 365 | 
 366 |         data_str = results.data.decode("utf-8")
 367 |         return json.loads(data_str)
 368 |     except Exception as e:
 369 |         return {"error": str(e)}
 370 | 
 371 | 
 372 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 373 | async def get_snapshot_all(
 374 |     market_type: str,
 375 |     tickers: Optional[List[str]] = None,
 376 |     include_otc: Optional[bool] = None,
 377 |     params: Optional[Dict[str, Any]] = None,
 378 | ) -> Dict[str, Any]:
 379 |     """
 380 |     Get a snapshot of all tickers in a market.
 381 |     """
 382 |     try:
 383 |         results = polygon_client.get_snapshot_all(
 384 |             market_type=market_type,
 385 |             tickers=tickers,
 386 |             include_otc=include_otc,
 387 |             params=params,
 388 |             raw=True,
 389 |         )
 390 | 
 391 |         data_str = results.data.decode("utf-8")
 392 |         return json.loads(data_str)
 393 |     except Exception as e:
 394 |         return {"error": str(e)}
 395 | 
 396 | 
 397 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 398 | async def get_snapshot_direction(
 399 |     market_type: str,
 400 |     direction: str,
 401 |     include_otc: Optional[bool] = None,
 402 |     params: Optional[Dict[str, Any]] = None,
 403 | ) -> Dict[str, Any]:
 404 |     """
 405 |     Get gainers or losers for a market.
 406 |     """
 407 |     try:
 408 |         results = polygon_client.get_snapshot_direction(
 409 |             market_type=market_type,
 410 |             direction=direction,
 411 |             include_otc=include_otc,
 412 |             params=params,
 413 |             raw=True,
 414 |         )
 415 | 
 416 |         data_str = results.data.decode("utf-8")
 417 |         return json.loads(data_str)
 418 |     except Exception as e:
 419 |         return {"error": str(e)}
 420 | 
 421 | 
 422 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 423 | async def get_snapshot_ticker(
 424 |     market_type: str,
 425 |     ticker: str,
 426 |     params: Optional[Dict[str, Any]] = None,
 427 | ) -> Dict[str, Any]:
 428 |     """
 429 |     Get snapshot for a specific ticker.
 430 |     """
 431 |     try:
 432 |         results = polygon_client.get_snapshot_ticker(
 433 |             market_type=market_type, ticker=ticker, params=params, raw=True
 434 |         )
 435 | 
 436 |         data_str = results.data.decode("utf-8")
 437 |         return json.loads(data_str)
 438 |     except Exception as e:
 439 |         return {"error": str(e)}
 440 | 
 441 | 
 442 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 443 | async def get_snapshot_option(
 444 |     underlying_asset: str,
 445 |     option_contract: str,
 446 |     params: Optional[Dict[str, Any]] = None,
 447 | ) -> Dict[str, Any]:
 448 |     """
 449 |     Get snapshot for a specific option contract.
 450 |     """
 451 |     try:
 452 |         results = polygon_client.get_snapshot_option(
 453 |             underlying_asset=underlying_asset,
 454 |             option_contract=option_contract,
 455 |             params=params,
 456 |             raw=True,
 457 |         )
 458 | 
 459 |         data_str = results.data.decode("utf-8")
 460 |         return json.loads(data_str)
 461 |     except Exception as e:
 462 |         return {"error": str(e)}
 463 | 
 464 | 
 465 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 466 | async def get_snapshot_crypto_book(
 467 |     ticker: str,
 468 |     params: Optional[Dict[str, Any]] = None,
 469 | ) -> Dict[str, Any]:
 470 |     """
 471 |     Get snapshot for a crypto ticker's order book.
 472 |     """
 473 |     try:
 474 |         results = polygon_client.get_snapshot_crypto_book(
 475 |             ticker=ticker, params=params, raw=True
 476 |         )
 477 | 
 478 |         data_str = results.data.decode("utf-8")
 479 |         return json.loads(data_str)
 480 |     except Exception as e:
 481 |         return {"error": str(e)}
 482 | 
 483 | 
 484 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 485 | async def get_market_holidays(
 486 |     params: Optional[Dict[str, Any]] = None,
 487 | ) -> Dict[str, Any]:
 488 |     """
 489 |     Get upcoming market holidays and their open/close times.
 490 |     """
 491 |     try:
 492 |         results = polygon_client.get_market_holidays(params=params, raw=True)
 493 | 
 494 |         data_str = results.data.decode("utf-8")
 495 |         return json.loads(data_str)
 496 |     except Exception as e:
 497 |         return {"error": str(e)}
 498 | 
 499 | 
 500 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 501 | async def get_market_status(
 502 |     params: Optional[Dict[str, Any]] = None,
 503 | ) -> Dict[str, Any]:
 504 |     """
 505 |     Get current trading status of exchanges and financial markets.
 506 |     """
 507 |     try:
 508 |         results = polygon_client.get_market_status(params=params, raw=True)
 509 | 
 510 |         data_str = results.data.decode("utf-8")
 511 |         return json.loads(data_str)
 512 |     except Exception as e:
 513 |         return {"error": str(e)}
 514 | 
 515 | 
 516 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 517 | async def list_tickers(
 518 |     ticker: Optional[str] = None,
 519 |     type: Optional[str] = None,
 520 |     market: Optional[str] = None,
 521 |     exchange: Optional[str] = None,
 522 |     cusip: Optional[str] = None,
 523 |     cik: Optional[str] = None,
 524 |     date: Optional[Union[str, datetime, date]] = None,
 525 |     search: Optional[str] = None,
 526 |     active: Optional[bool] = None,
 527 |     sort: Optional[str] = None,
 528 |     order: Optional[str] = None,
 529 |     limit: Optional[int] = None,
 530 |     params: Optional[Dict[str, Any]] = None,
 531 | ) -> Dict[str, Any]:
 532 |     """
 533 |     Query supported ticker symbols across stocks, indices, forex, and crypto.
 534 |     """
 535 |     try:
 536 |         results = polygon_client.list_tickers(
 537 |             ticker=ticker,
 538 |             type=type,
 539 |             market=market,
 540 |             exchange=exchange,
 541 |             cusip=cusip,
 542 |             cik=cik,
 543 |             date=date,
 544 |             search=search,
 545 |             active=active,
 546 |             sort=sort,
 547 |             order=order,
 548 |             limit=limit,
 549 |             params=params,
 550 |             raw=True,
 551 |         )
 552 | 
 553 |         data_str = results.data.decode("utf-8")
 554 |         return json.loads(data_str)
 555 |     except Exception as e:
 556 |         return {"error": str(e)}
 557 | 
 558 | 
 559 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 560 | async def get_ticker_details(
 561 |     ticker: str,
 562 |     date: Optional[Union[str, datetime, date]] = None,
 563 |     params: Optional[Dict[str, Any]] = None,
 564 | ) -> Dict[str, Any]:
 565 |     """
 566 |     Get detailed information about a specific ticker.
 567 |     """
 568 |     try:
 569 |         results = polygon_client.get_ticker_details(
 570 |             ticker=ticker, date=date, params=params, raw=True
 571 |         )
 572 | 
 573 |         data_str = results.data.decode("utf-8")
 574 |         return json.loads(data_str)
 575 |     except Exception as e:
 576 |         return {"error": str(e)}
 577 | 
 578 | 
 579 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 580 | async def list_ticker_news(
 581 |     ticker: Optional[str] = None,
 582 |     published_utc: Optional[Union[str, datetime, date]] = None,
 583 |     limit: Optional[int] = None,
 584 |     sort: Optional[str] = None,
 585 |     order: Optional[str] = None,
 586 |     params: Optional[Dict[str, Any]] = None,
 587 | ) -> Dict[str, Any]:
 588 |     """
 589 |     Get recent news articles for a stock ticker.
 590 |     """
 591 |     try:
 592 |         results = polygon_client.list_ticker_news(
 593 |             ticker=ticker,
 594 |             published_utc=published_utc,
 595 |             limit=limit,
 596 |             sort=sort,
 597 |             order=order,
 598 |             params=params,
 599 |             raw=True,
 600 |         )
 601 | 
 602 |         data_str = results.data.decode("utf-8")
 603 |         return json.loads(data_str)
 604 |     except Exception as e:
 605 |         return {"error": str(e)}
 606 | 
 607 | 
 608 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 609 | async def get_ticker_types(
 610 |     asset_class: Optional[str] = None,
 611 |     locale: Optional[str] = None,
 612 |     params: Optional[Dict[str, Any]] = None,
 613 | ) -> Dict[str, Any]:
 614 |     """
 615 |     List all ticker types supported by Polygon.io.
 616 |     """
 617 |     try:
 618 |         results = polygon_client.get_ticker_types(
 619 |             asset_class=asset_class, locale=locale, params=params, raw=True
 620 |         )
 621 | 
 622 |         data_str = results.data.decode("utf-8")
 623 |         return json.loads(data_str)
 624 |     except Exception as e:
 625 |         return {"error": str(e)}
 626 | 
 627 | 
 628 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 629 | async def list_splits(
 630 |     ticker: Optional[str] = None,
 631 |     execution_date: Optional[Union[str, datetime, date]] = None,
 632 |     reverse_split: Optional[bool] = None,
 633 |     limit: Optional[int] = None,
 634 |     params: Optional[Dict[str, Any]] = None,
 635 | ) -> Dict[str, Any]:
 636 |     """
 637 |     Get historical stock splits.
 638 |     """
 639 |     try:
 640 |         results = polygon_client.list_splits(
 641 |             ticker=ticker,
 642 |             execution_date=execution_date,
 643 |             reverse_split=reverse_split,
 644 |             limit=limit,
 645 |             params=params,
 646 |             raw=True,
 647 |         )
 648 | 
 649 |         data_str = results.data.decode("utf-8")
 650 |         return json.loads(data_str)
 651 |     except Exception as e:
 652 |         return {"error": str(e)}
 653 | 
 654 | 
 655 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 656 | async def list_dividends(
 657 |     ticker: Optional[str] = None,
 658 |     ex_dividend_date: Optional[Union[str, datetime, date]] = None,
 659 |     frequency: Optional[int] = None,
 660 |     dividend_type: Optional[str] = None,
 661 |     limit: Optional[int] = None,
 662 |     params: Optional[Dict[str, Any]] = None,
 663 | ) -> Dict[str, Any]:
 664 |     """
 665 |     Get historical cash dividends.
 666 |     """
 667 |     try:
 668 |         results = polygon_client.list_dividends(
 669 |             ticker=ticker,
 670 |             ex_dividend_date=ex_dividend_date,
 671 |             frequency=frequency,
 672 |             dividend_type=dividend_type,
 673 |             limit=limit,
 674 |             params=params,
 675 |             raw=True,
 676 |         )
 677 | 
 678 |         data_str = results.data.decode("utf-8")
 679 |         return json.loads(data_str)
 680 |     except Exception as e:
 681 |         return {"error": str(e)}
 682 | 
 683 | 
 684 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 685 | async def list_conditions(
 686 |     asset_class: Optional[str] = None,
 687 |     data_type: Optional[str] = None,
 688 |     id: Optional[int] = None,
 689 |     sip: Optional[str] = None,
 690 |     params: Optional[Dict[str, Any]] = None,
 691 | ) -> Dict[str, Any]:
 692 |     """
 693 |     List conditions used by Polygon.io.
 694 |     """
 695 |     try:
 696 |         results = polygon_client.list_conditions(
 697 |             asset_class=asset_class,
 698 |             data_type=data_type,
 699 |             id=id,
 700 |             sip=sip,
 701 |             params=params,
 702 |             raw=True,
 703 |         )
 704 | 
 705 |         data_str = results.data.decode("utf-8")
 706 |         return json.loads(data_str)
 707 |     except Exception as e:
 708 |         return {"error": str(e)}
 709 | 
 710 | 
 711 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 712 | async def get_exchanges(
 713 |     asset_class: Optional[str] = None,
 714 |     locale: Optional[str] = None,
 715 |     params: Optional[Dict[str, Any]] = None,
 716 | ) -> Dict[str, Any]:
 717 |     """
 718 |     List exchanges known by Polygon.io.
 719 |     """
 720 |     try:
 721 |         results = polygon_client.get_exchanges(
 722 |             asset_class=asset_class, locale=locale, params=params, raw=True
 723 |         )
 724 | 
 725 |         data_str = results.data.decode("utf-8")
 726 |         return json.loads(data_str)
 727 |     except Exception as e:
 728 |         return {"error": str(e)}
 729 | 
 730 | 
 731 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 732 | async def list_stock_financials(
 733 |     ticker: Optional[str] = None,
 734 |     cik: Optional[str] = None,
 735 |     company_name: Optional[str] = None,
 736 |     company_name_search: Optional[str] = None,
 737 |     sic: Optional[str] = None,
 738 |     filing_date: Optional[Union[str, datetime, date]] = None,
 739 |     filing_date_lt: Optional[Union[str, datetime, date]] = None,
 740 |     filing_date_lte: Optional[Union[str, datetime, date]] = None,
 741 |     filing_date_gt: Optional[Union[str, datetime, date]] = None,
 742 |     filing_date_gte: Optional[Union[str, datetime, date]] = None,
 743 |     period_of_report_date: Optional[Union[str, datetime, date]] = None,
 744 |     period_of_report_date_lt: Optional[Union[str, datetime, date]] = None,
 745 |     period_of_report_date_lte: Optional[Union[str, datetime, date]] = None,
 746 |     period_of_report_date_gt: Optional[Union[str, datetime, date]] = None,
 747 |     period_of_report_date_gte: Optional[Union[str, datetime, date]] = None,
 748 |     timeframe: Optional[str] = None,
 749 |     include_sources: Optional[bool] = None,
 750 |     limit: Optional[int] = None,
 751 |     sort: Optional[str] = None,
 752 |     order: Optional[str] = None,
 753 |     params: Optional[Dict[str, Any]] = None,
 754 | ) -> Dict[str, Any]:
 755 |     """
 756 |     Get fundamental financial data for companies.
 757 |     """
 758 |     try:
 759 |         results = polygon_client.vx.list_stock_financials(
 760 |             ticker=ticker,
 761 |             cik=cik,
 762 |             company_name=company_name,
 763 |             company_name_search=company_name_search,
 764 |             sic=sic,
 765 |             filing_date=filing_date,
 766 |             filing_date_lt=filing_date_lt,
 767 |             filing_date_lte=filing_date_lte,
 768 |             filing_date_gt=filing_date_gt,
 769 |             filing_date_gte=filing_date_gte,
 770 |             period_of_report_date=period_of_report_date,
 771 |             period_of_report_date_lt=period_of_report_date_lt,
 772 |             period_of_report_date_lte=period_of_report_date_lte,
 773 |             period_of_report_date_gt=period_of_report_date_gt,
 774 |             period_of_report_date_gte=period_of_report_date_gte,
 775 |             timeframe=timeframe,
 776 |             include_sources=include_sources,
 777 |             limit=limit,
 778 |             sort=sort,
 779 |             order=order,
 780 |             params=params,
 781 |             raw=True,
 782 |         )
 783 | 
 784 |         data_str = results.data.decode("utf-8")
 785 |         return json.loads(data_str)
 786 |     except Exception as e:
 787 |         return {"error": str(e)}
 788 | 
 789 | 
 790 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 791 | async def list_ipos(
 792 |     ticker: Optional[str] = None,
 793 |     listing_date: Optional[Union[str, datetime, date]] = None,
 794 |     listing_date_lt: Optional[Union[str, datetime, date]] = None,
 795 |     listing_date_lte: Optional[Union[str, datetime, date]] = None,
 796 |     listing_date_gt: Optional[Union[str, datetime, date]] = None,
 797 |     listing_date_gte: Optional[Union[str, datetime, date]] = None,
 798 |     ipo_status: Optional[str] = None,
 799 |     limit: Optional[int] = None,
 800 |     sort: Optional[str] = None,
 801 |     order: Optional[str] = None,
 802 |     params: Optional[Dict[str, Any]] = None,
 803 | ) -> Dict[str, Any]:
 804 |     """
 805 |     Retrieve upcoming or historical IPOs.
 806 |     """
 807 |     try:
 808 |         results = polygon_client.vx.list_ipos(
 809 |             ticker=ticker,
 810 |             listing_date=listing_date,
 811 |             listing_date_lt=listing_date_lt,
 812 |             listing_date_lte=listing_date_lte,
 813 |             listing_date_gt=listing_date_gt,
 814 |             listing_date_gte=listing_date_gte,
 815 |             ipo_status=ipo_status,
 816 |             limit=limit,
 817 |             sort=sort,
 818 |             order=order,
 819 |             params=params,
 820 |             raw=True,
 821 |         )
 822 | 
 823 |         data_str = results.data.decode("utf-8")
 824 |         return json.loads(data_str)
 825 |     except Exception as e:
 826 |         return {"error": str(e)}
 827 | 
 828 | 
 829 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 830 | async def list_short_interest(
 831 |     ticker: Optional[str] = None,
 832 |     settlement_date: Optional[Union[str, datetime, date]] = None,
 833 |     settlement_date_lt: Optional[Union[str, datetime, date]] = None,
 834 |     settlement_date_lte: Optional[Union[str, datetime, date]] = None,
 835 |     settlement_date_gt: Optional[Union[str, datetime, date]] = None,
 836 |     settlement_date_gte: Optional[Union[str, datetime, date]] = None,
 837 |     limit: Optional[int] = None,
 838 |     sort: Optional[str] = None,
 839 |     order: Optional[str] = None,
 840 |     params: Optional[Dict[str, Any]] = None,
 841 | ) -> Dict[str, Any]:
 842 |     """
 843 |     Retrieve short interest data for stocks.
 844 |     """
 845 |     try:
 846 |         results = polygon_client.list_short_interest(
 847 |             ticker=ticker,
 848 |             settlement_date=settlement_date,
 849 |             settlement_date_lt=settlement_date_lt,
 850 |             settlement_date_lte=settlement_date_lte,
 851 |             settlement_date_gt=settlement_date_gt,
 852 |             settlement_date_gte=settlement_date_gte,
 853 |             limit=limit,
 854 |             sort=sort,
 855 |             order=order,
 856 |             params=params,
 857 |             raw=True,
 858 |         )
 859 | 
 860 |         data_str = results.data.decode("utf-8")
 861 |         return json.loads(data_str)
 862 |     except Exception as e:
 863 |         return {"error": str(e)}
 864 | 
 865 | 
 866 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 867 | async def list_short_volume(
 868 |     ticker: Optional[str] = None,
 869 |     date: Optional[Union[str, datetime, date]] = None,
 870 |     date_lt: Optional[Union[str, datetime, date]] = None,
 871 |     date_lte: Optional[Union[str, datetime, date]] = None,
 872 |     date_gt: Optional[Union[str, datetime, date]] = None,
 873 |     date_gte: Optional[Union[str, datetime, date]] = None,
 874 |     limit: Optional[int] = None,
 875 |     sort: Optional[str] = None,
 876 |     order: Optional[str] = None,
 877 |     params: Optional[Dict[str, Any]] = None,
 878 | ) -> Dict[str, Any]:
 879 |     """
 880 |     Retrieve short volume data for stocks.
 881 |     """
 882 |     try:
 883 |         results = polygon_client.list_short_volume(
 884 |             ticker=ticker,
 885 |             date=date,
 886 |             date_lt=date_lt,
 887 |             date_lte=date_lte,
 888 |             date_gt=date_gt,
 889 |             date_gte=date_gte,
 890 |             limit=limit,
 891 |             sort=sort,
 892 |             order=order,
 893 |             params=params,
 894 |             raw=True,
 895 |         )
 896 | 
 897 |         data_str = results.data.decode("utf-8")
 898 |         return json.loads(data_str)
 899 |     except Exception as e:
 900 |         return {"error": str(e)}
 901 | 
 902 | 
 903 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 904 | async def list_treasury_yields(
 905 |     date: Optional[Union[str, datetime, date]] = None,
 906 |     date_any_of: Optional[str] = None,
 907 |     date_lt: Optional[Union[str, datetime, date]] = None,
 908 |     date_lte: Optional[Union[str, datetime, date]] = None,
 909 |     date_gt: Optional[Union[str, datetime, date]] = None,
 910 |     date_gte: Optional[Union[str, datetime, date]] = None,
 911 |     limit: Optional[int] = None,
 912 |     sort: Optional[str] = None,
 913 |     order: Optional[str] = None,
 914 |     params: Optional[Dict[str, Any]] = None,
 915 | ) -> Dict[str, Any]:
 916 |     """
 917 |     Retrieve treasury yield data.
 918 |     """
 919 |     try:
 920 |         results = polygon_client.list_treasury_yields(
 921 |             date=date,
 922 |             date_lt=date_lt,
 923 |             date_lte=date_lte,
 924 |             date_gt=date_gt,
 925 |             date_gte=date_gte,
 926 |             limit=limit,
 927 |             sort=sort,
 928 |             order=order,
 929 |             params=params,
 930 |             raw=True,
 931 |         )
 932 | 
 933 |         data_str = results.data.decode("utf-8")
 934 |         return json.loads(data_str)
 935 |     except Exception as e:
 936 |         return {"error": str(e)}
 937 | 
 938 | 
 939 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 940 | async def list_inflation(
 941 |     date: Optional[Union[str, datetime, date]] = None,
 942 |     date_any_of: Optional[str] = None,
 943 |     date_gt: Optional[Union[str, datetime, date]] = None,
 944 |     date_gte: Optional[Union[str, datetime, date]] = None,
 945 |     date_lt: Optional[Union[str, datetime, date]] = None,
 946 |     date_lte: Optional[Union[str, datetime, date]] = None,
 947 |     limit: Optional[int] = None,
 948 |     sort: Optional[str] = None,
 949 |     params: Optional[Dict[str, Any]] = None,
 950 | ) -> Dict[str, Any]:
 951 |     """
 952 |     Get inflation data from the Federal Reserve.
 953 |     """
 954 |     try:
 955 |         results = polygon_client.list_inflation(
 956 |             date=date,
 957 |             date_any_of=date_any_of,
 958 |             date_gt=date_gt,
 959 |             date_gte=date_gte,
 960 |             date_lt=date_lt,
 961 |             date_lte=date_lte,
 962 |             limit=limit,
 963 |             sort=sort,
 964 |             params=params,
 965 |             raw=True,
 966 |         )
 967 | 
 968 |         data_str = results.data.decode("utf-8")
 969 |         return json.loads(data_str)
 970 |     except Exception as e:
 971 |         return {"error": str(e)}
 972 | 
 973 | 
 974 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
 975 | async def list_benzinga_analyst_insights(
 976 |     date: Optional[Union[str, date]] = None,
 977 |     date_any_of: Optional[str] = None,
 978 |     date_gt: Optional[Union[str, date]] = None,
 979 |     date_gte: Optional[Union[str, date]] = None,
 980 |     date_lt: Optional[Union[str, date]] = None,
 981 |     date_lte: Optional[Union[str, date]] = None,
 982 |     ticker: Optional[str] = None,
 983 |     ticker_any_of: Optional[str] = None,
 984 |     ticker_gt: Optional[str] = None,
 985 |     ticker_gte: Optional[str] = None,
 986 |     ticker_lt: Optional[str] = None,
 987 |     ticker_lte: Optional[str] = None,
 988 |     last_updated: Optional[str] = None,
 989 |     last_updated_any_of: Optional[str] = None,
 990 |     last_updated_gt: Optional[str] = None,
 991 |     last_updated_gte: Optional[str] = None,
 992 |     last_updated_lt: Optional[str] = None,
 993 |     last_updated_lte: Optional[str] = None,
 994 |     firm: Optional[str] = None,
 995 |     firm_any_of: Optional[str] = None,
 996 |     firm_gt: Optional[str] = None,
 997 |     firm_gte: Optional[str] = None,
 998 |     firm_lt: Optional[str] = None,
 999 |     firm_lte: Optional[str] = None,
1000 |     rating_action: Optional[str] = None,
1001 |     rating_action_any_of: Optional[str] = None,
1002 |     rating_action_gt: Optional[str] = None,
1003 |     rating_action_gte: Optional[str] = None,
1004 |     rating_action_lt: Optional[str] = None,
1005 |     rating_action_lte: Optional[str] = None,
1006 |     benzinga_firm_id: Optional[str] = None,
1007 |     benzinga_firm_id_any_of: Optional[str] = None,
1008 |     benzinga_firm_id_gt: Optional[str] = None,
1009 |     benzinga_firm_id_gte: Optional[str] = None,
1010 |     benzinga_firm_id_lt: Optional[str] = None,
1011 |     benzinga_firm_id_lte: Optional[str] = None,
1012 |     benzinga_rating_id: Optional[str] = None,
1013 |     benzinga_rating_id_any_of: Optional[str] = None,
1014 |     benzinga_rating_id_gt: Optional[str] = None,
1015 |     benzinga_rating_id_gte: Optional[str] = None,
1016 |     benzinga_rating_id_lt: Optional[str] = None,
1017 |     benzinga_rating_id_lte: Optional[str] = None,
1018 |     limit: Optional[int] = None,
1019 |     sort: Optional[str] = None,
1020 |     params: Optional[Dict[str, Any]] = None,
1021 | ) -> Dict[str, Any]:
1022 |     """
1023 |     List Benzinga analyst insights.
1024 |     """
1025 |     try:
1026 |         results = polygon_client.list_benzinga_analyst_insights(
1027 |             date=date,
1028 |             date_any_of=date_any_of,
1029 |             date_gt=date_gt,
1030 |             date_gte=date_gte,
1031 |             date_lt=date_lt,
1032 |             date_lte=date_lte,
1033 |             ticker=ticker,
1034 |             ticker_any_of=ticker_any_of,
1035 |             ticker_gt=ticker_gt,
1036 |             ticker_gte=ticker_gte,
1037 |             ticker_lt=ticker_lt,
1038 |             ticker_lte=ticker_lte,
1039 |             last_updated=last_updated,
1040 |             last_updated_any_of=last_updated_any_of,
1041 |             last_updated_gt=last_updated_gt,
1042 |             last_updated_gte=last_updated_gte,
1043 |             last_updated_lt=last_updated_lt,
1044 |             last_updated_lte=last_updated_lte,
1045 |             firm=firm,
1046 |             firm_any_of=firm_any_of,
1047 |             firm_gt=firm_gt,
1048 |             firm_gte=firm_gte,
1049 |             firm_lt=firm_lt,
1050 |             firm_lte=firm_lte,
1051 |             rating_action=rating_action,
1052 |             rating_action_any_of=rating_action_any_of,
1053 |             rating_action_gt=rating_action_gt,
1054 |             rating_action_gte=rating_action_gte,
1055 |             rating_action_lt=rating_action_lt,
1056 |             rating_action_lte=rating_action_lte,
1057 |             benzinga_firm_id=benzinga_firm_id,
1058 |             benzinga_firm_id_any_of=benzinga_firm_id_any_of,
1059 |             benzinga_firm_id_gt=benzinga_firm_id_gt,
1060 |             benzinga_firm_id_gte=benzinga_firm_id_gte,
1061 |             benzinga_firm_id_lt=benzinga_firm_id_lt,
1062 |             benzinga_firm_id_lte=benzinga_firm_id_lte,
1063 |             benzinga_rating_id=benzinga_rating_id,
1064 |             benzinga_rating_id_any_of=benzinga_rating_id_any_of,
1065 |             benzinga_rating_id_gt=benzinga_rating_id_gt,
1066 |             benzinga_rating_id_gte=benzinga_rating_id_gte,
1067 |             benzinga_rating_id_lt=benzinga_rating_id_lt,
1068 |             benzinga_rating_id_lte=benzinga_rating_id_lte,
1069 |             limit=limit,
1070 |             sort=sort,
1071 |             params=params,
1072 |             raw=True,
1073 |         )
1074 | 
1075 |         data_str = results.data.decode("utf-8")
1076 |         return json.loads(data_str)
1077 |     except Exception as e:
1078 |         return {"error": str(e)}
1079 | 
1080 | 
1081 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1082 | async def list_benzinga_analysts(
1083 |     benzinga_id: Optional[str] = None,
1084 |     benzinga_id_any_of: Optional[str] = None,
1085 |     benzinga_id_gt: Optional[str] = None,
1086 |     benzinga_id_gte: Optional[str] = None,
1087 |     benzinga_id_lt: Optional[str] = None,
1088 |     benzinga_id_lte: Optional[str] = None,
1089 |     benzinga_firm_id: Optional[str] = None,
1090 |     benzinga_firm_id_any_of: Optional[str] = None,
1091 |     benzinga_firm_id_gt: Optional[str] = None,
1092 |     benzinga_firm_id_gte: Optional[str] = None,
1093 |     benzinga_firm_id_lt: Optional[str] = None,
1094 |     benzinga_firm_id_lte: Optional[str] = None,
1095 |     firm_name: Optional[str] = None,
1096 |     firm_name_any_of: Optional[str] = None,
1097 |     firm_name_gt: Optional[str] = None,
1098 |     firm_name_gte: Optional[str] = None,
1099 |     firm_name_lt: Optional[str] = None,
1100 |     firm_name_lte: Optional[str] = None,
1101 |     full_name: Optional[str] = None,
1102 |     full_name_any_of: Optional[str] = None,
1103 |     full_name_gt: Optional[str] = None,
1104 |     full_name_gte: Optional[str] = None,
1105 |     full_name_lt: Optional[str] = None,
1106 |     full_name_lte: Optional[str] = None,
1107 |     limit: Optional[int] = None,
1108 |     sort: Optional[str] = None,
1109 |     params: Optional[Dict[str, Any]] = None,
1110 | ) -> Dict[str, Any]:
1111 |     """
1112 |     List Benzinga analysts.
1113 |     """
1114 |     try:
1115 |         results = polygon_client.list_benzinga_analysts(
1116 |             benzinga_id=benzinga_id,
1117 |             benzinga_id_any_of=benzinga_id_any_of,
1118 |             benzinga_id_gt=benzinga_id_gt,
1119 |             benzinga_id_gte=benzinga_id_gte,
1120 |             benzinga_id_lt=benzinga_id_lt,
1121 |             benzinga_id_lte=benzinga_id_lte,
1122 |             benzinga_firm_id=benzinga_firm_id,
1123 |             benzinga_firm_id_any_of=benzinga_firm_id_any_of,
1124 |             benzinga_firm_id_gt=benzinga_firm_id_gt,
1125 |             benzinga_firm_id_gte=benzinga_firm_id_gte,
1126 |             benzinga_firm_id_lt=benzinga_firm_id_lt,
1127 |             benzinga_firm_id_lte=benzinga_firm_id_lte,
1128 |             firm_name=firm_name,
1129 |             firm_name_any_of=firm_name_any_of,
1130 |             firm_name_gt=firm_name_gt,
1131 |             firm_name_gte=firm_name_gte,
1132 |             firm_name_lt=firm_name_lt,
1133 |             firm_name_lte=firm_name_lte,
1134 |             full_name=full_name,
1135 |             full_name_any_of=full_name_any_of,
1136 |             full_name_gt=full_name_gt,
1137 |             full_name_gte=full_name_gte,
1138 |             full_name_lt=full_name_lt,
1139 |             full_name_lte=full_name_lte,
1140 |             limit=limit,
1141 |             sort=sort,
1142 |             params=params,
1143 |             raw=True,
1144 |         )
1145 | 
1146 |         data_str = results.data.decode("utf-8")
1147 |         return json.loads(data_str)
1148 |     except Exception as e:
1149 |         return {"error": str(e)}
1150 | 
1151 | 
1152 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1153 | async def list_benzinga_consensus_ratings(
1154 |     ticker: str,
1155 |     date: Optional[Union[str, date]] = None,
1156 |     date_gt: Optional[Union[str, date]] = None,
1157 |     date_gte: Optional[Union[str, date]] = None,
1158 |     date_lt: Optional[Union[str, date]] = None,
1159 |     date_lte: Optional[Union[str, date]] = None,
1160 |     limit: Optional[int] = None,
1161 |     params: Optional[Dict[str, Any]] = None,
1162 | ) -> Dict[str, Any]:
1163 |     """
1164 |     List Benzinga consensus ratings for a ticker.
1165 |     """
1166 |     try:
1167 |         results = polygon_client.list_benzinga_consensus_ratings(
1168 |             ticker=ticker,
1169 |             date=date,
1170 |             date_gt=date_gt,
1171 |             date_gte=date_gte,
1172 |             date_lt=date_lt,
1173 |             date_lte=date_lte,
1174 |             limit=limit,
1175 |             params=params,
1176 |             raw=True,
1177 |         )
1178 | 
1179 |         data_str = results.data.decode("utf-8")
1180 |         return json.loads(data_str)
1181 |     except Exception as e:
1182 |         return {"error": str(e)}
1183 | 
1184 | 
1185 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1186 | async def list_benzinga_earnings(
1187 |     date: Optional[Union[str, date]] = None,
1188 |     date_any_of: Optional[str] = None,
1189 |     date_gt: Optional[Union[str, date]] = None,
1190 |     date_gte: Optional[Union[str, date]] = None,
1191 |     date_lt: Optional[Union[str, date]] = None,
1192 |     date_lte: Optional[Union[str, date]] = None,
1193 |     ticker: Optional[str] = None,
1194 |     ticker_any_of: Optional[str] = None,
1195 |     ticker_gt: Optional[str] = None,
1196 |     ticker_gte: Optional[str] = None,
1197 |     ticker_lt: Optional[str] = None,
1198 |     ticker_lte: Optional[str] = None,
1199 |     importance: Optional[int] = None,
1200 |     importance_any_of: Optional[str] = None,
1201 |     importance_gt: Optional[int] = None,
1202 |     importance_gte: Optional[int] = None,
1203 |     importance_lt: Optional[int] = None,
1204 |     importance_lte: Optional[int] = None,
1205 |     last_updated: Optional[str] = None,
1206 |     last_updated_any_of: Optional[str] = None,
1207 |     last_updated_gt: Optional[str] = None,
1208 |     last_updated_gte: Optional[str] = None,
1209 |     last_updated_lt: Optional[str] = None,
1210 |     last_updated_lte: Optional[str] = None,
1211 |     date_status: Optional[str] = None,
1212 |     date_status_any_of: Optional[str] = None,
1213 |     date_status_gt: Optional[str] = None,
1214 |     date_status_gte: Optional[str] = None,
1215 |     date_status_lt: Optional[str] = None,
1216 |     date_status_lte: Optional[str] = None,
1217 |     eps_surprise_percent: Optional[float] = None,
1218 |     eps_surprise_percent_any_of: Optional[str] = None,
1219 |     eps_surprise_percent_gt: Optional[float] = None,
1220 |     eps_surprise_percent_gte: Optional[float] = None,
1221 |     eps_surprise_percent_lt: Optional[float] = None,
1222 |     eps_surprise_percent_lte: Optional[float] = None,
1223 |     revenue_surprise_percent: Optional[float] = None,
1224 |     revenue_surprise_percent_any_of: Optional[str] = None,
1225 |     revenue_surprise_percent_gt: Optional[float] = None,
1226 |     revenue_surprise_percent_gte: Optional[float] = None,
1227 |     revenue_surprise_percent_lt: Optional[float] = None,
1228 |     revenue_surprise_percent_lte: Optional[float] = None,
1229 |     fiscal_year: Optional[int] = None,
1230 |     fiscal_year_any_of: Optional[str] = None,
1231 |     fiscal_year_gt: Optional[int] = None,
1232 |     fiscal_year_gte: Optional[int] = None,
1233 |     fiscal_year_lt: Optional[int] = None,
1234 |     fiscal_year_lte: Optional[int] = None,
1235 |     fiscal_period: Optional[str] = None,
1236 |     fiscal_period_any_of: Optional[str] = None,
1237 |     fiscal_period_gt: Optional[str] = None,
1238 |     fiscal_period_gte: Optional[str] = None,
1239 |     fiscal_period_lt: Optional[str] = None,
1240 |     fiscal_period_lte: Optional[str] = None,
1241 |     limit: Optional[int] = None,
1242 |     sort: Optional[str] = None,
1243 |     params: Optional[Dict[str, Any]] = None,
1244 | ) -> Dict[str, Any]:
1245 |     """
1246 |     List Benzinga earnings.
1247 |     """
1248 |     try:
1249 |         results = polygon_client.list_benzinga_earnings(
1250 |             date=date,
1251 |             date_any_of=date_any_of,
1252 |             date_gt=date_gt,
1253 |             date_gte=date_gte,
1254 |             date_lt=date_lt,
1255 |             date_lte=date_lte,
1256 |             ticker=ticker,
1257 |             ticker_any_of=ticker_any_of,
1258 |             ticker_gt=ticker_gt,
1259 |             ticker_gte=ticker_gte,
1260 |             ticker_lt=ticker_lt,
1261 |             ticker_lte=ticker_lte,
1262 |             importance=importance,
1263 |             importance_any_of=importance_any_of,
1264 |             importance_gt=importance_gt,
1265 |             importance_gte=importance_gte,
1266 |             importance_lt=importance_lt,
1267 |             importance_lte=importance_lte,
1268 |             last_updated=last_updated,
1269 |             last_updated_any_of=last_updated_any_of,
1270 |             last_updated_gt=last_updated_gt,
1271 |             last_updated_gte=last_updated_gte,
1272 |             last_updated_lt=last_updated_lt,
1273 |             last_updated_lte=last_updated_lte,
1274 |             date_status=date_status,
1275 |             date_status_any_of=date_status_any_of,
1276 |             date_status_gt=date_status_gt,
1277 |             date_status_gte=date_status_gte,
1278 |             date_status_lt=date_status_lt,
1279 |             date_status_lte=date_status_lte,
1280 |             eps_surprise_percent=eps_surprise_percent,
1281 |             eps_surprise_percent_any_of=eps_surprise_percent_any_of,
1282 |             eps_surprise_percent_gt=eps_surprise_percent_gt,
1283 |             eps_surprise_percent_gte=eps_surprise_percent_gte,
1284 |             eps_surprise_percent_lt=eps_surprise_percent_lt,
1285 |             eps_surprise_percent_lte=eps_surprise_percent_lte,
1286 |             revenue_surprise_percent=revenue_surprise_percent,
1287 |             revenue_surprise_percent_any_of=revenue_surprise_percent_any_of,
1288 |             revenue_surprise_percent_gt=revenue_surprise_percent_gt,
1289 |             revenue_surprise_percent_gte=revenue_surprise_percent_gte,
1290 |             revenue_surprise_percent_lt=revenue_surprise_percent_lt,
1291 |             revenue_surprise_percent_lte=revenue_surprise_percent_lte,
1292 |             fiscal_year=fiscal_year,
1293 |             fiscal_year_any_of=fiscal_year_any_of,
1294 |             fiscal_year_gt=fiscal_year_gt,
1295 |             fiscal_year_gte=fiscal_year_gte,
1296 |             fiscal_year_lt=fiscal_year_lt,
1297 |             fiscal_year_lte=fiscal_year_lte,
1298 |             fiscal_period=fiscal_period,
1299 |             fiscal_period_any_of=fiscal_period_any_of,
1300 |             fiscal_period_gt=fiscal_period_gt,
1301 |             fiscal_period_gte=fiscal_period_gte,
1302 |             fiscal_period_lt=fiscal_period_lt,
1303 |             fiscal_period_lte=fiscal_period_lte,
1304 |             limit=limit,
1305 |             sort=sort,
1306 |             params=params,
1307 |             raw=True,
1308 |         )
1309 | 
1310 |         data_str = results.data.decode("utf-8")
1311 |         return json.loads(data_str)
1312 |     except Exception as e:
1313 |         return {"error": str(e)}
1314 | 
1315 | 
1316 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1317 | async def list_benzinga_firms(
1318 |     benzinga_id: Optional[str] = None,
1319 |     benzinga_id_any_of: Optional[str] = None,
1320 |     benzinga_id_gt: Optional[str] = None,
1321 |     benzinga_id_gte: Optional[str] = None,
1322 |     benzinga_id_lt: Optional[str] = None,
1323 |     benzinga_id_lte: Optional[str] = None,
1324 |     limit: Optional[int] = None,
1325 |     sort: Optional[str] = None,
1326 |     params: Optional[Dict[str, Any]] = None,
1327 | ) -> Dict[str, Any]:
1328 |     """
1329 |     List Benzinga firms.
1330 |     """
1331 |     try:
1332 |         results = polygon_client.list_benzinga_firms(
1333 |             benzinga_id=benzinga_id,
1334 |             benzinga_id_any_of=benzinga_id_any_of,
1335 |             benzinga_id_gt=benzinga_id_gt,
1336 |             benzinga_id_gte=benzinga_id_gte,
1337 |             benzinga_id_lt=benzinga_id_lt,
1338 |             benzinga_id_lte=benzinga_id_lte,
1339 |             limit=limit,
1340 |             sort=sort,
1341 |             params=params,
1342 |             raw=True,
1343 |         )
1344 | 
1345 |         data_str = results.data.decode("utf-8")
1346 |         return json.loads(data_str)
1347 |     except Exception as e:
1348 |         return {"error": str(e)}
1349 | 
1350 | 
1351 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1352 | async def list_benzinga_guidance(
1353 |     date: Optional[Union[str, date]] = None,
1354 |     date_any_of: Optional[str] = None,
1355 |     date_gt: Optional[Union[str, date]] = None,
1356 |     date_gte: Optional[Union[str, date]] = None,
1357 |     date_lt: Optional[Union[str, date]] = None,
1358 |     date_lte: Optional[Union[str, date]] = None,
1359 |     ticker: Optional[str] = None,
1360 |     ticker_any_of: Optional[str] = None,
1361 |     ticker_gt: Optional[str] = None,
1362 |     ticker_gte: Optional[str] = None,
1363 |     ticker_lt: Optional[str] = None,
1364 |     ticker_lte: Optional[str] = None,
1365 |     positioning: Optional[str] = None,
1366 |     positioning_any_of: Optional[str] = None,
1367 |     positioning_gt: Optional[str] = None,
1368 |     positioning_gte: Optional[str] = None,
1369 |     positioning_lt: Optional[str] = None,
1370 |     positioning_lte: Optional[str] = None,
1371 |     importance: Optional[int] = None,
1372 |     importance_any_of: Optional[str] = None,
1373 |     importance_gt: Optional[int] = None,
1374 |     importance_gte: Optional[int] = None,
1375 |     importance_lt: Optional[int] = None,
1376 |     importance_lte: Optional[int] = None,
1377 |     last_updated: Optional[str] = None,
1378 |     last_updated_any_of: Optional[str] = None,
1379 |     last_updated_gt: Optional[str] = None,
1380 |     last_updated_gte: Optional[str] = None,
1381 |     last_updated_lt: Optional[str] = None,
1382 |     last_updated_lte: Optional[str] = None,
1383 |     fiscal_year: Optional[int] = None,
1384 |     fiscal_year_any_of: Optional[str] = None,
1385 |     fiscal_year_gt: Optional[int] = None,
1386 |     fiscal_year_gte: Optional[int] = None,
1387 |     fiscal_year_lt: Optional[int] = None,
1388 |     fiscal_year_lte: Optional[int] = None,
1389 |     fiscal_period: Optional[str] = None,
1390 |     fiscal_period_any_of: Optional[str] = None,
1391 |     fiscal_period_gt: Optional[str] = None,
1392 |     fiscal_period_gte: Optional[str] = None,
1393 |     fiscal_period_lt: Optional[str] = None,
1394 |     fiscal_period_lte: Optional[str] = None,
1395 |     limit: Optional[int] = None,
1396 |     sort: Optional[str] = None,
1397 |     params: Optional[Dict[str, Any]] = None,
1398 | ) -> Dict[str, Any]:
1399 |     """
1400 |     List Benzinga guidance.
1401 |     """
1402 |     try:
1403 |         results = polygon_client.list_benzinga_guidance(
1404 |             date=date,
1405 |             date_any_of=date_any_of,
1406 |             date_gt=date_gt,
1407 |             date_gte=date_gte,
1408 |             date_lt=date_lt,
1409 |             date_lte=date_lte,
1410 |             ticker=ticker,
1411 |             ticker_any_of=ticker_any_of,
1412 |             ticker_gt=ticker_gt,
1413 |             ticker_gte=ticker_gte,
1414 |             ticker_lt=ticker_lt,
1415 |             ticker_lte=ticker_lte,
1416 |             positioning=positioning,
1417 |             positioning_any_of=positioning_any_of,
1418 |             positioning_gt=positioning_gt,
1419 |             positioning_gte=positioning_gte,
1420 |             positioning_lt=positioning_lt,
1421 |             positioning_lte=positioning_lte,
1422 |             importance=importance,
1423 |             importance_any_of=importance_any_of,
1424 |             importance_gt=importance_gt,
1425 |             importance_gte=importance_gte,
1426 |             importance_lt=importance_lt,
1427 |             importance_lte=importance_lte,
1428 |             last_updated=last_updated,
1429 |             last_updated_any_of=last_updated_any_of,
1430 |             last_updated_gt=last_updated_gt,
1431 |             last_updated_gte=last_updated_gte,
1432 |             last_updated_lt=last_updated_lt,
1433 |             last_updated_lte=last_updated_lte,
1434 |             fiscal_year=fiscal_year,
1435 |             fiscal_year_any_of=fiscal_year_any_of,
1436 |             fiscal_year_gt=fiscal_year_gt,
1437 |             fiscal_year_gte=fiscal_year_gte,
1438 |             fiscal_year_lt=fiscal_year_lt,
1439 |             fiscal_year_lte=fiscal_year_lte,
1440 |             fiscal_period=fiscal_period,
1441 |             fiscal_period_any_of=fiscal_period_any_of,
1442 |             fiscal_period_gt=fiscal_period_gt,
1443 |             fiscal_period_gte=fiscal_period_gte,
1444 |             fiscal_period_lt=fiscal_period_lt,
1445 |             fiscal_period_lte=fiscal_period_lte,
1446 |             limit=limit,
1447 |             sort=sort,
1448 |             params=params,
1449 |             raw=True,
1450 |         )
1451 | 
1452 |         data_str = results.data.decode("utf-8")
1453 |         return json.loads(data_str)
1454 |     except Exception as e:
1455 |         return {"error": str(e)}
1456 | 
1457 | 
1458 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1459 | async def list_benzinga_news(
1460 |     published: Optional[str] = None,
1461 |     published_any_of: Optional[str] = None,
1462 |     published_gt: Optional[str] = None,
1463 |     published_gte: Optional[str] = None,
1464 |     published_lt: Optional[str] = None,
1465 |     published_lte: Optional[str] = None,
1466 |     last_updated: Optional[str] = None,
1467 |     last_updated_any_of: Optional[str] = None,
1468 |     last_updated_gt: Optional[str] = None,
1469 |     last_updated_gte: Optional[str] = None,
1470 |     last_updated_lt: Optional[str] = None,
1471 |     last_updated_lte: Optional[str] = None,
1472 |     tickers: Optional[str] = None,
1473 |     tickers_all_of: Optional[str] = None,
1474 |     tickers_any_of: Optional[str] = None,
1475 |     channels: Optional[str] = None,
1476 |     channels_all_of: Optional[str] = None,
1477 |     channels_any_of: Optional[str] = None,
1478 |     tags: Optional[str] = None,
1479 |     tags_all_of: Optional[str] = None,
1480 |     tags_any_of: Optional[str] = None,
1481 |     author: Optional[str] = None,
1482 |     author_any_of: Optional[str] = None,
1483 |     author_gt: Optional[str] = None,
1484 |     author_gte: Optional[str] = None,
1485 |     author_lt: Optional[str] = None,
1486 |     author_lte: Optional[str] = None,
1487 |     limit: Optional[int] = None,
1488 |     sort: Optional[str] = None,
1489 |     params: Optional[Dict[str, Any]] = None,
1490 | ) -> Dict[str, Any]:
1491 |     """
1492 |     List Benzinga news.
1493 |     """
1494 |     try:
1495 |         results = polygon_client.list_benzinga_news(
1496 |             published=published,
1497 |             published_any_of=published_any_of,
1498 |             published_gt=published_gt,
1499 |             published_gte=published_gte,
1500 |             published_lt=published_lt,
1501 |             published_lte=published_lte,
1502 |             last_updated=last_updated,
1503 |             last_updated_any_of=last_updated_any_of,
1504 |             last_updated_gt=last_updated_gt,
1505 |             last_updated_gte=last_updated_gte,
1506 |             last_updated_lt=last_updated_lt,
1507 |             last_updated_lte=last_updated_lte,
1508 |             tickers=tickers,
1509 |             tickers_all_of=tickers_all_of,
1510 |             tickers_any_of=tickers_any_of,
1511 |             channels=channels,
1512 |             channels_all_of=channels_all_of,
1513 |             channels_any_of=channels_any_of,
1514 |             tags=tags,
1515 |             tags_all_of=tags_all_of,
1516 |             tags_any_of=tags_any_of,
1517 |             author=author,
1518 |             author_any_of=author_any_of,
1519 |             author_gt=author_gt,
1520 |             author_gte=author_gte,
1521 |             author_lt=author_lt,
1522 |             author_lte=author_lte,
1523 |             limit=limit,
1524 |             sort=sort,
1525 |             params=params,
1526 |             raw=True,
1527 |         )
1528 | 
1529 |         data_str = results.data.decode("utf-8")
1530 |         return json.loads(data_str)
1531 |     except Exception as e:
1532 |         return {"error": str(e)}
1533 | 
1534 | 
1535 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1536 | async def list_benzinga_ratings(
1537 |     date: Optional[Union[str, date]] = None,
1538 |     date_any_of: Optional[str] = None,
1539 |     date_gt: Optional[Union[str, date]] = None,
1540 |     date_gte: Optional[Union[str, date]] = None,
1541 |     date_lt: Optional[Union[str, date]] = None,
1542 |     date_lte: Optional[Union[str, date]] = None,
1543 |     ticker: Optional[str] = None,
1544 |     ticker_any_of: Optional[str] = None,
1545 |     ticker_gt: Optional[str] = None,
1546 |     ticker_gte: Optional[str] = None,
1547 |     ticker_lt: Optional[str] = None,
1548 |     ticker_lte: Optional[str] = None,
1549 |     importance: Optional[int] = None,
1550 |     importance_any_of: Optional[str] = None,
1551 |     importance_gt: Optional[int] = None,
1552 |     importance_gte: Optional[int] = None,
1553 |     importance_lt: Optional[int] = None,
1554 |     importance_lte: Optional[int] = None,
1555 |     last_updated: Optional[str] = None,
1556 |     last_updated_any_of: Optional[str] = None,
1557 |     last_updated_gt: Optional[str] = None,
1558 |     last_updated_gte: Optional[str] = None,
1559 |     last_updated_lt: Optional[str] = None,
1560 |     last_updated_lte: Optional[str] = None,
1561 |     rating_action: Optional[str] = None,
1562 |     rating_action_any_of: Optional[str] = None,
1563 |     rating_action_gt: Optional[str] = None,
1564 |     rating_action_gte: Optional[str] = None,
1565 |     rating_action_lt: Optional[str] = None,
1566 |     rating_action_lte: Optional[str] = None,
1567 |     price_target_action: Optional[str] = None,
1568 |     price_target_action_any_of: Optional[str] = None,
1569 |     price_target_action_gt: Optional[str] = None,
1570 |     price_target_action_gte: Optional[str] = None,
1571 |     price_target_action_lt: Optional[str] = None,
1572 |     price_target_action_lte: Optional[str] = None,
1573 |     benzinga_id: Optional[str] = None,
1574 |     benzinga_id_any_of: Optional[str] = None,
1575 |     benzinga_id_gt: Optional[str] = None,
1576 |     benzinga_id_gte: Optional[str] = None,
1577 |     benzinga_id_lt: Optional[str] = None,
1578 |     benzinga_id_lte: Optional[str] = None,
1579 |     benzinga_analyst_id: Optional[str] = None,
1580 |     benzinga_analyst_id_any_of: Optional[str] = None,
1581 |     benzinga_analyst_id_gt: Optional[str] = None,
1582 |     benzinga_analyst_id_gte: Optional[str] = None,
1583 |     benzinga_analyst_id_lt: Optional[str] = None,
1584 |     benzinga_analyst_id_lte: Optional[str] = None,
1585 |     benzinga_firm_id: Optional[str] = None,
1586 |     benzinga_firm_id_any_of: Optional[str] = None,
1587 |     benzinga_firm_id_gt: Optional[str] = None,
1588 |     benzinga_firm_id_gte: Optional[str] = None,
1589 |     benzinga_firm_id_lt: Optional[str] = None,
1590 |     benzinga_firm_id_lte: Optional[str] = None,
1591 |     limit: Optional[int] = None,
1592 |     sort: Optional[str] = None,
1593 |     params: Optional[Dict[str, Any]] = None,
1594 | ) -> Dict[str, Any]:
1595 |     """
1596 |     List Benzinga ratings.
1597 |     """
1598 |     try:
1599 |         results = polygon_client.list_benzinga_ratings(
1600 |             date=date,
1601 |             date_any_of=date_any_of,
1602 |             date_gt=date_gt,
1603 |             date_gte=date_gte,
1604 |             date_lt=date_lt,
1605 |             date_lte=date_lte,
1606 |             ticker=ticker,
1607 |             ticker_any_of=ticker_any_of,
1608 |             ticker_gt=ticker_gt,
1609 |             ticker_gte=ticker_gte,
1610 |             ticker_lt=ticker_lt,
1611 |             ticker_lte=ticker_lte,
1612 |             importance=importance,
1613 |             importance_any_of=importance_any_of,
1614 |             importance_gt=importance_gt,
1615 |             importance_gte=importance_gte,
1616 |             importance_lt=importance_lt,
1617 |             importance_lte=importance_lte,
1618 |             last_updated=last_updated,
1619 |             last_updated_any_of=last_updated_any_of,
1620 |             last_updated_gt=last_updated_gt,
1621 |             last_updated_gte=last_updated_gte,
1622 |             last_updated_lt=last_updated_lt,
1623 |             last_updated_lte=last_updated_lte,
1624 |             rating_action=rating_action,
1625 |             rating_action_any_of=rating_action_any_of,
1626 |             rating_action_gt=rating_action_gt,
1627 |             rating_action_gte=rating_action_gte,
1628 |             rating_action_lt=rating_action_lt,
1629 |             rating_action_lte=rating_action_lte,
1630 |             price_target_action=price_target_action,
1631 |             price_target_action_any_of=price_target_action_any_of,
1632 |             price_target_action_gt=price_target_action_gt,
1633 |             price_target_action_gte=price_target_action_gte,
1634 |             price_target_action_lt=price_target_action_lt,
1635 |             price_target_action_lte=price_target_action_lte,
1636 |             benzinga_id=benzinga_id,
1637 |             benzinga_id_any_of=benzinga_id_any_of,
1638 |             benzinga_id_gt=benzinga_id_gt,
1639 |             benzinga_id_gte=benzinga_id_gte,
1640 |             benzinga_id_lt=benzinga_id_lt,
1641 |             benzinga_id_lte=benzinga_id_lte,
1642 |             benzinga_analyst_id=benzinga_analyst_id,
1643 |             benzinga_analyst_id_any_of=benzinga_analyst_id_any_of,
1644 |             benzinga_analyst_id_gt=benzinga_analyst_id_gt,
1645 |             benzinga_analyst_id_gte=benzinga_analyst_id_gte,
1646 |             benzinga_analyst_id_lt=benzinga_analyst_id_lt,
1647 |             benzinga_analyst_id_lte=benzinga_analyst_id_lte,
1648 |             benzinga_firm_id=benzinga_firm_id,
1649 |             benzinga_firm_id_any_of=benzinga_firm_id_any_of,
1650 |             benzinga_firm_id_gt=benzinga_firm_id_gt,
1651 |             benzinga_firm_id_gte=benzinga_firm_id_gte,
1652 |             benzinga_firm_id_lt=benzinga_firm_id_lt,
1653 |             benzinga_firm_id_lte=benzinga_firm_id_lte,
1654 |             limit=limit,
1655 |             sort=sort,
1656 |             params=params,
1657 |             raw=True,
1658 |         )
1659 | 
1660 |         data_str = results.data.decode("utf-8")
1661 |         return json.loads(data_str)
1662 |     except Exception as e:
1663 |         return {"error": str(e)}
1664 | 
1665 | 
1666 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1667 | async def list_futures_aggregates(
1668 |     ticker: str,
1669 |     resolution: str,
1670 |     window_start: Optional[str] = None,
1671 |     window_start_lt: Optional[str] = None,
1672 |     window_start_lte: Optional[str] = None,
1673 |     window_start_gt: Optional[str] = None,
1674 |     window_start_gte: Optional[str] = None,
1675 |     limit: Optional[int] = None,
1676 |     sort: Optional[str] = None,
1677 |     params: Optional[Dict[str, Any]] = None,
1678 | ) -> Dict[str, Any]:
1679 |     """
1680 |     Get aggregates for a futures contract in a given time range.
1681 |     """
1682 |     try:
1683 |         results = polygon_client.list_futures_aggregates(
1684 |             ticker=ticker,
1685 |             resolution=resolution,
1686 |             window_start=window_start,
1687 |             window_start_lt=window_start_lt,
1688 |             window_start_lte=window_start_lte,
1689 |             window_start_gt=window_start_gt,
1690 |             window_start_gte=window_start_gte,
1691 |             limit=limit,
1692 |             sort=sort,
1693 |             params=params,
1694 |             raw=True,
1695 |         )
1696 | 
1697 |         data_str = results.data.decode("utf-8")
1698 |         return json.loads(data_str)
1699 |     except Exception as e:
1700 |         return {"error": str(e)}
1701 | 
1702 | 
1703 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1704 | async def list_futures_contracts(
1705 |     product_code: Optional[str] = None,
1706 |     first_trade_date: Optional[Union[str, date]] = None,
1707 |     last_trade_date: Optional[Union[str, date]] = None,
1708 |     as_of: Optional[Union[str, date]] = None,
1709 |     active: Optional[str] = None,
1710 |     type: Optional[str] = None,
1711 |     limit: Optional[int] = None,
1712 |     sort: Optional[str] = None,
1713 |     params: Optional[Dict[str, Any]] = None,
1714 | ) -> Dict[str, Any]:
1715 |     """
1716 |     Get a paginated list of futures contracts.
1717 |     """
1718 |     try:
1719 |         results = polygon_client.list_futures_contracts(
1720 |             product_code=product_code,
1721 |             first_trade_date=first_trade_date,
1722 |             last_trade_date=last_trade_date,
1723 |             as_of=as_of,
1724 |             active=active,
1725 |             type=type,
1726 |             limit=limit,
1727 |             sort=sort,
1728 |             params=params,
1729 |             raw=True,
1730 |         )
1731 | 
1732 |         data_str = results.data.decode("utf-8")
1733 |         return json.loads(data_str)
1734 |     except Exception as e:
1735 |         return {"error": str(e)}
1736 | 
1737 | 
1738 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1739 | async def get_futures_contract_details(
1740 |     ticker: str,
1741 |     as_of: Optional[Union[str, date]] = None,
1742 |     params: Optional[Dict[str, Any]] = None,
1743 | ) -> Dict[str, Any]:
1744 |     """
1745 |     Get details for a single futures contract at a specified point in time.
1746 |     """
1747 |     try:
1748 |         results = polygon_client.get_futures_contract_details(
1749 |             ticker=ticker,
1750 |             as_of=as_of,
1751 |             params=params,
1752 |             raw=True,
1753 |         )
1754 | 
1755 |         data_str = results.data.decode("utf-8")
1756 |         return json.loads(data_str)
1757 |     except Exception as e:
1758 |         return {"error": str(e)}
1759 | 
1760 | 
1761 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1762 | async def list_futures_products(
1763 |     name: Optional[str] = None,
1764 |     name_search: Optional[str] = None,
1765 |     as_of: Optional[Union[str, date]] = None,
1766 |     trading_venue: Optional[str] = None,
1767 |     sector: Optional[str] = None,
1768 |     sub_sector: Optional[str] = None,
1769 |     asset_class: Optional[str] = None,
1770 |     asset_sub_class: Optional[str] = None,
1771 |     type: Optional[str] = None,
1772 |     limit: Optional[int] = None,
1773 |     sort: Optional[str] = None,
1774 |     params: Optional[Dict[str, Any]] = None,
1775 | ) -> Dict[str, Any]:
1776 |     """
1777 |     Get a list of futures products (including combos).
1778 |     """
1779 |     try:
1780 |         results = polygon_client.list_futures_products(
1781 |             name=name,
1782 |             name_search=name_search,
1783 |             as_of=as_of,
1784 |             trading_venue=trading_venue,
1785 |             sector=sector,
1786 |             sub_sector=sub_sector,
1787 |             asset_class=asset_class,
1788 |             asset_sub_class=asset_sub_class,
1789 |             type=type,
1790 |             limit=limit,
1791 |             sort=sort,
1792 |             params=params,
1793 |             raw=True,
1794 |         )
1795 | 
1796 |         data_str = results.data.decode("utf-8")
1797 |         return json.loads(data_str)
1798 |     except Exception as e:
1799 |         return {"error": str(e)}
1800 | 
1801 | 
1802 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1803 | async def get_futures_product_details(
1804 |     product_code: str,
1805 |     type: Optional[str] = None,
1806 |     as_of: Optional[Union[str, date]] = None,
1807 |     params: Optional[Dict[str, Any]] = None,
1808 | ) -> Dict[str, Any]:
1809 |     """
1810 |     Get details for a single futures product as it was at a specific day.
1811 |     """
1812 |     try:
1813 |         results = polygon_client.get_futures_product_details(
1814 |             product_code=product_code,
1815 |             type=type,
1816 |             as_of=as_of,
1817 |             params=params,
1818 |             raw=True,
1819 |         )
1820 | 
1821 |         data_str = results.data.decode("utf-8")
1822 |         return json.loads(data_str)
1823 |     except Exception as e:
1824 |         return {"error": str(e)}
1825 | 
1826 | 
1827 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1828 | async def list_futures_quotes(
1829 |     ticker: str,
1830 |     timestamp: Optional[str] = None,
1831 |     timestamp_lt: Optional[str] = None,
1832 |     timestamp_lte: Optional[str] = None,
1833 |     timestamp_gt: Optional[str] = None,
1834 |     timestamp_gte: Optional[str] = None,
1835 |     session_end_date: Optional[str] = None,
1836 |     session_end_date_lt: Optional[str] = None,
1837 |     session_end_date_lte: Optional[str] = None,
1838 |     session_end_date_gt: Optional[str] = None,
1839 |     session_end_date_gte: Optional[str] = None,
1840 |     limit: Optional[int] = None,
1841 |     sort: Optional[str] = None,
1842 |     params: Optional[Dict[str, Any]] = None,
1843 | ) -> Dict[str, Any]:
1844 |     """
1845 |     Get quotes for a futures contract in a given time range.
1846 |     """
1847 |     try:
1848 |         results = polygon_client.list_futures_quotes(
1849 |             ticker=ticker,
1850 |             timestamp=timestamp,
1851 |             timestamp_lt=timestamp_lt,
1852 |             timestamp_lte=timestamp_lte,
1853 |             timestamp_gt=timestamp_gt,
1854 |             timestamp_gte=timestamp_gte,
1855 |             session_end_date=session_end_date,
1856 |             session_end_date_lt=session_end_date_lt,
1857 |             session_end_date_lte=session_end_date_lte,
1858 |             session_end_date_gt=session_end_date_gt,
1859 |             session_end_date_gte=session_end_date_gte,
1860 |             limit=limit,
1861 |             sort=sort,
1862 |             params=params,
1863 |             raw=True,
1864 |         )
1865 | 
1866 |         data_str = results.data.decode("utf-8")
1867 |         return json.loads(data_str)
1868 |     except Exception as e:
1869 |         return {"error": str(e)}
1870 | 
1871 | 
1872 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1873 | async def list_futures_trades(
1874 |     ticker: str,
1875 |     timestamp: Optional[str] = None,
1876 |     timestamp_lt: Optional[str] = None,
1877 |     timestamp_lte: Optional[str] = None,
1878 |     timestamp_gt: Optional[str] = None,
1879 |     timestamp_gte: Optional[str] = None,
1880 |     session_end_date: Optional[str] = None,
1881 |     session_end_date_lt: Optional[str] = None,
1882 |     session_end_date_lte: Optional[str] = None,
1883 |     session_end_date_gt: Optional[str] = None,
1884 |     session_end_date_gte: Optional[str] = None,
1885 |     limit: Optional[int] = None,
1886 |     sort: Optional[str] = None,
1887 |     params: Optional[Dict[str, Any]] = None,
1888 | ) -> Dict[str, Any]:
1889 |     """
1890 |     Get trades for a futures contract in a given time range.
1891 |     """
1892 |     try:
1893 |         results = polygon_client.list_futures_trades(
1894 |             ticker=ticker,
1895 |             timestamp=timestamp,
1896 |             timestamp_lt=timestamp_lt,
1897 |             timestamp_lte=timestamp_lte,
1898 |             timestamp_gt=timestamp_gt,
1899 |             timestamp_gte=timestamp_gte,
1900 |             session_end_date=session_end_date,
1901 |             session_end_date_lt=session_end_date_lt,
1902 |             session_end_date_lte=session_end_date_lte,
1903 |             session_end_date_gt=session_end_date_gt,
1904 |             session_end_date_gte=session_end_date_gte,
1905 |             limit=limit,
1906 |             sort=sort,
1907 |             params=params,
1908 |             raw=True,
1909 |         )
1910 | 
1911 |         data_str = results.data.decode("utf-8")
1912 |         return json.loads(data_str)
1913 |     except Exception as e:
1914 |         return {"error": str(e)}
1915 | 
1916 | 
1917 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1918 | async def list_futures_schedules(
1919 |     session_end_date: Optional[str] = None,
1920 |     trading_venue: Optional[str] = None,
1921 |     limit: Optional[int] = None,
1922 |     sort: Optional[str] = None,
1923 |     params: Optional[Dict[str, Any]] = None,
1924 | ) -> Dict[str, Any]:
1925 |     """
1926 |     Get trading schedules for multiple futures products on a specific date.
1927 |     """
1928 |     try:
1929 |         results = polygon_client.list_futures_schedules(
1930 |             session_end_date=session_end_date,
1931 |             trading_venue=trading_venue,
1932 |             limit=limit,
1933 |             sort=sort,
1934 |             params=params,
1935 |             raw=True,
1936 |         )
1937 | 
1938 |         data_str = results.data.decode("utf-8")
1939 |         return json.loads(data_str)
1940 |     except Exception as e:
1941 |         return {"error": str(e)}
1942 | 
1943 | 
1944 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1945 | async def list_futures_schedules_by_product_code(
1946 |     product_code: str,
1947 |     session_end_date: Optional[str] = None,
1948 |     session_end_date_lt: Optional[str] = None,
1949 |     session_end_date_lte: Optional[str] = None,
1950 |     session_end_date_gt: Optional[str] = None,
1951 |     session_end_date_gte: Optional[str] = None,
1952 |     limit: Optional[int] = None,
1953 |     sort: Optional[str] = None,
1954 |     params: Optional[Dict[str, Any]] = None,
1955 | ) -> Dict[str, Any]:
1956 |     """
1957 |     Get schedule data for a single futures product across many trading dates.
1958 |     """
1959 |     try:
1960 |         results = polygon_client.list_futures_schedules_by_product_code(
1961 |             product_code=product_code,
1962 |             session_end_date=session_end_date,
1963 |             session_end_date_lt=session_end_date_lt,
1964 |             session_end_date_lte=session_end_date_lte,
1965 |             session_end_date_gt=session_end_date_gt,
1966 |             session_end_date_gte=session_end_date_gte,
1967 |             limit=limit,
1968 |             sort=sort,
1969 |             params=params,
1970 |             raw=True,
1971 |         )
1972 | 
1973 |         data_str = results.data.decode("utf-8")
1974 |         return json.loads(data_str)
1975 |     except Exception as e:
1976 |         return {"error": str(e)}
1977 | 
1978 | 
1979 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
1980 | async def list_futures_market_statuses(
1981 |     product_code_any_of: Optional[str] = None,
1982 |     product_code: Optional[str] = None,
1983 |     limit: Optional[int] = None,
1984 |     sort: Optional[str] = None,
1985 |     params: Optional[Dict[str, Any]] = None,
1986 | ) -> Dict[str, Any]:
1987 |     """
1988 |     Get market statuses for futures products.
1989 |     """
1990 |     try:
1991 |         results = polygon_client.list_futures_market_statuses(
1992 |             product_code_any_of=product_code_any_of,
1993 |             product_code=product_code,
1994 |             limit=limit,
1995 |             sort=sort,
1996 |             params=params,
1997 |             raw=True,
1998 |         )
1999 | 
2000 |         data_str = results.data.decode("utf-8")
2001 |         return json.loads(data_str)
2002 |     except Exception as e:
2003 |         return {"error": str(e)}
2004 | 
2005 | 
2006 | @poly_mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
2007 | async def get_futures_snapshot(
2008 |     ticker: Optional[str] = None,
2009 |     ticker_any_of: Optional[str] = None,
2010 |     ticker_gt: Optional[str] = None,
2011 |     ticker_gte: Optional[str] = None,
2012 |     ticker_lt: Optional[str] = None,
2013 |     ticker_lte: Optional[str] = None,
2014 |     product_code: Optional[str] = None,
2015 |     product_code_any_of: Optional[str] = None,
2016 |     product_code_gt: Optional[str] = None,
2017 |     product_code_gte: Optional[str] = None,
2018 |     product_code_lt: Optional[str] = None,
2019 |     product_code_lte: Optional[str] = None,
2020 |     limit: Optional[int] = None,
2021 |     sort: Optional[str] = None,
2022 |     params: Optional[Dict[str, Any]] = None,
2023 | ) -> Dict[str, Any]:
2024 |     """
2025 |     Get snapshots for futures contracts.
2026 |     """
2027 |     try:
2028 |         results = polygon_client.get_futures_snapshot(
2029 |             ticker=ticker,
2030 |             ticker_any_of=ticker_any_of,
2031 |             ticker_gt=ticker_gt,
2032 |             ticker_gte=ticker_gte,
2033 |             ticker_lt=ticker_lt,
2034 |             ticker_lte=ticker_lte,
2035 |             product_code=product_code,
2036 |             product_code_any_of=product_code_any_of,
2037 |             product_code_gt=product_code_gt,
2038 |             product_code_gte=product_code_gte,
2039 |             product_code_lt=product_code_lt,
2040 |             product_code_lte=product_code_lte,
2041 |             limit=limit,
2042 |             sort=sort,
2043 |             params=params,
2044 |             raw=True,
2045 |         )
2046 | 
2047 |         data_str = results.data.decode("utf-8")
2048 |         return json.loads(data_str)
2049 |     except Exception as e:
2050 |         return {"error": str(e)}
2051 | 
2052 | 
2053 | # Directly expose the MCP server object
2054 | # It will be run from entrypoint.py
2055 | 
2056 | 
2057 | def run(transport: Literal["stdio", "sse", "streamable-http"] = "stdio") -> None:
2058 |     """Run the Polygon MCP server."""
2059 |     poly_mcp.run(transport)
2060 | 
```