Skip to main content
Glama
PNX89
by PNX89

QUOTEZ

Рыночные данные для агентов. Только чтение по конструкции, а не по настройке.

CI Python License: MIT

MCP-сервер, который предоставляет рыночные данные MetaTrader 5 в виде типизированных инструментов только для чтения, которые может вызывать LLM-агент. Требуется Python 3.11 или новее, одна зависимость времени выполнения, транспорт stdio. Значок останавливается на 3.13, потому что там останавливаются классификаторы; CI также запускает 3.14, помеченный как рекомендательный, и 3.14 присоединится к значку, как только он станет достаточно стабильным, чтобы быть обещанием, а не надеждой.

Агент настолько хорош, насколько хороши инструменты, которые вы ему даёте, и рыночные данные — это то, где неаккуратный инструмент наносит реальный ущерб. Модель пересказывает всё, что возвращает инструмент, как факт, поэтому полезная нагрузка без единиц измерения, часового пояса и источника происхождения превращается в уверенное предложение о цене, на которую кто-то может отреагировать. QUOTEZ отвечает сгенерированными схемами вывода, а не текстовыми блоками, везде UTC, флагом synthetic на каждой полезной нагрузке и отсутствием пути записи в коде.

Это один инструмент, созданный так, чтобы он не мог нанести ущерб, что является меньшим и более проверяемым вопросом, чем можно ли доверять агенту в целом с инструментами. Более крупный вопрос решается в QUELLZ.

Область применения и ограничения

  • Только чтение: никаких order_send, order_check, symbol_select, никаких операций записи любого рода.

  • Для live-данных MetaTrader требуется Windows и работающий терминал; колеса только для win_amd64.

  • Источник по умолчанию воспроизводит сгенерированные данные и помечает каждую полезную нагрузку synthetic: true.

  • Время везде UTC, и каждый бар помечен своим открытием (левая граница интервала).

Пример сессии агента

Реальный вывод, а не вставка. Повторно сгенерируйте его с помощью uv run python examples/agent_session.py; tests/test_readme.py проверяет этот блок побайтово на соответствие stdout этой команды. Цены воспроизведения сгенерированы, а не записаны с какого-либо рынка.

QUOTEZ over an in-memory MCP client, source=replay.
Every price below is generated. This repository bundles no real market data.

>>> list_symbols(group="*FX*")
{
  "source": "replay",
  "synthetic": true,
  "count": 2,
  "symbols": [
    {"name": "SYNTH_FX_ALPHA", "description": "Synthetic FX pair Alpha", "digits": 5, "point": 1e-05},
    {"name": "SYNTH_FX_BETA", "description": "Synthetic FX pair Beta", "digits": 3, "point": 0.001}
  ]
}

>>> get_quote(symbol="SYNTH_FX_ALPHA")
{
  "symbol": "SYNTH_FX_ALPHA",
  "time": "2026-06-12T13:59:00Z",
  "bid": 1.08044,
  "ask": 1.08056,
  "spread_points": 12,
  "source": "replay",
  "synthetic": true
}

>>> get_bars(symbol="SYNTH_FX_ALPHA", timeframe="H1", count=5)
{
  "symbol": "SYNTH_FX_ALPHA",
  "timeframe": "H1",
  "source": "replay",
  "synthetic": true,
  "count": 5,
  "bars": [
    {"time": "2026-06-12T08:00:00Z", "open": 1.07985, "high": 1.08231, "low": 1.07978, "close": 1.08125, "tick_volume": 4257, "spread": null},
    {"time": "2026-06-12T09:00:00Z", "open": 1.08125, "high": 1.0844, "low": 1.08113, "close": 1.08302, "tick_volume": 2501, "spread": null},
    {"time": "2026-06-12T10:00:00Z", "open": 1.08302, "high": 1.08439, "low": 1.08298, "close": 1.08368, "tick_volume": 1643, "spread": null},
    {"time": "2026-06-12T11:00:00Z", "open": 1.08368, "high": 1.08395, "low": 1.08036, "close": 1.08097, "tick_volume": 1570, "spread": null},
    {"time": "2026-06-12T12:00:00Z", "open": 1.08097, "high": 1.08284, "low": 1.08084, "close": 1.08159, "tick_volume": 2589, "spread": null}
  ]
}

