Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8e3deed
feat: enhance UI responsiveness and proxy stability
ronny-rentner Feb 4, 2026
a7f914d
fix: ensure tools pane resizer respects minSize and matches pane height
ronny-rentner Feb 4, 2026
24ee03b
feat: only show search when more than 3 items are present
ronny-rentner Feb 4, 2026
8675033
feat: implement search auto-focus logic in ToolsTab
ronny-rentner Feb 4, 2026
11040d4
feat: add clear button to search input in ListPane
ronny-rentner Feb 5, 2026
acd6c44
fix: move Copy Input button next to Run Tool for better proximity to …
ronny-rentner Feb 5, 2026
e7778c3
fix: restore internal tools scrolling and cap resizer height
ronny-rentner Feb 5, 2026
9e02bf3
fix: final layout improvements, resizer alignment, and independent sc…
ronny-rentner Feb 6, 2026
3e70fb3
feat: switch to percentage-based resizing for proportional window sca…
ronny-rentner Feb 6, 2026
2feb364
fix: robust percentage-based resizing and pixel-perfect resizer align…
ronny-rentner Feb 6, 2026
e2571ce
fix: final layout and style stability improvements
ronny-rentner Feb 7, 2026
d2144d7
feat: implement reusable usePanelToggle hook and enable double-click …
ronny-rentner Feb 7, 2026
2a3776c
fix: resolve build errors by removing unused imports and duplicate st…
ronny-rentner Feb 7, 2026
515ca46
fix: ensure app takes 100% viewport height by fixing SidebarProvider …
ronny-rentner Feb 7, 2026
1c7f7df
fix: ensure tab items don't overlap by allowing horizontal scrolling
ronny-rentner Feb 7, 2026
c8d155e
feat: add dynamic input/textarea switcher for strings to enable brows…
ronny-rentner Feb 7, 2026
417dffc
Fix: Enable scrolling for History, Notifications, and main tabs.
ronny-rentner Feb 26, 2026
a6e5657
Chore: Migrate to react-resizable-panels v4.6.5
ronny-rentner Feb 27, 2026
34915fd
feat: disable auth on localhost by default and migrate layout persist…
ronny-rentner Mar 2, 2026
d633d7a
chore: upgrade to React 19 and update dependencies
ronny-rentner Mar 3, 2026
3330cc4
chore: upgrade to Tailwind CSS v4 and clean up configuration
ronny-rentner Mar 3, 2026
532a386
chore: remove obsolete tailwind and postcss config files
ronny-rentner Mar 3, 2026
2bc7525
chore: update dependencies across monorepo (root, server, cli)
ronny-rentner Mar 4, 2026
65bdfa4
chore: finalize modernization and fix all tests
ronny-rentner Mar 10, 2026
cc161f2
chore: complete tech stack modernization and fix all tests
ronny-rentner Mar 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ client/test-results/
client/e2e/test-results/
mcp.json
.claude/settings.local.json
*.log
mcp-logs/
client/coverage/
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
registry="https://registry.npmjs.org/"
@modelcontextprotocol:registry="https://registry.npmjs.org/"
package-lock=true
save=true
10 changes: 9 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,12 @@ server/build
CODE_OF_CONDUCT.md
SECURITY.md
mcp.json
.claude/settings.local.json
.claude/settings.local.json

