Module 6: MCP Apps and Interactive UI
Module 6: MCP Apps and Interactive UI
Module 6: MCP Apps and Interactive UI
Capsule description
Until now, every MCP server you built returns text. A JSON with data, a string with a message, an error with a description. The model reads that text, processes it, and presents it to you. It works. But there's a problem: when the data is complex — tables with 50 rows, system metrics, the status of 20 tasks — plain text falls short.
Imagine you ask Claude Code: "show me the status of all my API's endpoints." Your MCP server queries the database and returns a JSON with 15 endpoints, each with status, latency, error rate, and last request. Claude Code receives that JSON and... shows it to you as a block of text. Functional, but hard to read. Now imagine that instead of plain text, your tool returns a formatted table with colors by status, progress bars for the latency, and an executive summary at the top. Same information, radically different presentation.
That's what this module explores: MCP servers whose tools go beyond plain text and return rich, structured output — markdown tables, formatted reports, ASCII visualizations, dashboards with organized sections. It's not a complete UI framework — it's the ability to make your tools' responses visually useful.
Where are we?
Context within the guide
Phase 1: MCP Fundamentals (Modules 1-3)
✅ Module 1: What MCP is and why it matters
✅ Module 2: Host-Client-Server Architecture
✅ Module 3: Three Primitives (Resources, Tools, Prompts)
Phase 2: Build MCP Servers (Modules 4-6)
✅ Module 4: MCP Server in TypeScript
✅ Module 5: MCP Server in Python
→ Module 6: MCP Apps and Interactive UI (YOU ARE HERE)
Phase 3: Production (Modules 7-8)
○ Module 7: Testing, Debugging, and Integration
○ Module 8: Project — Real MCP Server
What you already know
From the previous modules you bring:
- Complete MCP — the protocol, the Host-Client-Server architecture, the three primitives
- Servers in two languages — TypeScript with Zod and Python with FastMCP/Pydantic
- Tool implementation — handlers, schemas, error handling, design patterns
- Resource implementation — static URIs, dynamic templates
- Transports — stdio for local, HTTP/SSE for remote
- Connection with Claude Code —
claude mcp add, end-to-end verification
What's missing
You know how to build MCP servers that return text. But you haven't yet explored:
- How to make your tools' output visually rich and easy to consume
- Techniques for formatting complex data (tables, reports, dashboards)
- Multi-step interactive workflows using tools and prompts together
- Patterns to capture user input in a structured way
- How to combine multiple tools into a cohesive experience
What are MCP Apps?
The core idea
An MCP App isn't a new technology. It's a design pattern: an MCP server whose tools are designed to return output that is visually rich and, in some cases, allows multi-step interaction with the user.
The key distinction:
Traditional MCP Server:
Tool → returns data as text/JSON
The model interprets and presents it as it can
MCP App:
Tool → returns formatted, structured output
The model presents it with the visual richness the format allows
In practice, this means your tools return:
- Markdown tables instead of JSON arrays
- Reports with sections instead of flat data
- ASCII charts for quick visualization
- Structured data that Claude Code can present in an organized way
- Multi-step workflows that guide the user through a process
The evolution: from text to experience
Think about how terminal programs evolved. First they were commands that returned pure text (ls, cat). Then came tools that formatted their output to make it readable (htop, git log --oneline --graph, docker ps). After that came the TUIs (Terminal User Interfaces) like lazygit and k9s — complete applications running in the terminal.
MCP Apps are in the second stage of that evolution. They're not complete TUIs, but they go far beyond returning plain text. They're tools that think about how they present the information, not just what information they return.
Evolution of output in MCP:
Level 1: Plain text
"15 files were found in the /src directory"
Level 2: Structured JSON
{"total": 15, "directory": "/src", "files": [...]}
Level 3: Formatted output (MCP Apps)
## 📁 Analysis of /src
**15 files** | 3 directories | 2.4 MB total
| File | Size | Modified |
|------------|--------|---------------|
| index.ts | 2.4 KB | 2 hours ago |
| utils.ts | 1.1 KB | 3 days ago |
**💡 Suggestion:** 4 files haven't been modified in >30 days
What you can do vs what you can't do
Let's be clear about the capabilities and limitations:
✅ What you CAN do:
├── Return formatted markdown (tables, headers, lists)
├── Create reports with sections and visual structure
├── Generate ASCII art and charts for visualization
├── Design multi-step workflows with confirmations
├── Combine tools + prompts for interactive flows
├── Return structured data that the model presents well
├── Format output for maximum readability
└── Use emojis and Unicode characters for visual indicators
❌ What you CAN'T do (today):
├── Render HTML/CSS in the terminal
├── Create complete graphical interfaces
├── Have buttons, sliders, or interactive widgets
├── Replace a web app or a web dashboard
├── Run JavaScript on the client side
├── Create UI experiences like React/Vue
└── Stream real-time updates
⚡ What is evolving:
├── Additional content types in MCP responses
├── Image support in tool responses
├── Structured data rendering by the hosts
└── Annotations and metadata in responses
MCP Apps aren't React apps. They're MCP servers that maximize the richness of the output within what the host (Claude Code) can present. That's much more than it seems — a good dashboard in formatted text can be surprisingly useful.
Anatomy of a tool response
Every tool in MCP returns an object with an array of content. Each content item has a type:
// A tool can return multiple content blocks
return {
content: [
{
type: "text",
text: "## Project Dashboard\n\n| Metric | Value |\n|---------|-------|\n| Tests | 142 passing |",
},
],
};
The type: "text" is the most common, but the text inside can be anything: markdown, JSON, tables, ASCII art, multi-section reports. The model (and the host) interpret and render the content according to the format.
The key is in the design of the text you return. A string that contains well-structured markdown is presented completely differently from a string with raw JSON.
Why does this module matter?
The "wall of JSON" problem
If you built the projects from modules 4 and 5, you already experienced this. You ask Claude Code to use your tool, the tool returns a JSON with 50 lines, and Claude Code shows you... a block of JSON. Technically correct, practically unreadable.
{
"endpoints": [
{"path": "/api/users", "method": "GET", "status": "healthy", "latency_ms": 45, "requests_24h": 12340, "error_rate": 0.2},
{"path": "/api/users", "method": "POST", "status": "healthy", "latency_ms": 120, "requests_24h": 3210, "error_rate": 0.5},
{"path": "/api/orders", "method": "GET", "status": "degraded", "latency_ms": 890, "requests_24h": 8900, "error_rate": 3.1},
{"path": "/api/orders", "method": "POST", "status": "healthy", "latency_ms": 200, "requests_24h": 2100, "error_rate": 0.8}
]
}
Now compare with the same information formatted:
## 📊 API Health Dashboard
**Overall status:** 3/4 endpoints healthy | 1 degraded
| Endpoint | Method | Status | Latency | Req/24h | Errors |
|----------|--------|--------|---------|---------|--------|
| /api/users | GET | ✅ Healthy | 45ms | 12,340 | 0.2% |
| /api/users | POST | ✅ Healthy | 120ms | 3,210 | 0.5% |
| /api/orders | GET | ⚠️ Degraded | 890ms | 8,900 | 3.1% |
| /api/orders | POST | ✅ Healthy | 200ms | 2,100 | 0.8% |
**⚠️ Attention:** `/api/orders GET` has high latency (890ms) and an elevated error rate (3.1%)
Same data. Information you can act on in seconds instead of minutes.
Real use cases
MCP Apps solve concrete problems:
- Project dashboards — task status, code metrics, test coverage
- System monitors — health checks, resource usage, formatted logs
- Database reports — analytics, frequent queries, table statistics
- Configuration flows — step-by-step setup with intermediate validations
- Code analysis — complexity reports, dependencies, technical debt
Module objective
By the end of this module, you'll be able to:
- ✅ Understand what MCP Apps are and how they differ from MCP servers that return plain text
- ✅ Design tools that return visually rich output (tables, reports, dashboards)
- ✅ Build dashboards with structured data and ASCII visualizations
- ✅ Implement multi-step workflows with confirmations and input capture
- ✅ Combine tools + prompts to create cohesive interactive flows
- ✅ Know the limitations of this approach and when it's appropriate vs a web app
- ✅ Have a functional MCP App with an interactive dashboard connected to Claude Code
Module roadmap
| Capsule | Topic | What you'll learn |
|---|---|---|
| 02 | What MCP Apps are | How they differ from traditional MCP servers, rich content types, the anatomy of a formatted response |
| 03 | Dashboards and Visualizations | Markdown tables, ASCII charts, structured reports, formatting complex data |
| 04 | Interactive Forms | Multi-step workflows, data capture, confirmations, tools + prompts together |
| 05 | Project: MCP App with a Dashboard | A complete server that returns an analytics dashboard with rich visualization |
Learning flow
The progression is deliberate:
- Concept (capsule 02) — what MCP Apps are, what types of rich output you can return, and the real capabilities of the ecosystem. Without overpromising, without underestimating.
- Visual output (capsule 03) — the meat of the module. You build tools that return dashboards, tables, ASCII charts, and formatted reports. This is what transforms a useful MCP server into a visually powerful one.
- Interaction (capsule 04) — the other axis of MCP Apps. Multi-step workflows, capturing user data, confirmations, and how to combine tools with prompts for complex flows.
- Project (capsule 05) — everything converges into an MCP App that implements a complete analytics dashboard. End-to-end with Claude Code.
What this module assumes
About your MCP knowledge
It assumes you completed modules 1-5:
- You understand the MCP protocol, the architecture, and the three primitives
- You've built MCP servers in TypeScript and Python
- You know how to implement tools, resources, and prompts
- You've connected MCP servers to Claude Code
- You master error handling and async patterns
About your technical knowledge
- You know how to read and write TypeScript and Python
- You've worked with markdown (tables, lists, headers)
- You understand JSON and can transform data between formats
- You've used the terminal and are comfortable with text output
You can choose your language
In modules 4 and 5, each language had its dedicated module. In this module, the concepts apply to both languages — a tool that returns formatted markdown works the same in TypeScript as in Python. Where it's practical, we show both implementations. Where it's not, choose the one you prefer.
Technical prerequisites
For this module you need:
- ✅ Node.js 18+ or Python 3.10+ (or both — choose your preferred one)
- ✅ MCP SDK installed (TypeScript or Python, from modules 4-5)
- ✅ Claude Code installed and working
- ✅ A previous MCP server working (from modules 4 or 5)
- ✅ A code editor with markdown support (to preview output)
Quick verification:
node --version # Node.js 18+
python --version # Python 3.10+
claude --version # Claude Code installed
If you completed modules 4 and 5, you're ready. This module doesn't introduce new dependencies — it uses the same SDKs.
Mindset for this module
"It's a pattern, not a technology"
MCP Apps don't require a different SDK, a new library, or a special configuration. It's the same server.tool() or @mcp.tool() you already know. What changes is how you design the output of your tools.
This is liberating: you already have all the tools. This module teaches you to use them in a way you hadn't considered.
"Formatting as a feature"
Formatting the output isn't cosmetic — it's a feature. A well-formatted dashboard can be the difference between a developer using your MCP server daily or abandoning it after the first use. Data presentation is part of the value your server provides.
Think about git log vs git log --oneline --graph --all. Same information, presentation that transforms the usefulness. That's what you're going to do with your MCP tools.
"Honesty about limitations"
This module isn't going to present MCP Apps as a replacement for web tools. They're a way to enrich the experience within Claude Code. Powerful within their context, limited outside it. Knowing when to use an MCP App and when to build a web app is part of the skill you develop here.
"The end user is the developer"
Your MCP Apps are used by a developer through Claude Code. They're not for end-users, they're not for non-technical stakeholders. They're internal tools that make your day-to-day more productive. Design for yourself and your team.
Connection to the capstone project
This module's mini-project (capsule 05)
You're going to build an MCP App that implements a Project Analytics Dashboard:
- Tools that return formatted metrics with tables and charts
- Visualization of file, commit, and project structure data
- Drill-down capability: from the general summary to the detail of a specific area
- An interactive workflow to configure which metrics to see
- Output that Claude Code presents in a visually rich way
Connection to module 8
The capstone project in module 8 can include rich output if you decide to implement it. This module gives you the patterns to do it. What you add in module 8 that this module doesn't cover:
- Automated testing of the formatted output (module 7)
- Integration with real production data
- Handling large volumes of data
- Professional documentation of the output format
Boundaries: what is NOT covered in this module
- ❌ Web UI frameworks (React, Vue, Svelte) — outside the scope of MCP
- ❌ HTML/CSS rendering — Claude Code doesn't render HTML in the terminal
- ❌ Bitmap graphics — MCP tools return text, not images (with limited exceptions)
- ❌ WebSockets for real-time — an MCP tool returns a response, not a continuous stream
- ❌ Output testing — that comes in module 7
- ❌ Deploying MCP Apps — outside the scope of the guide
- ❌ Professional UX design — basic principles yes, UX theory no
This module is exploration of rich output in MCP. You come in knowing how to return plain text, you leave knowing how to return dashboards and interactive workflows.
Comparison: when to use what
A question that naturally arises: "when do I use an MCP App vs a web app vs a script?"
| Need | Best option | Why |
|---|---|---|
| A quick dashboard for yourself | MCP App | Integrated in Claude Code, no deploy |
| A dashboard for the team (non-devs) | Web app | They need a real graphical UI |
| A one-off data report | MCP App | Low effort, immediate result |
| An internal tool for the dev team | MCP App | Everyone uses Claude Code, no infra overhead |
| A product for customers | Web app | They need a polished experience |
| Flow automation | MCP App + tools | Claude Code orchestrates, the tools execute |
| Complex data visualization | Web app | Interactive charts, zoom, dynamic filters |
| A quick formatted DB query | MCP App | A markdown table is enough |
The general rule: if the consumer is a developer who already uses Claude Code, an MCP App is probably enough. If you need a complete visual experience or non-technical users, you need a web app.
Signs of success
By the end of this module, you'll know you succeeded if:
- ✅ You can articulate what an MCP App is and how it differs from a traditional MCP server
- ✅ Your tools return markdown tables, formatted reports, and structured dashboards
- ✅ You can build multi-step workflows with confirmations and input capture
- ✅ You know when to use rich output vs plain text (and when to use a web app instead)
- ✅ You have a functional MCP App with an interactive dashboard running in Claude Code
- ✅ You feel comfortable combining tools and prompts to create interactive flows
- ✅ You can incorporate rich output into the capstone project in module 8 if you decide to
Summary
- This module explores MCP Apps: MCP servers whose tools return visually rich output
- It's not a new technology — it's a design pattern over the tools you already know how to build
- You're going to learn to create dashboards, tables, reports, ASCII charts, and multi-step workflows
- The capabilities are real but limited — it doesn't replace web apps, it enriches the experience in Claude Code
- By the end you'll have a functional MCP App with an interactive dashboard
- The patterns apply directly to the capstone project in module 8
Additional resources
- MCP Specification — Tool Results — Specification of content types in responses
- MCP TypeScript SDK — Official TypeScript SDK
- MCP Python SDK — Official Python SDK
- Markdown Tables Generator — Tool to generate markdown tables
- ASCII Art Generator — Inspiration for ASCII visualizations
Next capsule: What MCP Apps are — the anatomy of a rich response, content types, and the difference between a tool that returns data and one that returns a visual experience.