>>> symbol_info(symbol="SYNTH_FX_ALPHA")
{
  "name": "SYNTH_FX_ALPHA",
  "description": "Synthetic FX pair Alpha",
  "digits": 5,
  "point": 1e-05,
  "spread": 12,
  "spread_float": true,
  "trade_stops_level": 10,
  "trade_freeze_level": 0,
  "trade_tick_value": 1.0,
  "trade_tick_size": 1e-05,
  "trade_contract_size": 100000.0,
  "volume_min": 0.01,
  "volume_max": 100.0,
  "volume_step": 0.01,
  "currency_base": "SYA",
  "currency_profit": "SYN",
  "currency_margin": "SYA",
  "source": "replay",
  "synthetic": true
}

A symbol that does not exist, to show what the model actually sees:

>>> get_quote(symbol="NOT_A_SYMBOL")
is_error: true
Error executing tool get_quote: Symbol 'NOT_A_SYMBOL' is not available on this server.

Быстрый старт

Одна команда, ничего настраивать не нужно, никакой установки MetaTrader:

uvx --from git+https://github.com/PNX89/QUOTEZ quotez --source replay

QUOTEZ не опубликован на PyPI, поэтому установка производится из git-формы; добавьте @main, тег или коммит для фиксации ревизии, согласно документации по зависимостям uv. Затем команда может зависнуть, потому что stdout — это провод JSON-RPC, и управление осуществляется хостом. Чтобы увидеть его работу без хоста, клонируйте репозиторий и запустите пример сессии, которая управляет тем же сервером из внутрипроцессного клиента:

git clone https://github.com/PNX89/QUOTEZ && cd QUOTEZ
uv run python examples/agent_session.py

В Windows, если терминал уже запущен и выполнен вход:

uvx --from "quotez[mt5] @ git+https://github.com/PNX89/QUOTEZ" quotez --source mt5

Скрипт консоли — единственная точка входа, принимающая флаги, и флаги имеют приоритет над переменными окружения. mcp run src/quotez/server.py также запускает этот сервер через глобальный объект mcp на уровне модуля, но он ничего не передаёт, поэтому этот путь считывает переменные.

Флаг

Переменная окружения

По умолчанию

Значение

--source

QUOTEZ_SOURCE

replay

replay читает встроенные сгенерированные файлы, mt5 читает live-терминал

--symbols

QUOTEZ_SYMBOLS

пусто

Разделённый запятыми белый список, без учёта регистра. Пустое значение открывает всё, что есть в источнике

--max-bars

QUOTEZ_MAX_BARS

1000

Максимальное количество баров, которое может вернуть один вызов, от 1 до 5000

--log-level

QUOTEZ_LOG_LEVEL

INFO

Порог логирования. Записи всегда идут в stderr, потому что stdout — это провод

Подключение к хосту

Хосты не сходятся в ключе конфигурации, и путаница между mcpServers и servers — обычная причина, по которой сервер никогда не появляется.

Хост

Файл

Ключ

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json на macOS, %APPDATA%\Claude\claude_desktop_config.json на Windows

mcpServers

Cursor

.cursor/mcp.json

mcpServers

VS Code

.vscode/mcp.json

servers, и добавьте "type": "stdio" рядом с command

Claude Code

нет файла, используйте CLI

claude mcp add quotez -- uv tool run --from git+https://github.com/PNX89/QUOTEZ quotez --source replay

{
  "mcpServers": {
    "quotez": {
      "command": "/absolute/path/to/uv",
      "args": ["tool", "run", "--from", "git+https://github.com/PNX89/QUOTEZ",
               "quotez", "--source", "replay"]
    }
  }
}

command должен быть абсолютным путём из which uv. Хост запускает сервер с почти пустым PATH, поэтому голый uv — самая распространённая причина, по которой сервер молча не подключается.

Инструменты

Восемь инструментов, зарегистрированных в этом порядке, который является порядком, возвращаемым tools/list; клиенты кешируют этот список, поэтому порядок зафиксирован намеренно. Один ресурс, symbols://list, предоставляет ту же вселенную инструментов в виде application/json.

Инструмент

Аргументы

Возвращает

Доступ

Источник Replay

Источник MetaTrader

list_symbols

group необязательный, синтаксис групп MetaTrader

SymbolList

чтение

4 сгенерированных инструмента

symbols_get(group=...)

get_quote

symbol

Quote

чтение

вычисляется из последнего сохранённого бара

symbol_info_tick

get_bars

symbol, timeframe, count (от 1 до 5000, не более --max-bars)

BarSeries

чтение

M1 сворачивается локально

copy_rates_from_pos

get_bars_range

symbol, timeframe, start, end

BarSeries

чтение

M1 сворачивается локально

