Skip to main content
Glama

Counterpart

One voice assistant for any small business that runs on orders.

Counterpart is a self-hosted MCP server that lets Alexa+ run a small business's day by voice: open a job, move it along, add parts or labor, check and reorder stock, take payment, and hear how the day is going. Built for the Alexa+ track of Build, Ship, Shape: Amazon Developer Hackathon (2026).

The idea

A mechanic under a car and a baker with frosting on their hands have the same problem: the system that runs their shop is on a computer across the room. Their businesses look nothing alike, but they share a shape — orders that move through stages, items that get used up, payments at the end.

Counterpart has one engine for that shape and a business profile for each kind of business. A profile is a YAML file with the business's vocabulary, stages, and tool names. The server generates each tool's name, description, and input schema from it, so Alexa+ reads a repair shop's open_work_order ("Open a new work order, also called a repair order, RO, ticket or job…") and a bakery's take_cake_order from the same code.

Related MCP server: @agentpos-alexa/bridge

Tools

Intent

Auto repair

Bakery

Day summary (with UI)

get_shop_snapshot

get_bakery_snapshot

Find orders

find_work_orders

find_cake_orders

Open an order

open_work_order

take_cake_order

Change stage

move_work_order_stage

move_cake_order_stage

Add to an order

add_parts_or_labor

add_to_cake_order

Check stock

check_parts_stock

check_ingredients

Reorder

reorder_parts

reorder_ingredients

Close out and charge

close_out_work_order

close_out_cake_order

Sales report (with UI)

sales_report

sales_report

Every reply is one or two plain English sentences meant to be spoken. People say "the Civic" or "Dana's", not "order 4821", so every tool accepts spoken references and asks "which one?" when two orders match. Voice assistants retry, so the writes that can safely repeat are idempotent: opening the same order again within two minutes returns the one already open, moving an order to the stage it is already in changes nothing, reordering skips items already on order, and closing out an order that was already closed today reports it without charging again. Adding parts or labor is deliberately not deduplicated, because adding the same item twice can be intended. The two reporting tools also return an MCP Apps UI for screen devices.

Architecture

MCP client (Alexa+ or any MCP host)
        │  Streamable HTTP · MCP 2025-11-25 · Authorization: Bearer <token>
        ▼
Counterpart
  http/      /ping · /mcp · token → business · per-client sessions bound to a business · JSON logs
  tools/     nine tools generated from the business profile · MCP Apps UIs
  domain/    pure rules: orders · inventory · spoken references · reports
  store/     MemoryStore (dev) · DynamoStore (single-table DynamoDB)

The bearer token decides which business is calling. Each client connection gets its own MCP session, built from that business's profile and bound to the business whose token opened it. A session only accepts requests that carry a token for that same business. An unknown session id, or one that belongs to another business, gets a 404 so the client starts a new session.

Quick start

Requirements: Node.js 24 and npm. Docker if you want DynamoDB.

npm ci
npm run dev

The in-memory store seeds two demo businesses at startup, with the development-only tokens demo-shop-token and demo-bakery-token. Check the server end to end:

npm run smoke -- http://127.0.0.1:3000/mcp demo-shop-token

To use a graphical MCP client such as the MCP Inspector, point it at http://127.0.0.1:3000/mcp with the header Authorization: Bearer demo-shop-token. For hosts that cannot send headers, run locally without a token instead:

npx cross-env COUNTERPART_DEV_BUSINESS=shop HOST=127.0.0.1 npm run dev

That mode is refused on any address other than 127.0.0.1.

Run with DynamoDB Local

docker compose up -d --build
npx cross-env COUNTERPART_STORE=dynamo DYNAMODB_ENDPOINT=http://localhost:8000 npm run seed -- --reset
npm run smoke -- http://localhost:3000/mcp demo-shop-token

DynamoDB Local runs in memory, so reseed whenever its container restarts.

To issue a real token for a business, stored only as a SHA-256 hash:

npx cross-env COUNTERPART_STORE=dynamo DYNAMODB_ENDPOINT=http://localhost:8000 npm run token -- shop

Configuration

Variable

Default

Meaning

PORT

3000

HTTP port

HOST

0.0.0.0

Bind address

COUNTERPART_STORE

memory

memory or dynamo. memory is refused when NODE_ENV=production, which the container image sets

DYNAMODB_TABLE

counterpart

Table name

AWS_REGION

us-east-1

AWS region

DYNAMODB_ENDPOINT

—

DynamoDB Local URL; unset for AWS

COUNTERPART_DEV_BUSINESS

—

Local no-token mode, only on 127.0.0.1

COUNTERPART_ALLOW_REMOTE_RESET

—

1 lets npm run seed -- --reset delete and reseed the demo businesses in a remote table; the table and its tokens are kept

Tests

npm test               # unit and integration
npm run typecheck
npm run dynamo:up      # start DynamoDB Local
npm run test:dynamo    # store contract against DynamoDB Local

DynamoDB Local takes a few seconds to start; wait for it before running npm run test:dynamo.

MemoryStore and DynamoStore run the same contract suite, including atomic writes and inclusive civil-date ranges. test/golden/ holds spoken phrases paired with the tool each should trigger, for evaluating tool selection against a real model.

Adding a business

Add a YAML file to src/profiles/ with the business's nouns and synonyms, its stages and which one closes an order, its nine tool names, an optional asset (for example a vehicle) and any order fields (for example a cake's flavor). Profiles are validated at startup: tool names must be unique and well formed, the closing stage must exist, and order fields cannot reuse the ids the tools already use. Seed data lives in seed/.

Project layout

src/profiles/   business profiles and their validation
src/domain/     pure business rules
src/store/      store interface, in-memory and DynamoDB implementations
src/speech/     spoken English phrasing
src/tools/      the nine MCP tools and the MCP Apps resources
src/http/       Express app, auth, sessions, request context
ui/             the two MCP Apps UIs (built with Vite into single HTML files)
seed/           deterministic demo data and the seeding CLI
infra/          token CLI, smoke check, build helpers
test/           unit, integration, contract and golden-phrase tests

Status

Done: the server, both profiles, the nine tools, token auth with per-business sessions, DynamoDB persistence, structured logs, the two MCP Apps UIs, the container image, and the tests.

In progress: deployment to AWS (ECS Express Mode with DynamoDB) and a live voice demo on Alexa. The Alexa+ MCP Toolkit is not publicly available (@alexa-ai/cli is served from a private registry), so the voice demo uses an Alexa Skill bridge that emulates the Alexa+ orchestrator. See docs/friction-log.md.

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables Alexa+ add-on functionality for AgentPOS stores, providing in-conversation checkout via UCP, payment rails (Stellar and Amazon Wallet), and merchant agent integration on Bedrock AgentCore.
    Apache 2.0
  • A
    license
    A
    quality
    A
    maintenance
    Enables small-business AI assistants to answer customer questions about hours, offerings, FAQs, staff, and booking from a single business.yaml config, with industry-specific tools and guardrails.
    2
    321 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables Alexa+ assistants to run multi-step personal-ops tasks and produce machine-checkable receipts with per-step evidence, so actions are only claimed done when actually verified.
    MIT