From 1801f557a27531389f5c647b862a03b9b7c07ad4 Mon Sep 17 00:00:00 2001 From: cliffhall Date: Tue, 10 Mar 2026 10:22:12 -0400 Subject: [PATCH] * Refactored menu on spec pages * Broke v2_tech_stack.md into v2_web_client.md, v2_server.md, and v2_storage.md * Added v2 components with information on the presenttional components pattern. --- specification/README.md | 3 +- specification/v1_problems.md | 4 +- specification/v2_scope.md | 4 +- specification/v2_screenshots.md | 6 +- .../{v2_tech_stack.md => v2_server.md} | 75 ++----------------- specification/v2_storage.md | 10 +-- specification/v2_ux.md | 5 +- specification/v2_ux_components.md | 66 ++++++++++++++++ specification/v2_ux_features.md | 4 +- specification/v2_ux_handlers.md | 4 +- specification/v2_web_client.md | 61 +++++++++++++++ 11 files changed, 152 insertions(+), 90 deletions(-) rename specification/{v2_tech_stack.md => v2_server.md} (61%) create mode 100644 specification/v2_ux_components.md create mode 100644 specification/v2_web_client.md diff --git a/specification/README.md b/specification/README.md index 5ea4e816c..ce3ffeb52 100644 --- a/specification/README.md +++ b/specification/README.md @@ -1,7 +1,6 @@ # Inspector V2 Brief -### Brief | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_tech_stack.md) -### UX: [Overview](v2_ux.md) | [Features](v2_ux_features.md) | [Handlers](v2_ux_handlers.md) | [Screenshots](v2_screenshots.md) +### Brief | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_web_client.md) | [V2 UX](v2_ux.md) ## Table of Contents * [Motivation and Context](#motivation-and-context) diff --git a/specification/v1_problems.md b/specification/v1_problems.md index b791d614a..0bf84ff83 100644 --- a/specification/v1_problems.md +++ b/specification/v1_problems.md @@ -1,7 +1,7 @@ # Inspector V1 Problems -### [Brief](README.md) | V1 Problems | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_tech_stack.md) -### UX: [Overview](v2_ux.md) | [Features](v2_ux_features.md) | [Handlers](v2_ux_handlers.md) | [Screenshots](v2_screenshots.md) +### [Brief](README.md) | V1 Problems | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_web_client.md) | [V2 UX](v2_ux.md) + ## Table of Contents * [Monolithic components](#monolithic-components) diff --git a/specification/v2_scope.md b/specification/v2_scope.md index ddaace9d0..abdb3e4bc 100644 --- a/specification/v2_scope.md +++ b/specification/v2_scope.md @@ -1,7 +1,7 @@ # Inspector V2 Scope -### [Brief](README.md) | [V1 Problems](v1_problems.md) | V2 Scope | [V2 Tech Stack](v2_tech_stack.md) -### UX: [Overview](v2_ux.md) | [Features](v2_ux_features.md) | [Handlers](v2_ux_handlers.md) | [Screenshots](v2_screenshots.md) +### [Brief](README.md) | [V1 Problems](v1_problems.md) | V2 Scope | [V2 Tech Stack](v2_web_client.md) | [V2 UX](v2_ux.md) + ## Table of Contents * [Protocol Features](#protocol-features) diff --git a/specification/v2_screenshots.md b/specification/v2_screenshots.md index f53c23ee0..0573c41a3 100644 --- a/specification/v2_screenshots.md +++ b/specification/v2_screenshots.md @@ -1,13 +1,13 @@ # Inspector V2 UX - Visual Reference -### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_tech_stack.md) -### UX: [Overview](v2_ux.md) | [Features](v2_ux_features.md) | [Handlers](v2_ux_handlers.md) | Screenshots +### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_web_client.md) | V2 UX +#### [Overview](v2_ux.md) | [Features](v2_ux_features.md) | [Handlers](v2_ux_handlers.md) | Screenshots | [Components](v2_ux_components.md) --- This document provides visual screenshots from the **Shadcn UI prototype** (`v2/prototype/shadcn`). These complement the ASCII wireframes in the UX specification documents. -**Note:** The V2 implementation will use **Mantine** (see [V2 Tech Stack](v2_tech_stack.md#mantine-rationale)). These Shadcn screenshots remain as historical reference showing how the UX spec translates to a working UI. The Mantine implementation will have the same screens and functionality with slightly different visual styling. +**Note:** The V2 implementation will use **Mantine** (see [V2 Tech Stack](v2_web_client.md#mantine-rationale)). These Shadcn screenshots remain as historical reference showing how the UX spec translates to a working UI. The Mantine implementation will have the same screens and functionality with slightly different visual styling. ## Table of Contents * [Server List](#server-list) diff --git a/specification/v2_tech_stack.md b/specification/v2_server.md similarity index 61% rename from specification/v2_tech_stack.md rename to specification/v2_server.md index f5bb64ca6..1b1bb2ff4 100644 --- a/specification/v2_tech_stack.md +++ b/specification/v2_server.md @@ -1,75 +1,10 @@ -# Inspector V2 Tech Stack +# Inspector V2 Tech Stack - Server -### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | V2 Tech Stack -### UX: [Overview](v2_ux.md) | [Features](v2_ux_features.md) | [Handlers](v2_ux_handlers.md) | [Screenshots](v2_screenshots.md) +### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | V2 Tech Stack | [V2 UX](v2_ux.md) -## Table of Contents - * [Web Client](#web-client) - * [Language and Framework](#language-and-framework) - * [Components and theme](#components-and-theme) - * [Proxy Server](#proxy-server) - * [Language and Runtime](#language-and-runtime) - * [Transport Operation](#server) - * [Logging](#logging) +#### [Web Client](v2_web_client.md) | Server | [Storage](v2_storage.md) - -## Web Client -### Language and Framework -* Typescript -* React - -### Components and Theme -* -[x] [Mantine](https://ui.mantine.dev/) -* -[ ] [Shadcn](https://ui.shadcn.com/) - -#### Mantine Rationale - -Mantine is recommended based on evaluation of both prototype implementations (`v2/prototype/shadcn` and `v2/prototype/mantine`) and group discussion. - -**Notes from Prototype Comparison:** - -Shadcn lacks layout components, requiring extensive Tailwind class management for containers, spacing, and alignment. This adds friction and cognitive load, based on our experiences with the current Inspector. Mantine's layout components (`Flex`, `Stack`, etc.) make the code more concise and easier to understand. - -Although the code may be less directly customizable, we don't expect extensive theming or branding to be a priority for Inspector as a debugging tool. - -See [PR #980 discussion](https://github.com/modelcontextprotocol/inspector/pull/980#issuecomment-3667102518) for example code comparison. - -| Requirement | Mantine | Shadcn | -|-------------|---------|--------| -| Layout components | Yes - Flex, Stack, Group, Grid | No - Use Tailwind divs | -| Out-of-box experience | Yes - Comprehensive | Partial - Assemble yourself | -| Code verbosity | Concise JSX props | Verbose Tailwind classes | -| Styling approach | Props + theme config | Tailwind utility classes | -| Documentation | Extensive API docs | Component examples | - -**Benefits:** - -1. **Built-in Layout Components** - Mantine provides layout primitives as JSX components: - - `Flex`, `Stack`, `Group`, `Grid`, `Center`, `Container` - - No need to manage `div` elements with Tailwind classes - - More declarative, readable code - -2. **Reduced Class Management** - Compare the same UI element: - ```tsx - // Mantine - concise - } color="yellow" title="Warning"> - {message} - - - // Shadcn + Tailwind - verbose class strings -
- -

