Skip to main content
Glama
vsoneji
by vsoneji
README.md10.9 kB
# Schwab MCP Server A Model Context Protocol (MCP) server that enables AI assistants like Claude to securely interact with Charles Schwab accounts and market data through the official Schwab API. ## What You Can Do Ask Claude to: - "Show me my Schwab account balances and positions" - "Get real-time quotes for AAPL, GOOGL, and MSFT" - "What are today's market movers in the $SPX?" - "Show me the options chain for TSLA with Greeks" - "Get my transactions from the last 30 days" - "Search for ETFs related to technology" - "Check if the markets are open" ## Unofficial MCP Server This is an unofficial, community-developed TypeScript MCP server for Charles Schwab. It has not been approved, endorsed, or certified by Charles Schwab. It is provided as-is, and its functionality may be incomplete or unstable. Use at your own risk, especially when dealing with financial data or transactions. ## Overview This MCP server acts as a bridge between AI assistants and the Schwab API, providing: - **Secure OAuth Authentication**: Implements Schwab's OAuth 2.0 flow with PKCE for secure authentication - **Comprehensive Trading Tools**: Access to accounts, orders, quotes, and transactions - **Market Data Tools**: Real-time quotes, price history, market hours, movers, and options chains - **Account Privacy**: Built-in account identifier scrubbing to protect sensitive information - **Local-Only**: Runs entirely on your machine with local HTTPS server and file-based token storage ## Features ### Trading Tools - **Account Management** - `getAccounts`: Retrieve all account information with positions and balances - `getAccountNumbers`: Get list of account identifiers - **Order Management** - `getOrder`: Get order by ID - `getOrders`: Fetch orders with filtering by status, time range, and symbol - `getOrdersByAccountNumber`: Get orders by account number - `cancelOrder`: Cancel an order (Experimental) - `placeOrder`: Place an order (Experimental) - `replaceOrder`: Replace an order (Experimental) - **Market Quotes** - `getQuotes`: Get real-time quotes for multiple symbols - `getQuoteBySymbolId`: Get detailed quote for a single symbol - **Transaction History** - `getTransactions`: Retrieve transaction history across all accounts with date filtering - **User Preferences** - `getUserPreference`: Retrieve user trading preferences and settings ### Market Data Tools - **Instrument Search** - `searchInstruments`: Search for securities by symbol with fundamental/reference data - **Price History** - `getPriceHistory`: Get historical price data with customizable periods and frequencies - **Market Hours** - `getMarketHours`: Check market operating hours by date - `getMarketHoursByMarketId`: Get specific market information - **Market Movers** - `getMovers`: Find top market movers by index ($SPX, $COMPX, $DJI) - **Options Chains** - `getOptionChain`: Retrieve full options chain data with Greeks - `getOptionExpirationChain`: Get option expiration dates ## Prerequisites 1. **Schwab Developer Account**: Register at [Schwab Developer Portal](https://developer.schwab.com) 2. **Node.js**: Version 20.x or higher (22.x recommended) ## Getting Started ### Quick Setup ```bash git clone <repository-url> cd schwab-mcp npm install # Configure your environment cp .env.example .env # Edit .env with your Schwab app credentials # Start the MCP server (will prompt for OAuth on first run) npm run start ``` ### Configuration #### 1. Create a Schwab App 1. Log in to the [Schwab Developer Portal](https://developer.schwab.com) 2. Create a new app with: - **App Name**: Your MCP server name (e.g., "My Schwab MCP") - **Callback URL**: `https://localhost:3000/callback` - **App Type**: Personal 3. Note your **App Key** (Client ID) and generate an **App Secret** #### 2. Configure Environment Variables Copy the `.env.example` file to `.env` and fill in your credentials: ```bash cp .env.example .env ``` Edit `.env`: ```env # Schwab OAuth Configuration SCHWAB_CLIENT_ID=your_schwab_app_key_here SCHWAB_CLIENT_SECRET=your_schwab_app_secret_here # OAuth Redirect URI (must match what you configured in Schwab Developer Portal) SCHWAB_REDIRECT_URI=https://localhost:3000/callback # Optional: Port for HTTPS server (default: 3000) PORT=3000 # Optional: Log level (trace, debug, info, warn, error, fatal) LOG_LEVEL=info # Optional: Environment (development, staging, production) ENVIRONMENT=production ``` #### 3. First Run - OAuth Authentication On the first run, the server will: 1. Generate self-signed certificates in `.certs/` directory (no OpenSSL required) 2. Start an HTTPS server on `https://localhost:3000` 3. Open your browser to the Schwab authorization page 4. After you authorize, tokens will be saved to `.auth/` directory 5. The MCP server will start and be ready to use ```bash npm run start ``` **Note**: You may need to trust the self-signed certificate in your browser or system. The certificate is only used for localhost OAuth callback and is generated automatically using Node.js crypto libraries. ## Usage ### Claude Desktop Configuration Add the server to your Claude Desktop configuration file: **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` ```json { "mcpServers": { "schwab": { "command": "npx", "args": [ "tsx", "/path/to/schwab-mcp/src/index.ts" ], "env": { "SCHWAB_CLIENT_ID": "your_app_key", "SCHWAB_CLIENT_SECRET": "your_app_secret", "SCHWAB_REDIRECT_URI": "https://localhost:3000/callback" } } } } ``` Or if you prefer to build first and run the compiled JavaScript: ```json { "mcpServers": { "schwab": { "command": "node", "args": [ "/path/to/schwab-mcp/dist/index.js" ], "env": { "SCHWAB_CLIENT_ID": "your_app_key", "SCHWAB_CLIENT_SECRET": "your_app_secret", "SCHWAB_REDIRECT_URI": "https://localhost:3000/callback" } } } } ``` Note: The first option using `tsx` is recommended as it doesn't require a build step. Restart Claude Desktop. The server will connect via stdio transport. ### Example Commands Once connected, you can ask Claude to: - "Show me my Schwab account balances" - "Get a quote for AAPL" - "What are today's market movers in the $SPX?" - "Show me the options chain for TSLA" - "Get my recent transactions from the last week" ## Architecture ### Technology Stack - **Runtime**: Node.js with TypeScript - **Authentication**: OAuth 2.0 with PKCE via `@sudowealth/schwab-api` - **API Client**: `@sudowealth/schwab-api` for type-safe Schwab API access - **MCP Framework**: `@modelcontextprotocol/sdk` with stdio transport - **State Management**: File-based token storage in `.auth/` directory - **OAuth Server**: Express with HTTPS for OAuth callback handling ### Security Features 1. **OAuth 2.0 with PKCE**: Secure authentication flow preventing authorization code interception 2. **Local Token Storage**: Tokens stored locally in `.auth/` directory (never sent to external servers) 3. **HTTPS Localhost**: Self-signed certificates for secure OAuth callback 4. **Automatic Token Refresh**: Tokens refreshed 5 minutes before expiration 5. **Account Scrubbing**: Sensitive account identifiers automatically replaced with display names 6. **Secret Redaction**: Automatic masking of sensitive data in logs ## Development ### Available Scripts ```bash npm run start # Start the MCP server npm run dev # Start in development mode (same as start) npm run build # Build TypeScript to JavaScript npm run typecheck # Run TypeScript type checking npm run lint # Run ESLint npm run format # Format code with Prettier npm run validate # Run typecheck and lint together ``` ### Project Structure ``` schwab-mcp/ ├── .auth/ # OAuth tokens (git-ignored) ├── .certs/ # Self-signed certificates (git-ignored) ├── src/ │ ├── index.ts # Main MCP server entry point │ ├── auth/ # OAuth authentication client │ ├── server/ # OAuth HTTP server and certificate generation │ ├── shared/ # Shared utilities (logging, token storage) │ └── tools/ # MCP tool implementations ├── .env # Environment variables (git-ignored) └── .env.example # Example environment variables ``` ### Debugging The server includes comprehensive logging with configurable levels: - **Log Levels**: trace, debug, info, warn, error, fatal - Set via `LOG_LEVEL` environment variable in `.env` Enable debug logging to see detailed OAuth flow and API interactions: ```env LOG_LEVEL=debug ``` ### Error Handling The server implements robust error handling with specific error types: - **Authentication Errors (401)**: Prompt for re-authentication - **Client Errors (400)**: Invalid parameters, missing data - **Server Errors (500)**: API failures, configuration issues - All errors include request IDs for Schwab API troubleshooting ## Contributing 1. Fork the repository 2. Create a feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request ## License MIT ## Troubleshooting ### Common Issues 1. **"Certificate error" in browser** - This is expected with self-signed certificates - Accept the certificate warning during OAuth flow - The certificate is only used for `https://localhost:3000/callback` 2. **"Cannot find module" errors** - Run `npm install` to ensure all dependencies are installed - Make sure you're using Node.js 20.x or higher 3. **Authentication failures** - Verify your redirect URI matches exactly: `https://localhost:3000/callback` - Check that your Schwab app credentials are correct in `.env` - Enable debug logging: `LOG_LEVEL=debug` in `.env` 4. **"Port already in use" error** - Change the PORT in `.env` to a different value - Make sure no other process is using port 3000 ## Recent Updates - **Local-Only Architecture**: Migrated from Cloudflare Workers to local Node.js server - **File-Based Token Storage**: Tokens stored securely in local `.auth/` directory - **HTTPS OAuth Flow**: Self-signed certificates for secure localhost OAuth callback - **Stdio Transport**: Uses standard MCP SDK with stdio for Claude Desktop integration ## Acknowledgments - Uses [Model Context Protocol](https://modelcontextprotocol.io/) - Powered by [@sudowealth/schwab-api](https://www.npmjs.com/package/@sudowealth/schwab-api) - Built with [@modelcontextprotocol/sdk](https://www.npmjs.com/package/@modelcontextprotocol/sdk)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vsoneji/schwab-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server