FirmFax prop firm data

Independent rule and fee data on 71 prop trading firms, every figure with its evidence state.

Should I use this

Quality & Safety

A
Description quality
87%
Schema completeness
85%
Naming quality
97%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Findings (2)

  • LOWTool 'get_firm' description lacks action verbin get_firm
  • LOWTool 'list_firms' description lacks action verbin list_firms

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~1,271Tokens (tool definitions)
~1.7 KBTypical response size
Moderate attention impact (0.99% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "prop-firm-data": {
      "url": "https://firmfax.com/api/mcp"
    }
  }
}

Remote endpoints

https://firmfax.com/api/mcpstreamable-http

What it can do

Tool inventory

Tools (6)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢get_firm(slug)

One prop trading firm. Every figure states whether we hold evidence for it, and a firm whose score range spans more than one band carries no letter grade at all.

Input Schema

{
  "type": "object",
  "properties": {
    "slug": {
      "type": "string",
      "description": "The firm slug, e.g. \"topstep\"."
    }
  },
  "required": [
    "slug"
  ]
}
🟢get_rule_changes(slug, since, kind, limit)

The dated record of what changed, newest first. Every entry states its KIND, and most of this tape is FirmFax correcting its own data rather than a firm changing its rules. Read counts before describing industry activity: a total taken across kinds overstates it.

Input Schema

{
  "type": "object",
  "properties": {
    "slug": {
      "type": "string",
      "description": "Limit to one firm. Omit for every firm."
    },
    "since": {
      "type": "string",
      "description": "ISO date, e.g. \"2026-08-01\". Entries dated on or after it."
    },
    "kind": {
      "type": "string",
      "enum": [
        "firm",
        "record",
        "withdrawn"
      ],
      "description": "firm = the firm changed a rule. record = FirmFax corrected its own data. withdrawn = we published an entry and then retracted it."
    },
    "limit": {
      "type": "number",
      "description": "How many entries to return, newest first. Default 50."
    }
  }
}
🟢get_evidence(slug, field)

The stored reading behind a figure: the verbatim quote, the page it came from, and the date we read it. Answers "we hold none" explicitly rather than returning an empty list. `outcome` is load-bearing: a `contradicted`, `contradiction` or `absent` row records what we read, not a figure we publish. Use get_firm for the published figure.

Input Schema

{
  "type": "object",
  "properties": {
    "slug": {
      "type": "string",
      "description": "The firm slug, e.g. \"topstep\"."
    },
    "field": {
      "type": "string",
      "description": "One field path, e.g. \"rules.dailyLossLimit\". Omit for every field we hold for this firm."
    }
  },
  "required": [
    "slug"
  ]
}
🟢find_firms(assetClass, maxActivationFee, maxResetFee, maxConsistencyPct, maxDailyLossLimit, ...)

Firms matching every criterion given. A firm whose record does not carry a criterion is never counted as a match and never silently dropped: it is returned separately under unknown, with the field that could not be tested. Absence is common here, so read counts before treating the matched list as the answer.

Input Schema

{
  "type": "object",
  "properties": {
    "assetClass": {
      "type": "string",
      "enum": [
        "forex",
        "futures",
        "crypto"
      ],
      "description": "Firms recorded as offering this. 21 of 71 records name no asset class and are returned as unknown."
    },
    "maxActivationFee": {
      "type": "number",
      "description": "Activation fee at or below this. 42 of 71 record no fee."
    },
    "maxResetFee": {
      "type": "number",
      "description": "Reset fee at or below this. 56 of 71 record no fee."
    },
    "maxConsistencyPct": {
      "type": "number",
      "description": "Consistency rule at or below this. 28 of 71 record none."
    },
    "maxDailyLossLimit": {
      "type": "number",
      "description": "Daily loss limit at or below this, in the unit dailyLossLimitUnit names. 31 of 71 record none."
    },
    "dailyLossLimitUnit": {
      "type": "string",
      "enum": [
        "percent",
        "usd"
      ],
      "description": "The unit maxDailyLossLimit is in. Daily loss limits are recorded in percent at some firms and in dollars at others, and the two are never compared: a firm recorded in the other unit is returned under unknown with its unit named."
    },
    "maxMinTradingDays": {
      "type": "number",
      "description": "Minimum trading days at or below this, counted as minTradingDaysUnit names. 16 of 71 record none."
    },
    "minTradingDaysUnit": {
      "type": "string",
      "enum": [
        "calendar_days",
        "trading_days",
        "winning_days"
      ],
      "description": "What maxMinTradingDays counts: calendar_days, trading_days or winning_days. A minimum is compared only with minimums counted the same way; a firm counting another way, or stating no unit, is returned under unknown with what it counts named."
    },
    "minTradingDaysMinProfit": {
      "type": "number",
      "description": "With winning_days only: the profit a day must reach to count. A firm whose winning days carry a different profit bar is returned under unknown."
    },
    "maxMinDaysToPayout": {
      "type": "number",
      "description": "Minimum days to first payout at or below this, counted as minDaysToPayoutUnit names. 26 of 71 record none."
    },
    "minDaysToPayoutUnit": {
      "type": "string",
      "enum": [
        "calendar_days",
        "trading_days",
        "winning_days"
      ],
      "description": "What maxMinDaysToPayout counts: calendar_days, trading_days or winning_days. A wait is compared only with waits counted the same way; a firm counting another way, or stating no unit, is returned under unknown with what it counts named."
    },
    "minDaysToPayoutMinProfit": {
      "type": "number",
      "description": "With winning_days only: the profit a day must reach to count. A firm whose winning days carry a different profit bar is returned under unknown."
    }
  }
}
⚪compare_firms(a, b)

Two firms side by side. Reports each figure with its evidence state and whether the pair is comparable at all: a field neither firm records is not a tie, and a field only one records is not a win. No per-field winner is declared, because the direction of "better" for several of these is a judgement the published scoring model already makes; each firm's grade is returned alongside so the verdict comes from that model rather than from this tool.

Input Schema

{
  "type": "object",
  "properties": {
    "a": {
      "type": "string",
      "description": "First firm slug."
    },
    "b": {
      "type": "string",
      "description": "Second firm slug."
    }
  },
  "required": [
    "a",
    "b"
  ]
}
🟢list_firms

Every firm slug and name. Carries no figures, so nothing here needs evidence.

Input Schema

{
  "type": "object",
  "properties": {}
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded6 tools
verifiedversion not recorded6 tools
verifiedversion not recorded6 tools
verifiedversion not recorded6 tools
verifiedversion not recorded6 tools
verifiedversion not recorded6 tools