DEV Community

Cover image for AI Engineering: Advent of AI with goose Day 17 - Building MCP Server & Wishlist AI Application
Erica
Erica

Posted on

AI Engineering: Advent of AI with goose Day 17 - Building MCP Server & Wishlist AI Application

Day 17: Building a Complete MCP Server & Wishlist Application with MCP and goose

For the final day of this Advent of AI journey, I wanted to build something that brought together everything I explored over the past sixteen days: UI engineering, state management, automation, accessibility, and full‑stack architecture. Instead of simply creating an application that runs inside an MCP environment, I built the MCP server itself. This meant defining the tool layer, managing the application state, and engineering a complete HTML rendering pipeline that outputs a fully interactive UI inside goose.

The result is a complete Wishlist Application powered by a custom MCP server. It exposes its own tools, maintains its own logic, and renders its own interface dynamically on every interaction. This project represents the culmination of a month of daily engineering with goose and demonstrates how expressive the Model Context Protocol becomes when the server and the UI are designed together.

What an MCP Server

The Model Context Protocol defines a structured way for external tools, applications, and services to communicate with an AI model. An MCP server exposes a set of capabilities through a predictable interface, allowing the client to call tools, request resources, and receive structured responses. Instead of building a traditional web server, an MCP server focuses on defining clear operations, returning machine-readable results, and maintaining state in a controlled environment. This makes it ideal for interactive applications that need to update their UI or logic in response to user actions.

For this my project, I created a custom MCP server that manages the entire Wishlist Application. It defines the full set of wish operations, maintains application state in memory, and generates the UI dynamically on every tool call. The server uses the official MCP TypeScript SDK and communicates with the client over stdio, which keeps the development loop simple and predictable. Each tool updates the state, triggers a fresh HTML render, and returns both text and UI resources to the client. This architecture allowed me to build a complete, interactive application entirely inside the MCP environment.

Overview
The Wishlist Application is not just a UI running inside MCP. It is a full MCP server that defines its own capabilities, manages its own state, and generates its own interface. The server exposes a complete tool suite for adding, removing, granting, filtering, and managing wishes. Each tool call triggers a full UI regeneration through a custom HTML rendering engine, allowing the interface to update in real time inside goose.

The architecture mirrors a full-stack web application: a state layer, a rendering layer, a tool layer, and a transport layer. The difference is that everything is delivered through the Model Context Protocol rather than a traditional HTTP server. This approach keeps the system modular, predictable, and easy to extend while still providing a polished, interactive experience.

My Wishlist Application is a fully stateful MCP server that exposes a complete UI through MCP-UI resources. It supports:

  • Adding, removing, and granting wishes
  • Secret wish handling
  • Category filtering
  • Dark and light mode
  • An admin panel with statistics
  • Dynamic HTML generation
  • A full CSS-driven interface
  • Real-time UI updates on every tool call The server uses the official MCP TypeScript SDK and integrates with the MCP-UI rendering system to deliver a complete visual experience inside the client.

Technology Stack
My application is built on a modern, modular stack:

  • MCP Server: TypeScript SDK
  • Transport: Stdio
  • UI Delivery: MCP-UI HTML resources
  • Rendering: Dynamic HTML + external CSS
  • State Management: In-memory application state
  • Tooling: Full suite of MCP tools for wish operations
  • Client: goose Desktop

This stack allows the application to behave like a full web app while running entirely inside an MCP environment.

Features

Core Functionality

  • Add, remove, and grant wishes
  • Toggle secret status
  • Filter by category or secret
  • Toggle dark mode
  • Toggle admin panel
  • Sparkle effect for granted wishes
  • Full UI rebuild on every interaction

UI System
The UI is generated dynamically using:

  • A complete HTML template
  • A CSS file loaded at runtime
  • Category icons
  • Secret indicators
  • Glassmorphism cards
  • Animated background orbs
  • A responsive layout The server returns the UI as a direct HTML resource, allowing the client to render it inline.

MCP Tools
The server exposes a full suite of tools:

  • view_wishes
  • add_wish
  • grant_wish
  • remove_wish
  • set_secret
  • set_filter
  • toggle_dark_mode
  • toggle_admin_panel
  • sparkle_granted Each tool updates the application state and returns both a text response and a fresh HTML UI resource.

Project Structure

wishlist-mcp/
├── JS/
│   ├── index.js            # Main MCP server (tools, state, HTML rendering)
│   ├── generate-html.js    # Standalone HTML generator for UI testing
│   └── index.js.backup     # Previous server version (reference only)
│
├── lib/
│   ├── render.ts           # HTML rendering engine
│   ├── state.ts            # Wish state and operations
│   └── commands.ts         # Natural-language command parsing
│
├── images/                 # UI icons and visual assets (magic, joy, snow, fairy, lock)
│
├── style.css               # Full UI styling (glassmorphism, layout, palette)
│
├── response.json           # Example MCP response (kept for debugging)
│
├── package.json            # Project metadata and dependencies
├── package-lock.json       # Dependency lockfile
│
└── node_modules/           # Installed dependencies (present in real projects)

