Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions includes/Handlers/Resources/ResourcesHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ function ( $item ) use ( $uri ) {
private function create_content_dto( array $item, string $default_uri ) {
$item_uri = $item['uri'] ?? $default_uri;
$mime_type = $item['mimeType'] ?? null;
$meta = isset( $item['_meta'] ) && is_array( $item['_meta'] ) ? $item['_meta'] : null;

// If there's blob data, create BlobResourceContents.
if ( isset( $item['blob'] ) ) {
Expand All @@ -286,6 +287,7 @@ private function create_content_dto( array $item, string $default_uri ) {
'uri' => $item_uri,
'blob' => (string) $item['blob'],
'mimeType' => is_string( $mime_type ) ? $mime_type : null,
'_meta' => $meta,
)
);
}
Expand All @@ -298,6 +300,7 @@ private function create_content_dto( array $item, string $default_uri ) {
'uri' => $item_uri,
'text' => (string) $text,
'mimeType' => is_string( $mime_type ) ? $mime_type : null,
'_meta' => $meta,
)
);
}
Expand Down
60 changes: 60 additions & 0 deletions tests/phpunit/Fixtures/DummyAbility.php
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,66 @@ public static function register_abilities(): void {
)
);

// Resource returning text content with _meta.
wp_register_ability(
'test/resource-text-with-meta',
array(
'label' => 'Resource Text With Meta',
'description' => 'A resource returning text content with _meta',
'category' => 'test',
'execute_callback' => static function () {
return array(
array(
'uri' => 'WordPress://local/resource-text-with-meta',
'text' => 'hello meta',
'mimeType' => 'text/plain',
'_meta' => array( 'ui' => array( 'prefersBorder' => true ) ),
),
);
},
'permission_callback' => static function () {
return true;
},
'meta' => array(
'mcp' => array(
'public' => true,
'type' => 'resource',
'uri' => 'WordPress://local/resource-text-with-meta',
),
),
)
);

// Resource returning blob content with _meta.
wp_register_ability(
'test/resource-blob-with-meta',
array(
'label' => 'Resource Blob With Meta',
'description' => 'A resource returning blob content with _meta',
'category' => 'test',
'execute_callback' => static function () {
return array(
array(
'uri' => 'WordPress://local/resource-blob-with-meta',
'blob' => base64_encode( 'binary-with-meta' ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
'mimeType' => 'application/octet-stream',
'_meta' => array( 'checksum' => 'abc123' ),
),
);
},
'permission_callback' => static function () {
return true;
},
'meta' => array(
'mcp' => array(
'public' => true,
'type' => 'resource',
'uri' => 'WordPress://local/resource-blob-with-meta',
),
),
)
);

// =========================================================================
// Prompt Icons and _meta Test Abilities (MCP 2025-11-25)
// =========================================================================
Expand Down
2 changes: 2 additions & 0 deletions tests/phpunit/Unit/Core/McpAdapterConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ static function ( $defaults ) use ( &$received_config ) {
'test/resource-multiple-contents',
'test/resource-text-with-mimetype',
'test/resource-plain-string',
'test/resource-text-with-meta',
'test/resource-blob-with-meta',
),
$received_config['resources']
);
Expand Down
46 changes: 46 additions & 0 deletions tests/phpunit/Unit/Handlers/ResourcesHandlerReadTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,50 @@ public function test_read_resource_with_throwing_result_filter_triggers_catch_bl

remove_filter( 'mcp_adapter_resource_read_result', $filter );
}

public function test_read_resource_preserves_meta_on_text_content(): void {
wp_set_current_user( 1 );

$server = $this->makeServer( array(), array( 'test/resource-text-with-meta' ) );
$handler = new ResourcesHandler( $server );

$result = $handler->read_resource(
array( 'params' => array( 'uri' => 'WordPress://local/resource-text-with-meta' ) )
);

$this->assertInstanceOf( ReadResourceResult::class, $result );

$contents = $result->getContents();
$this->assertNotEmpty( $contents );
$this->assertInstanceOf( TextResourceContents::class, $contents[0] );

// Verify _meta is preserved end-to-end.
$meta = $contents[0]->get_meta();
$this->assertIsArray( $meta, '_meta should be an array, not null.' );
$this->assertArrayHasKey( 'ui', $meta );
$this->assertTrue( $meta['ui']['prefersBorder'] );
}

public function test_read_resource_preserves_meta_on_blob_content(): void {
wp_set_current_user( 1 );

$server = $this->makeServer( array(), array( 'test/resource-blob-with-meta' ) );
$handler = new ResourcesHandler( $server );

$result = $handler->read_resource(
array( 'params' => array( 'uri' => 'WordPress://local/resource-blob-with-meta' ) )
);

$this->assertInstanceOf( ReadResourceResult::class, $result );

$contents = $result->getContents();
$this->assertNotEmpty( $contents );
$this->assertInstanceOf( BlobResourceContents::class, $contents[0] );

// Verify _meta is preserved end-to-end.
$meta = $contents[0]->get_meta();
$this->assertIsArray( $meta, '_meta should be an array, not null.' );
$this->assertArrayHasKey( 'checksum', $meta );
$this->assertSame( 'abc123', $meta['checksum'] );
}
}
Loading