Skip to main content
Glama
Flyrel MCP

Flyrel MCP

by faiznazeer

Flyrel MCP

A self-hosted Python foundation for working with multiple brokers through one MCP server. Initial markets: India and US cash equities. Initial adapters: Zerodha Kite and Alpaca.

Status: early foundation, not a trading product. External brokers are read-only. All order mutations stay in a local synthetic sandbox. No live-order implementation or enable-live flag exists. No broker credentials are needed to run the demo.

Product direction

Flyrel is experimenting with an independent security, permissions and approval layer for agentic investing/trading. The customer segment is undecided. Candidates include companies building trading agents, brokers, quant firms if relevant needs emerge, and individual or multi-account traders. There is no committed audience order or decision to sell exclusively to companies.

The intended promise is explicitly limited trading permissions with independent approval and verifiable enforcement. Broker connectivity and portfolio reports support that workflow. The interface, deployment model, buyer and end user remain discovery questions. Reddit research can inform user needs; company integration, ownership and purchasing needs require separate evidence. Flyrel does not promise guaranteed profits, loss-free trading or "100% security".

The current local setup does not provide that independent boundary: agents with shell access can read credentials and change policy/state. Protected credentials, agent-resistant policy controls, independent approval and broker execution remain future work. Agreement on product direction does not authorize external execution or change the read-only adapters.

See the product decision, roadmap, and neutral community research drafts.

Related MCP server: Open Paper Trading MCP

Quick start

Requires Python 3.12+ and uv.

git clone https://github.com/faiznazeer/flyrel-mcp.git
cd flyrel-mcp
uv sync --locked
uv run flyrel check
uv run flyrel serve

serve speaks MCP over stdio and waits for a client. Application output must not be written to stdout while serving. See MCP client configuration; replace the example absolute project path with your checkout. The uv --directory argument also ensures the correct .env and state directory are used when the client starts elsewhere.

Try these tools from your MCP client:

  1. list_brokers and get_policy.

  2. get_quotes with {"broker_id":"paper","symbols":["US:AAPL","NSE:RELIANCE"]}.

  3. propose_order with the request in examples/paper-order.json.

  4. confirm_order with the returned token, then list_orders.

  5. cancel_order with that order ID, or kill_switch to block new sandbox orders.

The demo quotes are fixed synthetic fixtures dated January 1, 2026, not current prices. Paper orders remain open until cancelled; they never fill, change positions, reserve real cash, or reach an external broker. Only whole-share BUY limit orders are supported. This is an order lifecycle sandbox, not a realistic execution, P&L, or backtesting simulator.

For a credential-free multi-account portfolio walkthrough, run uv run flyrel demo-portfolio or call get_demo_portfolio from MCP. It shows four invented accounts with explicit synthetic labels, separate broker holdings, fractional/short positions and an unpriced position. The fixtures are fixed at January 1, 2026. The CLI demo loads no credentials, connects to no broker and writes no local state. Follow the offline walkthrough.

Optional broker connections

Copy .env.example to .env and configure your own keys locally. Never put keys in chat, issues, examples, or commits. The server reads .env but does not create tokens or perform login.

Adapter

Credentials

Implemented access

Order execution

paper

None

Synthetic accounts/quotes, empty positions/holdings, persisted local orders

Local sandbox only

kite

API key + current access token

Profile, quotes, raw history, cash-equity positions/holdings, day order book

None

alpaca

Key + secret

Account, quotes, raw history, US equity positions, open orders

None

Kite tokens must be obtained/renewed through the broker's supported login flow. Market data and historical access depend on broker entitlements. Alpaca defaults to the broker's paper account endpoint and IEX stock data; FLYREL_ALPACA_PAPER=false selects a live read-only account snapshot. It does not enable trading. Automated adapter tests use mocked HTTP. User-authorized Alpaca paper-account read checks passed on October 29, 2026 for account access, positions, holdings, open orders and an IEX quote. Kite Personal account/holding/position/day-order reads also passed that day, and the owner reported that available holding values matched the UI. Populated Alpaca and Kite position/order mappings, historical data, and private UI checks of the new performance fields remain pending. See the dated validation record for the exact scope.

Run uv run flyrel verify-brokers to explicitly make read-only API checks for both brokers (or add --broker kite / --broker alpaca). The report includes status and row counts, omits account details, and creates no local state. Missing credentials or failed checks return exit code 1. Optional --history-start and --history-end add daily-bar checks. Follow the broker validation checklist for private broker-UI comparison and the workflow validation guide for the first user sessions.

Multiple accounts at the same broker use named credential connections in FLYREL_BROKER_CONNECTIONS. Read tools accept connection_id and require it when a broker has multiple configured connections. Broker-returned account IDs, broker IDs and environments stay separate from those local names. See multiple accounts and local instruments.

Portfolio snapshots preserve currencies and broker views. The starter does not report consolidated NAV: it excludes cash and FX conversion, and keeps Kite holdings separate to avoid silently double-counting delivery positions. Alpaca holdings alias positions. Unsupported non-equity positions fail explicitly rather than disappearing from a purported complete portfolio.

For a current-holdings review, call get_holdings_summary or run:

uv run flyrel holdings-summary --broker kite

This uses account/holding reads only, including on Kite Personal. It shows holding count, market value and broker-reported unrealized P&L per account/currency, with explicit missing-data flags. Per-holding daily price changes are distinct from monetary daily P&L: Kite provides the former; Alpaca also supplies daily unrealized P&L. The existing portfolio summary includes holding metrics separately from position values. No historical return, account-growth calculation or NAV is implied. See holdings performance.

