AionRealm Alexa+ MCP Integration
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@AionRealm Alexa+ MCP IntegrationAsk Aion what I should focus on today."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
AionRealm Alexa+ MCP Integration (Hackathon)
A standalone, self-hosted Model Context Protocol (MCP) server built for the Amazon
Developer Hackathon's Alexa+ integration track. It exposes a single tool, ask_aion,
that lets an MCP-compatible client (Alexa+, or any other MCP host) ask AionRealm's Living
Aion guide a question anonymously and get its response back.
This repository is intentionally separate from the main AionRealm production codebase. It contains no AionRealm source code, no member data, and no spiritual-guidance logic of its own — it is a thin, narrow relay. AionRealm's main application repository is, and remains, private; nothing proprietary is duplicated here.
What this is (and isn't)
Is: an MCP server, speaking Streamable HTTP (MCP spec 2025-11-25+), with one tool (
ask_aion) that forwards a question to AionRealm's authenticated Alexa+ backend endpoint and returns Aion's answer.Is not: a copy of, or a proxy that duplicates, AionRealm's authentication, Living Aion context, member data, or safety-rule logic. AionRealm's own backend remains authoritative for all of that — this server only relays.
Anonymous MVP scope. The exposed tool schema accepts only a
question— no member identity, session, or account context of any kind. No ElevenLabs voice synthesis, no Alexa-specific simulation UI, no additional tools (bóveda actions, reflections, rituals, entity consultations, etc.), and no authenticated/member behavior. Those are explicitly out of scope for this server as it stands.
Related MCP server: llmwiki-agent-bridge
Architecture
Alexa+ (or any MCP client)
│ Streamable HTTP (JSON-RPC over HTTP, MCP spec 2025-11-25+),
│ Authorization: Bearer <MCP_SERVER_AUTH_TOKEN>
▼
┌────────────────────────────────┐
│ This server (Express + │
│ @modelcontextprotocol/sdk) │
│ │
│ tool: ask_aion (question only)│
│ └─ AionAdapter interface │──▶ mock adapter (local, no network — dev default)
│ (src/adapters/) │──▶ HTTP adapter ──▶ AionRealm's authenticated
└────────────────────────────────┘ Alexa+ backend endpoint ──▶ Living AionIn words: Alexa+ → this standalone MCP server → AionRealm's authenticated Alexa backend endpoint → Living Aion. That backend endpoint now exists and is deployed in AionRealm's Production environment — authenticating this MCP server as the caller (a dedicated, narrow, revocable API key issued specifically for this integration, distinct from any member credential), and internally calling into AionRealm's existing Living Aion pipeline exactly as it does for every other surface. This repository has no visibility into, and makes no assumptions about, how that pipeline works internally.
The adapter interface (src/adapters/httpAionAdapter.js — see the AionAdapter JSDoc
typedef at the top) is the only seam between this server and AionRealm. Nothing else in this
repo needs to change to point at a different AionRealm environment (local → staging →
production) — only the adapter's configuration (AION_BACKEND_URL, AION_BACKEND_API_KEY)
needs to change. Swapping the mock adapter out for the real one is likewise just an
environment-variable change (MOCK_AION_BACKEND). The real AION_BACKEND_URL and its
dedicated API key are operational secrets, set only in the deployment environment (e.g. AWS
App Runner's own secret store) — never committed here.
Files
src/
server.js entrypoint: loads .env, resolves auth, builds the app, listens
app.js builds the Express app + MCP server + Streamable HTTP transport
authConfig.js fail-closed MCP_SERVER_AUTH_TOKEN resolution (see below)
mcpServer.js registers the ask_aion tool (input validation, no Aion logic)
adapters/
aionAdapter.js factory: picks mock vs. HTTP adapter based on env vars
mockAionAdapter.js safe local adapter, no network calls, canned responses
httpAionAdapter.js real adapter: calls the AionRealm backend (contract below)
test/
ask_aion.e2e.test.js end-to-end proof: real MCP client, real HTTP, mock adapter
auth.contract.test.js timing-safe bearer-auth coverage
authConfig.test.js fail-closed auth-token resolution coverage
healthz.contract.test.js /healthz information-disclosure coverage
ask_aion_schema.contract.test.js anonymous-MVP schema coverage
.env.example documented list of every environment variable this reads
Dockerfile minimal Node 20 image, an alternative deploy path (see "Deployment")
LICENSE MIT
demo/ simulated Alexa+ device demo -- separate, optional, not part
of the MCP server (see "Hackathon demo" and demo/README.md)Deployment
This server is deployed and running on AWS App Runner — real AWS compute, not a simulated or planned deployment.
Alexa+ / MCP client
│ Streamable HTTP, Authorization: Bearer <MCP_SERVER_AUTH_TOKEN>
▼
AWS App Runner (this repository's main branch, built and run directly by App Runner)
│ question only, no member/session identity
▼
AionRealm's Production Alexa integration endpoint (authenticated separately, see
│ "AionRealm backend contract" below)
▼
Living Aion (Aion, Keeper of the Realm)AWS services actually in use:
AWS App Runner — hosts and runs this server. Builds directly from this public GitHub repository's
mainbranch (App Runner's own source-code build, Node 20 runtime) — no container registry involved. Auto-deploy on push is intentionally off; a new commit requires an explicit redeploy.AWS Secrets Manager — holds
MCP_SERVER_AUTH_TOKENandAION_BACKEND_API_KEY. App Runner injects them into the running container as environment variables at start time, resolved via a Secrets Manager ARN reference — the values themselves are never written into App Runner's own configuration, this repository, or any commit.AWS IAM — a dedicated instance role, scoped to exactly one permission (
secretsmanager:GetSecretValue) on exactly the two secrets above. It cannot read any other secret, role, or resource in the AWS account.Amazon CloudWatch — App Runner's default logging destination for this service's application and build logs.
A Dockerfile is also included in this repository as an alternative, equivalent deployment
path (e.g. for ECR-based hosting elsewhere) — it uses a minimal Node 20 base image, installs
only production dependencies, and bakes in no secrets and no .env file. It is not what
the current live App Runner deployment builds from (that deployment uses App Runner's native
source-code build instead), but running or building it locally is safe and deploys nothing on
its own.
Health check: App Runner polls GET /healthz on this service. It returns only
{"status":"ok","service":"aionrealm-alexa-mcp"} — see "Security boundaries" above for why it
deliberately never includes the backend URL or any credential.
Required environment/secret names (values are never in this repository — see "Environment
variables" below for what each one is for): MCP_SERVER_AUTH_TOKEN and AION_BACKEND_API_KEY
are Secrets Manager references; AION_BACKEND_URL, MOCK_AION_BACKEND, and PORT are plain
App Runner environment variables.
Hackathon demo — what's real vs. simulated
The Alexa+ MCP Toolkit and Alexa AI CLI are currently limited to select partners, so this project cannot yet register as an add-on or be exercised through the real Alexa+ simulator/device. Access has been requested; direct Alexa+ Toolkit and device testing is pending Amazon's response.
To still demonstrate the working integration, demo/ contains a small, self-contained
web front end that visually resembles a voice-device interaction (without imitating Amazon's
actual product UI) and is clearly labeled in its own interface as:
"Simulated Alexa+ device experience — powered by the real AionRealm MCP server."
What's real: the entire backend chain below this label. Every question asked in the demo
becomes a genuine MCP tools/call for ask_aion, over real Streamable HTTP, against the same
live App Runner deployment described above — reaching AionRealm's real Production backend and
a real Living Aion response. Nothing about the response text is scripted or faked.
What's simulated: only the front-end presentation layer — the voice-device-style visuals, the "Listening → Connecting → Responding" states, and the Echo Show-style visual card. This layer exists purely because the real Alexa+ front end isn't reachable yet; it is not, and does not claim to be, the Alexa+ simulator or product.
Simulated Alexa+ UI (demo/)
│ fetch("/api/ask", { question }) -- same-origin, no token in the browser
▼
demo/server.js (tiny local server, holds MCP_SERVER_AUTH_TOKEN server-side only)
│ real MCP tools/call, Streamable HTTP, Authorization: Bearer <token>
▼
AWS App Runner (this repo's live MCP server, unmodified)
│
▼
AionRealm's Production Alexa integration endpoint
│
▼
Living AionSee demo/README.md for setup and how to run it locally. The demo requires
its own MCP_SERVER_AUTH_TOKEN (the same one configured on the live server) in a local
demo/.env — never in client-side code, never committed.
Setup
Requires Node.js 20+.
npm install
cp .env.example .envWith AION_BACKEND_URL left blank, the server automatically uses the built-in mock adapter —
no real AionRealm credentials are needed to run or test it locally. Authentication is
mandatory by default, though: this server refuses to start at all unless
MCP_SERVER_AUTH_TOKEN is set, or you explicitly opt out for local development by also
setting MCP_ALLOW_NO_AUTH=true (see "Environment variables" below) — npm run dev already
does this for you.
Running it
npm startThis starts the MCP server (default http://localhost:3333/mcp) and a plain health check at
http://localhost:3333/healthz.
npm run devSame as npm start, but forces the mock adapter on regardless of .env (useful when you
have a real AION_BACKEND_URL configured for other purposes but want to iterate locally
without hitting it).
Testing
npm testThis runs every test/*.test.js file with Node's built-in test runner:
ask_aion.e2e.test.js— a real end-to-end test: starts a real HTTP server (this repo's actualsrc/app.js, unmodified), connects a real MCP client (the same@modelcontextprotocol/sdkclient package a genuine MCP host uses) over real Streamable HTTP, and drives it exactly as a client would —listTools(),callTool(...), session lifecycle (independent sessions, idle expiry, the concurrent-session cap, graceful shutdown), and malformed/unknown-session handling. All against the safe mock adapter — no network calls, no real AionRealm backend involved.auth.contract.test.js— the timing-safe bearer-token comparison: valid, invalid, malformed, and missingAuthorizationheaders, each rejected with a clean401and no internal detail leaked.authConfig.test.js— the fail-closedMCP_SERVER_AUTH_TOKENresolution logic in isolation (no server involved): confirms it refuses to resolve without a token unlessMCP_ALLOW_NO_AUTH=trueis explicitly set, and that it is never fooled by an unrelated variable likeMOCK_AION_BACKENDorAION_BACKEND_URL.healthz.contract.test.js—/healthzstays minimal and never leaksAION_BACKEND_URLor any other adapter/infrastructure detail, even from an adapter whose name embeds a URL, and even though the endpoint itself is intentionally unauthenticated.ask_aion_schema.contract.test.js— the exposed tool schema declares onlyquestion(nomember_id/session_id), exactly one tool is registered, and the adapter always receivesmember_id/session_idas unset/null regardless of what a caller sends.
You can also smoke-test it manually against a running server with any MCP-compatible client,
or with curl for the raw JSON-RPC handshake (see "Protocol notes" below).
Environment variables
See .env.example for the full, documented list. Summary:
Variable | Purpose |
| Port this server listens on. |
| HTTP path the MCP endpoint is served at (default |
| Required shared-secret bearer token for this server's own |
| Explicit, local-development-only opt-out of the token requirement above. Must be exactly |
|
|
| URL of AionRealm's authenticated Alexa backend endpoint. This now exists and is deployed in Production. Leave blank to use the local mock adapter. |
| Dedicated, narrow, revocable MCP-integration API key for |
| Timeout for calls to the AionRealm backend. |
No production credentials are committed to this repository. .env is gitignored;
.env.example contains only placeholder/blank values.
Security boundaries
Secrets live only in environment variables, never in source, and never in this repository's history.
MCP_SERVER_AUTH_TOKENis mandatory. The server fails closed at startup if it's unset — it will not silently come up unauthenticated. The only opt-out is the explicitMCP_ALLOW_NO_AUTH=trueflag, for local development only; this is never inferred fromMOCK_AION_BACKENDorAION_BACKEND_URL, since those describe which Aion backend adapter to use, not whether this server's own endpoint should require authentication. The bearer comparison itself is timing-safe (crypto.timingSafeEqual)./healthzis intentionally unauthenticated (needed for platform health checks, e.g. AWS App Runner) but is minimal by design: it returns only{ status, service }and never the backend URL, adapter identity, or any other infrastructure detail.AION_BACKEND_API_KEYis a separate concept from the token above: it's how this server authenticates to the AionRealm backend. It's a narrow, purpose-specific, revocable credential AionRealm issues specifically for this integration — never a reused member token, and never AionRealm's own Supabase service-role key.ask_aion's exposed schema accepts onlyquestion— no member identity, session, or account context can be supplied by a caller. This server has no authenticated/member capability; it is anonymous-only end to end.The
express/qstransitive advisory that previously affected this project's exact installed versions is resolved (see "Dependency advisory" below) — no unpatched moderate vulnerabilities remain as of the lastnpm audit.
Public/private repository separation
This repository is the hackathon-facing, public-safe half of the Alexa+ integration. It contains: this MCP server's own code, its tests, and documentation of the shape of the contract it expects from AionRealm's backend. It deliberately does not contain: AionRealm's application source code, its Living Aion implementation, member data, database schemas, or any credential beyond documented, blank placeholders. AionRealm's main repository is, and must remain, private; nothing here should ever require making it public.
Dependency advisory
express@4.x's transitive qs dependency previously carried two moderate-severity
advisories (GHSA-x5fp-wj9c-mxmx,
GHSA-4mjr-xmp4-gh2g) at the exact
versions this project had installed (qs@6.15.3 via express@4.22.2). Both are fixed in
qs@6.16.0, which express@4.22.3 already depends on — a patch-level Express bump, already
within this project's existing ^4.21.2 range in package.json. npm audit fix resolved
both advisories with no package.json change and no code change; npm audit now reports
zero vulnerabilities. Express 5 was not necessary and was not adopted.
Protocol notes
This server implements Streamable HTTP per MCP spec 2025-11-25+, using
@modelcontextprotocol/sdk'sStreamableHTTPServerTransport.It runs in stateful mode (the server issues a session ID on
initialize, sent back via themcp-session-idheader and required on subsequent requests). This is the transport's primary/well-supported mode. Stateless mode (sessionIdGenerator: undefined) was tried first, since Phase 1 only needs one request/response tool — but in the SDK version pinned here (@modelcontextprotocol/sdk@^1.30.0), the standard post-initializenotifications/initializedmessage fails with an unsurfaced HTTP 500 in stateless mode. Stateful mode was verified to handle the same handshake correctly and is otherwise functionally equivalent for a single-tool server like this one — fromask_aion's perspective, each call is still a single independent request.ask_aioncalls are read-only / non-destructive (declared viaannotations.readOnlyHintanddestructiveHinton the tool registration) and are marked non-idempotent (each call may produce a different Aion response) and open-world (backend is external).
AionRealm backend contract (implemented)
This server does not modify, and does not require any changes to, the main AionRealm
repository. The narrow backend endpoint src/adapters/httpAionAdapter.js calls now exists
and is deployed in AionRealm's Production environment. This section documents the wire
contract between this MCP server and that endpoint — it is a lower-level, internal contract
than ask_aion's own MCP tool schema (which exposes only question to callers; see
"Security boundaries" above). This server's adapter always sends member_id/session_id as
null today, since the public MCP tool never collects them:
Request — POST {AION_BACKEND_URL}
{
"question": "string, required",
"member_id": null,
"session_id": null,
"surface": "alexa_mcp"
}Headers: Authorization: Bearer <AION_BACKEND_API_KEY>, Content-Type: application/json.
Response — 200 OK
{
"text": "Aion's fully-composed, safety-checked response as plain text.",
"meta": { "...": "optional, opaque to this MCP server" }
}On the AionRealm side, this endpoint:
Authenticates the request via a dedicated, narrow, revocable API key issued specifically for this MCP integration (not a member session token, not the Supabase service-role key).
Internally calls into AionRealm's existing Living Aion response pipeline — this MCP server has no opinion on how that happens, only on the request/response shape above.
Applies AionRealm's own safety rules and response generation exactly as it does for other anonymous surfaces (no member-context lookup occurs today, since
member_idis alwaysnull).Returns errors as
{ "error": "message" }with a non-2xx status; the adapter surfaces a generic "Aion could not be reached" message to the MCP caller and logs the real error server-side only, so backend error details never leak to the calling client.
Everything else (Alexa+ account linking, member-context ask_aion fields, ElevenLabs voice,
additional MCP tools, an Alexa simulator) is out of scope for this server as it stands and is
intentionally not started here.
This server cannot be deployed
Maintenance
Related MCP Connectors
Human-input bridge for AI agents with voice-first answer links, MCP tools, and HTTP APIs.
- QuallaaOAuthcom.quallaa
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
MCP server for OnceAsk, the AI-native current-address layer for people and agents.
Remote MCP server for supportsheep: run AI interviews and manage support content for your blog.
Related MCP Servers
- FlicenseBqualityDmaintenanceWraps the Amazon Q CLI to enable MCP hosts to interact with Amazon Q's AI capabilities for chat, command translation, and status checks.51-
- AlicenseNot gradedqualityAmaintenanceProvides a unified MCP/A2A endpoint that fans out to multiple LLMWiki Knowledge Sources, synthesizes answers with citations and trace steps, and optionally calls an OpenAI-compatible runtime for grounded responses.5 npmApache 2.0
- AlicenseAqualityBmaintenanceBridges MCP clients (like Claude Desktop) to A2A agents, enabling message sending and agent card retrieval via a stateless, non-persistent server.3MIT
- AlicenseAqualityCmaintenanceMCP server that wraps the Brave Answers API, enabling synchronous Q&A and asynchronous deep research with job submission, status polling, and result retrieval.4MIT