copy_rates_range

symbol_info

symbol

SymbolSpec

чтение

из symbols.json

symbol_info

get_account

нет

Account

чтение

фиктивные данные, synthetic: true

account_info, логин маскируется

list_positions

нет

PositionList

чтение

всегда пусто

positions_get

list_orders

нет

OrderList

чтение

всегда пусто

orders_get

list_symbols использует собственный синтаксис фильтра групп MetaTrader вместо создания собственного: подстановочные знаки * в начале и конце шаблона, условия, разделённые запятыми, и ! для отрицания. Включения должны предшествовать исключениям, поэтому "*, !*USD*" — это всё, кроме инструментов USD, а "!*USD*, *" соответствует всему. Mt5Source передаёт строку в symbols_get; источник воспроизведения применяет тот же синтаксис через quotez.groups, поэтому оба одинаково обрабатывают фильтр.

Каждый инструмент возвращает модель Pydantic, поэтому SDK выводит outputSchema из аннотации возврата, заполняет structuredContent и проверяет полезную нагрузку перед тем, как она покинет сервер. Используется незавёрнутый BaseModel, поэтому get_bars возвращает объект с ключом bars, а не {"result": ...}.

Как это работает

flowchart LR
    host["MCP host<br/>Claude Desktop, Cursor, VS Code"]
    server["quotez.server<br/>8 tools, 1 resource"]
    proto["MarketDataSource<br/>Protocol"]
    replay["ReplaySource<br/>bundled CSVs, any OS"]
    mt5["Mt5Source<br/>Windows only, lazy import"]
    term["MetaTrader 5 terminal"]
    host -- "JSON-RPC over stdio" --> server
    server --> proto
    proto --> replay
    proto --> mt5
    mt5 -- "read calls only" --> term

MarketDataSource — это шов, на котором написан весь сервер. Ничто выше него не импортирует MetaTrader5, и Mt5Source разрешает расширение внутри частного помощника при первом использовании, а не при импорте модуля, поэтому import quotez работает там, где нет установленного колеса. Именно это делает ReplaySource полноценной реализацией, а не макетом: уровень инструментов не может различить их, поэтому весь набор выполняется по реальному пути кода без установленного терминала.

Встроенные данные — это четыре сгенерированных инструмента (SYNTH_FX_ALPHA, SYNTH_FX_BETA, SYNTH_IDX_GAMMA, SYNTH_MTL_DELTA), по 3600 баров M1 каждый, с 08:00 до 14:00 UTC по будням с 2026-06-01 по 2026-06-12, с девятью разрывами сессий: восемь ночных и один через выходные, потому что непрерывный ряд — это ряд, скрывающий ошибку агрегации. scripts/generate_replay_data.py создал файлы один раз из seed-генератора random.Random, и вывод зафиксирован. CSV-файлы читаются через importlib.resources, а не через Path(__file__).parent, что работает в репозитории, но ломается под запакованной установкой, которую выполняет uvx.

Инструменты и ресурсы — это не одно и то же

Инструмент — это то, что вызывать решает МОДЕЛЬ; ресурс — это то, что загружать решает ПРИЛОЖЕНИЕ. get_bars управляется моделью: она выбирает символ, таймфрейм и количество в процессе рассуждения. symbols://list управляется приложением: хост один раз помещает вселенную в контекст до того, как модель что-либо решит. Вот почему это не случайное дублирование list_symbols, который является фильтрованным поиском, запускаемым моделью намеренно.

Очевидный следующий ресурс, bars://{symbol}/{timeframe}, был намеренно не построен: он дублирует get_bars для тех же данных, а URI с заполнителями — это шаблон ресурса, который переводит resources/list в resources/templates/list и плохо или вообще не отображается многими хостами. Тест проверяет, что не зарегистрировано никаких шаблонов ресурсов.

Агрегация таймфреймов

Источник воспроизведения хранит один базовый таймфрейм, M1, а quotez.aggregate сворачивает из него M5, M15, M30, H1, H4 и D1. Одна сохранённая копия, одно сворачивание, тестируется самостоятельно, что важно, потому что его режим отказа молчалив: неправильная агрегация возвращает правдоподобные числа вечно и никогда не вызывает исключений.

Источник MetaTrader ничего не сворачивает. Терминал уже содержит все периоды, поэтому его запрашивают напрямую по таймфрейму; повторное получение их из M1 было бы медленнее и расходилось бы с графиками, которые открыты у оператора. Поэтому два источника отвечают на один и тот же вызов слегка по-разному для D1, H4 и spread, что указано в ограничениях, а не оставлено для самостоятельного обнаружения.

