Skip to content

Support WIT resource types in MCP tool calls #601

Description

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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