Skip to content

Latest commit

 

History

History
127 lines (93 loc) · 5.58 KB

File metadata and controls

127 lines (93 loc) · 5.58 KB

MCP Resources Refactor Analysis (Implementation-Focused, Minimal, Extensible)

Goals

  • Keep the low-level Server API (no McpServer registry).
  • Preserve current resource behavior (Skyfire readme + OpenAI widgets).
  • Make the implementation easy to extend without extra abstractions.
  • Keep changes minimal and localized.
  • Do not add new resources or templates in this phase.

Current State (Summary)

  • Resource handlers are thin and delegate to createResourceService.
  • Resource service lives in src/resources/resource_service.ts.
  • Widget registry lives in src/resources/widgets.ts.
  • Supported resources:
    • file://readme.md (Skyfire usage guide, gated by skyfireMode)
    • ui://widget/* (OpenAI UI widgets, gated by uiMode === "openai")
  • Templates are not exposed (ListResourceTemplatesRequestSchema returns empty list).

Implementation (Current, Behavior-Preserving)

1. Minimal Resource Service

Create a single service module that owns list/read/templates logic and keeps handlers thin.

Location:

  • src/resources/resource_service.ts

API:

  • listResources(): Promise<ListResourcesResult>
  • readResource(uri: string): Promise<ReadResourceResult> (extended to include html for widgets)
  • listResourceTemplates(): Promise<ListResourceTemplatesResult> (empty for now)

2. Thin MCP Handlers

ActorsMcpServer.setupResourceHandlers delegates directly:

  • ListResourcesRequestSchemaresourceService.listResources()
  • ReadResourceRequestSchemaresourceService.readResource(uri)
  • ListResourceTemplatesRequestSchemaresourceService.listResourceTemplates()

3. Behavior Preservation

  • Skyfire readme only when skyfireMode is true.
  • Widgets only when uiMode === "openai" and the widget file exists.
  • Read failures return plain-text content (no throw).

Extension Points (Future-Friendly, Not Implemented Now)

  • Add new resource types by extending resource_service.ts.
  • Add resource templates by returning non-empty resourceTemplates.
  • Add subscriptions/notifications by layering a small subscription manager in the service.

Non-Goals

  • No new resource types or templates.
  • No change to low-level Server usage.
  • No behavior changes for current clients.

Implementation Notes (Simplicity + Extensibility)

  • Use MCP SDK types (Resource, ListResourcesResult, ReadResourceResult) for clarity.
  • Keep widget metadata in _meta with OpenAI keys as-is.
  • Keep service synchronous where possible and avoid extra indirection.

Reference Implementations and Patterns

Official MCP TypeScript SDK (High-Level McpServer)

The official SDK’s conformance server (/home/jirka/github/typescript-sdk/src/conformance/everything-server.ts) uses McpServer.registerResource and ResourceTemplate. The SDK’s high-level server owns:

  • Resource registry (static and template resources)
  • resources/list, resources/read, and resources/templates/list handlers
  • Template matching and completion

This is a different abstraction layer than the low-level Server we use here, so the registry and handlers are not available to reuse.

FastMCP

FastMCP is also built on the low-level Server but provides its own registry layer:

  • Maintains internal maps: #resources and #resourceTemplates
  • Registers low-level handlers:
    • ListResourcesRequestSchema returns the cached list from the map
    • ReadResourceRequestSchema loads a direct resource or resolves a template
    • ListResourceTemplatesRequestSchema returns templates (if present)
  • Exposes convenience methods: addResource, addResources, addResourceTemplate, removeResource, etc.
  • Handles template matching via parseURITemplate

There is no ResourceProvider abstraction. FastMCP centralizes list/read logic in one place and uses an internal registry to keep handlers simple.

Is a ResourceProvider Interface Required?

No. A provider interface is optional and not part of MCP or the official SDK. Given the current scope, a single minimal resource service (like a small registry) keeps the code shortest and easiest to follow. Add a provider interface only if the number of resource types grows enough to justify the extra indirection.

MCP Resources Spec Highlights (2025-11-25)

Capabilities

  • Servers that support resources must declare capabilities.resources.
  • Optional flags:
    • subscribe: server supports resources/subscribe and update notifications.
    • listChanged: server emits notifications/resources/list_changed.

Core Methods

  • resources/list supports pagination and returns resources plus optional nextCursor.
  • resources/read returns contents containing text or binary resource blocks.
  • resources/templates/list returns URI templates for parameterized resources.

Notifications

  • notifications/resources/list_changed when the list changes.
  • notifications/resources/updated for subscribed resources.

Resource Shapes

  • Resource fields: uri, name, optional title, description, icons, mimeType, size.
  • ResourceContent contains either text or blob (base64), plus uri and mimeType.
  • Optional annotations: audience, priority, lastModified.

URI Schemes

  • https://: only when client can fetch directly.
  • file://: filesystem-like resources (virtual or real).
  • git://: version control resources.
  • Custom schemes must follow RFC 3986.

Errors

  • Resource not found: -32002
  • Internal error: -32603

References

  • Official MCP TypeScript SDK: /home/jirka/github/typescript-sdk
  • Example server implementing full MCP specs: /home/jirka/github/servers/src/everything
  • FastMCP: /home/jirka/github/fastmcp