Инварианты сворачивания, каждый из которых является именем теста:

  1. M1 — единственный базовый таймфрейм. Все старшие получаются агрегацией.

  2. Бары привязаны к астрономическому времени и вычисляются целочисленным делением эпохальной секунды, а не группировкой каждых N строк подряд.

  3. Целевые таймфреймы — целые кратные 60 секунд. Всё остальное вызывает InvalidRequest.

  4. OHLC: первый open, максимальный high, минимальный low, последний close.

  5. tick_volume суммируется. spread — нет: это свойство котировки в конкретный момент времени, поэтому агрегированный бар возвращает null.

  6. Бары маркируются по левой границе в UTC.

  7. Незавершённый последний бар отбрасывается, а не выдаётся как частичный. Бар эмитируется только тогда, когда во входных данных есть бар на момент окончания этого бара или позже.

  8. Пустой ввод возвращает пустой список.

Инвариант 2 заслуживает своих тестов. Группировка по позиции совпадает с группировкой по астрономическому времени на непрерывном ряде и расходится при наличии пропуска: группировка 360 баров сессии по четыре помещает закрытие пятницы и открытие понедельника в один бар, называя его четырёхчасовой свечой. Инвариант 7 — его пара, потому что окончание сессии — не то же самое, что исчерпание данных.

Безопасность

Утверждение структурное, а не настраиваемое. В этой кодовой базе нет путей записи. В src/quotez/ нет order_send, order_check, symbol_select, изменений MarketWatch или записи в файлы. Никакая конфигурация не может включить запись, потому что включать нечего.

Два теста это закрепляют, и второй из них — значимый. Первый ищет в пакете три вызова MetaTrader: дёшево, покрывает все файлы и обходится именем, собранным во время выполнения. Второй обходит AST mt5source.py и утверждает позитивное свойство: набор атрибутов, которые этот пакет читает из терминального модуля, в точности равен вызовам чтения, перечисленным в его собственной строке документации, плюс семь констант таймфреймов, без доступа через getattr и без переприсваивания второй переменной. _mt5() возвращает весь модуль MetaTrader5, поэтому отсутствие трёх имён из нескольких сотен атрибутов само по себе мало что доказывает. Пять намеренно сломанных фрагментов проверяются этим обходом, чтобы сам обход гарантированно выдавал ошибку, когда должен.

Каждый инструмент объявлен как ToolAnnotations(read_only_hint=True, open_world_hint=False). Это объявление — любезность для клиентов и не более: спецификация MCP предписывает клиентам считать аннотации инструментов ненадёжными, если они не получены от доверенного сервера. read_only_hint=True описывает инструмент, а не ограничивает клиента, и свойство, которое может проверить рецензент, — это отсутствие вызовов, а не наличие флага. В проекции на собственные Рекомендации по безопасности для инструментов спецификации, включая требования, которым этот сервер не соответствует:

Требование спецификации

QUOTEZ

Где

Проверять все входные данные

Да

JSON Schema, полученная из аннотаций типов, Literal таймфреймы, Field(ge=1, le=5000) для count, плюс проверки во время выполнения в обработчиках

Реализовать контроль доступа

Да

белый список символов применяется к каждому инструменту и ресурсу, а не только к геттерам

Ограничивать частоту вызовов

Нет

не реализовано и указано в ограничениях. Stdio-сервер — дочерний процесс ровно одного хоста, поэтому хост отвечает за ограничение частоты

Очищать выходные данные

Да

логин учётной записи маскируется до последних четырёх цифр, имена брокера, сервера и владельца счёта никогда не возвращаются, а synthetic — обязательное поле в каждой полезной нагрузке

Заблокированный символ сообщается как SymbolNotFound с сообщением, которое получает опечатка: «Символ 'X' недоступен на этом сервере». Отдельное «не разрешено» превратило бы белый список в оракул для обнаружения инструментов, которые оператор решил не раскрывать.

Ошибки передаются по одному из двух каналов, в зависимости от того, могла ли более умная модель избежать сбоя. Опечатка в символе — могла, поэтому SymbolNotFound и InvalidRequest — обычные исключения, которые становятся ошибками инструмента, которые модель может прочитать и повторить попытку. Терминал, который не запущен, — не мог, поэтому SourceUnavailable вызывается как MCPError, протокольная ошибка без какого-либо результата. Здесь ничего не возвращает строку ошибки: возвращаемая строка имеет is_error=False и читается как успешный ответ. Тест вызывает каждый инструмент с некорректными данными и проверяет флаг.