Warning

{message}
-
- ``` - -3. **Better Out-of-Box Experience**: - - Single install provides all components - - Consistent API across all components - -## Proxy Server +## Overview ### Language and Runtime * Typescript * Node @@ -132,7 +67,7 @@ Pino is selected for synergy with the **History Screen** feature. The log file s ``` ┌─────────────────────────────────────────────────────────────────┐ -│ Proxy Server │ +│ Server │ │ │ │ MCP Request ──▶ Pino Logger ──┬──▶ history.ndjson (file) │ │ │ │ diff --git a/specification/v2_storage.md b/specification/v2_storage.md index 4bf08b575..40595edb5 100644 --- a/specification/v2_storage.md +++ b/specification/v2_storage.md @@ -1,8 +1,8 @@ -# V2 Storage Specification +# Inspector V2 Tech Stack - Storage Specification -**Status:** Draft -**Issue:** [#983](https://github.com/modelcontextprotocol/inspector/issues/983) -**Last Updated:** 2026-02-01 +### Brief | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | V2 Tech Stack | [V2 UX](v2_ux.md) + +#### [Web Client](v2_web_client.md) | [Server](v2_server.md) | Storage ## Overview @@ -44,7 +44,7 @@ The Pino logger on the proxy writes MCP request/response records to NDJSON forma - Caching fetched history for UI performance - User preferences that don't belong on the server -See [v2_tech_stack.md](./v2_tech_stack.md#pino-rationale) for Pino configuration details. +See [v2_server.md](./v2_server.md#pino-rationale) for Pino configuration details. --- diff --git a/specification/v2_ux.md b/specification/v2_ux.md index 7a5263b6b..67efd697c 100644 --- a/specification/v2_ux.md +++ b/specification/v2_ux.md @@ -1,6 +1,7 @@ -# Inspector V2 UX Specification +# Inspector V2 UX - Specification -### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_tech_stack.md) | V2 UX +### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_web_client.md) | V2 UX +#### Overview | [Features](v2_ux_features.md) | [Handlers](v2_ux_handlers.md) | [Screenshots](v2_screenshots.md) | [Components](v2_ux_components.md) ## Table of Contents * [Design Principles](#design-principles) diff --git a/specification/v2_ux_components.md b/specification/v2_ux_components.md new file mode 100644 index 000000000..83590304e --- /dev/null +++ b/specification/v2_ux_components.md @@ -0,0 +1,66 @@ +# Inspector V2 UX - Component Development + +### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_web_client.md) | V2 UX +#### [Overview](v2_ux.md) | [Features](v2_ux_features.md) | [Handlers](v2_ux_handlers.md) | [Screenshots](v2_screenshots.md) | Components + +We are developing React components with Mantine, Zustand, and Storybook using a pattern called "Presentational Components" that emphasizes separation of concerns and testability. + +## The Presentational / Container Split + +The idea is that a component receives everything it needs through props — the data it renders *and* the callbacks it fires when the user interacts. The component itself has no idea where the data came from or what happens when a button is clicked. It just calls `onSave(formData)` and trusts that someone upstream is handling it. + +This creaes clean layering: Zustand stores own the state and logic, container components (or hooks) wire stores to presentational components, and the presentational components themselves are pure rendering machines. Storybook targets that bottom layer exclusively. + +## What Storybook Does + +Storybook gives you a dev server that renders individual components in isolation, outside your application's component tree. You write "stories" — which are essentially named configurations of a component with specific props. A story for a `UserCard` might look like: + +```typescript +export const Default: Story = { + args: { + user: { name: 'Ada Lovelace', role: 'Engineer' }, + onEdit: fn(), + onDelete: fn(), + }, +}; + +export const LongName: Story = { + args: { + user: { name: 'A Very Long Username That Might Break Layout', role: 'Admin' }, + onEdit: fn(), + onDelete: fn(), + }, +}; +``` + +Each story appears in a sidebar, and you click through them to visually verify the component under different conditions. The `fn()` helper from Storybook creates a mock function that logs calls to an "Actions" panel, so you can see "onDelete was called with these arguments" without any real logic executing. + +## Storybook Development Loop + +The typical cycle is: define the component's prop interface (the "model" in your framing), write the component to render based on those props, write stories that exercise various prop combinations (empty states, error states, loading, overflowing content, etc.), and then visually verify in the Storybook UI. You do all of this before the component ever touches real data or lives inside the actual app. + +This naturally pushes you toward building bottom-up — atoms first (buttons, inputs, badges), then molecules (form groups, cards), then organisms (full panels, modals). You can't easily skip ahead and build a page-level component first because it would need too many dependencies you haven't isolated yet. + +## Disciplines That Keep Logic Out of Components + +This is where the real challenge lives, because React makes it *very* easy to let logic creep in. A few principles worth internalizing: + +**Props as the complete contract.** If a component needs to know whether a user has permission to delete something, don't pass in the user's role and let the component figure it out. Pass `canDelete: boolean`. The decision logic belongs in the store or a hook, not in the rendering layer. This also makes stories trivial to write — you just set `canDelete` to `true` or `false`. + +**Callbacks over store access.** If a presentational component imports a Zustand store directly, it's no longer testable in isolation without mocking the store. Instead, have a thin wrapper hook or container that does `const { items, addItem } = useStore(...)` and passes those down. The presentational component just sees `items: Item[]` and `onAdd: (item: Item) => void`. + +**Derived state lives outside.** Filtering, sorting, computed totals — all of that should happen in Zustand selectors or custom hooks, not inside the component. The component receives the *already filtered* list. + +**Local UI state is the exception.** Things like "is this dropdown open" or "which tab is active" are legitimately component-internal. That's fine — that's UI state, not application state. The heuristic is: if the application would need to know about it (say, to restore state on navigation), it belongs in Zustand. If only the component cares, `useState` is appropriate. + +## Mantine-Specific Considerations + +Since Mantine provides a theming layer and its own component library, we will want our Storybook to wrap stories in Mantine's `MantineProvider` with our theme. This is done through Storybook's `decorators` in the config, so every story gets the correct styling context. We can just write global decorators manually, but there's a `storybook-addon-mantine` package that simplifies this. + +## Is Storybook the Only Option? + +It's the most mature choice, but it's not the only one. Ladle is a lighter alternative with a similar API. Histoire is popular in the Vue world but has React support. Some teams skip a dedicated tool entirely and just create a `/dev` route in their app that renders a component gallery — less infrastructure, but you lose the story-based organization and addon ecosystem. + +For your stack, Storybook is the most well-trodden path and has the best TypeScript support for auto-generating controls from your prop types, which is genuinely useful. It will infer knobs/controls from your interfaces so you can tweak props interactively in the browser. + +The bottom line: your instinct is right. Design your components around a typed model (the props interface), keep decision-making in Zustand, and Storybook becomes the natural place to develop and verify the visual layer independently. The discipline isn't really about Storybook — it's about prop interface design. Storybook just makes it obvious when you've violated the boundary, because a component that reaches outside its props becomes painful to write stories for. diff --git a/specification/v2_ux_features.md b/specification/v2_ux_features.md index d8cfde764..a91ee7948 100644 --- a/specification/v2_ux_features.md +++ b/specification/v2_ux_features.md @@ -1,7 +1,7 @@ # Inspector V2 UX - Feature Screens -### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_tech_stack.md) -### UX: [Overview](v2_ux.md) | Features | [Handlers](v2_ux_handlers.md) | [Screenshots](v2_screenshots.md) +### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_web_client.md) | V2 UX +#### [Overview](v2_ux.md) | Features | [Handlers](v2_ux_handlers.md) | [Screenshots](v2_screenshots.md) | [Components](v2_ux_components.md) --- diff --git a/specification/v2_ux_handlers.md b/specification/v2_ux_handlers.md index 80f21a44f..0b32bc734 100644 --- a/specification/v2_ux_handlers.md +++ b/specification/v2_ux_handlers.md @@ -1,7 +1,7 @@ # Inspector V2 UX - Handlers & Patterns -### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_tech_stack.md) -### UX: [Overview](v2_ux.md) | [Features](v2_ux_features.md) | Handlers | [Screenshots](v2_screenshots.md) +### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | [V2 Tech Stack](v2_web_client.md) | V2 UX +#### [Overview](v2_ux.md) | [Features](v2_ux_features.md) | Handlers | [Screenshots](v2_screenshots.md) | [Components](v2_ux_components.md) --- diff --git a/specification/v2_web_client.md b/specification/v2_web_client.md new file mode 100644 index 000000000..8399116b7 --- /dev/null +++ b/specification/v2_web_client.md @@ -0,0 +1,61 @@ +# Inspector V2 Tech Stack + +### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | V2 Tech Stack | [V2 UX](v2_ux.md) + +#### Web Client | [Server](v2_server.md) | [Storage](v2_storage.md) + +## Overview +### Language and Framework +* Typescript +* React + +### Components and Theme +* -[x] [Mantine](https://ui.mantine.dev/) +* -[ ] [Shadcn](https://ui.shadcn.com/) + +#### Mantine Rationale + +Mantine is recommended based on evaluation of both prototype implementations (`v2/prototype/shadcn` and `v2/prototype/mantine`) and group discussion. + +**Notes from Prototype Comparison:** + +Shadcn lacks layout components, requiring extensive Tailwind class management for containers, spacing, and alignment. This adds friction and cognitive load, based on our experiences with the current Inspector. Mantine's layout components (`Flex`, `Stack`, etc.) make the code more concise and easier to understand. + +Although the code may be less directly customizable, we don't expect extensive theming or branding to be a priority for Inspector as a debugging tool. + +See [PR #980 discussion](https://github.com/modelcontextprotocol/inspector/pull/980#issuecomment-3667102518) for example code comparison. + +| Requirement | Mantine | Shadcn | +|-------------|---------|--------| +| Layout components | Yes - Flex, Stack, Group, Grid | No - Use Tailwind divs | +| Out-of-box experience | Yes - Comprehensive | Partial - Assemble yourself | +| Code verbosity | Concise JSX props | Verbose Tailwind classes | +| Styling approach | Props + theme config | Tailwind utility classes | +| Documentation | Extensive API docs | Component examples | + +**Benefits:** + +1. **Built-in Layout Components** - Mantine provides layout primitives as JSX components: + - `Flex`, `Stack`, `Group`, `Grid`, `Center`, `Container` + - No need to manage `div` elements with Tailwind classes + - More declarative, readable code + +2. **Reduced Class Management** - Compare the same UI element: + ```tsx + // Mantine - concise + } color="yellow" title="Warning"> + {message} + + + // Shadcn + Tailwind - verbose class strings +
+ +

Warning

{message}
+
+ ``` + +3. **Better Out-of-Box Experience**: + - Single install provides all components + - Consistent API across all components