Inspiration

Speaking practice needs a running clock, a responsive examiner, and follow-up questions. Typing cannot replace that. Viva explores what it would feel like to practise an IELTS or TCF speaking exam through a hands-free assistant while doing everyday tasks.

A conversational model can discuss an exam, but the exam's phases, deadlines, rubric, and progress history need to survive individual turns. That is the job of Viva's server.

What it does

Viva is a self-hosted MCP server designed for Alexa+, demonstrated through a browser client that plays the assistant's role. It is not a published or certified Alexa+ add-on, and has not been tested on a real Alexa+ host or Echo device.

  • Runs IELTS Speaking Parts 1–3 in en-US and a smaller TCF practice set in fr-FR. The corpus contains 59 original practice items: 49 IELTS and 10 TCF.
  • Owns the exam phases and deadlines. Late answers are accepted and marked as overruns; the server does not interrupt the speaker.
  • Returns follow-up questions from the exam bank immediately. An optional Bedrock probe generator can replace a seed question if its result has already arrived; turn-taking never waits for it.
  • Implements asynchronous scoring for Fluency & Coherence, Lexical Resource, and Grammatical Range & Accuracy. The rubric expects an IELTS band or TCF CEFR level, an evidence quote, and one improvement for each verified criterion.
  • Never scores pronunciation: the server receives transcripts, not audio.
  • Tracks recurring weak criteria under the OAuth grant subject. Progress can persist in a JSON file; exam sessions and OAuth credentials remain in memory.
  • Includes three MCP Apps views for the cue card, speaking, and results, alongside spoken tool responses.

The Bedrock scoring and probe integrations are implemented and tested with fakes. No live Bedrock call is verified in the repository. Without a configured grader, the exam still runs and scoring reports that it is unavailable.

How we built it

TypeScript on Node 24, Express, zod, the official MCP TypeScript SDK, and the MCP Apps extension. The server uses MCP spec 2025-11-25 over Streamable HTTP, with seven tools: start_exam, get_status, submit_response, advance_phase, score_session, get_results, and get_progress.

A server-side state machine controls briefing, preparation, speaking, follow-ups, scoring, and completion. Illegal actions return an error describing the phase and legal next moves. Each MCP session has its own transport so multiple clients and page reloads can coexist.

The optional Bedrock integration uses the Anthropic Bedrock Mantle client for structured rubric scoring and follow-up generation. score_session starts an asynchronous job and get_results polls. Outputs are independently validated; invalid output gets one retry, partial results are never padded, and a model failure is reported as unavailable rather than a low score.

Authentication uses OAuth 2.1 with PKCE S256, RFC 8707 resource binding, hashed tokens, refresh rotation, and no Dynamic Client Registration. A failed exchange burns the authorization code; replaying a redeemed code revokes its token lineage. The demo consent page uses a shared passcode with throttling, rather than a production identity provider.

The browser demo signs in through OAuth and calls the same MCP tools. It uses browser speech synthesis and the Web Speech API, with typed input as a fallback. The recorded Chrome demo verifies microphone transcription across the initial answer and follow-up questions. Each answer starts with an explicit Start listening click. Recognition errors expose a typed fallback, and stale callbacks from an earlier recognizer cannot overwrite a later answer. The visual resources have been checked in a stand-in browser host, not a real MCP Apps host.

Development followed written feature specs and a gaps register, with Claude Code assistance for implementation, review, and documentation. The current checkout passes 276 tests across 15 test files.

Challenges we ran into

The repository records that the Alexa+ add-on CLI, inspector, simulator, and certification path were unavailable during development. I built a browser stand-in against the open MCP spec rather than claiming a real Alexa+ integration.

Grading cannot fit in a fast conversational turn. Separating scoring into start-and-poll kept model calls off the turn-taking path. Generated probes use the same principle: return a seed unless a replacement is already available.

Progress needs an identity that outlives a conversation. I used the OAuth grant subject and avoided recording unattributable sessions under a shared identity.

Integration testing caught transport and OAuth details that unit tests alone missed: a transport that accepted only one initialization, and an OAuth error type that rejected tokens without the challenge a client needs to reauthenticate. The friction log records these issues and workarounds.

Accomplishments that we're proud of

The exam remains usable when the model is unavailable. It can complete with seed follow-ups and explicitly unavailable scoring.

Scoring honesty is enforced in tests: unsupported levels are rejected, missing criteria are disclosed, and pronunciation is never guessed from text.

The committed latency benchmark exercises the real OAuth and HTTP path locally. Client-observed p95 round trips are under 1 ms against per-tool budgets of 50–150 ms, with a worst round trip under 5 ms. These measurements use loopback networking and fake model services; they are not end-to-end Alexa+ latency.

The project includes persistent progress, multiple MCP sessions, three visual resources, an original corpus with mandatory provenance, and a documented friction log.

What we learned

A voice-first product should work without a screen. Visuals can support a speaking exam without becoming a dependency.

Tool errors are part of the user experience: naming the phase and legal next action helps an assistant recover.

A transcript supports some feedback and cannot support other feedback. Reporting that boundary is more useful than inventing a pronunciation score.

What's next for Viva: Mock Speaking Exams by Voice

Run scoring and follow-up generation against live Bedrock and measure the real requests and latency. Extend microphone testing beyond the verified Chrome desktop demo, and verify the MCP Apps resources in a real host. Move to the actual Alexa+ integration path when accessible.

Replace the shared demo passcode with individual accounts, add a token-revocation endpoint, expand the question bank, and explore a database-backed progress store. French content exists server-side, but French behavior on Alexa+ remains unverified.

Built With

Share this project:

Updates

Submission history