Content
# Amber
A dinosaur theme park management app that doubles as a demonstration of building a **remote MCP server** secured with a real **OAuth 2.1** authorization server in Elixir. Companion to a YouTube video on exposing your application's data and actions to AI agents using **Ash AI** and **AshLua**.
Built with [Phoenix](https://www.phoenixframework.org/) and the [Ash Framework](https://ash-hq.org/).
[](https://youtu.be/xejfNsxjK3o)
## What's Inside
Amber is a small park-operations app: it tracks **dinosaurs**, **paddocks**, and **incident reports**, with role-based access (rangers can write, visitors can read).
The video builds on that foundation to add:
- An **OAuth 2.1 authorization server** (`AshAuthentication.Oauth2Server`) with Dynamic Client Registration, so MCP clients like Claude.ai and the ChatGPT Apps SDK can connect and authenticate users.
- A **remote MCP server** (`AshAi.Mcp.Router`) mounted at `/mcp` and protected by the OAuth bearer token.
- **"Code mode"** tools powered by [AshLua](https://ash-lua.hexdocs.pm/) — instead of exposing one MCP tool per action, the server exposes a small Lua sandbox (`amber_lua_docs` + `amber_lua_eval`) that lets an agent script against the park's read/update actions.
## Getting Started
### Prerequisites
- [Elixir](https://elixir-lang.org/install.html) and Erlang/OTP (see `mix.exs` for the required version)
- A running **PostgreSQL** instance
### Run the App
1. Install and set up dependencies (this also creates the database and seeds it):
```bash
mix setup
```
2. Start the server inside IEx:
```bash
iex -S mix phx.server
```
3. Open [`localhost:4000`](http://localhost:4000).
### Seed Accounts
`mix setup` seeds a single park with two users:
| Email | Password | Role |
| -------------------- | ------------------- | ---------------- |
| `ranger@amber.park` | `dinosaurs-are-cool` | writer (read/write) |
| `visitor@amber.park` | `dinosaurs-are-cool` | reader (read-only) |
## Connecting an MCP Client
The MCP endpoint is served at `http://localhost:4000/mcp`. Point an MCP client (Claude.ai connectors, the ChatGPT Apps SDK, or any client that supports OAuth + Dynamic Client Registration) at that URL. The client will be redirected to sign in and grant the `mcp` scope, then receive a bearer token used to call the exposed tools.
## References
- **[Ash Framework](https://ash.hexdocs.pm/)** — declarative application framework for Elixir
- **[Ash AI](https://ash-ai.hexdocs.pm/)** — turn Ash actions into MCP tools and LLM integrations
- **[AshLua](https://ash-lua.hexdocs.pm/)** — run sandboxed Lua against your Ash actions ("code mode")
- **[Ash Authentication](https://ash-authentication.hexdocs.pm/)** — user authentication for Ash
- **[Ash Authentication OAuth2 Server](https://ash-authentication-oauth2-server.hexdocs.pm/)** — the OAuth 2.1 authorization server
- **[Model Context Protocol](https://modelcontextprotocol.io/)** — the protocol MCP clients and servers speak