Snapshots now include per-account values and flag duplicate accounts exposed by different connections. A currency with an unpriced position has a null full position value, alongside an explicit partial priced value. Neither is consolidated NAV. The optional local instrument registry assigns user-maintained IDs; unknown symbols stay unregistered rather than receiving guessed identities. Registry metadata is not a live broker instrument master.

Local policy and state

Default sandbox allow-list: US:AAPL, NSE:RELIANCE. Per-order caps: USD 1,000 / INR 100,000. Open-order aggregate caps: USD 5,000 / INR 500,000. Proposal TTL: 120 seconds. Values are checked again at confirmation under a SQLite write transaction. Persistent idempotency keys reject conflicting payloads and make confirmation retries return the existing order within token TTL.

uv run flyrel set-policy examples/policy.json
uv run flyrel halt
uv run flyrel resume

Policy modification and resume are local CLI operations, never MCP tools. The kill switch blocks new local orders; it does not cancel outstanding orders or affect broker accounts. Both proposal and confirmation are callable by an agent, so two calls do not establish human approval. A separately authenticated human approval channel is future work before remote execution.

State lives in ignored .state/: flyrel.sqlite3 holds proposals/orders/audit metadata, alongside optional policy.json. New state directories/files use restrictive permissions. Tokens are stored as hashes. Tool audit records store action/outcome metadata, not credentials, confirmation tokens, arguments, or account responses. This is a local diagnostic log, not a tamper-proof compliance or replay archive. Protect local files: any agent with shell access can change local policy and state.

Development

The minimal public waitlist page lives in website/. It includes email capture and a searchable, regional broker multi-select, backed by a separate Cloudflare Worker and D1 database. Broker selections measure interest; they do not expand implemented integrations or authorize broker execution. See its README for local development, checks and deployment.

uv sync --locked
uv run ruff check .
uv run ruff format --check .
uv run pytest -q
uv build

CI runs lint, format checks, tests (including a real MCP stdio client/server round trip), and package builds on Python 3.12 and 3.13. See architecture, tool inventory, roadmap, and regulatory research.

Scope and regulation

Self-hosting and bring-your-own keys are deployment choices, not regulatory exemptions. There is no compliance certification or automated India/US compliance engine in this release. Review the dated primary sources in the regulatory notes and your broker's requirements before expanding to order routing, distributing strategies, or operating a hosted service.

MIT licensed. Not affiliated with Zerodha, Alpaca, or any exchange. This software does not provide investment advice.

Available Tools

14 tools
cancel_orderA

Cancel one synthetic local order. Cannot cancel orders at an external broker.

Inputs: order_id (required), broker_id. Returns: object

confirm_orderB

Confirm a local sandbox proposal. Creates an open synthetic order that never fills.

Inputs: token (required). Returns: object

get_capabilitiesC

Get the capabilities of one configured broker.

Inputs: broker_id (required). Returns: result

get_holdingsB

Read holdings. Alpaca holdings alias positions; Kite holdings are a separate view.

Inputs: broker_id (required). Returns: result

get_order_statusA

Read one local sandbox order. External broker status lookup is not implemented.

Inputs: order_id (required). Returns: object

get_policyA

Read local paper limits and halt state. Policy changes require the local CLI.

Inputs: no named parameters. Returns: object

get_portfolio_summaryA

Read separate broker position snapshots by currency; no FX conversion or netting.

Inputs: no named parameters. Returns: object

get_positionsB

Read broker positions. Do not add this collection to holdings without reconciliation.

Inputs: broker_id (required). Returns: result

get_quotesB

Read quotes for canonical equity symbols. Paper quotes are fixed synthetic fixtures.

Inputs: symbols (required), broker_id (required). Returns: result

kill_switchA

Persistently block new local paper orders. Does not cancel orders or affect brokers.

Inputs: no named parameters. Returns: object

list_accountsC

Read accounts; synthetic, broker-paper and live balances are labelled separately.

Inputs: broker_id (required). Returns: result

list_brokersA

List configured brokers, supported markets, and capability flags.

Inputs: no named parameters. Returns: result

list_ordersB

Read local paper orders, Alpaca open orders, or Kite's current-day order book.

Inputs: broker_id. Returns: object

propose_orderB

Validate a synthetic BUY limit order and return an expiring confirmation token.

Inputs: request (required). Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 14 tools

    Disambiguation4/5

    Tools are mostly distinct by resource and action, with clear separation between broker listing, account reads, quotes, policy, and order lifecycle operations. The only meaningful overlap is positions vs holdings vs portfolio summary, but the descriptions explicitly clarify aliasing and snapshot semantics so selection remains clear.

    Naming Consistency5/5

    All tool names consistently use snake_case with a recognizable verb_noun pattern such as list_brokers, get_quotes, propose_order, confirm_order, and cancel_order. kill_switch is a slight stylistic outlier but still follows the same readable convention.

    Tool Count5/5

    14 tools sits comfortably within the appropriate range and each tool maps to a distinct broker or paper-trading operation. There are no obvious filler tools or redundant lifecycle steps.

    Completeness4/5

    The surface covers broker/account discovery, quotes, positions/holdings, policy, and the local order lifecycle through propose, confirm, list, status, cancel, and kill switch. Minor gaps remain around external broker order status/cancel and historical fills, but those limitations are explicitly stated and mostly outside the local sandbox scope.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to execute stock trading operations with built-in risk controls and human approval workflows. Supports paper trading simulation, real brokerage integration (Alpaca, Tradier), backtesting, sentiment analysis, and portfolio management while maintaining strict separation between AI intelligence and trade execution.
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI agents to propose stock, ETF, and crypto trades through Alpaca paper trading while enforcing deterministic policy rules and recording every decision in an audit trail.
      13 npm
      MIT