Inspiration

You can't love what you can't picture. Yet most conservation campaigns ask us to care about abstract ideas like "biodiversity" or "the environment"—things far removed from daily life.

Globie Earth is rooted in Northeastern Thailand, a place many of its potential supporters will never see in person. But audio changes that. A voice can slip into a kitchen, a quiet commute, or a morning routine. It gives a name to a tree on a trail, a bird in the canopy, or a plant in a family recipe. The moment a feature of nature has a name, it stops being abstract and starts mattering.

That idea was our starting point. The hackathon just gave us the push to speak it out loud.

We also did not want a one-and-done hackathon demo. The test we set ourselves was whether the thing still earns its place after the weekend — a product we can keep running, keep using, and keep building on. That is why every project we build sits on the work OpenmindProjects already does on the ground: native nurseries, IoT soil monitoring, agroforestry training for local youth, field-verified tree deeds, and the Openmind.Travel catalogue of responsible-travel and volunteer experiences. The hackathon set the deadline; the direction came from an organisation with real work to point at.

What it does

We built a self-hosted Model Context Protocol server that puts a live reforestation and nature-audio backend in front of Alexa+, plus a Skill that turns conversational speech into tool calls against a closed, allowlisted tool list. 55 tools, Streamable HTTP on protocol 2025-11-25, running in production at mcp.globie.earth. One project, three surfaces: the server, the Skill, and a native TV app that is a client of the same server.

Four things you can actually do:

  • Ask a real forest question. "Tell me about trees that fix paddy soil." That request runs a local 384-dimension embedding search over the curated forest catalogue, so the answer comes from stored records rather than fixture copy. Ask what the site is like today and it reports current Open-Meteo values for the sanctuary's coordinates, labelled as modelled data rather than an on-site sensor reading. Species recommendations are matched to what you have already adopted, so a first-time listener needs one adoption before the list is non-empty.
  • Listen. The same server resolves a spoken theme to a real podcast episode or a guided meditation. search_podcasts returned 20 real feeds when probed on 2026-10-23, and get_podcast_stream_url mints a signed two-hour proxy link to the episode audio — fetched live, it answers 206 audio/mpeg — so the request can end in audio rather than a list.
  • Go further. search_local_culture runs the same embedding search over the project's own Thai cookbook, asked for "som tam", it returned Som Tum Isan with its Thai name and get_recipe opens the full ingredients and method. om_get_impact_travel_options returned real responsible-travel tours from the Openmind.Travel catalogue.
  • Watch and play. The same project lives on the television. On the TV app's LEARN screen the field guide reported 16,383 species — the living things that share this planet with us — on the screen a room is already looking at. Say "open quests" to an Echo and a gamified hub appears: a biodiversity mission, a species-pairs memory match, a photo quiz, and a pass-the-remote family quiz, where every answer grows the field guide, so a child, a parent or a neighbour plays instead of watching. "Play guess who" reads real species aloud — a Green Chiretta, a White-winged Duck, a hare — and anyone in the room answers by voice, with no controller and no menu; the score is judged server-side so the spoken score and the drawn score cannot drift apart. "Search the TV for forest podcasts" runs the same search_podcasts tool the Skill calls, and the same screen plays the episode. Friends, family and classmates end up learning the names of the living world together, which is the point: a named thing starts to matter.

The same server owns that command channel: POST /v1/tv/commands queues a typed TvCommand, the TV long-polls GET /v1/tv/commands?waitMs=N and navigates, commands expire after two minutes, and the queue holds eight. The command set is a closed union of navigation outcomes with no raw key event, so a stale queued command can never move the viewer's cursor. The TV app is a separate repository and a client of this server — the Skill needs no television, and this entry is judged on the server and the voice experience.

How we built it

TypeScript on Fastify, @modelcontextprotocol/sdk 1.32 over Streamable HTTP, PostgreSQL through PostgREST, Docker for the image. Embeddings run locally on CPU with transformers.js and multilingual-e5-small (384 dims), with Bedrock Titan as the optional path. Amazon Polly (Joanna, neural) is the configured voice on this deployment's /voice/speak route; Alexa speaks Skill replies in its own voice. An S3-compatible bucket (globie-media) holds contributed media through the AWS SDK's S3 client.

The skill is a thin adapter. Alexa's intent arrives in infra/mcp/src/alexa.ts, which resolves entities, disambiguates, picks one tool per turn from the server's own tools/list at temperature 0 against a closed allowlist, then builds that same server in-process and calls it over an in-memory transport — no second deployment and no network hop on a voice turn. External clients reach the identical tool surface over Streamable HTTP at POST /mcp.

The TV app is a native Vega OS app — React Native 0.83 on the Kepler runtime, in its own repository — and it is a client of that relay, not a dependency of the server. It polls for a command and renders the screen the command names; it never receives a keystroke, so a stale command cannot move the viewer's focus.

Every MCP request carries an identity: a device UUID, a GoTrue JWT, the static demo bearer, or an MCP OAuth 2.1 token. OAuth 2.1 (client credentials and authorization-code with PKCE) is implemented but dormant in production — it needs a configured client, redirect URIs and a signing secret — so /oauth/authorize and /oauth/token return 503 today. Treat it as a capability, not a description of this deployment.

Run it with docker compose up in infra/mcp, with POSTGREST_URL, STUDIO_URL and PODCAST_URL. The server's own credentials are its model key (DeepSeek; Bedrock would need model access granted to this account) and the object store's S3-API keys (a self-hosted MinIO bucket). The studio origin separately holds the Gemini (Lyria) key and the podcast origin the Podcast Index key, and the server reaches both through proxies instead of reading those keys. README.md has the env table, the Dockerfile and the health check.

Challenges we ran into

Our biggest blocker was not code but account verification. The router and the embeddings adapter were wired to Amazon Nova and Bedrock Titan, but this account was still under new-account verification, so the Bedrock calls never left the ground: Nova Lite and Nova Pro return 502 on live requests, and Titan embeddings had to stay an optional path. We moved the default to local transformers.js embeddings. Storage hit the same constraint from the other side: rather than depend on a provisioned AWS S3 bucket, we run a self-hosted MinIO bucket behind the S3 API, so contributed media still moves through the AWS SDK's S3 client with nothing rewritten above it. Rather than present a fallback we could not demonstrate, /health reports the providers actually in use, and this write-up says the same.

Accomplishments that we're proud of

55 tools that a voice interface can actually reach, a health endpoint that reports the protocol version and every subsystem's real state instead of a hard-coded "ok", and a second surface — a native TV app driven by the same backend, where a room can scroll 16,383 species, play a server-scored voice quiz and start a forest podcast without picking up a remote.

What's next for Globie Earth MCP + Alexa Skill

Submit the skill to the Alexa Skills Store (Skills Shop). And once the account clears verification, put Nova and Titan back beside the local path, and expose the ledger through MCP Apps so a host can render a tree's growth stage as a card instead of a sentence.

Built With

  • alexa-skills-kit
  • amazon-polly
  • docker
  • fastify
  • mcp-streamable-http
  • model-context-protocol-sdk-1.32
  • node.js
  • postgresql-/-postgrest
  • s3-compatible-storage-(minio)
  • transformers.js
  • transformers.js-(multilingual-e5-small)
  • vega
  • vega-sdk
Share this project:

Updates

Submission history