Skip to main content
Glama

TradeStation MCP Server

by maven81g
test-mcp-functions.js•9.14 kB
// Test script for TradeStation MCP Server functions // This script tests all endpoints to verify they work correctly import axios from 'axios'; import dotenv from 'dotenv'; dotenv.config(); const TS_TOKEN_URL = 'https://signin.tradestation.com/oauth/token'; const TS_API_BASE = 'https://sim-api.tradestation.com/v3'; // Get fresh access token async function getAccessToken() { const TS_CLIENT_ID = process.env.TRADESTATION_CLIENT_ID; const TS_CLIENT_SECRET = process.env.TRADESTATION_CLIENT_SECRET; const TS_REFRESH_TOKEN = process.env.TRADESTATION_REFRESH_TOKEN; if (!TS_CLIENT_ID || !TS_CLIENT_SECRET || !TS_REFRESH_TOKEN) { console.error('āŒ Missing required environment variables'); process.exit(1); } try { console.log('šŸ”‘ Obtaining access token...'); const response = await axios.post(TS_TOKEN_URL, new URLSearchParams({ grant_type: 'refresh_token', client_id: TS_CLIENT_ID, client_secret: TS_CLIENT_SECRET, refresh_token: TS_REFRESH_TOKEN }), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); console.log('āœ… Access token obtained\n'); return response.data.access_token; } catch (error) { console.error('āŒ Failed to obtain access token:', error.response?.data || error.message); process.exit(1); } } // Test helper function async function testEndpoint(name, method, endpoint, token, data = null) { console.log(`\nšŸ“” Testing: ${name}`); console.log(` Endpoint: ${method} ${endpoint}`); try { const config = { method, url: `${TS_API_BASE}${endpoint}`, headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', 'Accept': 'application/json' }, timeout: 30000 }; if (data && (method === 'POST' || method === 'PUT')) { config.data = data; } const response = await axios(config); console.log(` āœ… SUCCESS (${response.status})`); console.log(` Response preview:`, JSON.stringify(response.data, null, 2).substring(0, 300) + '...'); return { success: true, data: response.data }; } catch (error) { const status = error.response?.status || 'ERROR'; const errorMsg = error.response?.data?.Message || error.response?.data?.message || error.message; console.log(` āŒ FAILED (${status}): ${errorMsg}`); return { success: false, error: errorMsg, status }; } } // Main test function async function runTests() { console.log('═══════════════════════════════════════════════════════'); console.log(' TradeStation MCP Server Function Tests'); console.log('═══════════════════════════════════════════════════════\n'); const token = await getAccessToken(); const results = []; // Phase 1: Market Data Functions console.log('\nā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”'); console.log('│ PHASE 1: Market Data Functions │'); console.log('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜'); results.push(await testEndpoint( 'marketData (quotes)', 'GET', '/marketdata/quotes/SPY,QQQ,AAPL', token )); results.push(await testEndpoint( 'barChart', 'GET', '/marketdata/barcharts/SPY?interval=5&unit=Minute&barsback=10', token )); results.push(await testEndpoint( 'searchSymbols', 'GET', '/marketdata/symbollookup?criteria=Apple', token )); results.push(await testEndpoint( 'optionChain', 'GET', '/marketdata/options/chains/SPXW?expiration=2025-10-21', token )); results.push(await testEndpoint( 'getSymbolDetails', 'GET', '/marketdata/symbols/SPY,QQQ', token )); // Phase 2: Account Functions console.log('\nā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”'); console.log('│ PHASE 2: Account Functions │'); console.log('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜'); // First get accounts to use a valid account ID const accountsResult = await testEndpoint( 'getAccounts', 'GET', '/brokerage/accounts', token ); results.push(accountsResult); // If we got accounts, use the first one for subsequent tests let accountId = null; if (accountsResult.success && accountsResult.data?.Accounts?.length > 0) { accountId = accountsResult.data.Accounts[0].AccountID; console.log(`\n ā„¹ļø Using Account ID: ${accountId} for remaining tests`); results.push(await testEndpoint( 'getBalances', 'GET', `/brokerage/accounts/${accountId}/balances`, token )); results.push(await testEndpoint( 'getPositions', 'GET', `/brokerage/accounts/${accountId}/positions`, token )); results.push(await testEndpoint( 'getOrders (All)', 'GET', `/brokerage/accounts/${accountId}/orders`, token )); results.push(await testEndpoint( 'getOrders (Open only)', 'GET', `/brokerage/accounts/${accountId}/orders?status=Open`, token )); // Note: These require valid order IDs, which may not exist console.log('\n ā„¹ļø Skipping getOrderDetails and getExecutions (require valid order IDs)'); } else { console.log('\n āš ļø No accounts found - skipping account-specific tests'); } // Phase 3: Order Preview (Safe - READ ONLY) console.log('\nā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”'); console.log('│ PHASE 3: Order Preview (READ-ONLY) │'); console.log('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜'); if (accountId) { const confirmOrderData = { AccountID: accountId, Symbol: 'SPY', Quantity: 1, OrderType: 'Limit', TradeAction: 'BUY', LimitPrice: 500.00, TimeInForce: { Duration: 'DAY' } }; results.push(await testEndpoint( 'confirmOrder (preview)', 'POST', '/orderexecution/orderconfirm', token, confirmOrderData )); } else { console.log(' āš ļø Skipping confirmOrder (no account ID available)'); } // Summary console.log('\n═══════════════════════════════════════════════════════'); console.log(' TEST SUMMARY'); console.log('═══════════════════════════════════════════════════════'); const successful = results.filter(r => r.success).length; const failed = results.filter(r => !r.success).length; const total = results.length; console.log(`\n Total Tests: ${total}`); console.log(` āœ… Passed: ${successful}`); console.log(` āŒ Failed: ${failed}`); console.log(` Success Rate: ${((successful/total)*100).toFixed(1)}%\n`); if (failed > 0) { console.log(' Failed Tests:'); results.forEach((r, i) => { if (!r.success) { console.log(` ${i + 1}. ${r.error} (Status: ${r.status})`); } }); } console.log('\n═══════════════════════════════════════════════════════\n'); if (successful === total) { console.log('šŸŽ‰ All tests passed! Your MCP server is ready to use.\n'); } else { console.log('āš ļø Some tests failed. Review the errors above.\n'); } } // Run tests runTests().catch(console.error);

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/maven81g/tradestation_mcp'

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