Repository navigation
docs(integrations): add agent framework integration guides for LlamaIndex, CrewAI, AutoGen, LangGraph #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,276 @@ | ||
| --- | ||
| description: "Connect LlamaIndex, CrewAI, AutoGen, and LangGraph to Hebb Mind for long-term AI agent memory using MCP tools or the REST API." | ||
| --- | ||
|
|
||
| # Agent Framework Integrations | ||
|
|
||
| Hebb Mind works with any Python agent framework. This page shows copy-paste snippets for **LlamaIndex**, **CrewAI**, **AutoGen**, and **LangGraph** using two approaches: | ||
|
|
||
| - **REST API** (no framework dependencies — just `httpx`) | ||
| - **MCP Tools** (via the `hebb-mcp` stdio server, for frameworks that support MCP) | ||
|
|
||
| All snippets assume a running `hebb service` at `http://localhost:8321`. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| ```bash | ||
| pipx install hebb-mind | ||
| hebb setup # downloads the embedding model | ||
| hebb service install # registers the background service | ||
| ``` | ||
|
|
||
| Or use the Python SDK directly (`pip install hebb-mind`): | ||
|
|
||
| ```python | ||
| from hebb import HebbMind | ||
| hc = HebbMind() # in-process, no HTTP server needed | ||
| ``` | ||
|
Comment on lines
+14
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Make both prerequisite sections runnable. Both pages install only Hebb Mind, while the snippets require framework packages, MCP adapters, and LLM configuration.
📍 Affects 2 files
🤖 Prompt for AI Agents |
||
|
|
||
| --- | ||
|
|
||
| ## LlamaIndex | ||
|
|
||
| LlamaIndex supports MCP tools natively via `llama-index-tools-mcp`. Alternatively, use the REST API with a simple wrapper. | ||
|
|
||
| ### Using MCP Tools (recommended for LlamaIndex 2024+) | ||
|
|
||
| ```python | ||
| from llama_index.core.agent import FunctionCallingAgentWorker | ||
| from llama_index.tools.mcp import MCPRemoteToolProvider | ||
| import asyncio | ||
|
|
||
| async def main(): | ||
| # Connect to the local hebb-mcp server | ||
| provider = MCPRemoteToolProvider( | ||
| name="hebb", | ||
| server_url="http://localhost:8321", | ||
| timeout=30, | ||
| ) | ||
| tools = await provider.get_tools() | ||
| worker = FunctionCallingAgentWorker(tools=tools, verbose=True) | ||
| agent = worker.as_agent() | ||
| agent.chat("What do I know about the user's UI preferences?") | ||
|
|
||
| asyncio.run(main()) | ||
| ``` | ||
|
Comment on lines
+33
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- English guide ---'
cat -n repo_pages/guide/agent-frameworks.md | sed -n '1,90p'
printf '%s\n' '--- Chinese guide ---'
cat -n repo_pages/zh/guide/agent-frameworks.md | sed -n '1,85p'
printf '%s\n' '--- Related MCP references ---'
rg -n -C 3 'MCPRemoteToolProvider|BasicMCPClient|McpToolSpec|hebb-mcp|8321|llama-index' repo_pages README.md reports 2>/dev/null || trueRepository: afx-team/hebb-mind Length of output: 50377 🌐 Web query:
💡 Result: LlamaIndex supports Model Context Protocol (MCP) integration through the llama-index-tools-mcp package [1][2]. The key components for this integration are BasicMCPClient and McpToolSpec [1][2]. BasicMCPClient The BasicMCPClient acts as the primary interface for connecting to MCP servers [2][3]. It supports multiple transport methods: - Server-Sent Events (SSE): BasicMCPClient("https://example.com/sse") [1][2] - Streamable HTTP: BasicMCPClient("https://example.com/mcp") [1][2] - Local Process (stdio): BasicMCPClient("python", args=["server.py"]) [1][2] Beyond tool execution, it provides methods to list and call tools, list and read resources, and list and use prompts [2][4]. It also supports OAuth authentication via the BasicMCPClient.with_oauth class method [2][3]. McpToolSpec McpToolSpec is used to convert tools exposed by an MCP server into LlamaIndex FunctionTool objects [5][1]. Usage workflow: 1. Initialize a BasicMCPClient pointing to your MCP server [1][2]. 2. Pass the client instance to McpToolSpec [1][2]. 3. Use to_tool_list (synchronous) or to_tool_list_async (asynchronous) to retrieve the tools for use in LlamaIndex agents [2][6]. Example: from llama_index.tools.mcp import BasicMCPClient, McpToolSpec # Connect to the server mcp_client = BasicMCPClient("http://127.0.0.1:8000/sse") # Create the tool spec mcp_tool_spec = McpToolSpec(client=mcp_client) # Convert to LlamaIndex tools tools = await mcp_tool_spec.to_tool_list_async Regarding "MCPRemoteToolProvider," it is not a primary component documented in the standard usage guides for this integration; the integration relies on BasicMCPClient for remote connections and McpToolSpec for abstraction [1][2]. Citations:
🌐 Web query:
💡 Result: BasicMCPClient and McpToolSpec are components within the llama-index-tools-mcp package, designed to facilitate the integration of Model Context Protocol (MCP) servers into LlamaIndex workflows [1]. BasicMCPClient serves as the client interface that handles the connection to an MCP server [1]. It supports various transport methods, including Server-Sent Events (SSE), standard HTTP, and local process execution [1]. McpToolSpec acts as a bridge or specification layer that takes a configured BasicMCPClient instance and converts the tools exposed by the MCP server into a format compatible with LlamaIndex [1]. By initializing an McpToolSpec with the client, developers can retrieve a list of tools using methods such as to_tool_list_async, enabling the LlamaIndex framework to interact with the external MCP tools seamlessly [1]. Example usage: from llama_index.tools.mcp import BasicMCPClient, McpToolSpec mcp_client = BasicMCPClient("http://127.0.0.1:8000/sse") mcp_tool_spec = McpToolSpec(client=mcp_client) tools = await mcp_tool_spec.to_tool_list_async Citations: 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- MCP implementation and packaging ---'
rg -n -C 4 'MCPRemoteToolProvider|BasicMCPClient|McpToolSpec|hebb-mcp|FastMCP|streamable|SSE|stdio|mcp' \
--glob '*.py' --glob 'pyproject.toml' --glob 'README.md' --glob '*.md' . \
| head -n 500
printf '%s\n' '--- MCP-related files ---'
git ls-files | rg '(^|/)(mcp|.*mcp.*|pyproject.toml)$|agent-frameworks'
printf '%s\n' '--- MCP entry points and server declarations ---'
rg -n -C 8 'hebb-mcp|mcp_server|FastMCP|`@mcp`|MCP' pyproject.toml setup.cfg setup.py src app hebb 2>/dev/null || trueRepository: afx-team/hebb-mind Length of output: 50377 🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
import ast
import re
files = [p for p in Path(".").rglob("*") if p.is_file() and (
p.name in {"pyproject.toml", "setup.py", "setup.cfg"} or
"mcp" in p.name.lower()
)]
for path in sorted(files):
text = path.read_text(errors="replace")
hits = []
for needle in ("hebb-mcp", "FastMCP", "MCPRemoteToolProvider",
"BasicMCPClient", "McpToolSpec", "stdio", "sse",
"streamable", "8321"):
if needle.lower() in text.lower():
hits.append(needle)
if hits:
print(f"{path}: {', '.join(hits)}")
for i, line in enumerate(text.splitlines(), 1):
if re.search(r"hebb-mcp|FastMCP|MCPRemoteToolProvider|BasicMCPClient|McpToolSpec|stdio|sse|streamable|8321", line, re.I):
print(f" {i}: {line.strip()}")
PYRepository: afx-team/hebb-mind Length of output: 4385 🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
import re
files = [p for p in Path(".").rglob("*") if p.is_file() and (
p.name in {"pyproject.toml", "setup.py", "setup.cfg"} or
"mcp" in p.name.lower()
)]
for path in sorted(files):
text = path.read_text(errors="replace")
if re.search(
r"hebb-mcp|FastMCP|MCPRemoteToolProvider|BasicMCPClient|McpToolSpec|"
r"stdio|sse|streamable|8321",
text,
re.I,
):
print(f"--- {path} ---")
for i, line in enumerate(text.splitlines(), 1):
if re.search(
r"hebb-mcp|FastMCP|MCPRemoteToolProvider|BasicMCPClient|McpToolSpec|"
r"stdio|sse|streamable|8321",
line,
re.I,
):
print(f"{i}: {line.strip()}")
PYRepository: afx-team/hebb-mind Length of output: 4241 Use the stdio MCP transport in both LlamaIndex guides. The Hebb MCP server exposes 📍 Affects 2 files
🤖 Prompt for AI Agents |
||
|
|
||
| ### Using REST API directly | ||
|
|
||
| ```python | ||
| import httpx | ||
|
|
||
| HEBB_URL = "http://localhost:8321" | ||
|
|
||
| def write_memory(content: str, tags: list[str] | None = None, importance: float = 5.0) -> str: | ||
| resp = httpx.post(f"{HEBB_URL}/api/v1/memories", json={ | ||
| "content": content, | ||
| "tags": tags or [], | ||
| "importance_score": importance, | ||
| }) | ||
| resp.raise_for_status() | ||
| return f"Memory saved (id={resp.json()['id']})" | ||
|
|
||
| def search_memory(query: str, top_k: int = 5) -> list[dict]: | ||
| resp = httpx.post(f"{HEBB_URL}/api/v1/search", json={ | ||
| "query": query, | ||
| "top_k": top_k, | ||
| "strict_recall": True, | ||
| }) | ||
| resp.raise_for_status() | ||
| return resp.json().get("results", []) | ||
|
|
||
| # Use in a LlamaIndex tool node | ||
| from llama_index.core.tools import FunctionTool | ||
|
|
||
| write_tool = FunctionTool.from_defaults(fn=write_memory) | ||
| search_tool = FunctionTool.from_defaults(fn=search_memory) | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## CrewAI | ||
|
|
||
| CrewAI supports custom tools out of the box. Wrap the REST API or MCP tools as CrewAI tools. | ||
|
|
||
| ### Using REST API | ||
|
|
||
| ```python | ||
| import httpx | ||
| from crewai import Agent, Task, Crew | ||
| from crewai.tools import BaseTool | ||
| from typing import Type | ||
| from pydantic import BaseModel, Field | ||
|
|
||
| class MemorySearchInput(BaseModel): | ||
| query: str = Field(..., description="Search query for memories") | ||
| top_k: int = Field(default=5, description="Number of results") | ||
|
|
||
| class MemorySearchTool(BaseTool): | ||
| name: str = "Search Hebb Memory" | ||
| description: str = "Search for related memories in Hebb Mind" | ||
| args_schema: Type[BaseModel] = MemorySearchInput | ||
|
|
||
| def _run(self, query: str, top_k: int = 5) -> str: | ||
| resp = httpx.post("http://localhost:8321/api/v1/search", json={ | ||
| "query": query, "top_k": top_k, "strict_recall": True, | ||
| }) | ||
| resp.raise_for_status() | ||
| results = resp.json().get("results", []) | ||
| return "\n".join(f"[{r['score']:.2f}] {r['memory']['content']}" for r in results[:top_k]) | ||
|
|
||
| # In your crew setup | ||
| agent = Agent(role="Researcher", backstory="You have access to long-term memory.", tools=[MemorySearchTool()]) | ||
| task = Task(description="What did the user say about their preferences?") | ||
| crew = Crew(agents=[agent], tasks=[task]) | ||
| crew.kickoff() | ||
|
Comment on lines
+121
to
+125
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- affected files ---'
git ls-files 'repo_pages/guide/agent-frameworks.md' 'repo_pages/zh/guide/agent-frameworks.md'
printf '%s\n' '--- English section ---'
sed -n '95,145p' repo_pages/guide/agent-frameworks.md
printf '%s\n' '--- Chinese section ---'
sed -n '92,140p' repo_pages/zh/guide/agent-frameworks.md
printf '%s\n' '--- CrewAI references and metadata ---'
rg -n -S 'CrewAI|crewai|MemorySearchTool|expected_output|backstory=.*memory|长期记忆' \
--glob '!node_modules' --glob '!dist' --glob '!build' .Repository: afx-team/hebb-mind Length of output: 7674 🏁 Script executed: #!/bin/bash
set -eu
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
curl -fsSL https://raw.githubusercontent.com/crewAIInc/crewAI/main/lib/crewai/src/crewai/task.py \
-o "$tmpdir/task.py"
printf '%s\n' '--- Task declarations and validation ---'
rg -n -C 4 'class Task|expected_output|model_config|field_validator|model_validator' "$tmpdir/task.py"
printf '%s\n' '--- Agent source candidates ---'
curl -fsSL https://api.github.com/repos/crewAIInc/crewAI/git/trees/main?recursive=1 |
jq -r '.tree[] | select(.path | test("agent.*\\.py$|agents/.+\\.py$")) | .path' |
head -80Repository: afx-team/hebb-mind Length of output: 10325 🏁 Script executed: #!/bin/bash
set -eu
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
curl -fsSL https://raw.githubusercontent.com/crewAIInc/crewAI/main/lib/crewai/src/crewai/task.py \
-o "$tmpdir/task.py"
printf '%s\n' '--- Task declarations and validation ---'
rg -n -C 4 'class Task|expected_output|model_config|field_validator|model_validator' "$tmpdir/task.py"
printf '%s\n' '--- Agent source candidates ---'
curl -fsSL 'https://api.github.com/repos/crewAIInc/crewAI/git/trees/main?recursive=1' |
jq -r '.tree[] | select(.path | test("agent.*\\.py$|agents/.+\\.py$")) | .path' |
head -80Repository: afx-team/hebb-mind Length of output: 10325 🌐 Web query:
💡 Result: In the CrewAI framework, the 'goal' field is a required attribute for the Agent class [1][2]. The framework's internal validation logic ensures that the 'role', 'goal', and 'backstory' fields are provided during agent initialization [1][2]. Specifically, the BaseAgent class uses a Pydantic model validator that raises a ValueError if these three fields are not set, either directly through the constructor or via a configuration object [1][2]. Consequently, 'goal' is essential for defining the agent's individual objective and guiding its decision-making process within the crew [3][4]. Citations:
🏁 Script executed: #!/bin/bash
set -eu
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
curl -fsSL https://raw.githubusercontent.com/crewAIInc/crewAI/main/lib/crewai/src/crewai/agents/agent_builder/base_agent.py \
-o "$tmpdir/base_agent.py"
curl -fsSL https://raw.githubusercontent.com/crewAIInc/crewAI/main/lib/crewai/src/crewai/task.py \
-o "$tmpdir/task.py"
python3 - "$tmpdir/base_agent.py" "$tmpdir/task.py" <<'PY'
import re
import sys
from pathlib import Path
agent_source = Path(sys.argv[1]).read_text()
task_source = Path(sys.argv[2]).read_text()
checks = {
"Agent.goal declaration": re.search(
r"^\s*goal:\s*str\s*=\s*Field\(\s*$", agent_source, re.MULTILINE
),
"Agent required-field validation": re.search(
r"role.*goal.*backstory|goal.*must be provided|goal.*required",
agent_source,
re.IGNORECASE | re.DOTALL,
),
"Task.expected_output declaration": re.search(
r"^\s*expected_output:\s*str\s*=\s*Field\(\s*$", task_source, re.MULTILINE
),
"Task required-field validation": re.search(
r"expected_output must be provided",
task_source,
),
}
for name, match in checks.items():
print(f"{name}: {'present' if match else 'missing'}")
if not match:
raise SystemExit(1)
PY
printf '%s\n' '--- Agent relevant lines ---'
rg -n -C 4 '^\s*(role|goal|backstory):|must be provided|validate_required_fields' "$tmpdir/base_agent.py"Repository: afx-team/hebb-mind Length of output: 188 🏁 Script executed: #!/bin/bash
set -eu
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
curl -fsSL https://raw.githubusercontent.com/crewAIInc/crewAI/main/lib/crewai/src/crewai/agents/agent_builder/base_agent.py \
-o "$tmpdir/base_agent.py"
printf '%s\n' '--- Agent field and validator context ---'
rg -n -C 8 'goal|backstory|role|validate_required_fields|must be provided' "$tmpdir/base_agent.py" | head -160
printf '%s\n' '--- Tolerant source checks ---'
python3 - "$tmpdir/base_agent.py" <<'PY'
import re
import sys
from pathlib import Path
source = Path(sys.argv[1]).read_text()
patterns = {
"goal field": r"(?m)^\s*goal\s*:\s*[^=\n]+\s*=\s*Field\b",
"role field": r"(?m)^\s*role\s*:\s*[^=\n]+\s*=\s*Field\b",
"backstory field": r"(?m)^\s*backstory\s*:\s*[^=\n]+\s*=\s*Field\b",
"required-field validator": r"(?is)(?:role.*goal.*backstory|goal.*backstory.*role).{0,1000}(?:must be provided|required)",
}
for name, pattern in patterns.items():
found = bool(re.search(pattern, source))
print(f"{name}: {'present' if found else 'missing'}")
PYRepository: afx-team/hebb-mind Length of output: 7002 Add CrewAI requires both fields, so each example fails during object construction. Use matching English and Chinese values in the respective snippets. 📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| ``` | ||
|
|
||
| ### Using MCP Tools via subprocess | ||
|
|
||
| ```python | ||
| import subprocess, json | ||
| from crewai.tools import BaseTool | ||
|
|
||
| class HebbMCPTrait(BaseTool): | ||
| name: str = "Hebb Memory" | ||
| description: str = "Write or search memory via hebb-mcp" | ||
|
|
||
| def _run(self, action: str, **kwargs) -> str: | ||
| result = subprocess.run( | ||
| ["hebb-mcp", "call", action, json.dumps(kwargs)], | ||
| capture_output=True, text=True | ||
| ) | ||
| return result.stdout | ||
|
Comment on lines
+128
to
+143
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- target files ---'
git ls-files 'repo_pages/guide/agent-frameworks.md' 'repo_pages/zh/guide/agent-frameworks.md'
printf '%s\n' '--- relevant excerpts ---'
sed -n '110,155p' repo_pages/guide/agent-frameworks.md
sed -n '110,155p' repo_pages/zh/guide/agent-frameworks.md
printf '%s\n' '--- related repository references ---'
rg -n --glob '!node_modules' --glob '!dist' --glob '!build' \
'HebbMCPTrait|hebb-mcp|MCP|crewai|subprocess\.run' .
printf '%s\n' '--- repository metadata and likely dependency files ---'
git ls-files | rg '(^|/)(README|pyproject\.toml|requirements[^/]*|package\.json|[^/]*lock|Dockerfile|compose[^/]*|\.github/)' | head -200Repository: afx-team/hebb-mind Length of output: 50376 🏁 Script executed: #!/bin/bash
set -e
printf '%s\n' '--- CrewAI sections ---'
sed -n '85,150p' repo_pages/guide/agent-frameworks.md
sed -n '82,145p' repo_pages/zh/guide/agent-frameworks.md
printf '%s\n' '--- MCP entry point and server main ---'
sed -n '55,75p' pyproject.toml
sed -n '1,235p' src/hebb/mcp/server.py
printf '%s\n' '--- CLI MCP documentation ---'
sed -n '185,205p' repo_pages/guide/mcp-integration.md
sed -n '135,148p' repo_pages/guide/mcp-integration.md
printf '%s\n' '--- project tests and docs for the MCP entry point ---'
rg -n -A8 -B8 'mcp\.server|hebb-mcp|serve\(' tests src/hebb repo_pages/guide/mcp-integration.md pyproject.toml \
| head -240Repository: afx-team/hebb-mind Length of output: 26920 🏁 Script executed: #!/bin/bash
set -e
python3 - <<'PY'
import ast
import inspect
import subprocess
from pathlib import Path
targets = [
Path("repo_pages/guide/agent-frameworks.md"),
Path("repo_pages/zh/guide/agent-frameworks.md"),
]
for path in targets:
text = path.read_text()
blocks = text.split("```python")
matches = [b.split("```", 1)[0] for b in blocks if "HebbMCPTrait" in b]
assert len(matches) == 1, (path, len(matches))
block = matches[0]
tree = ast.parse(block)
classes = [
node for node in tree.body
if isinstance(node, ast.ClassDef) and node.name == "HebbMCPTrait"
]
assert len(classes) == 1
class_node = classes[0]
run_methods = [
node for node in class_node.body
if isinstance(node, ast.FunctionDef) and node.name == "_run"
]
assert len(run_methods) == 1
calls = [
node for node in ast.walk(run_methods[0])
if isinstance(node, ast.Call)
and isinstance(node.func, ast.Attribute)
and node.func.attr == "run"
]
assert len(calls) == 1
argv = calls[0].args[0]
assert isinstance(argv, ast.List)
argv_text = [
elt.value if isinstance(elt, ast.Constant) else ast.unparse(elt)
for elt in argv.elts
]
print(f"{path}: class_only=True subprocess_argv={argv_text}")
assert "Agent(" not in block and "Crew(" not in block
server = Path("src/hebb/mcp/server.py").read_text()
server_tree = ast.parse(server)
main = next(
node for node in server_tree.body
if isinstance(node, ast.FunctionDef) and node.name == "main"
)
main_calls = [
node for node in ast.walk(main)
if isinstance(node, ast.Call)
and isinstance(node.func, ast.Attribute)
and node.func.attr == "run"
]
print("src/hebb/mcp/server.py: main_mcp_run_calls=", len(main_calls))
assert len(main_calls) == 1
assert any(
kw.arg == "transport"
and isinstance(kw.value, ast.Constant)
and kw.value.value == "stdio"
for kw in main_calls[0].keywords
)
print("src/hebb/mcp/server.py: transport='stdio', no CLI call dispatch in main")
sig = inspect.signature(subprocess.run)
params = sig.parameters
print(
"subprocess.run defaults:",
"check=", params["check"].default,
"timeout=", params["timeout"].default,
)
assert params["check"].default is False
assert params["timeout"].default is None
PYRepository: afx-team/hebb-mind Length of output: 575 Replace the CrewAI MCP subprocess examples with a real MCP client integration.
📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## AutoGen | ||
|
|
||
| AutoGen supports MCP servers via `autogen-ext[mcp]`. Connect directly to `hebb-mcp`. | ||
|
|
||
| ### Using MCP Tools (AutoGen 0.4+) | ||
|
|
||
| ```python | ||
| import asyncio | ||
| from autogen import Agent, AssistantAgent, UserProxyAgent | ||
| from autogen_ext.tools.mcp import McpSession, McpServerConnectionStdio | ||
|
|
||
| async def main(): | ||
| # Connect to hebb-mcp via stdio | ||
| async with McpSession(McpServerConnectionStdio(command="hebb-mcp")) as session: | ||
| # List available tools | ||
| tools = await session.list_tools() | ||
| print("Available tools:", [t.name for t in tools]) | ||
|
|
||
| assistant = AssistantAgent( | ||
| "assistant", | ||
| llm_config={"config_list": [{"model": "gpt-4o", "api_key": "YOUR_KEY"}]}, | ||
| system_message="You have access to Hebb Mind memory. Use the hebb tools to remember and recall.", | ||
| ) | ||
| user = UserProxyAgent("user") | ||
|
|
||
| chat_result = await user.initiate_chat( | ||
| assistant, | ||
| message="I prefer dark mode. Remember that.", | ||
| extra_args={"tools": tools}, | ||
| ) | ||
|
|
||
| asyncio.run(main()) | ||
|
Comment on lines
+150
to
+179
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- candidate files ---'
git ls-files 'repo_pages/guide/agent-frameworks.md' 'repo_pages/zh/guide/agent-frameworks.md'
printf '%s\n' '--- English section ---'
sed -n '125,190p' repo_pages/guide/agent-frameworks.md
printf '%s\n' '--- Chinese section ---'
sed -n '120,185p' repo_pages/zh/guide/agent-frameworks.md
printf '%s\n' '--- AutoGen references ---'
rg -n -C 3 'AutoGen|autogen-ext|McpSession|McpServerConnectionStdio|StdioServerParams|mcp_server_tools|McpWorkbench|autogen_agentchat' repo_pages package.json pyproject.toml 2>/dev/null || trueRepository: afx-team/hebb-mind Length of output: 9395 🌐 Web query:
💡 Result: In AutoGen, the integration of Model Context Protocol (MCP) servers is primarily handled through the McpWorkbench class [1][2]. This class acts as a client that manages the MCP session, allowing your agents to interact with tools, resources, and prompts hosted by an MCP server [1][3][2]. Core Integration Pattern The standard workflow involves three main steps: 1. Configure Connection: Use StdioServerParams to define how to launch and communicate with the local MCP server (e.g., via stdio) [4][5]. 2. Manage Session: Use McpWorkbench as an asynchronous context manager to start and stop the connection [6][1][3]. 3. Expose Tools: You can pass the workbench instance directly to an AssistantAgent, or use workbench.create_toolset to retrieve tools and pass them into the agent's tools parameter [1][7][4]. Key Components - StdioServerParams: Configures the command and arguments used to start the MCP server [6][8]. - McpWorkbench: The central class from autogen_ext.tools.mcp. It automates the discovery, listing, and execution of tools provided by the MCP server [6][3][2]. - AssistantAgent: Can be configured with a workbench (via the workbench parameter) or a toolset to automatically gain access to the MCP server's tools [7][4][2]. Example Workflow async with McpWorkbench(server_params=StdioServerParams(command="uvx", args=["mcp-server-fetch"])) as workbench: agent = AssistantAgent( name="assistant", model_client=model_client, workbench=workbench) result = await agent.run(task="...") Regarding your mention of mcp_server_tools, while some earlier or third-party tutorials may refer to a helper function by that name [5], current official AutoGen documentation emphasizes using the McpWorkbench class directly to manage sessions and expose tools [6][1][2]. Always ensure you only connect to trusted MCP servers, as they can execute commands within your local environment [8][3][2]. Citations:
🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
from urllib.request import urlopen
from html.parser import HTMLParser
import re
urls = [
"https://microsoft.github.io/autogen/stable/reference/python/autogen_ext.tools.mcp.html",
"https://microsoft.github.io/autogen/stable/user-guide/core-user-guide/components/workbench.html",
"https://microsoft.github.io/autogen/stable/user-guide/agentchat-user-guide/tutorial/agents.html",
]
class TextParser(HTMLParser):
def __init__(self):
super().__init__()
self.parts = []
def handle_data(self, data):
self.parts.append(data)
def text(self):
return "\n".join(self.parts)
for url in urls:
print(f"\n--- {url} ---")
try:
raw = urlopen(url, timeout=15).read().decode("utf-8", "replace")
parser = TextParser()
parser.feed(raw)
text = parser.text()
lines = [re.sub(r"\s+", " ", line).strip() for line in text.splitlines()]
matches = [
line for line in lines
if any(term in line for term in (
"StdioServerParams", "McpWorkbench", "mcp_server_tools",
"autogen_agentchat.agents", "AssistantAgent(", "extra_args",
"workbench=", "tools=",
))
]
print("\n".join(matches[:80]))
except Exception as exc:
print(type(exc).__name__, str(exc))
PYRepository: afx-team/hebb-mind Length of output: 894 🌐 Web query:
💡 Result: In the Microsoft AutoGen framework, StdioServerParams and McpWorkbench are components used to integrate Model Context Protocol (MCP) servers with agents [1][2]. These components are found in the Citations:
🌐 Web query:
💡 Result: In AutoGen, McpWorkbench is a component used to integrate agents with Model Context Protocol (MCP) servers, allowing them to access tools and resources provided by those servers [1][2][3]. Key integration details: 1. Role: The McpWorkbench acts as an MCP client that manages the connection to an MCP server [2]. When assigned to an AssistantAgent, it enables the agent to discover, list, and invoke tools served by the MCP protocol [1][3]. 2. Implementation: It is typically imported from Citations:
Update both AutoGen MCP examples to the current AgentChat API. Use 📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| ``` | ||
|
|
||
| ### Using REST API directly | ||
|
|
||
| ```python | ||
| import httpx | ||
|
|
||
| def write_memory(content: str, tags: list[str] | None = None) -> str: | ||
| resp = httpx.post("http://localhost:8321/api/v1/memories", json={ | ||
| "content": content, "tags": tags or [] | ||
| }) | ||
| resp.raise_for_status() | ||
| return f"Saved: {resp.json()['id']}" | ||
|
|
||
| def search_memories(query: str, top_k: int = 5) -> str: | ||
| resp = httpx.post("http://localhost:8321/api/v1/search", json={ | ||
| "query": query, "top_k": top_k | ||
| }) | ||
| resp.raise_for_status() | ||
| return "\n".join(r["memory"]["content"] for r in resp.json()["results"]) | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## LangGraph | ||
|
|
||
| LangGraph works with any tool. Wrap the REST API or MCP tools and pass them to your graph nodes. | ||
|
|
||
| ### Using REST API | ||
|
|
||
| ```python | ||
| import httpx | ||
| from langgraph.prebuilt import create_react_agent | ||
| from langchain_core.tools import tool | ||
|
|
||
| @tool | ||
| def hebb_write_memory(content: str, tags: list[str] | None = None) -> str: | ||
| """Write a memory to Hebb Mind.""" | ||
| resp = httpx.post("http://localhost:8321/api/v1/memories", json={ | ||
| "content": content, "tags": tags or [] | ||
| }) | ||
| resp.raise_for_status() | ||
| return f"Memory saved (id={resp.json()['id']})" | ||
|
|
||
| @tool | ||
| def hebb_search_memory(query: str, top_k: int = 5) -> str: | ||
| """Search Hebb Mind for relevant memories.""" | ||
| resp = httpx.post("http://localhost:8321/api/v1/search", json={ | ||
| "query": query, "top_k": top_k, "strict_recall": True | ||
| }) | ||
| resp.raise_for_status() | ||
| results = resp.json().get("results", []) | ||
| return "\n".join(f"[{r['score']:.2f}] {r['memory']['content']}" for r in results) | ||
|
|
||
| # Build the graph | ||
| agent = create_react_agent( | ||
| model="gpt-4o", | ||
| tools=[hebb_write_memory, hebb_search_memory], | ||
| ) | ||
|
|
||
| # Use it | ||
| result = agent.invoke({"messages": [("user", "I like minimalist designs. Remember this.")]}) | ||
| print(result["messages"][-1].content) | ||
| ``` | ||
|
|
||
| ### Using MCP Tools | ||
|
|
||
| ```python | ||
| from langgraph_prebuilt import create_react_agent | ||
| from langchain_mcp_adapters.client import MultiServerMCPClient | ||
|
|
||
| async def get_tools(): | ||
| client = MultiServerMCPClient({ | ||
| "hebb": {"command": "hebb-mcp"} | ||
| }) | ||
| return await client.get_tools() | ||
|
|
||
| tools = await get_tools() | ||
| agent = create_react_agent(model="gpt-4o", tools=tools) | ||
| ``` | ||
|
Comment on lines
+245
to
+259
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- English source context ---'
sed -n '220,275p' repo_pages/guide/agent-frameworks.md
printf '%s\n' '--- Chinese source context ---'
sed -n '220,270p' repo_pages/zh/guide/agent-frameworks.md
printf '%s\n' '--- Relevant repository references ---'
rg -n --hidden -S \
'langgraph_prebuilt|langgraph\.prebuilt|MultiServerMCPClient|transport: ["'\'']stdio["'\'']|hebb-mcp' \
repo_pages package.json pyproject.toml requirements.txt 2>/dev/null || true
printf '%s\n' '--- Candidate dependency/version references ---'
rg -n --hidden -S \
'langchain-mcp-adapters|langgraph' \
. -g '!*node_modules*' -g '!*.lock' -g '!repo_pages/guide/agent-frameworks.md' -g '!repo_pages/zh/guide/agent-frameworks.md' \
2>/dev/null | head -200 || trueRepository: afx-team/hebb-mind Length of output: 11825 🌐 Web query:
💡 Result: The MultiServerMCPClient from the langchain-mcp-adapters package is designed to manage connections to multiple Model Context Protocol (MCP) servers, including those using the stdio transport for local subprocess communication [1][2][3]. When using stdio with MultiServerMCPClient, you provide a configuration dictionary where the connection specifies "transport": "stdio", the "command" to run the server, and the "args" containing the absolute path to the server script [1][2][4]. Key integration points and best practices include: 1. Agent Integration: You can retrieve MCP tools using client.get_tools and pass them to LangGraph's create_react_agent function [1][5]. 2. LLM Tool Binding: When creating a ReAct agent, it is critical to ensure your language model is explicitly bound to the retrieved tools using llm.bind_tools(mcp_tools) before passing it to create_react_agent [6]. 3. Stateless by Default: The MultiServerMCPClient is stateless by default, meaning each tool invocation creates a fresh MCP ClientSession and then cleans it up [2][7][5]. 4. Stateful Options: If you require persistent connections, you can use the client.session(server_name) context manager to explicitly manage the lifetime of an MCP session and load tools from it [4][5]. Official documentation and resources for these components can be found in the LangChain MCP Adapters GitHub repository, the LangChain documentation, and the LangChain Python reference site [1][2][3][8]. Citations:
🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- LangGraph section and project metadata ---'
sed -n '185,265p' repo_pages/guide/agent-frameworks.md
sed -n '185,262p' repo_pages/zh/guide/agent-frameworks.md
sed -n '45,85p' pyproject.toml
printf '%s\n' '--- Python syntax probe for the documented pattern ---'
python3 - <<'PY'
import ast
samples = {
"module_level_await": """async def get_tools():
return []
tools = await get_tools()
""",
"inside_async_main": """import asyncio
async def main():
async def get_tools():
return []
tools = await get_tools()
return tools
asyncio.run(main())
""",
}
for name, source in samples.items():
try:
ast.parse(source)
except SyntaxError as exc:
print(f"{name}: SyntaxError: {exc.msg} at line {exc.lineno}")
else:
print(f"{name}: parses as standard Python")
PY
printf '%s\n' '--- Upstream adapter examples (read-only HTTP fetch) ---'
curl -L --fail --silent --show-error \
https://raw.githubusercontent.com/langchain-ai/langchain-mcp-adapters/main/README.md |
rg -n -A18 -B5 'MultiServerMCPClient|transport.*stdio|create_react_agent' | head -160
printf '%s\n' '--- Upstream LangGraph prebuilt import references ---'
curl -L --fail --silent --show-error \
https://raw.githubusercontent.com/langchain-ai/langgraph/main/README.md |
rg -n -A3 -B3 'langgraph\.prebuilt|create_react_agent' | head -80 || trueRepository: afx-team/hebb-mind Length of output: 11694 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- Adapter source defaults and stdio config validation ---'
curl -L --fail --silent --show-error \
https://raw.githubusercontent.com/langchain-ai/langchain-mcp-adapters/main/langchain_mcp_adapters/client.py |
rg -n -A35 -B10 'class StdioConnection|transport|command|args|MultiServerMCPClient' | head -260
printf '%s\n' '--- Official example files mentioning stdio ---'
for url in \
https://raw.githubusercontent.com/langchain-ai/langchain-mcp-adapters/main/examples/multiple_servers.py \
https://raw.githubusercontent.com/langchain-ai/langchain-mcp-adapters/main/examples/multi_server.py \
https://raw.githubusercontent.com/langchain-ai/langchain-mcp-adapters/main/examples/README.md
do
echo "--- $url"
curl -L --fail --silent --show-error "$url" |
rg -n -A20 -B5 'stdio|MultiServerMCPClient|command' | head -120 || true
done
printf '%s\n' '--- Package metadata and import path references from upstream ---'
curl -L --fail --silent --show-error \
https://raw.githubusercontent.com/langchain-ai/langchain-mcp-adapters/main/pyproject.toml |
rg -n -A4 -B4 'langgraph|dependencies|name' | head -100Repository: afx-team/hebb-mind Length of output: 9823 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- Standard Python compilation probe ---'
python3 - <<'PY'
samples = {
"documented_pattern": """async def get_tools():
return []
tools = await get_tools()
""",
"async_main_pattern": """import asyncio
async def main():
async def get_tools():
return []
tools = await get_tools()
return tools
asyncio.run(main())
""",
}
for name, source in samples.items():
try:
compile(source, f"<{name}>", "exec")
except SyntaxError as exc:
print(f"{name}: SyntaxError: {exc.msg!r} at line {exc.lineno}")
else:
print(f"{name}: compiles as standard Python")
PY
printf '%s\n' '--- Adapter connection type definitions ---'
curl -L --fail --silent --show-error \
https://raw.githubusercontent.com/langchain-ai/langchain-mcp-adapters/main/langchain_mcp_adapters/sessions.py |
rg -n -A80 -B10 'StdioConnection|Connection =|transport' | head -260
printf '%s\n' '--- PyPI lookup for the claimed import package ---'
python3 - <<'PY'
import json
import urllib.request
for package in ("langgraph-prebuilt", "langgraph_prebuilt", "langgraph"):
url = f"https://pypi.org/pypi/{package}/json"
try:
with urllib.request.urlopen(url) as response:
data = json.load(response)
print(f"{package}: found, latest={data['info']['version']}")
except Exception as exc:
print(f"{package}: {type(exc).__name__}: {exc}")
PY
printf '%s\n' '--- Repository language consistency around both documents ---'
python3 - <<'PY'
from pathlib import Path
for path in (Path("repo_pages/guide/agent-frameworks.md"),
Path("repo_pages/zh/guide/agent-frameworks.md")):
text = path.read_text()
latin = sum(c.isascii() and c.isalpha() for c in text)
cjk = sum('\u4e00' <= c <= '\u9fff' for c in text)
print(f"{path}: latin_letters={latin}, CJK_letters={cjk}")
PYRepository: afx-team/hebb-mind Length of output: 10447 Fix the LangGraph MCP examples before publishing. Update both blocks to:
📍 Affects 2 files
🤖 Prompt for AI Agents |
||
|
|
||
| --- | ||
|
|
||
| ## Summary | ||
|
|
||
| | Framework | Easiest approach | Key dependency | | ||
| |-----------|-----------------|----------------| | ||
| | LlamaIndex | MCP via `llama-index-tools-mcp` | `llama-index-tools-mcp` | | ||
| | CrewAI | REST API as custom tool | `httpx` | | ||
| | AutoGen | MCP via `autogen_ext[mcp]` | `autogen-ext[mcp]` | | ||
| | LangGraph | REST API as `@tool` | `langgraph`, `httpx` | | ||
|
|
||
| All snippets target the same surfaces: | ||
| - **REST**: `POST /api/v1/memories` (write), `POST /api/v1/search` (read) | ||
| - **MCP**: `write_memory`, `search_memory`, `consolidate`, `ingest_conversation` | ||
|
|
||
| See also: [MCP Integration](./mcp-integration.md) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Correct the guide path in the starting-point picker.
examples/README.mdpoints todocs/guide/agent-frameworks.md, but the added guide is underrepo_pages/guide/agent-frameworks.md. The table below already uses the correct relative path. Update the picker to use../repo_pages/guide/agent-frameworks.mdor the published guide path.🤖 Prompt for AI Agents