Enter fullscreen mode Exit fullscreen mode

This structure separates UI, state, rendering, and server logic for clarity and maintainability.


Technical Architecture Diagram

                           ┌──────────────────────────────────────────┐
                         │        Wishlist MCP Server               │
                         │        (JS/index.js entrypoint)          │
                         └──────────────────────────────────────────┘
                                        │
                                        ▼
                   ┌──────────────────────────────────────────────┐
                   │              MCP Tool Layer                   │
                   │  add, remove, grant, filter, toggle, sparkle │
                   │  (Defined in JS/index.js)                    │
                   └──────────────────────────────────────────────┘
                                        │
                                        ▼
                   ┌──────────────────────────────────────────────┐
                   │            Application State Layer            │
                   │  lib/state.ts                                 │
                   │  wishes, filters, dark mode, admin panel      │
                   └──────────────────────────────────────────────┘
                                        │
                                        ▼
                   ┌──────────────────────────────────────────────┐
                   │              Rendering Engine                 │
                   │  lib/render.ts                                │
                   │  HTML builder + CSS + icons + UI logic        │
                   └──────────────────────────────────────────────┘
                                        │
                                        ▼
                   ┌──────────────────────────────────────────────┐
                   │           Command Parsing Layer               │
                   │  lib/commands.ts                              │
                   │  Natural-language interpretation               │
                   └──────────────────────────────────────────────┘
                                        │
                                        ▼
                   ┌──────────────────────────────────────────────┐
                   │               MCP-UI Resource                │
                   │ directHtml delivered to goose Desktop         │
                   └──────────────────────────────────────────────┘

Enter fullscreen mode Exit fullscreen mode

This architecture: a full-stack web application, albeit delivered entirely through MCP.

Development Notes
The server is built using the official MCP TypeScript SDK, with Stdio transport for local integration. Each tool call triggers a full UI regeneration, ensuring the interface always reflects the current state. The rendering engine composes HTML, CSS, and UI assets into a complete interface that can be displayed by any MCP-UI capable client.

Accessibility Techniques Used
My Wishlist Application incorporates accessibility directly into its UI rendering layer. Icon‑only controls use explicit aria-label attributes to ensure they are announced correctly by screen readers, and all interactive elements are implemented using semantic HTML such as header, h1, and button. Images include descriptive alt text when meaningful, and decorative assets can be marked with empty alt attributes to avoid unnecessary verbosity.

The interface is fully keyboard accessible because all actions are exposed through native button elements rather than custom div-based controls. The CSS supports readable contrast in both light and dark modes, and the layout remains stable without relying on motion-heavy effects. These techniques collectively align with WCAG principles and ensure that the UI remains usable across a wide range of assistive technologies.

Accessibility is always considered throughout the UI design. The HTML structure uses semantic elements, descriptive alt text, and predictable interaction patterns. The CSS avoids motion-heavy effects and maintains readable contrast across both light and dark modes.

The backend logic is cleanly separated from the UI layer. State operations, filtering, and wish manipulation are handled in dedicated functions, while the rendering engine focuses solely on producing the visual interface. This separation makes the application maintainable and extensible.

My Final Thoughts
Day 17 brought the entire Advent of AI journey full circle. I started this month building small utilities and CLI workflows, and I ended it by engineering a complete MCP application with a dynamic UI, a full tool suite, and a rendering pipeline. This project represents the intersection of everything I explored: front-end design, backend logic, accessibility, automation, and protocol-driven architecture.

What I appreciate most is how natural it felt to build a complete system on top of the Model Context Protocol. I was not just creating an application inside an MCP environment. I built the server itself, defined the tool interface, implemented the state management layer, and engineered the entire UI rendering pipeline. The protocol’s structure encouraged a clean separation of concerns, and goose made the development loop fast and expressive.

This final challenge was more than a conclusion. It demonstrated how far this architecture can be pushed when the server, the UI, and the interaction model are all designed together. A month of AI engineering produced seventeen distinct systems, each building on the last. The Wishlist Application is a fitting finale: a complete, interactive, architecturally coherent MCP server with a fully custom UI, polished, interactive, and architecturally complete.

Although this marks the final chapter of the Advent of AI challenge and the end of this phase, it is simply the continuation of my AI engineering journey in which I plan to keep learning & building daily; which I truly enjoy!

This post is part of my Advent of AI journey - AI Engineering: Advent of AI with goose Day 17 of AI engineering challenges.

Follow along for more AI Engineering Adventures with Eri!

Top comments (0)