Skip to content

Move to paginated UI for gateways, servers and agents#1955

Merged
crivetimihai merged 20 commits intomainfrom
add-partial-for-gateways
Jan 8, 2026
Merged

Move to paginated UI for gateways, servers and agents#1955
crivetimihai merged 20 commits intomainfrom
add-partial-for-gateways

Conversation

@madhav165
Copy link
Copy Markdown
Collaborator

@madhav165 madhav165 commented Jan 7, 2026

✨ Feature / Enhancement PR

🔗 Epic / Issue

Updates points in #1224


🚀 Summary (1-2 sentences)

Refactors admin UI tables (Gateways, Servers, A2A Agents) to use HTMX partial loading with out-of-band swaps, improving performance by eliminating N+1 queries and enabling dynamic pagination without full page reloads.

Additionally implements A2A agent to tool update and deletion logic.


📋 Key Changes

Backend (admin.py)

  • Added HTMX partial endpoints for Gateways (/admin/gateways/partial), Servers (/admin/servers/partial), and A2A Agents (/admin/a2a/partial)
  • Added search endpoints (/gateways/search, /servers/search, /a2a/search) for selector infinite scroll
  • Added IDs endpoints (/gateways/ids, /servers/ids, /a2a/ids) for "select all" functionality
  • Eliminated N+1 queries by batch-fetching team names and using service layer convert_*_to_read() methods
  • Supports three render modes: default (full table), controls (pagination only), selector (infinite scroll items)

Frontend Templates

  • Created partial templates: gateways_partial.html, servers_partial.html, agents_partial.html
  • Created selector templates: gateways_selector_items.html, servers_selector_items.html, agents_selector_items.html
  • Updated admin.html: Added HTMX-enabled divs with loading placeholders for dynamic content loading

JavaScript (admin.js)

  • Added tab switching handlers for catalog (servers), gateways, and a2a-agents tabs to trigger HTMX loads when tabs become visible
  • Updated table filter functions to use new element IDs (#servers-table-body, #agents-table)

Service Layer (a2a_service.py, tool_service.py)

  • Refactored convert_agent_to_read(): Changed parameter order to (db_agent, include_metrics, db, team_map) for consistency
  • Pre-populated team handling: Checks if team name already exists on db_agent before querying database
  • Implemented A2A agent-tool synchronization: Agent updates/deletes now propagate to associated tools using direct foreign key lookup
  • Optimized tool creation: Reduced commits from 3 to 2 by using db.flush() instead of intermediate commit

Database Schema (db.py, Alembic)

  • Added tool_id foreign key column to a2a_agents table with SQLAlchemy relationship
  • Migration includes logic to populate tool_id for existing agents by matching via annotations

🔧 Technical Details

  • Performance: Batch queries eliminate N+1 problems when loading lists
  • UX: HTMX provides instant table updates without page reloads
  • Pagination: Out-of-band swaps update both table content and pagination controls simultaneously
  • Route conflict resolution: Specific routes (/servers/partial) now registered before parameterized routes (/servers/{server_id})
  • A2A-Tool Sync: Direct foreign key relationship reduces tool lookup from 2 queries to 1 (O(1) via db.get())
  • Transaction optimization: Using db.flush() for intermediate state reduces unnecessary commits

🧪 Checks

  • make lint passes
  • make test passes

@madhav165 madhav165 changed the title Add partial endpoints for gateways, servers, agents Move to paginated UI for gateways, servers, agents Jan 7, 2026
@madhav165 madhav165 changed the title Move to paginated UI for gateways, servers, agents Move to paginated UI for gateways, servers and agents Jan 7, 2026
@crivetimihai crivetimihai self-assigned this Jan 7, 2026
madhav165 and others added 20 commits January 7, 2026 23:05
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>
- Remove commented-out admin_list_gateway_ids endpoint (replaced by new implementation)
- Remove console.log debug statements from admin.js tab switching logic
- Add standard encoding header to migration file

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
- Fix A2A route mismatch: /admin/agents/partial → /admin/a2a/partial
- Fix A2A element ID mismatch: #a2a-agents-table-body → #agents-table-body
- Fix gateway selector class: .gateway-item → .tool-item for JS compatibility
- Restore REST/A2A null gateway checkbox in gateway selector (page 1 only)

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
- Add selectinload for server relationships (tools, resources, prompts,
  a2a_agents) to prevent N+1 queries in convert_server_to_read
- Add db.commit() before template rendering in servers, gateways, and
  a2a partial endpoints to release transactions and avoid idle-in-transaction
  timeouts under load

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
…ilures

- Preserve existing tool visibility and team_id when updating tool from
  A2A agent to prevent unintentionally making private/team tools public
  (ToolUpdate defaults to "public" which was overriding existing settings)
- Wrap tool sync in try/except to handle failures gracefully - the agent
  update is the primary operation and should succeed even if tool sync fails

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
- Fix gateway.last_seen template to handle both datetime objects and
  ISO strings (after jsonable_encoder serialization)
- Fix A2A tool auth sync to use auth=AuthenticationValues(...) instead
  of auth_type/auth_value which are not fields on ToolUpdate schema

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
@crivetimihai crivetimihai force-pushed the add-partial-for-gateways branch from 69440ac to 8152218 Compare January 8, 2026 01:03
@crivetimihai
Copy link
Copy Markdown
Member

Review Changes After Rebase

The PR was rebased onto main and the following fixes were applied during code review:

1. Code Cleanup

  • Removed commented-out admin_list_gateway_ids endpoint from admin.py
  • Removed debug console.log statements from admin.js tab switching logic

2. Route and Element ID Fixes

  • Fixed A2A route paths from /admin/agents/partial to /admin/a2a/partial in templates (admin.html, agents_selector_items.html)
  • Fixed A2A element ID mismatch: changed #a2a-agents-table-body to #agents-table-body in admin.py
  • Fixed gateway selector class from .gateway-item to .tool-item for JS compatibility
  • Restored missing null gateway "REST/A2A" checkbox option in gateways_selector_items.html

3. Database Performance & Transaction Fixes

  • Added selectinload for server relationships (tools, resources, prompts, a2a_agents) to prevent N+1 queries
  • Added db.commit() before template rendering in servers/gateways/a2a partial endpoints to properly release read transactions

4. A2A Agent Update Fixes

  • Preserved existing tool visibility when updating A2A agents (prevents defaulting to "public")
  • Wrapped tool sync in try/except to handle sync failures gracefully without failing the agent update
  • Fixed A2A tool auth sync to use auth=AuthenticationValues(...) instead of invalid auth_type/auth_value fields
  • Removed invalid team_id parameter from ToolUpdate call

5. Template Field Name Fixes

  • Changed gateway.last_seen to gateway.lastSeen (camelCase) for consistency with jsonable_encoder output
  • Changed gateway.owner_email to gateway.ownerEmail
  • Changed server.owner_email to server.ownerEmail
  • Added handling for both datetime objects and ISO strings in lastSeen template rendering

All 4683 tests pass. Flake8, web linting, and Bandit security scans all pass.

Copy link
Copy Markdown
Member

@crivetimihai crivetimihai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebased and tested

@crivetimihai crivetimihai merged commit 1a8c50c into main Jan 8, 2026
52 checks passed
@crivetimihai crivetimihai deleted the add-partial-for-gateways branch January 8, 2026 01:18
crivetimihai added a commit that referenced this pull request Jan 24, 2026
The Export Config button was not included when pagination was
implemented in PR #1955. This button allows users to export
MCP client configuration in stdio/SSE/HTTP formats.

Closes #2362

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
crivetimihai added a commit that referenced this pull request Jan 24, 2026
…2363)

