Agents need to interact with banks, airlines, and legacy portals that will never ship official APIs. Pomerado (YC F26) wraps these sites as MCP servers by recording a single manual workflow, then generating deterministic HTTP-based scrapers that self-heal when the DOM changes. The pitch is simple: describe a task in natural language, answer a few questions, and get a working MCP in under an hour. Future calls skip the browser and return results in 5-30 seconds.
This matters because computer use (Anthropic's term for pixel-level browser automation) is too slow and brittle for repeated financial workflows. Most banks also ban headless browsers in their terms of service. Pomerado's approach sidesteps both problems by converting the site into a structured API that agents can call like any other tool.
Traditional web scraping breaks when a bank changes a CSS class or reorders form fields. Pomerado claims "deterministic" scrapers, which means the same input always produces the same output, even after site updates. Here's how that works in practice:
The key insight is that financial sites change their presentation layer frequently but rarely change their underlying form schemas or API contracts. Pomerado bets that HTTP-level scraping (not Selenium clicks) can remain stable if you track structural invariants instead of surface selectors.
When a bank's login page changes, Pomerado's MCP server detects the mismatch and triggers a repair workflow:
This only works if the site's underlying behavior is stable. If a bank redesigns its entire authentication flow (OAuth to SAML, for example), no amount of selector healing will help. Pomerado's model assumes incremental UI changes, not architectural rewrites.
Financial agents need to maintain authenticated sessions across multiple tool calls. Pomerado's MCP servers handle this by:
check_balance() followed by transfer_funds(), both requests reuse the same session.
The authentication boundary is critical. Pomerado stores credentials on behalf of the agent, which means the MCP server becomes a privileged component. If an attacker compromises the MCP, they gain access to the underlying bank account. This is why Pomerado positions itself as infrastructure for internal agents (employee assistants, back-office automation) rather than consumer-facing bots.
When an agent tries to execute a trade through a scraped brokerage interface, several things can go wrong:
| Failure Type | Detection Method | Agent-Visible Error |
|---|---|---|
| DOM structure changed | Hash mismatch on page load | ToolUnavailable: Site structure changed, healing in progress |
| Session expired | 401 or redirect to login | AuthenticationRequired: Re-run with fresh credentials |
| Rate limit hit | 429 or CAPTCHA challenge | RateLimitExceeded: Retry after 60s |
| Transaction rejected | Error message in response body | TransactionFailed: Insufficient funds (parsed from site error) |
| Network timeout | No response after 30s | Timeout: Site unresponsive, retry or escalate |
The worst failure mode is silent success. If Pomerado's parser misreads a confirmation page and reports a trade as executed when it actually failed, the agent will proceed with incorrect state. To mitigate this, Pomerado validates every response against an expected schema. If the schema match confidence is below 90%, the MCP returns Uncertain instead of a false positive.
Here's the end-to-end flow for creating a new MCP:
The generated code looks like this (simplified):
import httpx
from mcp.server import MCPServer
class ChaseBalanceTool:
def __init__(self, session_store):
self.session = session_store
self.client = httpx.Client(cookies=self.session.cookies)
async def get_balance(self, account_id: str) -> dict:
resp = self.client.get(
"https://secure.chase.com/web/auth/dashboard",
headers={"User-Agent": "Mozilla/5.0..."}
)
if resp.status_code == 401:
raise AuthenticationRequired()
balance_elem = self._find_element(resp.text, [
{"selector": "span.balance-amount"},
{"text_contains": "Available Balance"},
{"aria_label": "account balance"}
])
if not balance_elem:
raise ToolUnavailable("Balance element not found, site may have changed")
return {
"account_id": account_id,
"balance": float(balance_elem.text.strip("$").replace(",", "")),
"currency": "USD"
}
def _find_element(self, html: str, strategies: list) -> Optional[Element]:
for strategy in strategies:
elem = self._try_selector(html, strategy)
if elem and self._validate_element(elem):
return elem
return None
server = MCPServer()
server.register_tool("chase_get_balance", ChaseBalanceTool.get_balance)
The _find_element method is where self-healing happens. Each strategy is tried in order until one succeeds. If all fail, the tool returns an error and logs the failure for manual review.
Testing an MCP built from a live bank site is tricky. You can't mock the responses because the whole point is to interact with the real site. Pomerado's testing strategy:
The CI/CD pipeline runs in a sandboxed environment with access to test credentials for each site. For production deployments, Pomerado recommends running MCP servers in a separate VPC with strict egress rules (only allow connections to the target site, no lateral movement).
Pomerado's architecture introduces several trust boundaries:
The weakest link is credential storage. If Pomerado's key management is compromised, an attacker gains access to all stored credentials. Pomerado mitigates this by:
For high-security deployments, Pomerado supports self-hosted MCP servers where credentials never leave the customer's infrastructure.
Pomerado makes sense when:
Avoid this approach when:
Pomerado solves a real problem: agents need structured access to legacy systems, and computer use is too slow for repeated workflows. The deterministic scraping approach is clever because it sidesteps the brittleness of traditional selectors while avoiding the latency of browser automation.
The self-healing mechanism is the key innovation. If it works as advertised (automatic recovery from 80% of site changes), this could be the difference between a tool that breaks every week and one that runs for months without intervention.
The biggest risk is credential management. Storing bank passwords in a third-party service is a hard sell for enterprises. Self-hosted deployments mitigate this, but they also eliminate Pomerado's ability to run centralized smoke tests and share healing updates across customers.
For internal agents (employee assistants, back-office automation), this is a pragmatic solution to the legacy integration problem. For consumer-facing agents, the security and compliance risks are too high. Use this when you own both the agent and the credentials, and when the alternative is paying humans to copy data between systems.