# Logs and transient data
mcp-logs/
*.log
server/*.log
server/*.yaml
server/mcp-logs/
react-resizable-panels-src/jest-source/
113 changes: 113 additions & 0 deletions GEMINI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Gemini Project Context: MCP Inspector

## Project Overview

The **MCP Inspector** is a developer tool designed for testing and debugging servers implementing the **Model Context Protocol (MCP)**. It provides a visual interface and a command-line interface to interact with MCP servers, explore their capabilities (tools, resources, prompts), and monitor protocol traffic.

### Architecture

The project is a TypeScript monorepo using NPM workspaces:

- **`client/`**: A React-based web UI (built with Vite, Tailwind CSS, and Radix UI) that provides an interactive dashboard.
- **`server/`**: An Express-based proxy server that bridges the web UI (running in a browser) to various MCP transport methods (STDIO, SSE, Streamable HTTP).
- **`cli/`**: A unified command-line interface that allows running the inspector in both UI and CLI-only modes.
- **`scripts/`**: Utility scripts for version management and consistency checks.

### Main Technologies

- **Languages**: TypeScript (Strict mode)
- **Frontend**: React 18, Vite, Tailwind CSS, Radix UI, Lucide Icons, Shadcn UI (components/ui)
- **Backend**: Node.js, Express 5, `@modelcontextprotocol/sdk`
- **CLI**: Commander.js
- **Testing**: Vitest (CLI), Jest (Client unit tests), Playwright (E2E)
- **Formatting/Linting**: Prettier, ESLint

---

## Building and Running

### Development

```bash
npm install # Install all dependencies
npm run dev # Start client and server in dev mode (default port 6274)
```

### Production Build

```bash
npm run build # Build all workspaces (client, server, cli)
npm start # Run the built application
```

### Testing

```bash
npm test # Run prettier check and client unit tests
npm run test-cli # Run CLI-specific tests (Vitest)
npm run test:e2e # Run Playwright E2E tests
```

---

## Development Conventions

### Code Style & Structure

- **Naming**:
- `PascalCase` for React components and Types/Interfaces.
- `camelCase` for variables and functions.
- `kebab-case` for file and directory names.
- **Components**: Functional components using React Hooks. Complex logic should be extracted into custom hooks (see `client/src/lib/hooks/`).
- **Styling**: Tailwind CSS for layout and styling. Prefer Radix UI primitives for accessible UI components.
- **Modules**: Strict use of ES Modules (`import/export`). `type: "module"` is set in `package.json`.

### MCP Protocol Handling

- The **Proxy Server** (`server/src/index.ts`) is critical for handling transport translation.
- **Security**: The proxy uses a session token (`MCP_PROXY_AUTH_TOKEN`) for authentication by default. DNS rebinding protection is implemented via origin validation.
- **Transports**: Supports `stdio`, `sse`, and `streamable-http`. Note that `sse` is often deprecated in favor of `streamable-http`.

### Testing Practices

- **Unit Tests**: Use Jest for React components (`client/__tests__`) and Vitest for CLI logic (`cli/__tests__`).
- **E2E Tests**: Use Playwright for browser-based automation tests in `client/e2e/`.
- **Pre-commit**: Husky is used to run `prettier --write` on staged files.

---

## Technical Learnings & Patterns

### UI & Resizing Logic

- **State vs. CSS Synchronization**: When using JS state to control element dimensions (e.g., `width`), always clamp the state values (`minSize`, `maxSize`) to match the CSS constraints. Failure to do so creates a "dead zone" where the UI feels stuck because the JS state continues to grow while CSS visually blocks it.
- **Resizer Usability**: To ensure resizers are grabable even when a panel is collapsed to 0px, remove `overflow-hidden` from the resizable container and use an absolute-positioned hit area (e.g., `left-[-8px]`).
- **Unified Resizing**: Prefer a generic `useResizable` hook that returns raw `size` values, allowing individual components to map them to `width` or `height` as needed.

### Browser Hacks

- **Autocomplete History**: Standard React forms often fail to trigger browser autocomplete history. A "Hidden Iframe Hack" (targeting an invisible `<iframe>` on form submission) can trick the browser into recording input history without requiring a page reload.

### Proxy Stability

- **Connection Resilience**: MCP Proxy `send` operations should always be wrapped in `.catch()` blocks. Standard stderr/stdout events from MCP servers can trigger after a browser client has disconnected, leading to unhandled promise rejections ("Not connected") that crash the proxy server.
- **Session Cleanup**: Always explicitly delete sessionId references from `webAppTransports`, `serverTransports`, and `sessionHeaderHolders` during any disconnection event to prevent memory leaks and "ghost" sessions.

### CLI Enhancements

- **Dev Mode Flexibility**: The `client/bin/start.js` script was updated to forward MCP server commands and arguments even in `--dev` mode, allowing developers to test local servers without full production builds.

---

## Milestones

- **2026-02-03**: Created [Pull Request #1050](https://github.com/modelcontextprotocol/inspector/pull/1050) targeting UI responsiveness and proxy stability. Includes resizable panels, browser history for tools, and proxy connection resilience.

## Key Files

- `package.json`: Root workspace configuration.
- `client/src/App.tsx`: Main React entry point and layout.
- `server/src/index.ts`: Proxy server entry point and transport routing logic.
- `cli/src/cli.ts`: CLI entry point for the unified inspector binary.
- `AGENTS.md`: High-level development guide for the project.
- `CLAUDE.md`: Quick reference for development commands.
59 changes: 59 additions & 0 deletions PANES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# MCP Inspector: Pane Hierarchy Documentation

This document defines the standardized layout structure for the MCP Inspector. All resizing logic and overflow boundaries must adhere to this hierarchy.

## Level 1: Root Layout

- **Container**: `flex h-screen w-screen overflow-hidden`
- **Axis**: Horizontal (Flex Row)
- **Pane A**: **Connection Pane** (Left Sidebar)
- Content: Connection settings, transport selection, configuration.
- Size: Percentage-based width.
- **Pane B**: **Working Area Container**
- Content: Flexible container holding the Main Pane and Notification Pane.
- Size: `flex-1`.
- **Resizer**: Controls the width boundary between Connection Pane and Working Area.

## Level 2: Working Area (Inside Level 1, Pane B)

- **Container**: `flex-1 flex flex-col min-h-0`
- **Axis**: Vertical (Flex Column)
- **Pane A**: **Main Pane**
- Content: Standard Tab navigation (Resources, Prompts, Tools, Tasks, etc.).
- Size: `flex-1`.
- **Pane B**: **Notification Pane** (History Drawer)
- Content: Contains the History and Server Notifications sub-panes.
- Size: Percentage-based height.
- **Resizer**: Controls the height boundary between Main Pane and Notification Pane.

## Level 3a: Main Pane Content (Inside Level 2, Pane A - Tools Tab)

- **Container**: `flex h-full w-full overflow-hidden`
- **Axis**: Horizontal (Flex Row)
- **Pane A**: **Tools List**
- Content: Scrollable list of available tools.
- Size: Percentage-based width.
- **Pane B**: **Tool Details**
- Content: Tool description, input form, and execution results.
- Size: `flex-1`.
- **Resizer**: Controls the width boundary between Tools List and Tool Details.

## Level 3b: Notification Pane Content (Inside Level 2, Pane B)

- **Container**: `flex h-full w-full overflow-hidden`
- **Axis**: Horizontal (Flex Row)
- **Pane A**: **History**
- Content: List of sent MCP requests and received responses.
- Size: `flex-1`.
- **Pane B**: **Server Notifications**
- Content: Real-time stream of server-sent notifications.
- Size: Percentage-based width.
- **Resizer**: Controls the width boundary between History and Server Notifications.

---

## Architectural Rules

1. **Clipping**: Every `Pane` component must strictly enforce `overflow-hidden` to provide a clear boundary.
2. **Resizers**: The `SplitResizer` must sit _between_ two panes (physically or as an absolute overlay) and update the size of the target pane without being clipped by it.
3. **Proportions**: All sizes must be percentage-based to ensure proportional scaling when the browser window is resized.
15 changes: 15 additions & 0 deletions PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# MCP Inspector Contribution Plan

- [x] **Phase 1: Repository Forking**
- [x] Fork `modelcontextprotocol/inspector` to `ronny-rentner/inspector`
- [x] Rename existing remote `origin` to `upstream`
- [x] Add the new fork as remote `origin`
- [x] Verify remotes are correctly configured
- [x] **Phase 2: Preparing and Pushing Changes**
- [x] Squash the 12 local commits into a single cohesive commit
- [x] Push local `main` to `origin/main`
- [x] Verify the fork on GitHub matches the local state
- [ ] **Phase 3: Review & Pull Request**
- [ ] Perform a final review of the diff against `upstream/main`
- [ ] Search for PR templates in the upstream repository
- [ ] Create a Pull Request from `origin/main` to `upstream/main`
10 changes: 8 additions & 2 deletions cli/__tests__/helpers/assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@ import type { CliResult } from "./cli-runner.js";
* Assert that CLI command succeeded (exit code 0)
*/
export function expectCliSuccess(result: CliResult) {
expect(result.exitCode).toBe(0);
expect(
result.exitCode,
`CLI failed with code ${result.exitCode}. Output:\n${result.output}`,
).toBe(0);
}

/**
* Assert that CLI command failed (non-zero exit code)
*/
export function expectCliFailure(result: CliResult) {
expect(result.exitCode).not.toBe(0);
expect(
result.exitCode,
`CLI expected to fail but succeeded with code 0. Output:\n${result.output}`,
).not.toBe(0);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion cli/__tests__/helpers/cli-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function runCli(
const child = spawn("node", [CLI_PATH, ...args], {
stdio: ["pipe", "pipe", "pipe"],
cwd: options.cwd,
env: { ...process.env, ...options.env },
env: { DEBUG: "true", ...process.env, ...options.env },
signal: options.signal,
// Kill child process tree on exit
detached: false,
Expand Down
Loading