Skip to main content

Resources and Prompts

6.1 Resources in Detail

Resources allow Servers to expose data to AI applications. The distinction from Tools:
ToolsResources
NatureExecute operationsProvide data
Controlled byAI model decides to invokeApplication (Host) actively reads
Side effectsPossible (write to DB, call API)None (read-only)
Scenario”Check inventory for me""Here is the product category structure”

Resource URIs

Each resource has a unique URI identifier:
commerce://catalog/categories     # Product categories
commerce://store/info             # Store information
file:///path/to/config.json       # Local file
https://api.example.com/data      # Remote data

URI Templates (RFC 6570)

MCP supports RFC 6570 URI template syntax for defining dynamic resources. Servers can include URI templates in resources/list responses, and Clients fill in template variables to request specific resources:
{
  "uriTemplate": "commerce://products/{sku}",
  "name": "Product Details",
  "description": "Get detailed information for a specific product by SKU",
  "mimeType": "application/json"
}
Common URI template patterns:
commerce://products/{sku}              # Single product
commerce://orders/{orderId}/items      # Order line items
commerce://categories/{categoryId}     # Category details
commerce://inventory/{sku}/{warehouse} # Inventory for a specific warehouse
Client usage with filled variables:
{
  "method": "resources/read",
  "params": {
    "uri": "commerce://products/SHOE-001"
  }
}

Annotations

Each resource can carry Annotations metadata to help the Host decide how to use the resource:
{
  "uri": "commerce://catalog/categories",
  "name": "Product Categories",
  "description": "Complete product category hierarchy",
  "mimeType": "application/json",
  "annotations": {
    "audience": ["user", "assistant"],
    "priority": 0.8,
    "lastModified": "2026-04-10T08:00:00Z"
  }
}
Annotations field descriptions:
FieldTypeDescription
audienceString arrayTarget audience. "user" means suitable for display to users; "assistant" means suitable for the AI model
priorityNumber (0-1)Priority. 1 is highest. The Host can use this to decide which resources to load first when context window space is limited
lastModifiedISO 8601 stringLast modified time. Helps the Client decide whether to re-read

Resource Subscriptions

If the Server declares resources: { subscribe: true } during initialization, the Client can subscribe to resource changes:
// Client -> Server: subscribe to resource
{
  "method": "resources/subscribe",
  "params": { "uri": "commerce://inventory/SHOE-001" }
}

// Server -> Client: resource content change notification
{
  "method": "notifications/resources/updated",
  "params": { "uri": "commerce://inventory/SHOE-001" }
}
Upon receiving the notification, the Client re-calls resources/read to get the latest data. This pattern suits scenarios with high real-time requirements, such as inventory monitoring. To unsubscribe:
{
  "method": "resources/unsubscribe",
  "params": { "uri": "commerce://inventory/SHOE-001" }
}

Resource List Change Notifications

When the Server’s resource collection changes (resources added or removed), it can notify the Client:
{ "method": "notifications/resources/list_changed" }
The Client then re-calls resources/list to get the latest resource list.

Implementation Example

// Static resource
server.resource(
  "commerce://catalog/categories",
  "Product Categories",
  "application/json",
  async () => {
    const categories = await db.categories.getAll();
    return JSON.stringify(categories, null, 2);
  }
);

// Dynamic resource (URI template)
server.resource(
  "commerce://products/{sku}",
  "Product Details",
  "application/json",
  async (uri) => {
    const sku = uri.pathname.split("/").pop();
    const product = await db.products.findBySku(sku);
    if (!product) throw new Error(`Product ${sku} not found`);
    return JSON.stringify(product, null, 2);
  }
);

6.2 Prompts in Detail

Prompts are predefined interaction templates provided by the Server. Unlike Tools and Resources, Prompts are user-controlled — users actively select which template to use in the Host application.

Prompt Structure

{
  "name": "product_comparison",
  "description": "Compare the pros and cons of two products",
  "arguments": [
    { "name": "product1", "description": "First product SKU", "required": true },
    { "name": "product2", "description": "Second product SKU", "required": true },
    { "name": "focus", "description": "Focus dimension (price/performance/reviews)", "required": false }
  ]
}

Getting a Prompt (with Arguments)

// Client -> Server
{
  "method": "prompts/get",
  "params": {
    "name": "product_comparison",
    "arguments": {
      "product1": "SHOE-001",
      "product2": "SHOE-002",
      "focus": "value for money"
    }
  }
}

// Server -> Client
{
  "result": {
    "messages": [
      {
        "role": "user",
        "content": {
          "type": "text",
          "text": "Please compare the following products from a value-for-money perspective:\n\nProduct 1: Nike Air Max (SHOE-001) - $89.90\nProduct 2: Adidas Ultra Boost (SHOE-002) - $129.90\n\nAnalyze the pros and cons of each and provide a purchase recommendation."
        }
      }
    ]
  }
}

Commerce Prompt Examples

// Product comparison
server.prompt(
  "product_comparison",
  "Compare the pros and cons of two products",
  [
    { name: "product1", description: "First product SKU", required: true },
    { name: "product2", description: "Second product SKU", required: true }
  ],
  async ({ product1, product2 }) => {
    const p1 = await db.products.findBySku(product1);
    const p2 = await db.products.findBySku(product2);
    return {
      messages: [{
        role: "user",
        content: {
          type: "text",
          text: `Please compare the following two products:\n\nProduct 1: ${JSON.stringify(p1)}\n\nProduct 2: ${JSON.stringify(p2)}\n\nAnalyze from three dimensions: price, features, and reviews.`
        }
      }]
    };
  }
);

// Order summary
server.prompt(
  "order_summary",
  "Generate a summary report of a user's orders",
  [
    { name: "userId", description: "User ID", required: true },
    { name: "period", description: "Time range (e.g. last_month)", required: false }
  ],
  async ({ userId, period = "last_month" }) => {
    const orders = await db.orders.getByUser(userId, period);
    return {
      messages: [{
        role: "user",
        content: {
          type: "text",
          text: `Here is the user's recent order data:\n\n${JSON.stringify(orders, null, 2)}\n\nPlease generate a concise spending summary including total spending, frequently purchased categories, and spending trends.`
        }
      }]
    };
  }
);

Multi-Message Prompts

Prompts can return multiple messages, including the system role:
server.prompt(
  "customer_service",
  "Activate customer service assistant mode",
  [],
  async () => {
    const policies = await db.policies.getAll();
    return {
      messages: [
        {
          role: "assistant",
          content: {
            type: "text",
            text: `You are a professional customer service assistant. Here are the store policies:\n\n${JSON.stringify(policies)}\n\nAlways answer user questions based on these policies.`
          }
        }
      ]
    };
  }
);

Prompts with Embedded Resources

Messages in Prompts can use the embedded_resource type to embed resource data:
server.prompt(
  "analyze_catalog",
  "Analyze the product catalog structure",
  [],
  async () => {
    return {
      messages: [{
        role: "user",
        content: {
          type: "resource",
          resource: {
            uri: "commerce://catalog/categories",
            mimeType: "application/json",
            text: await db.categories.getJsonString()
          }
        }
      }]
    };
  }
);

When to Use Prompt vs Tool vs Resource

ScenarioRecommendationReason
Fixed interaction patternsPromptTemplated, user-selectable
Dynamic operationsToolAI model decides autonomously
Requires specific question formatPromptControls input quality
Requires executing an actionToolPrompts only provide templates
Static context dataResourceNo side effects, Host controls read timing
High-priority background informationResource + Annotationspriority field controls loading priority

Next Chapter: Security and Authentication — OAuth 2.1 integration and permission management