FilingCheck runs three surfaces off one SEC-filing analysis engine: a Poe
bot, a ChatGPT Apps (MCP) endpoint, and a self-serve /buy page
with its own Stripe checkout. My first instinct was to keep them apart --
api/index.py for the Poe bot, a new api/mcp.py for
the MCP routes, each with its own FastAPI app object. Clean
separation, easy to reason about.
It deployed without error. /mcp returned a 404. So did every
other path I tried on that file. No traceback, no build warning -- just a
404 that looked exactly like a route that had never been registered.
The actual behavior: with no vercel.json in the project,
Vercel's zero-config Python builder treats the entire api/
directory as the source for one lambda, and that lambda
serves whichever file's app object the builder happens to pick
-- in this case index.py. mcp.py was bundled into
the deployment (imports resolved, no error) but never actually invoked for
any request. Every path, including ones mcp.py was supposed to
own, got routed to index.py's app and fell through to its
default 404 handler. There's no log line that says "wrong file" -- you just
get a plausible-looking, completely wrong 404.
A second, smaller version of the same class of bug: that single lambda
also doesn't add its own directory to sys.path by default, so
a plain from bot_core import X import between sibling files in
api/ can 500 with no traceback visible anywhere -- Vercel's
deployment-events API only exposes build logs, not runtime ones. The fix
there is sys.path.insert(0, os.path.dirname(__file__)) before
the import, and if you need to see a real traceback, temporarily wrap the
risky import in try/except and expose it via a throwaway
route.
The real fix for the routing issue: stop pretending there are multiple
files with independent authority. Mount every route -- Poe's, MCP's, the
Stripe checkout flow's, robots.txt, sitemap.xml -- onto the single
app object the one lambda actually serves. That's what this
file does now: one app, every path added onto it explicitly
with app.add_api_route, no sibling file pretending to be its
own service.
If you're debugging a Vercel Python route that 404s despite deploying
clean, check for exactly this shape first: is this route living in a
different file from the one Vercel is actually routing to? If your project
has no vercel.json, the answer is almost certainly yes.
This is the same engine behind FilingCheck -- $2 to check a stock's Graham fair value and margin of safety against its actual SEC 10-K numbers, no LLM guessing the figures.