Skip to content

Conversation

@jonpspri
Copy link
Collaborator

@jonpspri jonpspri commented Jan 9, 2026

Summary

Fixes #840

  • Add user input field for A2A agent testing: The test button now opens a modal with a query input field, allowing users to send custom queries like calc: 7*8 or weather: Dallas instead of a hardcoded message
  • Fix A2A agent tools visibility: Tools created for A2A agents now default to public visibility when the agent's visibility is not set, ensuring they appear in the Global Tools tab
  • Add demo A2A agent script: A standalone script to create and register a demo agent with calculator and weather tools for testing

Changes

File Description
mcpgateway/admin.py Parse request body to extract user query for A2A agent testing
mcpgateway/templates/admin.html Add A2A test modal with query textarea input
mcpgateway/static/admin.js Add modal functions for A2A agent testing
mcpgateway/services/tool_service.py Default tool visibility to public when agent visibility is unset
mcpgateway/services/a2a_service.py Add error handling and logging for tool creation
scripts/demo_a2a_agent.py Demo A2A agent with calculator and weather tools
tests/unit/mcpgateway/test_issue_840_a2a_agent.py Unit tests for both issues

Test plan

  • Create an A2A agent and verify tools appear in Global Tools tab
  • Click Test button on an A2A agent and verify modal opens with Query input
  • Enter custom query (e.g., weather: Dallas) and verify agent receives the query
  • Run demo agent: uv run python scripts/demo_a2a_agent.py
  • Run unit tests: uv run pytest tests/unit/mcpgateway/test_issue_840_a2a_agent.py -v

🤖 Generated with Claude Code

@jonpspri jonpspri added the a2a Support for A2A protocol label Jan 9, 2026
@jonpspri jonpspri marked this pull request as ready for review January 9, 2026 19:58
Copilot AI review requested due to automatic review settings January 9, 2026 19:58
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses issue #840 by adding user input functionality for A2A agent testing and fixing tool visibility issues. The changes enable users to test A2A agents with custom queries through a modal dialog, and ensure that A2A agent tools appear in the Global Tools tab by defaulting their visibility to "public".

Key changes:

  • Added modal-based testing interface with customizable query input for A2A agents
  • Fixed A2A tool visibility by defaulting to "public" when agent visibility is unset
  • Added comprehensive error handling for tool creation during agent registration

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
mcpgateway/admin.py Parses request body to extract user-provided query for A2A agent testing
mcpgateway/templates/admin.html Adds A2A test modal with query textarea and result display
mcpgateway/static/admin.js Implements modal handling, form submission, and cleanup for A2A testing
mcpgateway/services/tool_service.py Defaults tool visibility to "public" when agent visibility is unset
mcpgateway/services/a2a_service.py Wraps tool creation in try-catch to prevent agent registration failure
scripts/demo_a2a_agent.py Provides standalone demo A2A agent with calculator and weather tools
tests/unit/mcpgateway/test_issue_840_a2a_agent.py Comprehensive unit tests covering both reported issues

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Add user input field for A2A agent testing: The test button now opens
  a modal with a query input field, allowing users to send custom queries
  like `calc: 7*8` or `weather: Dallas` instead of a hardcoded message
- Fix A2A agent tools visibility: Tools created for A2A agents now default
  to `public` visibility when the agent's visibility is not set, ensuring
  they appear in the Global Tools tab
- Fix transaction handling: Commit agent BEFORE attempting tool creation
  to prevent agent loss if ToolService.register_tool calls db.rollback()
- Add error handling for tool creation during agent registration
- Add demo A2A agent script for testing
- Add unit tests for both issues
- Add integration tests using official a2a-sdk (23 tests)

Closes #840

Signed-off-by: Mihai Criveti <[email protected]>
Signed-off-by: Mihai Criveti <[email protected]>
Signed-off-by: Mihai Criveti <[email protected]>
Signed-off-by: Mihai Criveti <[email protected]>
Copy link
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.

PR #2001: fix(#840): Add user input for A2A agent testing and fix tool visibility

Overview

This PR addresses Issue #840 with the following improvements:

  1. User Input for A2A Agent Testing - The admin UI test button now opens a modal with a query input field
  2. Tool Visibility Fix - A2A agent tools now default to public visibility when agent visibility is unset
  3. Transaction Handling Fix - Agent is committed before tool creation to prevent data loss on rollback
  4. Cache Invalidation Resilience - Cache failures don't fail the request when agent is already committed
  5. Custom Agent Query Format Fix - Custom (non-JSONRPC) agents now receive flat query strings instead of JSONRPC message objects
  6. Integration Test Marker - Integration tests require --with-integration flag (opt-in)
  7. Documentation Update - Added "Local Testing" section to A2A docs

Files Changed

