Skip to main content
Glama
nonnname

T-Invest MCP Server

by nonnname

post_stop_order

Place stop-loss, take-profit, or stop-limit orders in T-Invest to automatically execute trades when specific price levels are reached, requiring confirmation for execution.

Instructions

Выставить стоп-заявку в Т-Инвестициях (требуется confirm: true для исполнения)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
accountIdYesИдентификатор счёта
tickerYesТикер инструмента
directionYesНаправление
quantityYesКоличество лотов (не более 10 000)
orderTypeYesТип стоп-заявки
stopPriceYesСтоп-цена активации
limitPriceNoЛимит-цена исполнения (для stop_limit)
expirationTypeNoТип срока действияgood_till_cancel
expireDateNoДата истечения (ISO 8601, для good_till_date, например 2025-12-31T23:59:59Z)
confirmNoПередайте true для исполнения

Implementation Reference

  • The `registerPostStopOrder` function defines and registers the `post_stop_order` MCP tool, including its input schema (using Zod) and the asynchronous handler that processes stop orders.
    export function registerPostStopOrder(
      server: McpServer,
      client: TInvestClient,
      requireConfirmation: boolean,
    ): void {
      server.tool(
        'post_stop_order',
        requireConfirmation
          ? 'Выставить стоп-заявку в Т-Инвестициях (требуется confirm: true для исполнения)'
          : 'Выставить стоп-заявку в Т-Инвестициях',
        {
          accountId: z.string().describe('Идентификатор счёта'),
          ticker: z.string().describe('Тикер инструмента'),
          direction: z.enum(['buy', 'sell']).describe('Направление'),
          quantity: z.number().int().min(1).max(10_000).describe('Количество лотов (не более 10 000)'),
          orderType: z.enum(['stop_loss', 'take_profit', 'stop_limit']).describe('Тип стоп-заявки'),
          stopPrice: z.number().positive().describe('Стоп-цена активации'),
          limitPrice: z.number().positive().optional().describe('Лимит-цена исполнения (для stop_limit)'),
          expirationType: z
            .enum(['good_till_cancel', 'good_till_date'])
            .default('good_till_cancel')
            .describe('Тип срока действия'),
          expireDate: z
            .string()
            .regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/, 'Формат: YYYY-MM-DDTHH:MM:SSZ')
            .optional()
            .describe('Дата истечения (ISO 8601, для good_till_date, например 2025-12-31T23:59:59Z)'),
          confirm: z.boolean().optional().describe('Передайте true для исполнения'),
        },
        DESTRUCTIVE,
        async ({ accountId, ticker, direction, quantity, orderType, stopPrice, limitPrice, expirationType, expireDate, confirm }) => {
          try {
            const item = await resolveTickerToInstrument(client, ticker);
            if (!item) {
              return { content: [{ type: 'text' as const, text: `Инструмент "${ticker}" не найден.` }], isError: true };
            }
    
            const preview = [
              `Стоп-заявка:`,
              `  Тикер:        ${ticker}`,
              `  Направление:  ${direction === 'buy' ? 'Покупка' : 'Продажа'}`,
              `  Тип:          ${STOP_ORDER_TYPE_LABELS[`STOP_ORDER_TYPE_${orderType.toUpperCase()}`] ?? orderType}`,
              `  Количество:   ${quantity} лот(ов)`,
              `  Стоп-цена:    ${stopPrice}`,
              limitPrice ? `  Лимит-цена:   ${limitPrice}` : '',
              `  Срок:         ${expirationType === 'good_till_cancel' ? 'До отмены' : `До ${expireDate}`}`,
              `  Счёт:         ${accountId}`,
            ].filter(Boolean).join('\n');
    
            if (requireConfirmation && confirm !== true) {
              return {
                content: [{ type: 'text' as const, text: `${preview}\n\nДля исполнения вызовите повторно с confirm: true` }],
              };
            }
    
            const ORDER_TYPE_MAP: Record<string, string> = {
              stop_loss: 'STOP_ORDER_TYPE_STOP_LOSS',
              take_profit: 'STOP_ORDER_TYPE_TAKE_PROFIT',
              stop_limit: 'STOP_ORDER_TYPE_STOP_LIMIT',
            };
    
            const EXPIRY_MAP: Record<string, string> = {
              good_till_cancel: 'STOP_ORDER_EXPIRATION_TYPE_GOOD_TILL_CANCEL',
              good_till_date: 'STOP_ORDER_EXPIRATION_TYPE_GOOD_TILL_DATE',
            };
    
            const body: Record<string, unknown> = {
              accountId,
              instrumentId: item.uid,
              quantity,
              direction: direction === 'buy' ? 'STOP_ORDER_DIRECTION_BUY' : 'STOP_ORDER_DIRECTION_SELL',
              stopOrderType: ORDER_TYPE_MAP[orderType],
              stopPrice: toQuotation(stopPrice),
              expirationType: EXPIRY_MAP[expirationType],
            };
    
            if (limitPrice !== undefined) body.price = toQuotation(limitPrice);
            if (expireDate) body.expireDate = expireDate;
    
            const resp = await client.post<PostStopOrderResponse>(
              API_PATHS.STOP_ORDERS.POST_STOP_ORDER,
              body,
            );
    
            return {
              content: [{ type: 'text' as const, text: `Стоп-заявка выставлена\nID: ${resp.stopOrderId}` }],
            };
          } catch (error) {
            return {
              content: [{ type: 'text' as const, text: `Ошибка: ${error instanceof Error ? error.message : String(error)}` }],
              isError: true,
            };
          }
        },
      );
    }

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/nonnname/t-invest-mcp-server'

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