Skip to content

Add MCP resource support to MCPClient #4284

@bnovik0v

Description

@bnovik0v

Summary

The MCP specification defines resources as read-only data exposed by MCP servers (files, database records, application state, real-time signals, etc.). Currently, MCPClient only supports tools — there is no way to list or read resources from an MCP server.

Motivation

Resources are a core MCP primitive alongside tools and prompts. Common use cases for voice/multimodal agents:

  • Device state — current song playing, application open, sensor readings
  • User context — profile data, preferences, session history
  • Knowledge bases — documents, FAQs, product catalogs injected into the system prompt
  • Real-time signals — IoT data, monitoring dashboards, live metrics

Without resource support, users who need this functionality have to bypass MCPClient entirely and use the raw mcp SDK to manage their own sessions — losing the benefits of Pipecat's persistent session management.

Proposed API

Add three methods to MCPClient, following the same patterns as the existing tool methods:

async with MCPClient(server_params=...) as mcp:
    # List available resources (metadata only)
    resource_list = await mcp.list_resources()
    # resource_list.resources -> List[MCPResource]
    # resource_list.supports_subscribe -> bool
    # resource_list.supports_list_changed -> bool

    # Read a specific resource
    resource = await mcp.read_resource("file:///config.json")
    # resource.text or resource.blob

    # Convenience: list + read all
    all_resources = await mcp.read_all_resources()

New dataclasses:

  • MCPResource — uri, name, description, mime_type, text, blob
  • MCPResourceList — resources list + server capability flags

Design Notes

  • Resources are data, not actions — they don't need LLM registration (unlike tools)
  • Reuses the existing persistent session from start()/close() (PR fixed MCPClient to reuse session across tool calls #4034)
  • Server capability flags (subscribe, listChanged) are exposed so users can build polling or subscription logic on top
  • Individual read failures in read_all_resources() are logged and skipped gracefully
  • Polling, context injection, and subscriptions are intentionally left out of scope — those are application-level concerns

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions