Skip to content

Commit 2981c73

Browse files
committed
Add A2A service skeleton and error types
Add a skeleton for the A2A agent service: new modules src/create.rs (A2aAgentCreate) and src/read.rs (A2aAgentRead), src/errors.rs (A2AAgentError enum with thiserror-based Display tests), and src/service.rs (A2aAgentService stub with todo!() methods). Remove the placeholder main.rs and update lib.rs to register the new modules in the Python module. Also add thiserror as a dependency in the workspace and mark it in the a2a_service Cargo.toml. Provides scaffolding and tests for error handling; implementation details are left as TODOs.
1 parent edc482e commit 2981c73

File tree

9 files changed

+155
-14
lines changed

9 files changed

+155
-14
lines changed

mcpgateway_rust/Cargo.lock

Lines changed: 11 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mcpgateway_rust/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ tokio = { version = "1.49", features = ["full"] }
2828
serde = { version = "1.0", features = ["derive"] }
2929
serde_json = "1.0"
3030

31+
# Error handling
32+
thiserror = "2.0"
33+
3134
[package]
3235
name = "mcpgateway_rust"
3336
version.workspace = true

mcpgateway_rust/services/a2a_service/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ reqwest.workspace = true
1717
tokio.workspace = true
1818
serde.workspace = true
1919
serde_json.workspace = true
20+
thiserror.workspace = true
2021

2122
[dev-dependencies]
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
#[derive(Debug, Serialize, Deserialize)]
4+
pub struct A2aAgentCreate {
5+
name: String,
6+
// Other fields from schema
7+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use thiserror::Error;
2+
3+
/// Base error type for A2A agent-related errors.
4+
#[derive(Debug, Clone, PartialEq, Eq, Error)]
5+
pub enum A2AAgentError {
6+
/// Raised when a requested A2A agent is not found.
7+
#[error("A2A agent not found: {0}")]
8+
NotFound(String),
9+
10+
/// Raised when an A2A agent name conflicts with an existing one.
11+
#[error(
12+
"A2A agent name conflict: {name} (active: {is_active}, agent_id: {agent_id:?}, visibility: {visibility})"
13+
)]
14+
NameConflict {
15+
name: String,
16+
is_active: bool,
17+
agent_id: Option<String>,
18+
visibility: String,
19+
},
20+
21+
/// Generic A2A agent operation error.
22+
#[error("A2A agent error: {0}")]
23+
Operation(String),
24+
25+
/// Permission denied error.
26+
#[error("Permission denied: {0}")]
27+
PermissionDenied(String),
28+
29+
/// Invalid value error.
30+
#[error("Invalid value: {0}")]
31+
ValueError(String),
32+
}
33+
34+
#[cfg(test)]
35+
mod tests {
36+
use super::*;
37+
38+
#[test]
39+
fn test_not_found_error_display() {
40+
let error = A2AAgentError::NotFound("agent-123".to_string());
41+
assert_eq!(error.to_string(), "A2A agent not found: agent-123");
42+
}
43+
44+
#[test]
45+
fn test_name_conflict_error_display() {
46+
let error = A2AAgentError::NameConflict {
47+
name: "test-agent".to_string(),
48+
is_active: true,
49+
agent_id: Some("agent-456".to_string()),
50+
visibility: "public".to_string(),
51+
};
52+
assert_eq!(
53+
error.to_string(),
54+
"A2A agent name conflict: test-agent (active: true, agent_id: Some(\"agent-456\"), visibility: public)"
55+
);
56+
}
57+
58+
#[test]
59+
fn test_operation_error_display() {
60+
let error = A2AAgentError::Operation("Failed to invoke agent".to_string());
61+
assert_eq!(error.to_string(), "A2A agent error: Failed to invoke agent");
62+
}
63+
64+
#[test]
65+
fn test_permission_denied_error_display() {
66+
let error =
67+
A2AAgentError::PermissionDenied("Only the owner can delete this agent".to_string());
68+
assert_eq!(
69+
error.to_string(),
70+
"Permission denied: Only the owner can delete this agent"
71+
);
72+
}
73+
74+
#[test]
75+
fn test_value_error_display() {
76+
let error = A2AAgentError::ValueError("Invalid passthrough_headers format".to_string());
77+
assert_eq!(
78+
error.to_string(),
79+
"Invalid value: Invalid passthrough_headers format"
80+
);
81+
}
82+
}
83+
84+
// Made with Bob

mcpgateway_rust/services/a2a_service/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@
44
// A2A Service - High-performance agent invocation with PyO3 bindings
55
//
66
// This module provides Rust-accelerated HTTP invocation for A2A agents,
7-
// offering 10-50x performance improvements over Python asyncio/httpx.
7+
// offering TODO: performance improvements over Python asyncio/httpx.
88

99
use pyo3::prelude::*;
1010

11+
mod create;
12+
mod errors;
13+
mod read;
14+
mod service;
15+
1116
/// A2A Service module
1217
#[pymodule]
1318
pub fn a2a_service(m: &Bound<'_, PyModule>) -> PyResult<()> {

mcpgateway_rust/services/a2a_service/src/main.rs

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
#[derive(Debug, Serialize, Deserialize)]
4+
pub struct A2aAgentRead {
5+
id: String,
6+
name: String,
7+
// Other fields
8+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use super::create::A2aAgentCreate;
2+
use super::errors::A2AAgentError;
3+
use super::read::A2aAgentRead;
4+
5+
struct A2aAgentService {
6+
initialized: bool,
7+
// Add event_streams: Vec<...> if needed
8+
}
9+
10+
impl A2aAgentService {
11+
pub fn new() -> Self {
12+
todo!()
13+
}
14+
15+
pub async fn initialize(&mut self) {
16+
todo!()
17+
}
18+
19+
pub async fn shutdown(&mut self) {
20+
todo!()
21+
}
22+
23+
pub async fn register_agent(
24+
&self,
25+
// db?
26+
agent_data: A2aAgentCreate,
27+
// Other optional args
28+
) -> Result<A2aAgentRead, A2AAgentError> {
29+
todo!()
30+
}
31+
32+
// TODO: Implement other methods similarly: list, get, update, delete, etc.
33+
// For visibility filters, use SQL WHERE clauses in queries.
34+
// For batch ops, use sqlx batches.
35+
}

0 commit comments

Comments
 (0)