{
  "serverInfo": {
    "name": "Fund Momentum",
    "version": "1.6.0",
    "description": "Live VC intelligence for 980 actively deploying funds. Query fund profiles, GP signal profiles, thesis tags and deployment status. LP coverage counts are free; LP records require an LP Radar subscription. Every fund profile carries a provenance block naming its source, last verification date and confidence.",
    "homepage": "https://fundmomentum.vc",
    "icon": "https://fundmomentum.vc/favicon.png",
    "endpoint": "https://fundmomentum.vc/_api/mcp",
    "transport": "streamable-http",
    "docs": "https://fundmomentum.vc/mcp",
    "tools_reference_markdown": "https://fundmomentum.vc/_api/mcp-tools",
    "usage": {
      "order_of_operations": "Call search_funds (or match_startup for a qualitative brief) FIRST and take the `slug` from its results. get_fund, get_fund_signals and get_gp_profile all require a slug that came from a search. Slugs are not derivable from a fund's display name.",
      "slug_resolution": "A near-miss slug is resolved only when exactly one fund matches (case or spacing differences, or a hyphen-boundary prefix of one real slug). It is served with `resolved_from` naming what was requested. Several matches are listed and none is served; no match is not_found. Resolution happens before any payment challenge, so a wrong name is never charged.",
      "refusal_messages": "Refusals open with the route for a person (a free key at the pricing page), then the route for automated callers (POST to the register URL). Structured fields in error.data / _meta are unchanged; parse those rather than the prose.",
      "staying_current": "Use get_changes with the previous response's next_since and etag instead of re-running search_funds on a schedule. For 'which funds just closed', call search_funds with closed_since; on Pro, subscribe a webhook for close_updated instead of polling.",
      "read_only": "All tools are read-only. Nothing on this server mutates anything."
    }
  },
  "counts": {
    "funds": 980,
    "disclosed_lps": 730,
    "counted_at": "2026-10-19T04:45:04.654Z",
    "note": "Live SELECT COUNT(*) at request time, not a marketing figure. Marketing copy elsewhere on the site rounds this down."
  },
  "limited_partners": {
    "dataset": {
      "disclosed_lps": 730,
      "hq_countries": 63,
      "backed_emerging_managers": 169
    },
    "coverage": {
      "tool": "check_lp_coverage",
      "access": "free",
      "keyless_allowed": true,
      "billed_to_credits": false,
      "returns": "Counts only: matched LPs, emerging-manager backers, undisclosed-HQ bucket. Never a name, slug, website or commitment.",
      "filters": [
        "country",
        "lp_type"
      ],
      "suppression": "Counts below 5 are returned as \"<5\"; zero is returned as \"none\"."
    },
    "records": {
      "tool": "search_lps",
      "access": "lp_radar_subscription",
      "price": "EUR 199 per month or EUR 1,499 per year",
      "product": "https://fundmomentum.vc/lp-radar",
      "auth": "The API key of the account that holds LP Radar. Agent keys cannot hold it.",
      "calls": "Unlimited for subscribers, not counted against any quota.",
      "max_records_per_call": 25,
      "refusal": "Without LP Radar: error_reason \"lp_access_required\", with the coverage count for the requested filters. Never a payment challenge."
    },
    "directory": "https://fundmomentum.vc/lp-database"
  },
  "not_available_here": {
    "lp_records_without_subscription": {
      "available": false,
      "reason": "LP records are not sold per call, on agent credits or on the keyless trial. Only an LP Radar subscription opens search_lps. Coverage counts via check_lp_coverage are free.",
      "product": "https://fundmomentum.vc/lp-radar"
    },
    "lp_commitment_history": {
      "available": false,
      "reason": "No tool returns LP commitment history, dates, fund sizes or allocation patterns, subscription or not. Those stay in the LP Radar web product.",
      "product": "https://fundmomentum.vc/lp-radar"
    }
  },
  "authentication": {
    "required": false,
    "registration_required": false,
    "email_required": false,
    "schemes": [
      "apiKey",
      "bearer"
    ],
    "header": "X-API-Key",
    "alternative_header": "Authorization: Bearer <key>",
    "query_parameter": "api_key",
    "keyless_trial": {
      "tools": [
        "search_funds",
        "get_fund",
        "get_changes",
        "check_lp_coverage"
      ],
      "calls_per_caller_per_utc_day": 10,
      "ip_ceiling_per_utc_day": 60,
      "signup_required": false,
      "note": "Call these with no credential at all to see real data before deciding anything."
    },
    "anonymous_key": {
      "endpoint": "/_api/agent/register",
      "method": "POST",
      "body": {
        "agent_name": "string (3-64 chars)"
      },
      "optional_body": {
        "operator_url": "string",
        "contact": "string, free text, never verified"
      },
      "free_credits": 25,
      "credit_value": "€0.01",
      "credits_never_expire": true,
      "registrations_per_ip_per_utc_day": 3,
      "registrations_per_ip24_per_utc_day": 10,
      "returns": "api_key and agent_id immediately. The key is shown ONCE; only a hash is stored.",
      "note": "No email, no approval, no human. Identity is the API key. Register and make a useful call in the same second."
    },
    "paid": {
      "protocol": "mpp",
      "spec": "https://mpp.dev",
      "methods": [
        "tempo_usdc"
      ],
      "no_key_required": true,
      "free_tool_price_eur": 0.01,
      "pro_tool_prices_eur": {
        "get_fund_signals": 0.1,
        "get_gp_profile": 0.1,
        "match_startup": 0.25
      },
      "topup_endpoint": "/_api/agent/credits/topup",
      "topup_amounts_eur": [
        5,
        20,
        50,
        100
      ],
      "daily_spend_limit_eur": 1000,
      "http_status_when_payment_required": 402,
      "note": "A Pro tool called with NO key answers 402 with a payable challenge. Pay, retry, get the data and a receipt. No account is created at any point.",
      "challenge_discovery": "standard",
      "challenge_header": "WWW-Authenticate",
      "discovery_document": "https://fundmomentum.vc/openapi.json",
      "network": "tempo-mainnet",
      "chain_id": 4217,
      "settlement": "USDC on Tempo mainnet, converted from EUR at the ECB daily reference rate plus a 1.5% buffer. The chain id and token address in the 402 challenge are authoritative."
    },
    "autonomous_payment_available": true,
    "optional_account_link": "/_api/agent/link",
    "account_link_note": "Entirely optional, for invoices and a dashboard. It grants NO access and changes NO credits. This and /_api/agent/link/resend are the only endpoints that ever send email.",
    "human_subscriptions": {
      "url": "https://fundmomentum.vc/pricing",
      "free_calls_per_month": 100,
      "note": "Monthly-quota plans for people. Unchanged by, and unrelated to, the agent tiers above."
    },
    "free_tier_response_shaping": {
      "search_funds_max_results": 10,
      "search_funds_max_results_paid": {
        "agent_credits": null,
        "agent_credits_max_funds_per_day": 150,
        "starter_per_call": 50,
        "pro_per_call": 250
      },
      "search_funds_price": "1 credit (EUR 0.01) per fund returned, minimum 1, for agents on credits or inline MPP.",
      "search_funds_note": "Responses carry returned, matched, limit, max_limit and truncated, and next_offset when more remain. Agents on credits have no per-call cap but may fetch the daily funds allowance per key per UTC day; a call that would exceed it is refused before any charge. Starter gets a smaller page and no offset; Pro pages with offset. An over-cap limit is rejected, not clamped, and offset needs a paying caller.",
      "get_changes_max_items": 20,
      "get_changes_max_lookback_days": 30,
      "note": "A shortened get_changes window is declared as since_floor_applied — do not treat such a response as a full catch-up. Paid callers are not shaped."
    },
    "instructions": "No registration and no email are required to use this server. Start with no credential at all: search_funds and get_fund and get_changes and check_lp_coverage answer 10 calls per caller per UTC day. For a key, POST {\"agent_name\":\"...\"} to https://fundmomentum.vc/_api/agent/register — no email field — and you get an api_key plus 25 free credits in the same response, worth €0.01 each. Free tools cost 1 credit per call; the Pro tools are priced per call (get_fund_signals €0.10, get_gp_profile €0.10, match_startup €0.25). check_lp_coverage is never billed; search_lps is never priced per call and needs an LP Radar subscription (https://fundmomentum.vc/lp-radar). When credits run out, or if you hold no key at all, a paid tool answers HTTP 402 with an MPP challenge (https://mpp.dev, Tempo USDC): pay it and retry, and you get the data plus a receipt. No account is created. Top up a key with POST /_api/agent/credits/topup. Spending is capped at €1000.00 per payer per UTC day. Linking an email at /_api/agent/link is optional, grants no access and changes no credits. Humans wanting monthly-quota plans instead: https://fundmomentum.vc/pricing."
  },
  "tools": [
    {
      "name": "search_funds",
      "title": "Search VC funds",
      "description": "START HERE for any question about funds. Search actively deploying venture capital funds by stage, country, industry and recent closes. COST: free, and it works with no API key at all. Returns name, slug, country, stage, fund size, industries, the latest published close (lastCloseDate, lastCloseType) and a durable profile URL. For 'which funds just closed', pass closed_since: results then come newest close first. The `slug` in each result is what every other tool takes as input, so run this first and copy the slug rather than constructing one from a fund's name.",
      "annotations": {
        "title": "Search VC funds",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      },
      "access": "free",
      "price_eur": 0.01,
      "payable_without_account": true,
      "requiredTier": "free",
      "price": "€0",
      "inputSchema": {
        "type": "object",
        "properties": {
          "stage": {
            "type": "string",
            "enum": [
              "growth",
              "late_stage",
              "pre_seed",
              "seed",
              "series_a",
              "series_b",
              "series_c"
            ],
            "description": "Funding stage. Matches every fund that invests at this stage, including multi-stage funds whose range covers it (each result lists all its stages in fundingStages). Must be one of the listed enum values (lowercase, underscores). Common spellings such as 'Pre-Seed' or 'Series A' are accepted and normalised."
          },
          "country": {
            "type": "string",
            "description": "Country of the fund's headquarters, spelled out in full (e.g. 'United States', 'United Kingdom', 'Germany'). Not an ISO code."
          },
          "industry": {
            "type": "string",
            "enum": [
              "agritech",
              "ai_ml",
              "biotech",
              "built_environment",
              "carbon_removal",
              "circular_economy",
              "climate_sustainability",
              "cloud_devops",
              "consumer_commerce",
              "creator_economy",
              "cybersecurity",
              "data_infrastructure",
              "deep_tech",
              "defense",
              "developer_tools",
              "diagnostics",
              "digital_banking",
              "digital_education_consumer",
              "digital_health",
              "digital_infrastructure",
              "ecommerce",
              "energy_tech",
              "enterprise_software",
              "evs_charging",
              "fashion_tech",
              "fem_tech",
              "fintech",
              "food_beverage",
              "food_tech",
              "gaming",
              "infrastructure_tech",
              "insur_tech",
              "iot",
              "manufacturing",
              "marketplaces",
              "med_tech",
              "mental_health",
              "mobility_transport",
              "payments_embedded_finance",
              "private_markets",
              "prop_tech",
              "robotics_automation",
              "saas",
              "semiconductors",
              "space",
              "supply_chain",
              "therapeutics",
              "travel_tech",
              "vertical_saas",
              "water_tech",
              "wealth_tech",
              "web3_finance",
              "web3_infrastructure",
              "wellness_lifestyle"
            ],
            "description": "Industry focus. Must be one of the listed enum values (lowercase, underscores), e.g. 'ai_ml', 'fintech', 'climate_sustainability'. Common spellings such as 'AI/ML', 'FinTech' or 'climate' are accepted and normalised."
          },
          "closed_since": {
            "type": "string",
            "format": "date",
            "description": "Only funds whose latest published close (first, interim or final close, or a launch) is on or after this date, ISO format YYYY-MM-DD (e.g. '2026-09-01'). Close data comes from Fund Momentum's own close coverage, each with a source URL in get_fund's last_close block."
          },
          "limit": {
            "type": "integer",
            "description": "Number of results to return. Without a paid account the maximum is 10 (default 10); a larger value is rejected, not clamped. Agents paying with credits are billed 1 credit (EUR 0.01) per fund returned, up to 150 funds per key per UTC day (a call that would exceed the remainder is refused before any charge); if limit is omitted they receive every match within that allowance. Starter gets up to 50 per call; Pro gets up to 250 and can page with offset. The response reports `matched` (total matches) and `truncated`."
          },
          "offset": {
            "type": "integer",
            "description": "Number of matches to skip, for paging through a large result set (use next_offset from a truncated response). Agents paying with credits and Pro plans only."
          }
        }
      }
    },
    {
      "name": "get_fund",
      "title": "Get fund profile",
      "description": "THEN: get the detailed profile of one fund, using a slug returned by search_funds. COST: free, no API key required. Every response carries a `provenance` block stating where each field came from (including per-field sources), when it was last verified, and how confident Fund Momentum is in it, plus a `last_close` block (close type, date, amount and currency as stated, source URL) when Fund Momentum has covered a close of this fund. Do not guess the slug from a fund's display name; it will usually be wrong and the call is wasted. A near-miss is resolved only when exactly one fund matches, and the result then carries `resolved_from`; a name matching several funds is listed, not guessed.",
      "annotations": {
        "title": "Get fund profile",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      },
      "access": "free",
      "price_eur": 0.01,
      "payable_without_account": true,
      "requiredTier": "free",
      "price": "€0",
      "inputSchema": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "The slug identifier of a fund, exactly as returned in the `slug` field of search_funds. Call search_funds first rather than guessing: slugs are not derivable from a fund's display name."
          }
        },
        "required": [
          "slug"
        ]
      }
    },
    {
      "name": "get_changes",
      "title": "Get changed funds since",
      "description": "FOR STAYING CURRENT, not for discovery: return only the funds whose data changed since a given timestamp. COST: free, no API key required. With no key it reaches back at most 7 days; a free key widens that to 30 days, and a paid caller is not limited. A shortened window is declared as since_floor_applied, never silently truncated. Designed for cheap repeated polling: send the `next_since` AND the `etag` from your previous response, and an unchanged window answers with `unchanged: true` and no rows. Each row has change_type created, signal_updated or close_updated; close_updated means Fund Momentum published a new first, interim or final close for that fund and carries a last_close block with type, date, size and source URL. Use this instead of re-running search_funds on a schedule. One call here replaces a full re-crawl.",
      "annotations": {
        "title": "Get changed funds since",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      },
      "access": "free",
      "price_eur": 0.01,
      "payable_without_account": true,
      "requiredTier": "free",
      "price": "€0",
      "inputSchema": {
        "type": "object",
        "properties": {
          "since": {
            "type": "string",
            "description": "Lower bound, exclusive. Accepts either an ISO 8601 timestamp ('2026-08-01T00:00:00Z') or a unix epoch in milliseconds as a string ('1785955265103'). Omit to receive the last 7 days."
          },
          "if_none_match": {
            "type": "string",
            "description": "The `etag` value from your previous get_changes response. If nothing changed, the reply is a few bytes instead of a full page. This is the cheapest poll available here."
          },
          "limit": {
            "type": "integer",
            "description": "Maximum rows to return (1-200)",
            "default": 50
          }
        }
      }
    },
    {
      "name": "get_fund_signals",
      "title": "Get fund investor signals",
      "description": "DRILL DOWN on a fund you already identified with search_funds or get_fund. Returns investor signals: GP thesis, bullish and contrarian signals, founder dos and don'ts, deployment status and source URLs. This is the tool to use before writing an outreach message to a specific fund. COST: included in Pro, or €0.10 per call over MPP if you have no key. Roughly 96% of funds carry signals; the rest return not_found BEFORE any payment is taken, so a wrong slug is never charged for.",
      "annotations": {
        "title": "Get fund investor signals",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      },
      "access": "pro",
      "price_eur": 0.1,
      "payable_without_account": true,
      "requiredTier": "pro",
      "price": "€29/mo",
      "inputSchema": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "The fund's slug, exactly as returned in the `slug` field of search_funds. Call search_funds first rather than guessing."
          }
        },
        "required": [
          "slug"
        ]
      }
    },
    {
      "name": "get_gp_profile",
      "title": "Get General Partner profiles",
      "description": "DRILL DOWN to the people: General Partner profiles for a fund you already identified. Use this when the question is who to approach and what they personally focus on, rather than what the fund does. COST: included in Pro, or €0.10 per call over MPP if you have no key. A fund with no published GP data returns not_found before any payment. Requires a slug from search_funds.",
      "annotations": {
        "title": "Get General Partner profiles",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      },
      "access": "pro",
      "price_eur": 0.1,
      "payable_without_account": true,
      "requiredTier": "pro",
      "price": "€29/mo",
      "inputSchema": {
        "type": "object",
        "properties": {
          "fund_slug": {
            "type": "string",
            "description": "The fund's slug, exactly as returned in the `slug` field of search_funds. Call search_funds first rather than guessing."
          },
          "gp_name": {
            "type": "string",
            "description": "Optional GP name to filter by"
          }
        },
        "required": [
          "fund_slug"
        ]
      }
    },
    {
      "name": "match_startup",
      "title": "Match startup to funds",
      "description": "ALTERNATIVE ENTRY POINT when you do not know what to search for. Describe a startup in plain language and receive the top 10 matching funds, each with a slug, a reason and a score. Use this instead of search_funds when the brief is qualitative ('climate hardware, pre-seed, Europe') rather than a filter. Slower than the other tools, three to ten seconds, because it reasons over every tracked fund: allow for that before you time out and retry. COST: included in Pro, or €0.25 per call over MPP if you have no key.",
      "annotations": {
        "title": "Match startup to funds",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      },
      "access": "pro",
      "price_eur": 0.25,
      "payable_without_account": true,
      "requiredTier": "pro",
      "price": "€29/mo",
      "inputSchema": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "description": "Startup description (max 500 chars)"
          },
          "stage": {
            "type": "string",
            "enum": [
              "growth",
              "late_stage",
              "pre_seed",
              "seed",
              "series_a",
              "series_b",
              "series_c"
            ],
            "description": "Funding stage. Must be one of the listed enum values; common spellings are normalised."
          },
          "country": {
            "type": "string",
            "description": "Country, spelled out in full"
          }
        },
        "required": [
          "description"
        ]
      }
    },
    {
      "name": "check_lp_coverage",
      "title": "Check LP coverage",
      "description": "START HERE for any question about limited partners (LPs). Answers \"does Fund Momentum cover my geography and LP type\" with COUNTS ONLY: how many disclosed LPs match, and how many of those have backed emerging managers. It never returns a name, slug, website or commitment. COST: free, works with no API key at all (counts against the keyless daily allowance), and is never billed to agent credits or a monthly quota. Counts below 5 are reported as \"<5\" and zero as \"none\". Call this before search_lps to find out whether LP Radar covers what you need.",
      "annotations": {
        "title": "Check LP coverage",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      },
      "access": "free",
      "price_eur": 0,
      "payable_without_account": false,
      "sold_per_call": false,
      "keyless_allowed": true,
      "requiredTier": "free",
      "price": "€0",
      "inputSchema": {
        "type": "object",
        "properties": {
          "country": {
            "type": "string",
            "description": "Headquarters country of the LP, spelled out in full (e.g. 'Germany', 'United States'). Two-letter ISO codes are accepted too. LPs whose headquarters is undisclosed are never counted under a country; they are reported separately as undisclosed_hq_count."
          },
          "lp_type": {
            "type": "string",
            "enum": [
              "Pension fund",
              "Insurer",
              "Foundation / Endowment",
              "University / Research",
              "Bank",
              "Public / State institution",
              "Sovereign wealth fund",
              "Fund-of-Funds",
              "Asset manager / Investment firm",
              "Family office / Holding",
              "Corporate / Strategic",
              "Impact investor",
              "Investment vehicle",
              "Individual / Angel",
              "Institutional LP"
            ],
            "description": "LP type. Must be one of the listed values; common spellings such as 'family office', 'pension' or 'fund of funds' are accepted and normalised."
          }
        }
      }
    },
    {
      "name": "search_lps",
      "title": "Search LP records",
      "description": "THEN, for LP Radar subscribers: return limited partner records (name, slug, LP type, HQ country and city, geographic focus, website, emerging-manager backing, verified flag) filtered by country, LP type and emerging-manager backing, at most 25 per call. Set backs_emerging_managers=true to see only LPs that have already backed a first or second fund — for a first-time manager that is usually the only filter that matters. Requires LP Radar (EUR 199 per month or EUR 1,499 per year, https://fundmomentum.vc/lp-radar). Not available per call, on agent credits or on the keyless trial. Unlimited calls for subscribers. Use check_lp_coverage first — it is free and tells you whether the dataset covers your geography and LP type before you pay anything. Send the API key of the account that holds LP Radar. A caller without it gets error_reason \"lp_access_required\" together with the coverage count for its filters, never a payment challenge. website is null when no website is on record; it is never omitted.",
      "annotations": {
        "title": "Search LP records",
        "readOnlyHint": true,
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false
      },
      "access": "lp_radar_subscription",
      "price_eur": null,
      "payable_without_account": false,
      "sold_per_call": false,
      "subscription": {
        "price": "EUR 199 per month or EUR 1,499 per year",
        "url": "https://fundmomentum.vc/lp-radar"
      },
      "requiredTier": "free",
      "price": "EUR 199 per month or EUR 1,499 per year",
      "inputSchema": {
        "type": "object",
        "properties": {
          "country": {
            "type": "string",
            "description": "Headquarters country of the LP, spelled out in full (e.g. 'Germany'). Two-letter ISO codes are accepted too."
          },
          "lp_type": {
            "type": "string",
            "enum": [
              "Pension fund",
              "Insurer",
              "Foundation / Endowment",
              "University / Research",
              "Bank",
              "Public / State institution",
              "Sovereign wealth fund",
              "Fund-of-Funds",
              "Asset manager / Investment firm",
              "Family office / Holding",
              "Corporate / Strategic",
              "Impact investor",
              "Investment vehicle",
              "Individual / Angel",
              "Institutional LP"
            ],
            "description": "LP type. Must be one of the listed values; common spellings such as 'family office' or 'pension' are accepted and normalised."
          },
          "backs_emerging_managers": {
            "type": "boolean",
            "description": "true returns only LPs that have backed an emerging manager; false returns only those that have not. Omit for both. Not available on check_lp_coverage, which reports the figure as a breakdown instead."
          },
          "limit": {
            "type": "integer",
            "description": "Records to return, 1-25. A value above 25 is rejected, not clamped.",
            "default": 10
          }
        }
      }
    }
  ],
  "polling": {
    "recommended_tool": "get_changes",
    "note": "Do not re-run search_funds on a schedule. Call get_changes, advance to the next_since it returns, and send the previous etag back as if_none_match; an unchanged window comes back with zero rows.",
    "http_alternative": {
      "method": "GET",
      "url": "https://fundmomentum.vc/_api/changes",
      "query": {
        "since": "<iso 8601 or unix ms>",
        "limit": "1-200"
      },
      "conditional": "Keep the ETag response header and send it back as If-None-Match. An unchanged window answers 304 with an empty body."
    },
    "change_types": [
      "created",
      "signal_updated",
      "close_updated"
    ]
  },
  "closes": {
    "get_fund_field": "last_close",
    "close_types": [
      "launch",
      "first",
      "interim",
      "final",
      "closed_unspecified",
      "target_only"
    ],
    "search_filter": "search_funds.closed_since (YYYY-MM-DD), newest close first",
    "amounts": "As stated by the fund, never converted",
    "coverage_note": "Only closes Fund Momentum covered. A null last_close means not covered, not 'not closed'."
  },
  "webhooks": {
    "events": [
      "close_updated"
    ],
    "access": "pro, enterprise",
    "subscribe": {
      "method": "POST",
      "url": "https://fundmomentum.vc/_api/webhooks/subscribe",
      "body": {
        "url": "https://...",
        "filters": {
          "stage": "optional",
          "country": "optional",
          "industry": "optional"
        }
      }
    },
    "list": {
      "method": "GET",
      "url": "https://fundmomentum.vc/_api/webhooks/list"
    },
    "test": {
      "method": "POST",
      "url": "https://fundmomentum.vc/_api/webhooks/test",
      "body": {
        "id": "<subscription id>"
      }
    },
    "delete": {
      "method": "POST",
      "url": "https://fundmomentum.vc/_api/webhooks/delete",
      "body": {
        "id": "<subscription id>"
      }
    },
    "signature": "FM-Signature: t=<unix>,v1=<hex HMAC-SHA256 of '<t>.<raw body>' with the subscription secret>",
    "retries": "1m, 5m, 30m, 2h, 6h, 12h, 24h",
    "max_subscriptions_per_key": 5,
    "docs": "https://fundmomentum.vc/mcp#webhooks"
  },
  "resources": [],
  "prompts": []
}