Endpoints: 28,729MCP servers: 18,413Payout addresses: 2,071Paid calls: 1,556Letters: 14Defects: 1,331counted 2 min ago
teppi

Server definition

Hash
sha256:a5415d6c5d295399104ee65373c59ff01ae4db32b61a9476c307149337a2b3d6
What it is
What a remote MCP server returned when asked what it offers: 10 tools

The blob, as servednamed by its sha256

{ "instructions": "BounceWatch keeps a dated record of what companies actually did — funding rounds,\nhiring surges, partnerships, expansion into new markets, leadership changes,\nproduct launches and risk events. Every entry carries the day we saw it, which is\nwhat separates something still worth acting on from old news.\n\nThis connection is not authenticated. You can read what the server offers; running\nany of it needs an account.\n\nTo connect, use whatever sign-in your client offers for this server, or create an\nAPI key and send it as `Authorization: Bearer <key>`. Both reach the same account\nand the same balance — there is no separate subscription for agent access, and new\naccounts start with credits included, so the tools can be tried immediately.\nDetails and setup for each client: https://bouncewatch.com/mcp", "tools": [ { "description": "Returns what has happened at the companies THIS KEY ALREADY WATCHES, since the\nlast time you asked.\n\nThis is a personal inbox, not a view of the index. Use it when the question is\nabout continuity — \"anything new since last time\", \"what did I miss\", \"what fired\non my watchlist\". If the question is what is happening at companies generally —\nlatest signals, who raised, who is hiring, anything about the market or a company\nnot already watched — that is search_signals, and this tool cannot answer it.\n\nDo not open a session with this call. Answer what was actually asked first; reach\nfor this when the user's question is about their own watches.\n\nEach event is handed over once: collecting it marks it seen, so the next call\nreturns only what is new. Pass include_acknowledged to re-read ones you already\ncollected.\n\nAn empty result means nothing matched YOUR watches. It is not a statement about\nthe market, and if you hold no watches it says nothing at all — the response\nreports how many you have so the two cases can be told apart.\n\nThe response also lists your active watches, so this is the only call needed to\nsee both what fired and what is armed.\n\nCost: free — call it as often as you need.", "inputSchema": { "additionalProperties": false, "properties": { "domain": { "description": "Only events for this watched domain.", "type": "string" }, "include_acknowledged": { "description": "Also return events already collected, and do not acknowledge anything on this call. Use when you lost context and need to re-read. Default false.", "type": "boolean" }, "limit": { "description": "Max events to return. Default 25, max 100. Anything beyond the limit stays queued for the next call.", "type": "integer" } }, "type": "object" }, "name": "check_watches", "outputSchema": null }, { "description": "Finds a company in the BounceWatch index by name, and returns its domain — which\nis what every other company tool needs.\n\nUse this whenever you have a company's NAME rather than its domain. Do not guess\nthe domain: a wrong guess comes back as \"not indexed\" for a company we actually\nhold, and sends you on to spend a scan on a domain nobody checked.\n\nReturns up to a handful of candidates with just enough to tell them apart —\ncountry, founding year, headcount, and when we last saw a signal. It never picks\nfor you: names are ambiguous and you have the context that decides. If several\nlook plausible, say so rather than choosing silently. Once you have picked,\nget_company returns the full profile.\n\nAn empty result means no company by that name is in our index. It is not a\nstatement about whether the company exists. If you know its domain,\nrefresh_company indexes it.\n\nCost: 3 credits per call. Failed calls are not charged.", "inputSchema": { "additionalProperties": false, "properties": { "country": { "description": "ISO 3166-1 alpha-2 code of the company HQ, e.g. \"NL\". Narrows an ambiguous name; a code that matches nothing is rejected rather than silently ignored.", "type": "string" }, "limit": { "description": "Max candidates to return. Default 5, max 10.", "type": "integer" }, "name": { "description": "Company name to look for, e.g. \"Silk and Cashmere\". A domain is also accepted and resolved directly.", "type": "string" } }, "required": [ "name" ], "type": "object" }, "name": "find_company", "outputSchema": null }, { "description": "Firmographic profile of one company from the BounceWatch index: identity, location,\nheadcount, funding history, tech stack, team and competitors.\n\nReturns what we currently hold — it never triggers a scan on its own. `coverage` says\nwhat monitoring this company is under; if it is not being followed continuously and\nthe answer depends on facts being current, call refresh_company explicitly.\n\nFor what has been HAPPENING at a company rather than what it IS, use\nget_company_signals.\n\nCost: 10 credits per call at minimum, rising with the extra data you request. Failed calls are not charged.", "inputSchema": { "additionalProperties": false, "properties": { "domain": { "description": "Company domain, e.g. \"stripe.com\". URLs are accepted and normalised.", "type": "string" }, "include": { "description": "Optional enrichment modules: business, technology, funding, team, competitors. Each adds credits — request only what you will use.", "items": { "enum": [ "business", "technology", "funding", "team", "competitors" ], "type": "string" }, "type": "array" } }, "required": [ "domain" ], "type": "object" }, "name": "get_company", "outputSchema": null }, { "description": "Returns the dated signal timeline for one company: funding, hiring, partnerships,\nexpansion, product launches, leadership changes and risk events.\n\nUse this when you already know which company you care about and need to know what\nhas been happening and when. To find companies by signal instead, use search_signals.\n\ncategories and signal_keys widen each other rather than narrowing to the overlap:\na category adds all of its keys to whatever signal_keys already lists.\n\nRead `coverage` before drawing conclusions. If `coverage.signal_absence_is_meaningful`\nis false, an empty or thin result reflects our scanning gap, not the company — say\nso rather than reporting the company as quiet.\n\nCost: 8 credits per call. Failed calls are not charged.", "inputSchema": { "additionalProperties": false, "properties": { "categories": { "description": "Restrict to signal categories (funding, hiring, business, product, growth, event, milestone, risk). Call get_signal_taxonomy for the list.", "items": { "type": "string" }, "type": "array" }, "days": { "description": "Lookback window in days. Default 90, max 365.", "maximum": 365, "minimum": 1, "type": "integer" }, "domain": { "description": "Company domain, e.g. \"stripe.com\". URLs are accepted and normalised.", "type": "string" }, "limit": { "description": "Max signals to return, newest first. Default 50, max 100.", "type": "integer" }, "signal_keys": { "description": "Restrict to exact signal keys, e.g. [\"recently_funded\",\"key_hire_announced\"]. Unrecognised keys are rejected rather than silently ignored.", "items": { "type": "string" }, "type": "array" } }, "required": [ "domain" ], "type": "object" }, "name": "get_company_signals", "outputSchema": null }, { "description": "Checks a scan queued by refresh_company, and WAITS for it.\n\nThis call blocks until the scan is done or `wait_seconds` runs out, so you do not\nhave to idle between polls — just call it again if it comes back unfinished. A\ntypical scan needs two or three calls at the default wait.\n\nRead `is_finished`, not `status`. A scan reaches `completed` when its jobs report\nback, but the signal analysis they started is still writing rows for a few seconds\nafter that — read too early and you get the pre-scan picture with a completed\nstamp on it. `status` becomes `settling` for that window and `is_finished` stays\nfalse until the writes stop.\n\nDo not answer from the old data while a scan you asked for is unfinished: you\nrequested it because the existing figures were too stale to rely on, and they have\nnot changed yet. Either wait for it, or say plainly that a refresh is in flight.\n\nWhen it finishes, `signals_added` says how many new signals the scan actually\nproduced — zero is a real answer and means we looked and found nothing new, not\nthat the scan failed. Then read the data with get_company or get_company_signals;\nthis tool returns progress, not company data.\n\nCost: free — call it as often as you need.", "inputSchema": { "additionalProperties": false, "properties": { "batch_id": { "description": "The batch_id returned by refresh_company.", "type": "string" }, "wait_seconds": { "description": "How long this call may block waiting for the scan, 0-25. Default 20. It returns the moment the scan finishes, and waiting the full 25 costs exactly what waiting 1 costs — so there is nothing to gain by polling with a low value.", "type": "integer" } }, "required": [ "batch_id" ], "type": "object" }, "name": "get_refresh_status", "outputSchema": null }, { "description": "Lists every signal type BounceWatch detects, grouped by category, with what each\none means and whether it is an announcement or an unconfirmed inference.\n\nIt also returns `coverage`, which says which categories produce steadily and which\nare rare by nature. Read it before designing a search: the rarest signals are the\nhighest-value ones — funding, acquisitions, shutdowns — and searching a window for\nthem usually returns almost nothing, because that is how often they happen. Those\nare caught with watch_company, not with a query.\n\nCall this before filtering by signal type in search_signals or get_company_signals:\nfilters are matched exactly, and an unrecognised key returns nothing rather than\nan error. The answer is stable, so once per session is enough.\n\nCost: free — call it as often as you need.", "inputSchema": { "additionalProperties": false, "properties": {}, "type": "object" }, "name": "get_signal_taxonomy", "outputSchema": null }, { "description": "Queues a fresh scan of one company and returns a batch id to poll with\nget_refresh_status. Works for companies already in the index and for domains we\nhave never seen, which is how you add one.\n\nA scan only refreshes what you ask for, and each module reads a different source.\nAnything you leave out keeps the date it already had, so pick by the fact you\nneed:\n\n signals recent events and announcements (default)\n funding rounds, investors, valuations (default)\n team headcount, leadership, open roles\n technology tech stack\n business positioning, model, target market\n competitors similar companies\n\nThe default is signals + funding, because those are the two that go out of date\nfastest and the two most answers turn on. Pass modules explicitly to go cheaper —\n`[\"signals\"]` alone is the least you can usefully scan.\n\nThis spends credits and real scanning budget, so call it deliberately: when\n`coverage` on a previous answer showed stale data AND the decision depends on\ncurrent facts. Do not call it speculatively across a list of candidates.\n\nReturns in a second or two; the scan itself typically takes 60-180 seconds.\nPoll get_refresh_status (free) until it reports finished, then re-read the data\nwith get_company or get_company_signals.\n\nCost: 36 credits per call at minimum, rising with the extra data you request. Failed calls are not charged.", "inputSchema": { "additionalProperties": false, "properties": { "domain": { "description": "Company domain, e.g. \"stripe.com\". URLs are accepted and normalised.", "type": "string" }, "modules": { "description": "What to refresh: business, technology, funding, team, signals, competitors. Each adds credits. Defaults to signals only, which is the cheapest useful scan.", "items": { "enum": [ "business", "technology", "funding", "team", "signals", "competitors" ], "type": "string" }, "type": "array" } }, "required": [ "domain" ], "type": "object" }, "name": "refresh_company", "outputSchema": null }, { "description": "Finds companies by firmographics — country, headcount, funding stage — within the\nset BounceWatch actively observes, most recently refreshed first.\n\nBy default it returns only companies we have observed in the last 90 days, so the\nfirmographics you get are backed by recent observation rather than a record we\nlast touched years ago. Each result reports its signal activity, so you can tell a\nclosely-watched company from a thinly-covered one.\n\nIf you want companies selected by what HAPPENED to them rather than by what they\nARE — recently funded, hiring, expanding — use search_signals instead. That is the\nstronger discovery path and usually the one you want.\n\nCost: 5 credits per call. Failed calls are not charged.", "inputSchema": { "additionalProperties": false, "properties": { "country": { "description": "ISO 3166-1 alpha-2 country code of the company HQ, e.g. \"NL\", \"DE\", \"US\".", "type": "string" }, "founded_after": { "description": "Only companies founded in or after this year, e.g. 2023. Companies whose founding year we do not hold are excluded when this is set, and the result says so.", "type": "integer" }, "founded_before": { "description": "Only companies founded in or before this year. Same exclusion of unknown founding years as founded_after.", "type": "integer" }, "funding_stage": { "description": "Funding stage, e.g. \"Seed\", \"Series A\", \"Pre Seed\". Spacing, case and hyphens are normalised; a value that matches nothing is rejected with the valid list rather than returning a near-empty result. This is the costliest filter here: a company whose stage we do not hold is excluded rather than guessed at, so it narrows the field twice — once by stage, once by what we know.", "type": "string" }, "limit": { "description": "Max companies to return. Default 20, max 50.", "type": "integer" }, "max_employees": { "description": "Maximum headcount. Same exclusion of unknown headcounts as min_employees.", "type": "integer" }, "min_employees": { "description": "Minimum headcount. Companies whose headcount we do not hold are excluded when this is set — same rule as founded_after, and for the same reason: not knowing a number is not evidence it falls outside the range.", "type": "integer" }, "observed_within_days": { "description": "Only companies we observed within this many days, 30-365. Default 90. Widening it grows the result set but lowers confidence in the firmographics, because the record is older. There is no way to switch this off — pass 0 and the widest available window (365) runs instead, and the answer says so. This tool covers the companies we watch, not the whole market.", "type": "integer" } }, "type": "object" }, "name": "search_companies", "outputSchema": null }, { "description": "The latest signals across the whole index: which companies did something recently,\nwhat it was, and when.\n\nThis is the tool for ANY question about what is happening. \"Show me the latest\nsignals\", \"what's new\", \"which companies raised a round and are now hiring sales in\nthe Netherlands\", \"who announced expansion in the last two weeks\", \"which of my\ntarget segment just made a key hire\". Returns matching companies with the signals\nthat matched and their dates.\n\nReach for this first. check_watches only reports on companies already being\nwatched by this key and cannot answer a question about the market or about a\ncompany that is not on that list.\n\nFilter by signal type, category, recency, country, headcount and funding stage.\nCall get_signal_taxonomy first if you are unsure which signal keys exist —\nunrecognised keys are rejected rather than quietly returning nothing.\n\nThe two signal filters WIDEN each other rather than narrowing to the overlap: a\ncategory adds all of its keys to whatever signal_keys already lists. min_weight\nthen cuts what is left, so a low-weight signal type named alongside a floor above\nits own weight returns nothing rather than one of the two being quietly ignored.\n\n`coverage` is working material for you, not for the answer: it bounds what this\nsearch could have found. Let it shape what you claim, and offer a narrower search\nrather than reporting figures about our index.\n\nCost: 12 credits per call. Failed calls are not charged.", "inputSchema": { "additionalProperties": false, "properties": { "categories": { "description": "Signal categories to match: funding, hiring, business, product, growth, event, milestone, risk.", "items": { "type": "string" }, "type": "array" }, "country": { "description": "ISO 3166-1 alpha-2 country code of the company HQ, e.g. \"NL\", \"DE\", \"US\".", "type": "string" }, "days": { "description": "Lookback window in days. Default 30. Max 365. Shorter windows mean sharper timing.", "type": "integer" }, "founded_after": { "description": "Only companies founded in or after this year, e.g. 2023. Companies whose founding year we do not hold are excluded when this is set, and the result says so.", "type": "integer" }, "founded_before": { "description": "Only companies founded in or before this year. Same exclusion of unknown founding years as founded_after.", "type": "integer" }, "funding_stage": { "description": "Funding stage, e.g. \"Seed\", \"Series A\", \"Pre Seed\". Spacing, case and hyphens are normalised; a value that matches nothing is rejected with the valid list rather than returning a near-empty result. This is the costliest filter here: a company whose stage we do not hold is excluded rather than guessed at, so it narrows the field twice — once by stage, once by what we know.", "type": "string" }, "limit": { "description": "Max companies to return. Default 25, max 100.", "type": "integer" }, "max_employees": { "description": "Maximum headcount. Same exclusion of unknown headcounts as min_employees.", "type": "integer" }, "min_employees": { "description": "Minimum headcount. Companies whose headcount we do not hold are excluded when this is set — not knowing a number is not evidence it falls outside the range.", "type": "integer" }, "min_weight": { "description": "Only count signals worth at least this much, 1-10. Background chatter (event attendance, news mentions, follower drift) sits at 1-2 and dominates an unfiltered result; 3 or 4 searches on substance and is the useful setting. Above 7 you are asking for rare events — funding, acquisitions, shutdowns are seldom what a window contains, because that is how often they happen, not how well we see them. Searching for those usually returns little; watch_company is how you catch them. Default 0 (everything).", "type": "integer" }, "require_all_keys": { "description": "When true, only return companies showing EVERY requested signal key in the window (signal stacking) rather than any of them. Default false.", "type": "boolean" }, "signal_keys": { "description": "Signal types to match, e.g. [\"recently_funded\",\"key_hire_announced\"]. See get_signal_taxonomy.", "items": { "type": "string" }, "type": "array" }, "sort": { "description": "most_recent (default) ranks by newest matching signal; most_active by how many matched.", "enum": [ "most_recent", "most_active" ], "type": "string" } }, "type": "object" }, "name": "search_signals", "outputSchema": null }, { "description": "Registers a standing watch on one company, so you find out what happened there\nwithout asking again. This is the only tool that persists between sessions.\n\nA watched company is kept under continuous monitoring — we keep looking at it for\nas long as the watch is active, rather than waiting for someone to ask about it.\n\nMatching signals are queued for you and collected with check_watches (free). If\nthis API key has a webhook URL configured, set deliver_webhook to also have them\npushed to it as they land — that is what lets a hosted agent be woken rather than\nhaving to poll.\n\nNarrow it. A watch with no filters delivers everything, including the background\nchatter that makes a feed unreadable: pass signal_keys for the events you care\nabout, or min_weight to set a floor on how much a signal has to matter. Given both,\na signal has to clear both — a named key that sits below the floor never fires.\n\nCall again with the same domain to change the filters, or with stop:true to end\nthe watch. Watching a domain we have not indexed is allowed, but nothing will fire\nuntil it is — refresh_company indexes it.\n\nCost: 5 credits per call. Failed calls are not charged.", "inputSchema": { "additionalProperties": false, "properties": { "deliver_webhook": { "description": "Also push matches to this key's configured webhook URL. Default false. Events are queued for check_watches either way.", "type": "boolean" }, "domain": { "description": "Company domain, e.g. \"stripe.com\". URLs are accepted and normalised.", "type": "string" }, "label": { "description": "Your own note for this watch, e.g. \"Q3 pipeline\". Returned with every event so you can route it without a second lookup.", "type": "string" }, "min_weight": { "description": "Floor on how much a signal has to matter, 1-10. Roughly: 8+ funding and leadership changes, 5+ hiring and expansion, below 4 background noise. Signals we do not weight never clear a floor.", "type": "integer" }, "signal_keys": { "description": "Only these signal types wake you. Omit for all of them. Values come from get_signal_taxonomy; an unrecognised key is rejected with the valid list rather than creating a watch that silently matches nothing.", "items": { "type": "string" }, "type": "array" }, "stop": { "description": "Ends the watch on this domain. Already-queued events stay collectable.", "type": "boolean" } }, "required": [ "domain" ], "type": "object" }, "name": "watch_company", "outputSchema": null } ] }
Verify it yourselfcurl -s https://api.teppi.xyz/v1/evidence/sha256:a5415d6c5d295399104ee65373c59ff01ae4db32b61a9476c307149337a2b3d6 | sha256sum