Skip to content

DON'T MERGE : [DEMO: e2e mcp flow testing in wasmcloud environment]#4

Draft
Aditya1404Sal wants to merge 1 commit intobettyblocks:mainfrom
Aditya1404Sal:mcp-testing-full
Draft

DON'T MERGE : [DEMO: e2e mcp flow testing in wasmcloud environment]#4
Aditya1404Sal wants to merge 1 commit intobettyblocks:mainfrom
Aditya1404Sal:mcp-testing-full

Conversation

@Aditya1404Sal
Copy link

@Aditya1404Sal Aditya1404Sal commented Feb 3, 2026

Tests Betty-mcp-component, Jwt-auth-component and mock-actions-component in a singular workload

  • loads ConfigMap that can be read using wasi:config/store.get_all
  • passes environment variables to betty-mcp-component, which can be read by the jwt-auth function
  • all tests pass, However it's to be noted that crates/wash-runtime/src/engine/workload.rs needed to be modified for enabling the multi-component setup (before the fix: mcp -> jwt worked, however in the same flow mcp -> actions failed)

Notes for team & future me :

  1. Env variable 101 :
    in a multicomponent setup, the environment variables are to be loaded into the component that acts as the main export
    in our mcp->(jwt,actions) setup the main entry point is the mcp component's http-incoming.handle.
    if we load the environment variables into the localresources of the secondary components, they will not link/load

Reference:

WorkloadStartRequest {
        workload_id: uuid::Uuid::new_v4().to_string(),
        workload: Workload {
            namespace: "test".to_string(),
            name: "mcp-workload".to_string(),
            annotations: HashMap::new(),
            service: None,
            components: vec![
                // Betty MCP Component - imports auth/jwt and actions, exports HTTP handler
                Component {
                    bytes: bytes::Bytes::from_static(BETTY_MCP_COMPONENT_WASM), // We load them here
                    local_resources: LocalResources {
                        memory_limit_mb: 256,
                        cpu_limit: 1,
                        config: HashMap::from([(
                            "mcp_servers".to_string(),
                            mcp_servers_config_json(),
                        )]),
                        environment: HashMap::from([
                            ("JWT_PUBLIC_KEY".to_string(), public_key_pem.to_string()),
                            ("JWT_ISSUER".to_string(), "Joken".to_string()),
                            ("JWT_AUDIENCE".to_string(), "Joken".to_string()),
                        ]),
                        volume_mounts: vec![],
                        allowed_hosts: vec![],
                    },
                    pool_size: 1,
                    max_invocations: 100,
                },
                // JWT Auth Component - exports betty-blocks:auth/jwt
                Component {
                    bytes: bytes::Bytes::from_static(JWT_AUTH_COMPONENT_WASM),
                    local_resources: LocalResources {
                        memory_limit_mb: 128,
                        cpu_limit: 1,
                        config: HashMap::new(),
                        environment: HashMap::new(),
                        volume_mounts: vec![],
                        allowed_hosts: vec![],
                    },
                    pool_size: 1,
                    max_invocations: 100,
                },
                // Mock Actions Component - exports betty-blocks:actions/actions
                Component {
                    bytes: bytes::Bytes::from_static(MOCK_ACTIONS_WASM),
                    local_resources: LocalResources {
                        memory_limit_mb: 128,
                        cpu_limit: 1,
                        config: HashMap::new(),
                        environment: HashMap::new(),
                        volume_mounts: vec![],
                        allowed_hosts: vec![],
                    },
                    pool_size: 1,
                    max_invocations: 100,
                },
            ],
            host_interfaces: mcp_host_interfaces(http_host_config, public_key_pem.to_string()),
            volumes: vec![],
        },
    }
  1. Wasi config 101:
    for loading the config k-v into our workload, the config is NOT passed to per-component localresources.config
    it's instead supposed to be passed to the wasi:config WitInterface present in host_interfaces as a config, where it acts as a global cofig store accessible by all the components in your workload.

reference :

fn mcp_servers_config_json() -> String {
    serde_json::json!({
        "mcp-servers": [
            {
                "id": "weather-server-001",
                "tools": [
                    {
                        "action-id": "action-weather-get",
                        "name": "get_weather",
                        "description": "Gets weather for a location",
                        "inputSchema": {
                            "type": "object",
                            "properties": {
                                "location": {
                                    "type": "string",
                                    "description": "City and province"
                                }
                            },
                            "required": ["location"]
                        }
                    }
                ]
            },
            {
                "id": "calculator-server-001",
                "tools": [
                    {
                        "action-id": "action-calc-add",
                        "name": "add_numbers",
                        "description": "Adds two numbers together",
                        "inputSchema": {
                            "type": "object",
                            "properties": {
                                "a": { "type": "number", "description": "First number" },
                                "b": { "type": "number", "description": "Second number" }
                            },
                            "required": ["a", "b"]
                        }
                    }
                ]
            }
        ]
    })
    .to_string()
}

// Config store
        WitInterface {
            namespace: "wasi".to_string(),
            package: "config".to_string(),
            interfaces: ["store".to_string()].into_iter().collect(),
            version: Some(semver::Version::parse("0.2.0-rc.1").unwrap()),
            config: HashMap::from([("mcp_servers".to_string(), mcp_servers_config_json())]),
        },

Signed-off-by: Aditya <aditya.salunkh919@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.

1 participant