Проектные решения

mcp>=2.0.0,<3 и MCPServer, а не привязка к v1 и FastMCP. SDK всё ещё предлагает mcp>=1.28,<2 для тех, кто ещё не мигрировал, но сервер эпохи v1 выдаёт себя за три секунды: from mcp.server.fastmcp import FastMCP. В руководстве по миграции есть переименования. Низкоуровневый Server был альтернативой и больше не оборачивает возвращаемые значения автоматически, поэтому пришлось бы вручную писать JSON Schema для восьми инструментов.

Типизированные возвращаемые значения Pydantic, а не текстовые блоки. Большинство публичных MCP-серверов возвращают прозу и оставляют её парсинг модели. Здесь аннотация возврата — это выходная схема, поэтому типизация ничего не стоит и даёт валидацию до того, как полезная нагрузка покинет сервер.

Два инструмента для баров, а не один с необязательными аргументами. JSON Schema не может выразить взаимное исключение, поэтому один get_bars(count or start..end) перенёс бы «либо то, либо другое, но не оба» на модель в виде прозы. У двух инструментов две полностью валидные схемы, и класс ошибки «оба заданы, ни один не задан» перестаёт существовать.

Сгенерированные данные, а не реальный фид. Лицензионное решение, а не предпочтение. Экспорт MetaTrader — это лицензированный фид брокера, а для индексных и акционерных CFD базовый актив лицензирован биржей. Страницы помощи Yahoo прямо указывают ограничение: вы не должны распространять информацию, отображаемую или предоставляемую Yahoo Finance, а её условия API для разработчиков отдельно ограничивают продажу или сублицензирование доступа. FAQ HistData не предоставляет никаких прав на распространение; там сказано только, что данные предоставляются без гарантии, а молчание — не лицензия. Размещение любых таких данных в репозитории MIT означало бы перелицензирование данных, на которое у меня нет прав.

Стандартная библиотека, а не pandas или numpy. В масштабах CSV-файлов в комплекте csv плюс datetime плюс dataclasses достаточно, и дерево остаётся проверяемым. Однако это дерево стоит называть честно, целиком: mcp 2.x — это одна прямая зависимость, которая тянет anyio, httpx2, jsonschema, mcp-types, opentelemetry-api, pydantic, pyjwt с его крипто-дополнением, python-multipart, sse-starlette, starlette, typing-extensions, typing-inspection и uvicorn, плюс pywin32 на Windows. Крипто-дополнение тянет за собой cryptography, cffi и pycparser. Это больший объём, чем v1, и тест читает зафиксированный uv.lock и завершается ошибкой, если этот список перестаёт ему соответствовать, потому что абзац, существующий для именования дерева, ничего не стоит, если он называет большую его часть.

Нет инструмента run_backtest. Бэктест неограничен по вычислительным ресурсам, требует гораздо больше, чем MarketDataSource, и дублировал бы QUACKZ, поэтому пара выглядела бы как два половинчатых проекта вместо двух сфокусированных. По той же причине ограничения здесь локальны для предметной области: проверка входных данных, ограниченные запросы, фиксированная вселенная инструментов, отсутствие побочных эффектов. Общие ограничения для агентов принадлежат QUELLZ, а не изобретаются заново пять раз.

