Skip to content

Support WIT resource types in MCP tool calls #601

@JMLX42

Description

@JMLX42

Problem

Currently, component2json does not support WIT resource types through MCP:

  • Outputs: Resources serialize to debug strings ("resource: {res:?}") — not usable handles
  • Inputs: Explicitly rejected with Err(ValError::ResourceError)

This prevents components from exposing interfaces like wasi:filesystem where operations return and accept descriptor resources.

Use Case

We want to build a storage component that exports wasi:filesystem so agents can:

open("/data/file.txt") -> descriptor(3)
read(descriptor(3), 1024) -> bytes
close(descriptor(3))

Without resource support, we must define custom wrapper interfaces that avoid resources entirely — defeating the goal of reusing standard WASI interfaces.

Proposed Solution

Serialize resources as integer handles that remain valid within a session:

Schema generation:

Type::Own(r) | Type::Borrow(r) => json!({
    "type": "integer",
    "description": format!("Handle to resource: {}", resource_name(r))
})

Output conversion:

// When component returns a resource, allocate a handle ID
Val::Resource(res) => {
    let handle_id = resource_table.insert(res);
    json!(handle_id)
}

Input conversion:

// When MCP passes an integer for a resource param, look up the handle
(Type::Own(_) | Type::Borrow(_), Value::Number(n)) => {
    let handle_id = n.as_u64().ok_or(ValError::InvalidHandle)?;
    let res = resource_table.get(handle_id).ok_or(ValError::HandleNotFound)?;
    Ok(Val::Resource(res))
}

Resource Lifecycle

  • Handles are scoped to the component instance (each agent session has isolated handles)
  • drop resource calls remove from table
  • Optional: auto-cleanup on session end

Alternatives Considered

  1. Custom wrapper interfaces — Works but forces every component to reimplement path-based wrappers instead of using standard WASI interfaces
  2. String-encoded handles — Possible but integers are cleaner and match how file descriptors work

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestrustPull requests that update rust code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions