Kiosk: Giving Every Business a Door Into the AI Economy
Inspiration
Picture a clothing seller in Port Harcourt. She runs her business from a physical shop, takes orders on WhatsApp, and posts her stock on Instagram. She has customers. She has products. She has a contact number.
But when someone asks an AI assistant — "Find me a clothing shop nearby that sells affordable shirts, check what's available, and help me contact them" — the AI has no structured way to answer. The business exists. The information exists. The gap is infrastructure.
Most of the world's businesses don't have APIs. They don't have developer teams. They don't have the resources or technical background to integrate with whatever AI platform is emerging this quarter. And yet the AI economy is arriving whether they're ready or not.
Kiosk is built on one conviction: every business should be reachable by AI agents, not just the ones with technical teams.
The name says it exactly. A kiosk is a stall. You walk up, find what you need, and get on with your day. Kiosk gives AI agents a clear window into what a business offers — and gives business owners a way to step into the AI economy in about two minutes, without writing a line of code.
What Kiosk Does
Kiosk is AI-facing discovery and interaction infrastructure. It has two distinct components that solve different halves of the problem.
The Stall — Master MCP (Discovery Layer)
The Master MCP is a structured directory for AI agents. It runs at a single endpoint and exposes 10 read-only discovery tools:
| Tool | What an agent uses it for |
|---|---|
discover_categories |
Understand what kinds of businesses are available |
search_businesses |
Find businesses by name, product, city, category, or open status |
check_business_status |
Verify a business is currently open (timezone-aware) |
get_business_endpoint |
Get the URL of a specific business's own MCP server |
get_business |
Retrieve a full public profile |
get_business_capabilities |
See what actions a business supports |
get_business_services |
Browse available services before connecting |
get_business_products |
Browse available products |
get_business_contact |
Get phone, WhatsApp URL, and website |
get_business_delivery |
Check delivery configuration |
Every query filters status = 'published' AND is_active = true at the SQL layer. Draft and inactive businesses are structurally invisible — not filtered in application code, but excluded by the query itself.
The Door — Business MCP (Interaction Layer)
Every published business gets its own MCP endpoint: POST https://d127130891zv0m.cloudfront.net/business-mcp/mcp/business/:slug
This is the business's own AI interface. The tools available depend on what the business has enabled:
| Tool | Capability | What it does |
|---|---|---|
get_business_info |
Always | Full public profile — name, description, hours, timezone |
get_services |
Always | Available services with prices |
get_hours |
Always | Opening hours by day |
get_contact |
Always | Phone, WhatsApp (wa.me/...), website |
get_capabilities |
Always | What the business supports |
get_products |
products | Product catalogue |
get_delivery_information |
delivery | Delivery areas and fees |
create_order_request |
ordering | Record order intent → returns order ref + WhatsApp URL |
request_booking |
booking | Record booking intent → returns booking ref |
Order and booking requests record intent and return the business's WhatsApp URL for confirmation. They do not process payment. This is intentional — Kiosk makes businesses AI-discoverable without forcing them to change how they operate.
The Onboarding — Two Minutes, No Code
Business owners fill a form: name, description, category, location, opening hours, phone, WhatsApp, and website. Then they answer plain-English questions:
- Can customers place orders?
- Do customers need to book?
- Do you offer delivery?
- Do you have a product catalogue?
These questions map invisibly to MCP capabilities. Owners never see the word "capability" or "MCP". When they hit publish, Kiosk validates the profile, provisions the endpoint, and the business is discoverable within seconds.
How We Built It
Kiosk is a TypeScript monorepo with four services deployed on AWS ECS Fargate behind CloudFront:
Live deployment
| Frontend | https://d127130891zv0m.cloudfront.net |
| Master MCP | POST https://d127130891zv0m.cloudfront.net/mcp |
| Business MCP | POST https://d127130891zv0m.cloudfront.net/business-mcp/mcp/business/:slug |
| ECS Cluster | kiosk-mcp-production · us-east-1 |
Multi-tenant MCP runtime — the hardest problem
The most consequential architectural decision was how to serve hundreds of business-specific MCP endpoints without running one server per business.
A naive approach one process per business doesn't scale. 1,000 businesses means 1,000 Node.js processes, each holding connections and consuming memory.
Our solution: a shared runtime with per-request tool registration.
Every request goes through this pipeline:
- Rate limit — 60 requests/minute per IP
- Resolve session — query the database for this slug. Cache the result for 30 seconds.
- Build tool list — 5 base tools plus optional tools for each enabled capability
- Register tools — each handler closes over
session.business.id - Connect and handle — fresh
McpServer+StreamableHTTPServerTransportper request - Record event — fire-and-forget insert into
agent_events
The closure is the security mechanism. When get_services runs for Mama's Kitchen, the business ID captured in its closure is Mama's Kitchen's ID not checked at runtime, but structurally fixed at registration time. A bug in the handler cannot accidentally query another tenant's data.
Amazon Bedrock — Titan Embeddings V2
Keyword search fails for queries like "something for my hair" or "a place that fixes phones". Semantic search bridges the gap.
We integrated Amazon Bedrock Titan Embeddings V2 (amazon.titan-embed-text-v2:0) into the search_businesses tool. The model generates 1024-dimension normalised vectors for business profiles and search queries, then scores results by cosine similarity.
We tested this against real business profile text before deploying. For example, feeding:
"Glow & Grace is a salon in Port Harcourt offering haircuts, braiding, and hair styling."
...produced a 1024-dimensional embedding where similar queries "hair salon", "braiding near me", "where to do my hair in Port Harcourt" all land close in vector space, even without exact keyword matches.
The scoring pipeline combines both signals: score = 0.65 × cosine_similarity(query_embedding, profile_embedding) + 0.35 × keyword_overlap
When BEDROCK_ENABLED=false or when the call fails, scoreAndRank() catches the error silently and returns the original SQL-ordered results. Discovery never breaks — it degrades gracefully to keyword ranking.
Validation at the schema layer
We hit a real data quality bug early on: a business owner entered their website URL into the phone field. get_contact returned a URL as the phone number, which broke every AI agent that tried to call or message the business.
The fix lives in lib/api-zod/src/schemas.ts:
- Phone rejects any value matching
https?:// - WhatsApp normalises to digits-only at write time (
+234 801 234 5678→2348012345678) soget_contactalways returns a cleanhttps://wa.me/2348012345678 - Website requires a valid
http://orhttps://URL
One Zod schema, inherited by both create and update routes. A regression test covers the website-in-phone case specifically.
AWS infrastructure
| Service | How it's used |
|---|---|
| ECS Fargate | 4 services on kiosk-mcp-production — no server management |
| CloudFront | HTTPS, redirect-to-https, CDN, single ALB origin |
| ECR | Container registry — all 4 images pushed and running |
| Secrets Manager | kiosk/database-url, kiosk/clerk-secret-key, kiosk/clerk-publishable-key — injected at task launch by ARN |
| CloudWatch | Structured pino JSON logs from all services with request ID correlation |
| Bedrock | Titan Embeddings V2 for semantic search scoring — tested locally, deployed with graceful fallback |
| AgentCore | Architecture compatible — Kiosk's Master MCP is designed as a first-class AgentCore tool provider |
Challenges We Faced
Connecting agents to real business data
The biggest technical challenge was the data integrity layer. Getting the business profile into a shape that an AI agent can reliably act on with correct phone numbers, valid URLs, structured contact fields, and accurate opening hours required more engineering than the MCP layer itself.
We split the legacy single "contact" field into separate phone, WhatsApp, and website fields. We added Zod validation at the schema layer. We built a publish readiness gate that blocks publishing until name, location, and at least one contact method are present. And we added a completeness progress bar in the dashboard so owners can see what's missing before hitting publish.
Multi-tenancy and session isolation
Serving every business from a shared runtime meant we had to guarantee that one business's tools could never accidentally return another business's data. We solved this with closure-based isolation at tool registration time not runtime checks, but structural guarantees. This decision also shaped our test strategy: we wrote integration tests using InMemoryTransport that create two real MCP server/client pairs with different sessions and assert the data never mixes.
Validating the Alexa+ interaction flow
This is an Alexa+ track submission. Kiosk's MCP infrastructure is designed so that any MCP-capable AI agent including Alexa+ can discover local businesses and interact with them through structured tools. To validate the full agent interaction flow end-to-end before Alexa+ MCP access was available to us directly, we used ChatGPT's custom MCP connector as a stand-in. It speaks the same protocol, calls tools the same way, and follows endpoint URLs exactly as Alexa+ would. The compatibility issues we hit are therefore real issues that any MCP-capable agent would encounter.
The first attempt failed immediately. ChatGPT's connector verifier sends a bare GET /mcp to probe the URL before accepting it. Our server only registered POST /mcp, so the probe returned 404. We added a GET handler it then returned 406. The MCP SDK enforces that GET requests carry Accept: text/event-stream, but the verifier sends no such header. We built a custom handler that inspects the Accept header and routes each case correctly: a proper SSE probe goes to the transport; a bare URL validation check gets a minimal 200. The ngrok logs moved from GET /mcp — 404 → 406 → 200 across three iterations. The same fix makes every Kiosk MCP endpoint compatible with Alexa+ and any other standards-adjacent MCP client.
Getting cloud infrastructure ready
We ran into an AWS account verification issue that blocked deployment for approximately one week. The original support case was not resolved in time. After exhausting the available escalation paths, we continued deployment using a separate verified account.
This wasn't just a configuration detail it changed how we approached the project. It forced us to think carefully about which parts of the system we could validate locally versus which required a live cloud deployment, and to build the MCP integration tests specifically to work without a database connection so we could verify business logic without cloud access.
A detailed account of every engineering obstacle including 13 tracked incidents with root causes, fixes, and test evidence is in our engineering friction log:
https://github.com/De-real-iManuel/Kiosk-mcp/blob/main/docs/hackathon/friction-log.md
What We Learned
Making AI-driven discovery accessible to ordinary businesses turns out to be two problems at once: a protocol problem and a data quality problem.
The protocol problem MCP transport, tool registration, tenant isolation, ChatGPT(Alexa+ simulation) compatibility is the interesting architectural work. But it only matters if the data behind the tools is structured correctly. A valid phone number in the phone field. A WhatsApp number in international format. A website that starts with https://. Opening hours in the right timezone. These unglamorous data quality constraints are what determine whether an AI agent can actually do something useful with the information Kiosk returns.
We also learned that the infrastructure gap getting cloud services provisioned and configured is a real part of the engineering journey, not a footnote. When account verification blocked us for a week, we had to build the system in a way that could be verified locally first. That turned out to make the tests better and the architecture cleaner.
The central idea we came away with: making AI-driven discovery accessible to ordinary businesses exposes both the technical challenges of connecting agents to real business data and the practical challenges of getting cloud infrastructure ready for real users.
What's Next
We are building toward the full journey: a business owner onboards in two minutes, their endpoint goes live, an AI agent discovers them, retrieves their information, and initiates a supported interaction.
The immediate next steps:
- Amazon Bedrock AgentCore — Kiosk's Master MCP is already AgentCore-compatible. Native integration would add managed orchestration, memory, and multi-step reasoning on top of the existing tool layer.
- Agentic payments — exploring x402 and Stripe Privy for agent-initiated transactions with appropriate customer authorisation. The order request framework is already in place — completing the loop is the next step.
- Direct Alexa+ skills — connecting Kiosk's discovery layer to Alexa+ so users can find and interact with local businesses by voice.
- Onboarding with real businesses — the platform is live. The work now is getting real business owners through the two-minute form and validating that the full discovery-to-interaction journey works for them.
Every business should have a door into the AI economy. Every AI agent should have a reliable way to find the right door.
Built With
- agentcore
- ai
- amazon
- bedrock
- cloudwatch
- ecs
- mcp
- next.js
- secrets
- typescript



Log in or sign up for Devpost to join the conversation.