File Changes
mcpgateway/admin.py Added request body parsing to extract user query for A2A test endpoint
mcpgateway/services/a2a_service.py Fixed transaction handling: commit agent before tool creation; wrapped cache invalidation in try/except
mcpgateway/services/tool_service.py Default tool visibility to public when agent visibility is None; Fixed custom agent query format (pass flat strings, not JSONRPC message objects)
mcpgateway/static/admin.js Added A2A test modal with query textarea, open/close/submit handlers
mcpgateway/templates/admin.html Added A2A test modal HTML structure
pyproject.toml Added a2a-sdk[http-server] as dev dependency
scripts/demo_a2a_agent.py New demo A2A agent with calculator and weather tools
tests/unit/mcpgateway/test_issue_840_a2a_agent.py Unit tests for the feature (10 tests, including custom agent query format tests)
tests/integration/test_a2a_sdk_integration.py Integration tests using official A2A SDK (23 tests); Added pytestmark = pytest.mark.integration
tests/unit/mcpgateway/services/test_a2a_service.py Updated commit count expectation (2 → 3)
docs/docs/using/agents/a2a.md Added "Local Testing" section with demo agent, SDK samples, and Admin UI instructions

Key Implementation Details

1. User Query Extraction (admin.py)

# Parse request body to get user-provided query
default_message = "Hello from MCP Gateway Admin UI test!"
try:
    body = await request.json()
    # Use 'or' to also handle empty string queries
    user_query = (body.get("query") if body else None) or default_message
except Exception:
    user_query = default_message

2. Transaction Handling Fix (a2a_service.py)

Problem: ToolService.register_tool() calls db.rollback() on error, which would undo a pending (flushed but uncommitted) agent.

Solution: Commit agent FIRST before attempting tool creation:

db.add(new_agent)
# Commit agent FIRST to ensure it persists even if tool creation fails
db.commit()
db.refresh(new_agent)

# Cache invalidation wrapped in try/except
try:
    a2a_stats_cache.invalidate()
    # ... other invalidations
except Exception as cache_error:
    logger.warning(f"Cache invalidation failed after agent commit: {cache_error}")

# Tool creation in separate try/except
try:
    tool_db = await tool_service.create_tool_from_a2a_agent(...)
except Exception as tool_error:
    logger.warning(f"Failed to create tool for A2A agent: {tool_error}")
    db.refresh(new_agent)  # Agent still persists

3. Tool Visibility Default (tool_service.py)

# Default to "public" visibility if agent visibility is not set
# This ensures A2A tools are visible in the Global Tools Tab
tool_visibility = agent.visibility or "public"

4. Frontend Modal (admin.js)

  • Opens modal with textarea for custom query input
  • Sends query to /admin/a2a/{agent_id}/test endpoint
  • Displays response with proper XSS escaping via escapeHtml()
  • Cleanup handlers for proper modal lifecycle management

5. Custom Agent Query Format Fix (tool_service.py)

Problem: Custom (non-JSONRPC) agents were receiving queries in JSONRPC message format, causing HTTP 422 errors:

{"parameters": {"message": {"messageId": "...", "role": "user", "parts": [{"type": "text", "text": "..."}]}}}

Solution: Check agent type BEFORE formatting query. Custom agents receive flat parameters:

# Build request data based on agent type
if agent.agent_type in ["generic", "jsonrpc"] or agent.endpoint_url.endswith("/"):
    # JSONRPC agents: Convert flat query to nested message structure
    params = {"message": {"messageId": ..., "parts": [...]}}
    request_data = {"jsonrpc": "2.0", "method": method, "params": params, "id": 1}
else:
    # Custom agents: Pass parameters directly without JSONRPC message conversion
    params = parameters if isinstance(parameters, dict) else {}
    request_data = {"interaction_type": ..., "parameters": params, "protocol_version": ...}

6. Integration Test Marker (test_a2a_sdk_integration.py)

# Mark all tests in this module as integration tests
# These tests require --with-integration flag to run
pytestmark = pytest.mark.integration

Behavior:

  • Without --with-integration: 23 tests skipped
  • With --with-integration: 23 tests run

7. Documentation Update (docs/docs/using/agents/a2a.md)

Added "Local Testing" section (lines 209-308) covering:

  • Demo A2A Agent setup and usage
  • A2A SDK HelloWorld sample integration
  • Admin UI query input modal
  • Testing via MCP Tools

Security Review

Check Status
XSS Protection ✅ All output escaped with escapeHtml()
SQL Injection ✅ No database queries with user input
Command Injection ✅ No system calls with user input
Authentication ✅ Auth dependencies unchanged
Information Disclosure ✅ Errors logged internally only

Demo Script Security

  • Calculator uses safe AST evaluation (no eval())
  • JWT_SECRET reads from JWT_SECRET_KEY environment variable with fallback
  • Binds to 0.0.0.0 (acceptable for demo purposes)

