|
| 1 | +# Inspector V2 |
| 2 | + |
| 3 | +This is an application for inspecting MCP servers. Has three incarnations, Web, TUI, and CLI. |
| 4 | + |
| 5 | +## Project Structure |
| 6 | + |
| 7 | +``` |
| 8 | +inspector/ |
| 9 | +├── clients/ |
| 10 | +│ ├── web/ # Web client code |
| 11 | +│ ├── cli/ # CLI client code |
| 12 | +│ ├── tui/ # TUI client code |
| 13 | +│ ├── launcher/ # Shared launcher |
| 14 | +├── core/ # Shared core code |
| 15 | +├── soecification/ # Build specification |
| 16 | +... |
| 17 | +``` |
| 18 | + |
| 19 | +## Maintenance Rules |
| 20 | + |
| 21 | +### Keep documentation files up to date |
| 22 | +- When adding, removing, renaming, or changing the purpose of any file or folder, update the corresponding entry in the main README.md and/or the related clients/*/README.md |
| 23 | +- When the structure of the project, the tech stack, or the developer setup changes, update appropriate README.md files with the details. |
| 24 | +- When adding new commands, dependencies, or architectural patterns, update the relevant sections of appropriate README.md files as well. |
| 25 | +- When rules for implementation and testing change, update this file AGENTS.md |
| 26 | + |
| 27 | +### Always test new or modified coderea |
| 28 | +- Ensure all code has corresponding tests |
| 29 | +- Ensure test coverage for each file is at least 90% |
| 30 | +- In unit tests that expect error output, suppress it from the console |
| 31 | + |
| 32 | +### Responding to Code Reviews |
| 33 | +- When asked to respond to a code review of a PR, |
| 34 | + - it is not necessary to implement all suggestions |
| 35 | + - you are free to implement suggestions in a different way or to ignore if there is a good reason |
| 36 | + - after making the changes, respond to each review comment with what was done (or why it was ignored) |
| 37 | + |
| 38 | +### Lint-fixed, Formatted code |
| 39 | +- Ensure linting and formatting are applied after every change |
| 40 | +- ALWAYS do `npm run format`, `npm run lint`, `npm run typecheck`, `npm run test` and `npm run build` before pushing any changes |
| 41 | + |
| 42 | +### Typescript instructions |
| 43 | +- Use TypeScript for all new code |
| 44 | +- Follow TypeScript best practices and coding standards |
| 45 | +- NEVER use 'any' as a type |
| 46 | +- NEVER suppress error types (e.g., no-unused-vars, no-explicit-any) in the typescript or eslint configuration as a way of satisfying the linter or compiler. |
| 47 | +- Utilize type annotations and interfaces to improve code clarity and maintainability |
| 48 | +- Leverage TypeScript's type inference and static analysis features for better code quality and refactoring |
| 49 | +- Use type guards and type assertions to handle potential type mismatches and ensure type safety |
| 50 | +- Take advantage of TypeScript's advanced features like generics, type aliases, and conditional types to write more expressive and reusable code |
| 51 | +- Regularly review and refactor TypeScript code to ensure it remains well-structured and adheres to evolving best practices |
| 52 | + |
| 53 | +## React instructions |
| 54 | +- UI Components |
| 55 | + - We are using the Mantine component library for UI. |
| 56 | + - Instructions are at https://mantine.dev/llms.txt |
| 57 | + - Avoid using div and other basic HTML elements for layout purposes. |
| 58 | + - Prefer Mantine's Box, Group, and Stack components for layout. |
| 59 | + - Use Mantine's theme and styling utilities to ensure a consistent and responsive design. |
| 60 | + - NEVER use inline styles on a component. |
| 61 | + - NEVER use raw hex values (`#ddd`, `#94a3b8`, etc.) or `rgba()` literals for colors in component props or theme files. Use `--inspector-*` CSS custom properties defined in `App.css :root` (e.g., `c: 'var(--inspector-text-primary)'`). If no existing token fits, add one to `:root` first. |
| 62 | + - NEVER add a CSS class to a Mantine component when the styles can instead be expressed as component props or a theme variant. CSS classes are a last resort. |
| 63 | + - PREFER component props (via `.withProps()`) to CSS for behavioral and visual styles. |
| 64 | + - PREFER defining styles as theme variants (via `Component.extend()` in `src/theme/<Component>.ts`) over CSS classes. Each Mantine component with custom variants has its own file in `src/theme/`, exporting a `Theme<Name>` constant. The barrel `src/theme/index.ts` re-exports them all and `theme.ts` imports from the barrel. Flat CSS properties (margin, padding, background, border, color, font-size, etc.) belong in the theme. Only pseudo-selectors, nested child selectors, keyframes, and native HTML element styles belong in App.css. |
| 65 | + - App.css must contain ONLY styles that cannot be expressed in the Mantine theme: `@keyframes`, pseudo-selectors (`:hover`, `:focus`), cross-component hover relationships, nested child-element selectors for third-party HTML output (e.g. ReactMarkdown), and styles for native HTML elements (`img`, `iframe`). When refactoring a component, actively move any flat CSS properties out of App.css and into theme variants or `.withProps()` constants. |
| 66 | + - NEVER use inline code; instead extract to functions in the same file, exported or located in a shared location if immediately reusable. |
| 67 | + - In a component's file, for sub-components: |
| 68 | + - ALWAYS use Mantine components for layout and content, configured with props for styling and behavior. |
| 69 | + - ALWAYS declare a meaningfully named subcomponent as a constant using `.withProps()` if a component has two or more props. |
| 70 | + - NEVER use `Box` for subcomponent constants — `Box` does not support `.withProps()`. Use `Group`, `Stack`, `Flex`, `Text`, `Paper`, `UnstyledButton`, or `Image` instead. Pick the component that best matches the purpose: `Paper` for bordered/surfaced containers, `Text` for any text or content wrapper, `Stack`/`Group`/`Flex` for layout. |
| 71 | + - NEVER use a CSS class on a subcomponent constant when the styles can be expressed as a Mantine theme variant instead. Define variants in `src/theme/<Component>.ts` using `Component.extend({ styles: (_theme, props) => { ... } })` and reference them with `variant="variantName"` on the component or in `.withProps()`. |
| 72 | + - CSS classes are ONLY acceptable on subcomponents for styles that cannot be expressed as flat CSS-in-JS properties in the theme — specifically: pseudo-selectors (`:hover`, `:focus`), cross-component hover relationships (`.parent:hover .child`), nested child-element selectors (`.wrapper p`, `.wrapper code`), `@keyframes` definitions, and native HTML elements (`img`, `iframe`) that are not Mantine components. |
| 73 | + - When a theme variant needs a CSS class for nested/pseudo selectors, use `classNames` in the theme extension to auto-assign it — never add `className` manually in JSX for theme-styled components. |
| 74 | + - Example — subcomponent constant with `withProps`: |
| 75 | + ```tsx |
| 76 | + const CardContent = Group.withProps({ |
| 77 | + flex: 1, |
| 78 | + align: 'flex-start', |
| 79 | + justify: 'space-between', |
| 80 | + wrap: 'nowrap', |
| 81 | + }); |
| 82 | + return <CardContent> ... </CardContent> |
| 83 | + ``` |
| 84 | + - Example — theme variant with auto-assigned className for nested selectors: |
| 85 | + ```tsx |
| 86 | + // src/theme/Paper.ts |
| 87 | + export const ThemePaper = Paper.extend({ |
| 88 | + classNames: (_theme, props) => { |
| 89 | + if (props.variant === 'message') return { root: 'message' }; |
| 90 | + return {}; |
| 91 | + }, |
| 92 | + styles: (_theme, props) => { |
| 93 | + if (props.variant === 'message') { |
| 94 | + return { root: { padding: '1.5rem', borderRadius: 12 } }; |
| 95 | + } |
| 96 | + return { root: {} }; |
| 97 | + }, |
| 98 | + }), |
| 99 | +
|
| 100 | + // Component.tsx |
| 101 | + const MessageContainer = Paper.withProps({ variant: 'message' }); |
| 102 | + ``` |
| 103 | +- Theme files vs. Storybook element components |
| 104 | + - **Theme files** (`src/theme/<Component>.ts`) and **element components** (`src/components/elements/`) serve different purposes and both are needed. |
| 105 | + - Theme files customize every instance of a Mantine component app-wide — defaults (size, radius), custom variants, and global style overrides. They are applied automatically by `MantineProvider`. |
| 106 | + - Element components add domain-specific semantics on top of Mantine primitives. For example, `AnnotationBadge` maps domain concepts (audience, destructive, longRun) to Mantine's styling primitives (color, variant). Storybook documents these domain components for designers and developers. |
| 107 | + - Element components MUST import from `@mantine/core`, NOT from `src/theme/`. The theme layer is applied transparently by the provider — elements do not need to know about `Theme<Name>` constants. |
| 108 | + - NEVER push domain-specific variant logic (e.g., annotation types, transport types) into theme files. Domain variants belong in the element component that owns those semantics. Theme files are for styling that applies to the Mantine primitive globally. |
0 commit comments