# How to Use MCP (Model Context Protocol) with Oracle AI Agent Memory

> Learn how to use MCP Model Context Protocol with Oracle AI Agent Memory to let LLMs invoke Python functions and manage persistent cross-session context. Enhance your AI agents today!

- Repository: [Oracle Developers/oracle-ai-developer-hub](https://github.com/oracle-devrel/oracle-ai-developer-hub)
- Tags: how-to-guide
- Published: 2026-05-10

---

**MCP (Model Context Protocol) enables LLMs to invoke Python functions as standardized tools, allowing agents to read from and write to Oracle AI Agent Memory for persistent, cross-session context.**

The Model Context Protocol (MCP) defines a JSON-RPC interface that bridges generative AI models with external capabilities. In the `oracle-devrel/oracle-ai-developer-hub` repository, MCP connects Claude Agent SDK-based agents to Oracle AI Agent Memory (OAMP), transforming ephemeral conversations into durable, searchable knowledge bases that survive agent restarts.

## Understanding the MCP Architecture for OAMP

MCP creates a standardized contract between the LLM and your business logic. When using MCP with Oracle AI Agent Memory, four core components work together to enable memory-aware agents.

### The `@tool` Decorator

The Claude Agent SDK provides the `@tool` decorator to convert regular Python functions into MCP-compatible endpoints. These functions must accept a dictionary of arguments and return content in the **MCP content format**:

```json
{"content": [{"type": "text", "text": "result here"}]}

```

In `notebooks/agent_memory/02_supply_chain_claude_agent_sdk.ipynb`, tools like `list_shipments` and `recall_operational_notes` are defined using this decorator (lines 95-165).

### The MCP Server Wrapper

The `create_sdk_mcp_server` function bundles multiple `@tool`-decorated functions into a lightweight HTTP-style server that speaks MCP. This server registers with the agent under a specific name, such as `supply-chain` or `demo`, which forms part of the tool invocation pattern.

### Oracle AI Agent Memory Integration

The `oracleagentmemory` package exposes `memory_client.add_memory()` and `memory_client.search()` methods. These allow tools to persist facts to Oracle AI Database and perform semantic retrieval across sessions. The vector store and document store reside on Oracle AI Database, ensuring durability and scalability.

### Agent Runtime Execution

The `ClaudeSDKClient` orchestrates the interaction loop. When the model decides it needs external data, it emits a tool call request (e.g., `mcp__sc__list_shipments`). The runtime forwards this to the MCP server, executes the Python function, and injects the returned text back into the LLM's prompt window.

## Implementing Memory-Aware MCP Tools

To build tools that interact with Oracle AI Agent Memory, you define asynchronous functions that handle both storage and retrieval patterns.

### Writing Memory with `add_memory`

Tools that persist operational state use `memory_client.add_memory()` to store facts with metadata. As shown in the Supply-Chain Assistant example (lines 36-42 in `02_supply_chain_claude_agent_sdk.ipynb`), the `update_shipment` tool records durable facts about shipment status, making the information available to future sessions.

### Searching Memory with Semantic Retrieval

Recall tools use `memory_client.search()` to perform vector similarity searches. The `recall_operational_notes` tool demonstrates this pattern (lines 56-62), allowing the agent to retrieve relevant historical context based on semantic similarity rather than exact keyword matches.

## Step-by-Step: Building a Memory-Augmented Agent

Follow these steps to implement MCP with Oracle AI Agent Memory in your Python environment.

### 1. Install Dependencies

Install the required packages including `oracleagentmemory`, `claude-agent-sdk`, and `nest_asyncio`:

```python

# 1️⃣ Install required packages (run once)

# %pip install -q "oracleagentmemory[litellm]" claude-agent-sdk nest_asyncio

```

### 2. Initialize the Memory Client

Connect to Oracle AI Database and instantiate the memory client with embedding and LLM configurations:

```python
import os, oracledb
from oracleagentmemory.core import OracleAgentMemory
from oracleagentmemory.core.llms import Llm

conn = oracledb.connect(
    user=os.getenv("DB_USER", "VECTOR"),
    password=os.getenv("DB_PASSWORD", "VectorPwd_2025"),
    dsn=os.getenv("DB_CONNECT_STRING", "localhost:1521/FREEPDB1"),
)

extract_llm = Llm("gpt-4o-mini", temperature=0.2)
memory = OracleAgentMemory(
    connection=conn,
    embedder="text-embedding-3-small",
    llm=extract_llm,
    extract_memories=True,
    schema_policy="create_if_necessary",
    table_name_prefix="demo_",
)

```

### 3. Define MCP Tools

Create functions decorated with `@tool` that interact with the memory client. Each tool must return content in the MCP format:

```python
from claude_agent_sdk import tool

@tool(
    "add_fact",
    "Persist a short fact string in Agent Memory for later retrieval.",
    {"fact": str},
)
async def add_fact(args: dict) -> dict:
    fact = args["fact"]
    memory.add_memory(
        fact,
        user_id="demo_user",
        agent_id="demo_agent",
        metadata={"kind": "fact"},
    )
    return {"content": [{"type": "text", "text": f"Fact stored: {fact}"}]}

@tool(
    "search_facts",
    "Semantic search for facts previously stored.",
    {"query": str, "max_results": int},
)
async def search_facts(args: dict) -> dict:
    results = memory.search(
        args["query"], 
        user_id="demo_user", 
        agent_id="demo_agent",
        max_results=args.get("max_results", 5),
    )
    if not results:
        return {"content": [{"type": "text", "text": "(no facts found)"}]}
    lines = [f"- {r.content} [dist={r.distance:.3f}]" for r in results]
    return {"content": [{"type": "text", "text": "\n".join(lines)}]}

```

### 4. Create and Register the MCP Server

Bundle your tools into an MCP server and register it with the agent using `ClaudeAgentOptions`. Note the `mcp__{server}__{tool}` naming convention in the allowlist:

```python
from claude_agent_sdk import create_sdk_mcp_server, ClaudeAgentOptions, ClaudeSDKClient

# Wrap tools in MCP server

demo_server = create_sdk_mcp_server(
    name="demo",
    tools=[add_fact, search_facts],
)

# Configure agent to use the MCP server

options = ClaudeAgentOptions(
    system="You are a helpful assistant that can store and recall facts via MCP.",
    mcp_servers=[demo_server],
    tool_allowlist=[
        "mcp__demo__add_fact", 
        "mcp__demo__search_facts"
    ],
)

```

### 5. Execute Memory-Enabled Conversations

Run the agent. The model automatically invokes `add_fact` when it needs to store information and `search_facts` when it needs to retrieve context:

```python
client = ClaudeSDKClient(options=options)

# Store a fact

resp1 = client.chat("Remember that the Office is on the 3rd floor.")
print(resp1.message)

# Retrieve the fact

resp2 = client.chat("What did I say about the Office location?")
print(resp2.message)

```

## Key Implementation Details from the Supply-Chain Assistant

The `02_supply_chain_claude_agent_sdk.ipynb` notebook demonstrates production patterns for MCP with OAMP:

- **Tool Definitions**: Lines 95-165 define `list_shipments`, `get_shipment_status`, `update_shipment`, and `recall_operational_notes` using the `@tool` decorator
- **MCP Server Creation**: Lines 95-99 bundle these tools under the server name `supply-chain` using `create_sdk_mcp_server`
- **Agent Configuration**: Lines 108-112 show `ClaudeAgentOptions` configuration with the `mcp__sc__*` naming pattern in the allowlist
- **Memory Operations**: Lines 36-42 demonstrate `memory_client.add_memory()` for persistence, while lines 56-62 show `memory_client.search()` for semantic recall

## Summary

- **MCP standardizes** tool invocation between LLMs and Python functions through a JSON-RPC interface
- **The `@tool` decorator** converts async functions into MCP-compatible endpoints that must return `{"content": [...]}` format
- **Oracle AI Agent Memory** provides durable vector storage via `add_memory()` and semantic search via `search()`
- **The naming convention** `mcp__{server_name}__{tool_name}` maps LLM tool calls to specific Python functions
- **Memory-augmented agents** maintain low token budgets by retrieving only relevant context rather than full conversation history

## Frequently Asked Questions

### What is the exact naming convention for MCP tools in ClaudeAgentOptions?

Tools follow the pattern `mcp__{server_name}__{tool_name}`. For example, if you create a server named `demo` with a tool named `add_fact`, you must include `mcp__demo__add_fact` in the `tool_allowlist` of `ClaudeAgentOptions`. This convention enables the `ClaudeSDKClient` to route tool calls from the LLM to the correct Python function.

### How does Oracle AI Agent Memory persist data across agent restarts?

Oracle AI Agent Memory stores data in Oracle AI Database using the `OracleAgentMemory` class. When you call `memory_client.add_memory()`, the system writes to a persistent vector store and document store on the database. Because the memory resides in Oracle AI Database rather than in-memory Python objects, the data survives agent restarts, container redeployments, and is accessible across multiple concurrent sessions using the same `user_id` and `agent_id`.

### What format must MCP tool functions return to be compatible with the Claude Agent SDK?

MCP tools must return a dictionary containing a `content` key with a list of content blocks. For text responses, use `{"content": [{"type": "text", "text": "your result here"}]}`. This standardized format allows the `ClaudeSDKClient` to inject the tool result back into the LLM's prompt window as part of the conversation context.

### Can I use multiple MCP servers with a single Claude Agent?

Yes. The `ClaudeAgentOptions` class accepts a list of servers via the `mcp_servers` parameter. You can create multiple servers using `create_sdk_mcp_server()`, each with its own set of tools, and pass them all to the options object. Ensure that each tool name in your `tool_allowlist` uses the correct `mcp__{server_name}__{tool_name}` prefix to avoid naming collisions between servers.