> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dedaluslabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Resources

> List and read resources from MCP servers

Resources are **read-only data** exposed by the server. A resource might be a file, a generated report, or any other content the server can provide without side effects.

## List resources

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from dedalus_mcp.client import open_connection

async with open_connection("http://127.0.0.1:8000/mcp") as client:
    resources = await client.list_resources()

    for r in resources.resources:
        print(f"{r.uri}: {r.name}")
```

## Resource schema

Each resource includes:

| Field         | Type          | Description                                        |
| ------------- | ------------- | -------------------------------------------------- |
| `uri`         | `str`         | Resource identifier (e.g. `resource://config/app`) |
| `name`        | `str`         | Human-readable name                                |
| `description` | `str \| None` | What the resource contains                         |
| `mimeType`    | `str \| None` | Content type (e.g. `application/json`)             |

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
for r in resources.resources:
    print(f"URI: {r.uri}")
    print(f"Name: {r.name}")
    print(f"Type: {r.mimeType}")
```

## Read resources

Read a specific resource by URI:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
result = await client.read_resource("resource://config/app")
```

`result` is a `ReadResourceResult` with a `contents` list. It can contain `TextResourceContents` (text) or `BlobResourceContents` (base64 blob).

## Response structure (text vs binary)

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import base64
from dedalus_mcp import types

result = await client.read_resource("resource://data/report")

if not result.contents:
    print("No contents (resource missing or empty)")
else:
    item = result.contents[0]

    if isinstance(item, types.TextResourceContents):
        print(item.text)

    elif isinstance(item, types.BlobResourceContents):
        data = base64.b64decode(item.blob)  # blob is base64 text
        with open("output.bin", "wb") as f:
            f.write(data)
```

## Example: Configuration reader

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import json
from dedalus_mcp.client import open_connection
from dedalus_mcp import types

async with open_connection("http://127.0.0.1:8000/mcp") as client:
    resources = await client.list_resources()
    print("Available resources:")
    for r in resources.resources:
        print(f"  - {r.uri} ({r.mimeType})")

    result = await client.read_resource("resource://config/app")
    if not result.contents or not isinstance(result.contents[0], types.TextResourceContents):
        raise RuntimeError("Expected text config resource")

    data = json.loads(result.contents[0].text)
    print(f"App config: {data}")
```

## Resource templates

Resource templates are just "patterns" a server can publish (like `resource://users/{user_id}`) to show what kinds of resource URLs exist. They don't automatically create resources. To read something, you still call `read_resource(...)` with a real URL (like `resource://users/123`), and it only works if the server actually serves that exact URI.

## Context manager

Again, `open_connection(...)` is an async context manager. It means you don't have to remember to call await `client.close()`. When the async with block exits, it automatically closes the underlying connection for you.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from dedalus_mcp.client import open_connection

async with open_connection("http://127.0.0.1:8000/mcp") as client:
    resources = await client.list_resources()
    result = await client.read_resource("resource://docs/readme")
```
