mcp-context-forge
mcp-context-forge copied to clipboard
📋 Epic: Unified Search & Filter - Consistent Cross-Tab Discovery
📋 Epic: Unified Search & Filter - Consistent Cross-Tab Discovery
Goal
Implement unified search and filter functionality across all Admin UI tabs (Servers, Virtual Servers, Tools, Prompts, Resources, A2A Agents) with a consistent, standardized interface. Enable users to quickly discover resources using both keyword search (name, description, endpoint) and tag filtering, with a cohesive UX that works identically across all entity types.
Why Now?
As ContextForge deployments grow, users manage hundreds of servers, tools, resources, and agents. Current limitations create operational friction:
- Tag-Only Filtering: Can only filter by tags, not search by name or description
- Inconsistent UI: Filter controls look different across tabs (some have tag filters, some don't)
- No Combined Search: Can't combine keyword search with tag filtering
- Poor Discovery: Hard to find "weather" tools or "database" servers across large inventories
- No Visual Consistency: Filter/search fields have different styles, positions, and behaviors
- Scalability Issues: Tag filtering alone doesn't scale when managing 100+ resources
By unifying search and filter with a consistent interface, operators can quickly discover resources using natural search terms while maintaining tag-based organization.
📖 User Stories
US-1: Developer - Search Servers by Name
As a Developer I want to search servers by name or description So that I can quickly find the "weather" or "database" server
Acceptance Criteria:
Given servers exist:
- Name: "weather-api-prod", Description: "Production weather API"
- Name: "weather-api-dev", Description: "Development weather API"
- Name: "database-postgres", Description: "PostgreSQL database server"
When I navigate to the Servers tab
Then I should see a unified search/filter bar with:
- Search input field (placeholder: "Search servers...")
- Tag filter dropdown/multi-select
- Clear button (visible when filters active)
When I type "weather" in the search field
Then the table should instantly show:
- weather-api-prod
- weather-api-dev
And the database-postgres server should be hidden
When I type "postgres" in the search field
Then the table should show only:
- database-postgres
When I clear the search field
Then all servers should be visible again
Technical Requirements:
- Client-side search (instant filtering without API calls)
- Search fields: name, description, endpoint
- Case-insensitive partial matching
- Alpine.js reactive filtering
- Debouncing (300ms) for performance
US-2: Operations Engineer - Combine Search and Tag Filter
As an Operations Engineer I want to combine keyword search with tag filtering So that I can find all "production" tools related to "database"
Acceptance Criteria:
Given tools exist:
- Name: "postgres-query", Tags: ["database", "production"]
- Name: "mysql-backup", Tags: ["database", "production"]
- Name: "redis-monitor", Tags: ["cache", "production"]
- Name: "postgres-dev", Tags: ["database", "development"]
When I navigate to the Tools tab
And I type "postgres" in the search field
And I select tag: "production"
Then the table should show:
- postgres-query (matches "postgres" AND has "production" tag)
And the table should NOT show:
- mysql-backup (no "postgres" in name)
- postgres-dev (not tagged "production")
When I clear the tag filter
Then I should see:
- postgres-query
- postgres-dev
(Both match "postgres" in name)
When I clear the search field
Then I should see all tools tagged "production":
- postgres-query
- mysql-backup
- redis-monitor
Technical Requirements:
- AND logic: search + tags both must match
- Live filtering (no page reload)
- Visual indication of active filters
- Clear all filters button
- Filter state persists during session
US-3: Platform Admin - Consistent UI Across All Tabs
As a Platform Administrator I want identical search/filter controls on all tabs So that I don't have to learn different interfaces for each resource type
Acceptance Criteria:
Given I navigate through tabs:
- Servers
- Virtual Servers
- Tools
- Prompts
- Resources
- A2A Agents
Then each tab should have the SAME layout:
- Search input (same size, same position, same placeholder pattern)
- Tag filter dropdown (same style, same position)
- Clear filters button (same position, same behavior)
- Active filter count badge (if filters applied)
And each tab should have the SAME behavior:
- Type in search → instant filtering
- Select tags → instant filtering
- Combined search + tags → AND logic
- Clear button → resets all filters
And each tab should have the SAME styling:
- Input field width: 400px (or 40% of container)
- Height: 40px
- Border radius: 8px
- Placeholder text color: #6B7280
- Clear button: "✕" icon, right-aligned
- Tag dropdown: Multi-select with badges
Technical Requirements:
- Shared Alpine.js component
- Shared CSS classes
- Shared HTML template (partial/component)
- Same search fields per entity type:
- Servers: name, description, endpoint
- Virtual Servers: name, description
- Tools: name, description, tags
- Prompts: name, description, tags
- Resources: name, uri, mimeType, description
- A2A Agents: name, url, description
US-4: SRE - Search Resources by URI or MIME Type
As an SRE I want to search resources by URI pattern or MIME type So that I can find all "image/png" resources or all S3 URIs
Acceptance Criteria:
Given resources exist:
- Name: "logo", URI: "s3://bucket/logo.png", MIME: "image/png"
- Name: "photo", URI: "s3://bucket/photo.jpg", MIME: "image/jpeg"
- Name: "doc", URI: "file:///docs/manual.pdf", MIME: "application/pdf"
When I navigate to the Resources tab
And I type "s3://" in the search field
Then the table should show:
- logo
- photo
When I type "image/png" in the search field
Then the table should show:
- logo
When I type "manual" in the search field
Then the table should show:
- doc
When I clear the search field
Then all resources should be visible
Technical Requirements:
- Search across name, uri, mimeType, description
- Substring matching for URIs
- Case-insensitive matching
- Highlight matching text (optional enhancement)
US-5: Developer - Visual Feedback for Active Filters
As a Developer I want clear visual indication when filters are active So that I understand why I'm seeing a subset of resources
Acceptance Criteria:
Given I'm on any resource tab (Servers, Tools, Resources, etc.)
When no filters are active
Then I should see:
- Search field: empty, placeholder visible
- Tag filter: "All tags" or placeholder
- No clear button (or clear button disabled/hidden)
- No filter count badge
When I enter search text "weather"
Then I should see:
- Search field: text visible
- Clear button: visible and clickable
- Filter count badge: "1 filter active"
- Filtered results in table
When I also select tags: ["production", "api"]
Then I should see:
- Search field: "weather"
- Tag badges: "production ✕", "api ✕"
- Filter count badge: "3 filters active" (1 search + 2 tags)
- Clear all button: visible and prominent
When I click "Clear all"
Then I should see:
- Search field: empty
- Tag filter: reset to "All tags"
- Filter count badge: hidden
- All resources visible in table
Technical Requirements:
- Visual states: empty, active, filtered
- Filter count badge
- Tag badges with remove (✕) button
- Clear all button (resets all filters)
- Smooth transitions (CSS animations)
US-6: Developer - Search Virtual Servers by Composed Tool Names
As a Developer I want to search virtual servers by the names of tools they compose So that I can find virtual servers that include specific tools
Acceptance Criteria:
Given virtual servers exist:
- Name: "data-ops", Description: "Data operations", Tools: ["postgres-query", "redis-cache"]
- Name: "web-ops", Description: "Web operations", Tools: ["nginx-config", "certbot"]
When I navigate to Virtual Servers tab
And I type "postgres" in the search field
Then the table should show:
- data-ops (because it contains "postgres-query" tool)
When I type "certbot" in the search field
Then the table should show:
- web-ops
When I type "data" in the search field
Then the table should show:
- data-ops (matches name AND description)
Technical Requirements:
- Search includes: name, description, tool names
- Load composed tool names for search indexing
- Client-side filtering with tool name arrays
- Optional: Show which tool matched in results
🏗 Architecture
Component Structure
Unified Search/Filter Bar (Shared Component)
├── Search Input Field
│ ├── Icon (magnifying glass)
│ ├── Text input
│ └── Clear button (✕)
│
├── Tag Filter Dropdown
│ ├── Multi-select dropdown
│ ├── Selected tag badges
│ └── Remove tag buttons
│
├── Filter Count Badge
│ └── "N filters active"
│
└── Clear All Button
└── Reset all filters
Search Fields by Entity Type
- Servers: name, description, endpoint
- Virtual Servers: name, description, tool_names (composed tools)
- Tools: name, description
- Prompts: name, description
- Resources: name, uri, mimeType, description
- A2A Agents: name, url, description
Filter Logic
- Search: OR logic across search fields (match ANY field)
- Tags: AND logic (resource must have ALL selected tags)
- Combined: Resource must match search AND have all selected tags
📋 Implementation Tasks
-
[ ] Shared Filter Component
- [ ] Create
filterBarComponent()Alpine.js function - [ ] Support configurable search fields per entity type
- [ ] Support configurable tag field name
- [ ] Implement
applyFilters()with search + tag AND logic - [ ] Implement
clearSearch()method - [ ] Implement
removeTag()method - [ ] Implement
clearAllFilters()method - [ ] Compute
activeFilterCountdynamically - [ ] Extract available tags from items
- [ ] Debounce search input (300ms)
- [ ] Create
-
[ ] Servers Tab Integration
- [ ] Add filter bar component to servers template
- [ ] Initialize with search fields: name, description, endpoint
- [ ] Pass server data to Alpine component
- [ ] Update table to render
filteredItems - [ ] Add empty state when no results
- [ ] Test search by name
- [ ] Test search by description
- [ ] Test search by endpoint
- [ ] Test tag filtering
- [ ] Test combined search + tags
-
[ ] Virtual Servers Tab Integration
- [ ] Add filter bar component to virtual servers template
- [ ] Initialize with search fields: name, description
- [ ] Extend component to include tool names in search
- [ ] Fetch composed tool names for each virtual server
- [ ] Pass virtual server data with tool_names to Alpine
- [ ] Update table to render
filteredItems - [ ] Add empty state
- [ ] Test search by name
- [ ] Test search by tool name
- [ ] Test tag filtering
-
[ ] Tools Tab Integration
- [ ] Add filter bar component to tools template
- [ ] Initialize with search fields: name, description
- [ ] Pass tool data to Alpine component
- [ ] Update table to render
filteredItems - [ ] Add empty state
- [ ] Test search by name
- [ ] Test search by description
- [ ] Test tag filtering
- [ ] Test combined filters
-
[ ] Prompts Tab Integration
- [ ] Add filter bar component to prompts template
- [ ] Initialize with search fields: name, description
- [ ] Pass prompt data to Alpine component
- [ ] Update table to render
filteredItems - [ ] Add empty state
- [ ] Test search functionality
- [ ] Test tag filtering
-
[ ] Resources Tab Integration
- [ ] Add filter bar component to resources template
- [ ] Initialize with search fields: name, uri, mimeType, description
- [ ] Pass resource data to Alpine component
- [ ] Update table to render
filteredItems - [ ] Add empty state
- [ ] Test search by name
- [ ] Test search by URI
- [ ] Test search by MIME type
- [ ] Test tag filtering
-
[ ] A2A Agents Tab Integration
- [ ] Add filter bar component to agents template
- [ ] Initialize with search fields: name, url, description
- [ ] Pass agent data to Alpine component
- [ ] Update table to render
filteredItems - [ ] Add empty state
- [ ] Test search by name
- [ ] Test search by URL
- [ ] Test tag filtering
-
[ ] CSS Styling
- [ ] Create shared CSS file for filter bar styles
- [ ] Consistent input field dimensions (400px width, 40px height)
- [ ] Consistent border radius (8px)
- [ ] Consistent colors (Tailwind gray scale)
- [ ] Search icon positioning (left: 12px)
- [ ] Clear button styling and positioning
- [ ] Tag badge styling with remove buttons
- [ ] Filter count badge styling
- [ ] Clear all button styling
- [ ] Focus states for all interactive elements
- [ ] Hover states for buttons
- [ ] Empty state styling
- [ ] Responsive design (mobile breakpoints)
-
[ ] Visual Feedback
- [ ] Show/hide clear search button based on input
- [ ] Show/hide filter count badge based on active filters
- [ ] Show/hide clear all button based on active filters
- [ ] Display selected tags as removable badges
- [ ] Update table in real-time (no page reload)
- [ ] Show empty state when no results
- [ ] Add smooth transitions (CSS)
- [ ] Maintain filter state during session
-
[ ] Performance Optimization
- [ ] Client-side filtering (no API calls)
- [ ] Debounce search input (300ms)
- [ ] Optimize filter algorithm for large datasets (500+ items)
- [ ] Test with 1000+ items per tab
- [ ] Profile Alpine.js reactive performance
- [ ] Consider virtualization for very large lists (future)
-
[ ] Accessibility
- [ ] Add ARIA labels to search input
- [ ] Add ARIA labels to tag filter
- [ ] Keyboard navigation for clear buttons
- [ ] Screen reader announcements for filter changes
- [ ] Focus management (clear button, tag badges)
- [ ] High contrast mode support
- [ ] Test with keyboard-only navigation
- [ ] Test with screen readers (NVDA, JAWS)
-
[ ] Testing
- [ ] Unit tests: filterBarComponent logic (10+ tests)
- [ ] Unit tests: Search filtering (case-insensitive, partial match)
- [ ] Unit tests: Tag filtering (AND logic)
- [ ] Unit tests: Combined search + tags
- [ ] Integration tests: Servers tab filtering (5+ tests)
- [ ] Integration tests: Virtual Servers tab filtering (5+ tests)
- [ ] Integration tests: Tools tab filtering (5+ tests)
- [ ] Integration tests: Prompts tab filtering (3+ tests)
- [ ] Integration tests: Resources tab filtering (5+ tests)
- [ ] Integration tests: A2A Agents tab filtering (5+ tests)
- [ ] Playwright tests: Search interaction (5+ tests)
- [ ] Playwright tests: Tag filter interaction (5+ tests)
- [ ] Playwright tests: Combined filters (3+ tests)
- [ ] Playwright tests: Clear functionality (3+ tests)
- [ ] Playwright tests: Empty state display (2+ tests)
- [ ] Playwright tests: Visual consistency across tabs (6+ tests)
- [ ] Performance tests: Filtering 1000+ items (<100ms)
- [ ] Accessibility tests: Keyboard navigation, screen readers
- [ ] Test coverage: 90%+ for filter component
-
[ ] Documentation
- [ ] Update CLAUDE.md with search/filter usage
- [ ] Document filterBarComponent() API
- [ ] Document search fields per entity type
- [ ] Document filter logic (AND for tags, OR for search fields)
- [ ] Add examples: common search queries
- [ ] Add examples: combining search + tags
- [ ] Document customization options
- [ ] Add screenshots of unified filter bar
- [ ] Document accessibility features
- [ ] Update admin UI guide
-
[ ] Code Quality
- [ ] Run
make lint-weband fix issues - [ ] Validate HTML structure
- [ ] Validate CSS (no unused styles)
- [ ] Validate JavaScript (ESLint)
- [ ] Ensure consistent naming conventions
- [ ] Add code comments for complex logic
- [ ] Remove any debug console.log statements
- [ ] Run
⚙️ Configuration
No new environment variables required. This is a pure UI enhancement.
Optional Future Configuration
# Optional: Configure search debounce delay
MCPGATEWAY_UI_SEARCH_DEBOUNCE_MS=300
# Optional: Configure max items before virtualization warning
MCPGATEWAY_UI_MAX_ITEMS_BEFORE_WARNING=1000
✅ Success Criteria
- [ ] Unified Interface: All tabs (Servers, Virtual Servers, Tools, Prompts, Resources, A2A Agents) have identical filter bar layout
- [ ] Search Functionality: Keyword search works across relevant fields for each entity type
- [ ] Tag Filtering: Multi-select tag filtering works on all tabs
- [ ] Combined Filters: Search + tags can be combined (AND logic)
- [ ] Visual Consistency: Same dimensions, colors, spacing, typography across all tabs
- [ ] Instant Filtering: Client-side filtering with no page reload (debounced 300ms)
- [ ] Visual Feedback: Active filters show count badge, clear button appears when needed
- [ ] Empty State: "No results found" message when filters return empty
- [ ] Accessibility: ARIA labels, keyboard navigation, screen reader support
- [ ] Performance: Filtering 1000+ items completes in <100ms
- [ ] Testing: 90%+ test coverage with unit, integration, and Playwright tests
- [ ] Documentation: Updated CLAUDE.md and admin UI guide
🏁 Definition of Done
- [ ] Shared
filterBarComponent()Alpine.js component created - [ ] Filter bar HTML template created and reusable
- [ ] Shared CSS styles created for consistent design
- [ ] Filter bar integrated into Servers tab
- [ ] Filter bar integrated into Virtual Servers tab (with tool name search)
- [ ] Filter bar integrated into Tools tab
- [ ] Filter bar integrated into Prompts tab
- [ ] Filter bar integrated into Resources tab (with URI and MIME type search)
- [ ] Filter bar integrated into A2A Agents tab
- [ ] Search functionality works on all tabs
- [ ] Tag filtering works on all tabs
- [ ] Combined search + tags works (AND logic)
- [ ] Clear search button functional
- [ ] Clear all filters button functional
- [ ] Active filter count badge displays correctly
- [ ] Empty state displays when no results found
- [ ] Visual consistency verified across all tabs
- [ ] Unit tests: filterBarComponent logic (10+ tests)
- [ ] Integration tests: All tabs (30+ tests total)
- [ ] Playwright tests: Search, filter, clear (20+ tests total)
- [ ] Performance tests: 1000+ items filtered in <100ms
- [ ] Accessibility tests: Keyboard navigation, screen readers
- [ ] Code passes
make lint-webchecks - [ ] Documentation updated: CLAUDE.md, admin UI guide
- [ ] Screenshots captured for documentation
- [ ] Backward compatible: No breaking changes to existing UI
📝 Additional Notes
🔹 Search Fields by Entity Type:
- Servers: name, description, endpoint
- Virtual Servers: name, description, tool_names (composed tools)
- Tools: name, description
- Prompts: name, description
- Resources: name, uri, mimeType, description
- A2A Agents: name, url, description
🔹 Filter Logic:
- Search: OR logic across search fields (match ANY field)
- Tags: AND logic (resource must have ALL selected tags)
- Combined: Resource must match search AND have all selected tags
🔹 Performance Considerations:
- Client-side filtering (no API calls)
- Debounced input (300ms) to reduce computations
- Optimized for up to 1000 items per tab
- Future: Consider virtual scrolling for 5000+ items
🔹 Accessibility Features:
- ARIA labels for all inputs
- Keyboard navigation (Tab, Enter, Escape)
- Screen reader announcements
- High contrast mode support
- Focus indicators
🔹 Future Enhancements:
- Advanced Search: Boolean operators (AND, OR, NOT)
- Search Syntax: Prefix search (name:weather, tag:production)
- Saved Filters: Save common filter combinations
- Filter Presets: Quick filters (e.g., "My servers", "Production only")
- Search History: Recent searches dropdown
- Fuzzy Search: Typo-tolerant matching
- Highlighting: Highlight matching text in results
- Export Filtered: Export only filtered results
- Virtual Scrolling: For 5000+ items performance
- Server-Side Search: For very large datasets (10K+ items)
🔹 Design Principles:
- Consistency: Same UI everywhere (muscle memory)
- Performance: Instant feedback (no waiting)
- Clarity: Clear visual indication of active filters
- Simplicity: Easy to understand and use
- Accessibility: Works for all users
🔹 Migration Notes:
- Existing tag-only filters remain functional
- New search + filter is additive (non-breaking)
- Filter state preserved during session (sessionStorage)
- No database changes required
- No API changes required
- Pure frontend enhancement
🔗 Related Issues
- Tag management system enhancements
- Admin UI performance optimization
- Accessibility improvements
- Virtual scrolling for large datasets