Schwab Model Context Protocol Server
by jkoelker
Verified
#
from typing import Annotated
import datetime
import schwab.client
from schwab_mcp.tools.registry import register
from schwab_mcp.tools.utils import call
@register
async def get_datetime() -> str:
"""
Get the current datetime in ISO format
"""
return datetime.datetime.now().isoformat()
@register
async def get_market_hours(
client: schwab.client.AsyncClient,
markets: Annotated[
list[str] | str,
"Markets to get hours for (EQUITY, OPTION, BOND, FUTURE, FOREX)",
],
date: Annotated[
str | None,
"Date to get hours for in 'YYYY-MM-DD' format. Accepts values up to one year from today.",
] = None,
) -> str:
"""
Get market hours for a specific market.
Market can be one of the following:
EQUITY
OPTION
BOND
FUTURE
FOREX
If date is not provided, the current date will be used.
"""
if isinstance(markets, str):
markets = [markets]
markets = [client.MarketHours.Market[m] for m in markets]
return await call(client.get_market_hours, markets, date=date)
@register
async def get_movers(
client: schwab.client.AsyncClient,
index: Annotated[
str,
"Index or market segment to get top movers for (DJI, COMPX, SPX, NYSE, etc.)",
],
sort: Annotated[
str,
"Sort criteria for ranking movers (VOLUME, TRADES, PERCENT_CHANGE_UP, PERCENT_CHANGE_DOWN)",
] = None,
frequency: Annotated[
str, "Minimum percentage change threshold (ZERO, ONE, FIVE, TEN, THIRTY, SIXTY)"
] = None,
) -> str:
"""
Get a list of the top ten movers for a specific index.
Index can be one of the following:
DJI
COMPX
SPX
NYSE
NASDAQ
OTCBB
INDEX_ALL
EQUITY_ALL
OPTION_ALL
OPTION_PUT
OPTION_CALL
Sort can be one of the following:
VOLUME
TRADES
PERCENT_CHANGE_UP
PERCENT_CHANGE_DOWN
Frequency can be one of the following:
ZERO
ONE
FIVE
TEN
THIRTY
SIXTY
"""
return await call(
client.get_movers,
index=client.Movers.Index[index],
sort=client.Movers.SortOrder[sort] if sort else None,
frequency=client.Movers.Frequency[frequency] if frequency else None,
)
@register
async def get_instruments(
client: schwab.client.AsyncClient,
symbol: Annotated[str, "Symbol or search term to find instruments"],
projection: Annotated[
str,
(
"Search method or data type to return (SYMBOL_SEARCH, SYMBOL_REGEX, "
"DESCRIPTION_SEARCH, DESCRIPTION_REGEX, SEARCH, FUNDAMENTAL)"
),
] = "symbol-search",
) -> str:
"""
Search for instruments with a specific symbol.
Projection can be one of the following:
SYMBOL_SEARCH
SYMBOL_REGEX
DESCRIPTION_SEARCH
DESCRIPTION_REGEX
SEARCH
FUNDAMENTAL
<example>
# Search for instruments with the symbol "AAPL"
get_instruments("AAPL")
</example>
<example>
# Search for AAPL options
get_instruments("AAPL .*", "symbol-regex")
</example>
<example>
# Return the fundamental data for AAPL
get_instruments("AAPL", "fundamental")
</example>
"""
return await call(
client.get_instruments,
symbol,
projection=client.Instrument.Projection[projection],
)