Ограничения

  • Ни один исполнитель непрерывной интеграции не тестирует живой путь MetaTrader, нигде. Нет колеса для не-Windows, и ни у одного исполнителя нет терминала или брокерского счёта. Задание Windows доказывает, что расширение импортируется и что Mt5Source корректно сообщает об отсутствующем терминале, и это всё. Сопоставление полей Mt5Source — наименее протестированный код здесь, покрытый тестами с фиктивным модулем.

  • MetaTrader5 работает только на Windows и не публикует исходную дистрибуцию, поэтому pip install quotez[mt5] намеренно ничего не делает на macOS и Linux. Тест проверяет, что маркер окружения сохраняет это поведение.

  • initialize() запускает терминал, если он ещё не запущен, и вся операция ограничена его аргументом timeout, по документации по умолчанию равным 60000 миллисекунд. Страница не указывает время самого запуска, поэтому считайте 60 секунд верхней границей вызова, а не измеренным временем запуска. QUOTEZ открывает соединение один раз за время жизни сервера, а не на каждый вызов, поэтому его стоимость ложится на запуск, а не заставляет первый вызов инструмента выглядеть зависшим.

  • Два источника не сходятся в том, где начинается D1 или H4 бар. Агрегация воспроизведения округляет вниз по эпохальной секунде, поэтому D1 открывается в 00:00 UTC, а H4 — в 00, 04, 08, 12, 16 и 20 UTC. Терминал MetaTrader выравнивает D1 и H4 по серверному дню брокера, который обычно UTC+2 или UTC+3, поэтому один и тот же get_bars(symbol, "D1") возвращает свечу с другим временем открытия и другими OHLC в зависимости от того, какой источник настроен. Здесь ничего не пересэмплирует M1 терминала, чтобы скрыть это, потому что бар, расходящийся с собственным графиком оператора, хуже документированного смещения.

  • По той же причине spread равен null на каждом баре воспроизведения выше M1 и установлен на каждом баре MetaTrader. Агрегация намеренно его очищает; терминал сообщает своё собственное значение на каждом таймфрейме, и QUOTEZ передаёт его, не отбрасывая данные, предоставленные источником.

  • copy_rates_from_pos и copy_rates_range молча ограничиваются настройкой терминала «Макс. баров в графике», поэтому запрос в пределах собственного лимита сервера всё равно может вернуться укороченным, и ничто в API MetaTrader об этом не сообщает.

  • get_bars пропускает бар, который терминал всё ещё строит, поэтому его самый новый бар всегда закрыт. get_bars_range — нет, потому что границы заданы вызывающей стороной: end внутри текущего интервала возвращает частичный бар этого интервала.

  • symbol_info() возвращает None для неизвестного символа вместо вызова исключения, как и symbols_get() при ошибке. Каждое место вызова здесь это проверяет, но такова форма оборачиваемого API.

  • MetaTrader хранит время баров и тиков в UTC без смещения, в то время как наивный datetime Python разрешается относительно локальной зоны; документация copy_rates_range говорит об этом. Каждая исходящая временная метка строится с tz=UTC, а наивные входные данные отклоняются, но это ловушка, которая молча сдвигает целый ряд на час.

  • Нет ограничения частоты запросов. Stdio-сервер — дочерний процесс одного хоста, и хост за это отвечает.

  • Данные воспроизведения — образцового масштаба и сгенерированы: 4 инструмента, по 3600 M1 баров каждый, десять торговых дней. Они демонстрируют инструменты и проверяют агрегацию, но не являются ни исследовательским набором данных, ни рынком.

  • Версия 0.1.0 — только для чтения и только stdio, без возможности prompts, без транспорта SSE или streamable HTTP и без OAuth.

Зачем я это создал

Я провожу исследования методом walk forward на индексных данных и держу терминалы MetaTrader для валютной и металлической стороны, так что обе половины уже были у меня на столе. Поводом написать это стало наблюдение за агентом, который повторял число из плохо типизированного инструмента как факт — без единиц, без часового пояса и без указания источника. В рыночных данных это не косметика: бар, обозначенный ценой закрытия вместо цены открытия, или метка времени, незаметно сдвинутая на местное время, даёт ответ, который выглядит правильным, но сдвинут на час. Поэтому в основном это решения о происхождении данных и о том, что может утверждать инструмент, обёрнутые вокруг небольшого кода агрегации.

Разработка

uv sync --dev
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run mypy

251 тест, без сети, за несколько секунд, и идентично на macOS, Linux и Windows. Это число проверено на реальном наборе данных, потому что число в README — это число, которое никто не обновляет.

Лицензия

MIT. См. LICENSE.

Часть набора инструментов Q...Z, пять инструментов для сбоя, который не объявляет о себе:

  • QUACKZ, сдувающий бэктест, который выглядит хорошо только потому, что был выбран из двухсот.

  • QUOTEZ, этот: рыночные данные, которые агент может прочитать, но не может на них действовать.

  • QUELLZ, измеряющий, во что обходится сдерживание инъекции промптов — как в полезности, так и в частоте атак.

  • QUIDZ, отклоняющий исходящий платёж, который мог бы уйти дважды.

  • QUESTZ, останавливающий скрапер, прежде чем он запишет CSV со страницы, изменившей форму.

-
license - not tested
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • MCP server exposing the Backtest360 engine API as tools for AI agents.

  • Connect any MCP client to MetaTrader 4/5 to read prices, manage positions, and place trades.

  • Agent-native crypto market-data over MCP+REST: order flow, whales, liquidations, calibrated scores

View all MCP Connectors

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/PNX89/QUOTEZ'

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