Testing

Test Coverage

Test File Tests Type Flag Required
tests/unit/mcpgateway/test_issue_840_a2a_agent.py 10 Unit No
tests/integration/test_a2a_sdk_integration.py 23 Integration --with-integration
tests/unit/mcpgateway/services/test_a2a_service.py 23 Unit No
Total 56 Mixed

Unit Tests (test_issue_840_a2a_agent.py)

  • TestIssue840UserInputForA2AAgentTest (3 tests)

    • User query extraction and invocation
    • Admin endpoint signature verification
    • Custom agent parameter format
  • TestIssue840A2AToolsNotListedInGlobalTools (4 tests)

    • Tool creation from A2A agent
    • Tool listing includes A2A tools
    • Tag filtering for A2A tools
    • Integration type preservation
  • TestIssue840ToolInvocationRouting (1 test)

    • A2A tool routes to agent service
  • TestIssue840CustomAgentQueryFormat (2 tests)

    • Custom agents receive string query (not JSONRPC object)
    • JSONRPC agents receive nested message structure

Integration Tests (test_a2a_sdk_integration.py)

  • A2A SDK Server Tests: Proper agent using official a2a-sdk

    • Agent card endpoint verification
    • Message/send JSON-RPC protocol
    • Streaming response handling
  • Protocol Compliance Tests:

    • Agent card has required A2A fields
    • message/send returns Task or Message per spec
  • User Query Feature Tests:

    • Query extraction from request body
    • Default message when body empty/None/empty string
  • Transaction Handling Tests:

    • Verifies agent committed before tool creation
    • Agent survives tool creation failure
  • Tool Visibility Tests:

    • Defaults to public when agent visibility is None
    • Respects explicit visibility when set

Running Tests

# Unit tests only (33 tests)
uv run pytest tests/unit/mcpgateway/test_issue_840_a2a_agent.py \
    tests/unit/mcpgateway/services/test_a2a_service.py -v

# Integration tests (23 tests, requires flag)
uv run pytest tests/integration/test_a2a_sdk_integration.py -v --with-integration

# All PR-related tests
uv run pytest tests/unit/mcpgateway/test_issue_840_a2a_agent.py \
    tests/integration/test_a2a_sdk_integration.py \
    tests/unit/mcpgateway/services/test_a2a_service.py \
    -v --with-integration

Manual Testing

Demo A2A Agent

# Terminal 1: Start ContextForge
make dev

# Terminal 2: Start demo agent (auto-registers with ContextForge)
uv run python scripts/demo_a2a_agent.py

# Test queries via Admin UI or API:
# - "calc: 7*8" → "56"
# - "calc: 100/4+25" → "50.0"
# - "weather: Dallas" → "The weather in Dallas is sunny, 25C"

Admin UI Testing

  1. Go to http://localhost:8000/admin
  2. Click "A2A Agents" tab
  3. Find "Demo Calculator Agent" and click Test
  4. Enter query like calc: 15*4+10 in the modal
  5. Click Run Test to see response

MCP Tool Invocation

# Get token
export TOKEN=$(python -m mcpgateway.utils.create_jwt_token \
  --username [email protected] --exp 60 --secret my-test-key)

# Invoke via MCP tools/call
curl -X POST "http://localhost:8000/rpc" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
      "name": "a2a_demo-calculator-agent",
      "arguments": {"query": "calc: 99+1"}
    },
    "id": 1
  }'

A2A SDK HelloWorld Sample

# Start the official A2A sample
git clone https://github.com/google/a2a-samples.git
cd a2a-samples/samples/python/agents/helloworld
uv run python __main__.py

# Register with ContextForge
curl -X POST http://localhost:8000/a2a \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": {
      "name": "Hello World Agent",
      "endpoint_url": "http://localhost:9999/",
      "agent_type": "jsonrpc"
    },
    "visibility": "public"
  }'

Review Feedback Addressed

Finding Resolution
XSS in response display Already uses escapeHtml()
Transaction handling bug Fixed: commit agent before tool creation
Cache invalidation failure misleads callers Fixed: wrapped in try/except
Unused imports (F401) Fixed: removed with ruff
Empty query handling Fixed: empty string uses default
Demo hardcodes JWT_SECRET Fixed: reads from env var with fallback
Integration tests lack marker Fixed: added pytestmark = pytest.mark.integration
MCP tool invocation HTTP 422 for custom agents Fixed: custom agents receive flat query strings

@crivetimihai crivetimihai merged commit 2880e15 into main Jan 11, 2026
52 checks passed
@crivetimihai crivetimihai deleted the 840-a2a-agent branch January 11, 2026 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a2a Support for A2A protocol

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: For A2A Agent test not working

3 participants