The Export Config button was not included when pagination was
implemented in PR #1955. This button allows users to export
MCP client configuration in stdio/SSE/HTTP formats.

Closes #2362

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
kcostell06 pushed a commit to kcostell06/mcp-context-forge that referenced this pull request Feb 24, 2026
* Add more partial endpoints
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Add ids and search APIs for gw, server, a2a
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Clean up APIs
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Add templates for gw, server and agent
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Update gw, agent to use htmx
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Fix bugs in gw loading
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Fix bugs in partial templates
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Fix agent fields in partial
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Fix flake8 issues
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Fix eslint issues
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Fix counts in server list
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Fix update and deletion of a2a tools
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* Fix test
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* pylint fixes
Signed-off-by: Madhav Kandukuri <madhav165@gmail.com>

* refactor: remove commented code and debug statements

- Remove commented-out admin_list_gateway_ids endpoint (replaced by new implementation)
- Remove console.log debug statements from admin.js tab switching logic
- Add standard encoding header to migration file

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>

* fix: correct route paths, element IDs, and restore null gateway option

- Fix A2A route mismatch: /admin/agents/partial → /admin/a2a/partial
- Fix A2A element ID mismatch: #a2a-agents-table-body → #agents-table-body
- Fix gateway selector class: .gateway-item → .tool-item for JS compatibility
- Restore REST/A2A null gateway checkbox in gateway selector (page 1 only)

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>

* fix: add eager loading and transaction cleanup for partial endpoints

- Add selectinload for server relationships (tools, resources, prompts,
  a2a_agents) to prevent N+1 queries in convert_server_to_read
- Add db.commit() before template rendering in servers, gateways, and
  a2a partial endpoints to release transactions and avoid idle-in-transaction
  timeouts under load

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>

* fix: preserve tool visibility on A2A agent updates and handle sync failures

- Preserve existing tool visibility and team_id when updating tool from
  A2A agent to prevent unintentionally making private/team tools public
  (ToolUpdate defaults to "public" which was overriding existing settings)
- Wrap tool sync in try/except to handle failures gracefully - the agent
  update is the primary operation and should succeed even if tool sync fails

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>

* fix: handle datetime string formatting and A2A tool auth sync

- Fix gateway.last_seen template to handle both datetime objects and
  ISO strings (after jsonable_encoder serialization)
- Fix A2A tool auth sync to use auth=AuthenticationValues(...) instead
  of auth_type/auth_value which are not fields on ToolUpdate schema

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>

* Rebase

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>

---------

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
Co-authored-by: Mihai Criveti <crivetimihai@gmail.com>
kcostell06 pushed a commit to kcostell06/mcp-context-forge that referenced this pull request Feb 24, 2026
…BM#2363)

The Export Config button was not included when pagination was
implemented in PR IBM#1955. This button allows users to export
MCP client configuration in stdio/SSE/HTTP formats.

Closes IBM#2362

Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants