{
  "schema_version": 2,
  "id": "develop/ai/context-engine/agent-playbooks/mcp",
  "title": "Connect with MCP",
  "url": "https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/mcp/",
  "summary": "Connect an MCP client, discover published knowledge, and load skill instructions and files.",
  "tags": [
    "docs",
    "develop",
    "ai"
  ],
  "last_updated": "2026-11-02T15:54:35-08:00",
  "page_type": "content",
  "content_hash": "94db47634fa030f918c5edd039351b4649697becd75765f90dcf30d7e3962d40",
  "sections": [
    {
      "id": "code-examples",
      "title": "Code examples",
      "role": "example",
      "text": "These examples connect to Iris services using SDKs or HTTP requests with curl. Follow one language throughout each walkthrough.\n\n\nConnect a Streamable HTTP MCP client to retrieve published FAQs and skill content. Redis Agent Playbooks expose three tools and standard skill resources. For framework examples that retrieve context before a model turn, see [Integrate with an agent](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/agent-integration)."
    },
    {
      "id": "before-you-begin",
      "title": "Before you begin",
      "role": "content",
      "text": "Get the data-plane endpoint, playbook identifier, and an API key with `read` permission. Save and load the `IRIS_AGENT_PLAYBOOKS_*` variables as shown in [Connect to the playbook](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/quickstart#connect-to-the-playbook).\n\nPublish the sample [FAQ](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/quickstart) or [skill](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/manage-skills) to test discovery. The basic clients use no model-provider key.\n\nFor the Python client, use Python 3.10 or later and install these dependencies:\n\n**Python**\n\n[code example]\n\n**HTTP**\n\n[code example]"
    },
    {
      "id": "configure-the-connection",
      "title": "Configure the connection",
      "role": "configuration",
      "text": "Use a client that supports Streamable HTTP and custom request headers:\n\n| Setting | Value |\n|:--------|:------|\n| Transport | Streamable HTTP |\n| Endpoint | `<data-plane-base-url>/iris/data/v1/agent-playbooks/playbooks/<playbook-id>/mcp` |\n| Request header | `Authorization: Bearer <reader-api-key>` |\n\nThe endpoint must be reachable from the client runtime. A hosted client needs an HTTPS endpoint reachable from its provider; a local address works for clients on the same host. Keep the playbook key in connection settings and out of agent instructions."
    },
    {
      "id": "use-the-tools",
      "title": "Use the tools",
      "role": "content",
      "text": "Call `tools/list` on an initialized connection to get the input schemas. MCP tool arguments use different names from some HTTP request fields:\n\n| Tool | Input | Result |\n|:-----|:------|:-------|\n| `discover_entries` | Required `query`; optional `filter`, `pinned_entries`, and `limit`. Each pin uses exactly one `entry_id` or `entry_key`. | Published FAQ answers and skill previews, including identifiers and versions. |\n| `load_skill` | The selected skill's `entry_id` and `version`. | Full instructions and resource descriptors. |\n| `fetch_resource` | A returned resource `uri`. | File content, media type, and digest. |\n\n![Discovery returns FAQ answers and skill previews. Loading a selected skill adds its instructions to the context. Fetching a resource adds only the file needed for the task.](https://redis.io/docs/latest/images/ai/context-engine/agent-playbook-disclosure.svg)\n\nUse the tools in this order:\n\n1. Discover knowledge for the task. Use an applicable FAQ answer directly.\n2. Select a skill preview, then load its instructions with the returned identifier and version together.\n3. Fetch supporting files when the instructions or task require them, using their returned URIs.\n\nSee [Discovery](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/retrieval#discovery) for selection controls. Progressive disclosure loads **skill content** on demand; these three tool definitions remain available on the connection."
    },
    {
      "id": "connect-a-client",
      "title": "Connect a client",
      "role": "content",
      "text": "This client connects, lists tools, and prints discovery results for a refund task. For an agent that selects a skill and loads its instructions and files, see [the framework examples](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/agent-integration).\n\nCopy the complete program and save it as `mcp_client.py` or `mcp_client.sh`. Run `python mcp_client.py` or `bash mcp_client.sh` with the connection values you exported.\n\n**Available in:** Python (Iris), cURL (Iris)\n\n##### Python (Iris)\n\n[code example]\n\n##### cURL (Iris)\n\n[code example]\n\n\n\nExpect the three tool names followed by the discovery response as JSON. It includes matching FAQ answers and skill previews. Empty `pinnedEntries` and `discoveredEntries` arrays can reflect the query, publication, filters, or [preview budget](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/retrieval#limit-discovery-previews). A request or tool error stops the program with an error."
    },
    {
      "id": "read-skill-files-as-mcp-resources",
      "title": "Read skill files as MCP resources",
      "role": "content",
      "text": "Clients can also read published skill files through standard MCP resources. Use the URI returned by discovery or `load_skill`.\n\n| Method | Request | Result |\n|:-------|:--------|:-------|\n| `resources/templates/list` | List resource templates on the initialized connection. | The template for published skill files, rather than an inventory of skills. |\n| `resources/read` | Set `uri` to a returned skill file URI. | A `contents` array with the URI, media type, and file content. |\n\nRead `text` when present. Otherwise, base64-decode `blob` to get the file bytes. An empty file can use an empty blob, so check field presence. The `fetch_resource` tool uses the same distinction and also returns a file digest; standard resource results omit that digest.\n\nFile reads enforce the current publication even with a management key. If publication changes between discovery and reading, rediscover and reassess the selected skill. Agent frameworks that expose tools can use `fetch_resource`."
    },
    {
      "id": "troubleshoot-the-connection",
      "title": "Troubleshoot the connection",
      "role": "errors",
      "text": "- If connection fails, check the full endpoint, network reachability, and reader key.\n- If a tool reports `isError`, inspect its error before using the content. Connection and transport failures can raise separately.\n- If loading fails after a publication change, rediscover once and reassess the returned previews. Preserve returned identifiers and URIs; do not construct replacements.\n\nKeep diagnostic details without logging keys or private content. See [service limits and errors](https://redis.io/docs/latest/develop/ai/context-engine/agent-playbooks/limits) for recovery guidance."
    }
  ],
  "examples": [
    {
      "id": "before-you-begin-ex0",
      "language": "bash",
      "code": "python -m pip install mcp==2.3.0 httpx2==2.13.1",
      "section_id": "before-you-begin"
    },
    {
      "id": "before-you-begin-ex1",
      "language": "bash",
      "code": "curl --version\njq --version",
      "section_id": "before-you-begin"
    },
    {
      "id": "connect-a-client-ex0",
      "language": "python",
      "code": "import asyncio\nimport json\nimport os\n\nimport httpx2\nfrom mcp import Client\nfrom mcp.client.streamable_http import streamable_http_client\n\n\ndef read_result(result):\n    if result.is_error:\n        raise RuntimeError(f\"Playbook tool failed: {result.content}\")\n    if result.structured_content is not None:\n        return result.structured_content\n    return json.loads(next(block.text for block in result.content if block.type == \"text\"))\n\n\nasync def main():\n    url = f\"{os.environ['IRIS_AGENT_PLAYBOOKS_URL'].rstrip('/')}/iris/data/v1/agent-playbooks/playbooks/{os.environ['IRIS_AGENT_PLAYBOOKS_PLAYBOOK_ID']}/mcp\"\n    async with httpx2.AsyncClient(\n        headers={\"Authorization\": f\"Bearer {os.environ['IRIS_AGENT_PLAYBOOKS_API_KEY']}\"}\n    ) as http:\n        async with Client(streamable_http_client(url, http_client=http)) as client:\n            print(\"Tools:\", [tool.name for tool in (await client.list_tools()).tools])\n            result = await client.call_tool(\n                \"discover_entries\",\n                {\n                    \"query\": \"Draft a reply to a customer whose refund status shows Processing.\",\n                    \"limit\": 3,\n                },\n            )\n            print(json.dumps(read_result(result), indent=2))\n\n\nasyncio.run(main())",
      "section_id": "connect-a-client"
    },
    {
      "id": "connect-a-client-ex1",
      "language": "bash",
      "code": "set -euo pipefail\nMCP_URL=\"${IRIS_AGENT_PLAYBOOKS_URL%/}/iris/data/v1/agent-playbooks/playbooks/$IRIS_AGENT_PLAYBOOKS_PLAYBOOK_ID/mcp\"\nPROTOCOL_VERSION=2025-11-25\n\npost() {\n  curl --fail-with-body --silent --show-error \"$MCP_URL\" \\\n    -H \"Authorization: Bearer $IRIS_AGENT_PLAYBOOKS_API_KEY\" \\\n    -H 'Content-Type: application/json' \\\n    -H 'Accept: application/json, text/event-stream' \\\n    -H \"MCP-Protocol-Version: $PROTOCOL_VERSION\" \\\n    --data-binary \"$1\"\n}\n\nrpc() {\n  local request response\n  request=$(jq -n --arg method \"$1\" --argjson params \"$2\" --argjson id \"$3\" \\\n    '{jsonrpc: \"2.0\", id: $id, method: $method, params: $params}') || return $?\n  response=$(post \"$request\") || return $?\n  jq -e '\n    if .error then error(\"MCP request failed: \" + .error.message)\n    elif .result.isError then error(\"Playbook tool failed: \" + (.result.content | tostring))\n    elif has(\"result\") | not then error(\"MCP response has no result\")\n    else .result end\n  ' <<< \"$response\"\n}\n\nINITIALIZED=$(rpc initialize '{\n  \"protocolVersion\": \"2025-11-25\",\n  \"capabilities\": {},\n  \"clientInfo\": {\"name\": \"playbook-curl-example\", \"version\": \"1.0.0\"}\n}' 1)\nPROTOCOL_VERSION=$(jq -er '.protocolVersion' <<< \"$INITIALIZED\")\ncase \"$PROTOCOL_VERSION\" in\n  2025-11-25|2025-06-18|2025-03-26|2024-11-05) ;;\n  *) printf 'Unsupported MCP protocol version: %s\\n' \"$PROTOCOL_VERSION\" >&2; exit 1 ;;\nesac\npost '{\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}' > /dev/null\nrpc tools/list '{}' 2 | jq -r '.tools[].name'\n\nread_result() {\n  jq -e '.structuredContent // ([.content[] | select(.type == \"text\")][0].text | fromjson)'\n}\n\nrpc tools/call '{\n  \"name\": \"discover_entries\",\n  \"arguments\": {\n    \"query\": \"Draft a reply to a customer whose refund status shows Processing.\",\n    \"limit\": 3\n  }\n}' 3 | read_result",
      "section_id": "connect-a-client"
    }
  ]
}
