Xquik MCP Server with a 10xGraph Agent
In shortConnect a 10xGraph ToolNode or ReactAgent to the remote Xquik MCP server with an API key and list its tools in Python.
- 3 min read
- 7 sections
- Updated
- v1.0.0rc4
- Markdown
This example connects 10xGraph’s ToolNode to the remote Xquik MCP server and loads its tool schemas without changing any framework defaults. A second script gives the same tools to a ReactAgent running on Anthropic claude-sonnet-5-5. See the MCP overview for the general pattern.
What you will build
client.py builds a client for the Xquik server, wraps it in a ToolNode, and prints the tool names. agent.py reuses that client and asks an agent which Xquik tools it can use.
Key concepts
fastmcp.Clientwith astreamable-httpserver and anx-api-keyheader.ToolNode([], client=...): a tool node with no local functions, only the remote tools.ToolNode.all_tools(): returns the discovered tool schemas.ReactAgent(client=...): the same client used by an agent.
Run it
git clone https://github.com/10xGraph/10xGraph.git
cd 10xGraph/agentflow
pip install "10xgraph[mcp]"
export XQUIK_API_KEY="your-api-key"
python examples/mcp/xquik/client.pyFor the agent, install 10xgraph[mcp,anthropic], set ANTHROPIC_API_KEY, and run:
python examples/mcp/xquik/agent.pySee the Xquik MCP overview for authentication, tool behavior, and safety requirements. This API-key example sends the x-api-key header. Xquik also supports OAuth 2.1 for compatible MCP clients.
How the code works
client.py
def require_api_key() -> str:
"""Read the Xquik API key without embedding it in source."""
api_key = os.getenv("XQUIK_API_KEY", "").strip()
if not api_key:
raise RuntimeError("Set XQUIK_API_KEY before running this example")
return api_keyThe key comes from the environment and the script fails early with a clear message if it is missing.
def build_client(api_key: str) -> Client:
"""Build a Streamable HTTP client for the remote Xquik MCP server."""
return Client(
{
"mcpServers": {
"xquik": {
"url": MCP_URL,
"transport": "streamable-http",
"headers": {"x-api-key": api_key},
}
}
}
)Same mcpServers shape as the other examples. The only difference from GitHub is the header name.
tool_node = ToolNode([], client=build_client(require_api_key()))
tools = await tool_node.all_tools()
names = sorted(tool["function"]["name"] for tool in tools)
print(f"Available Xquik tools: {', '.join(names)}")An empty list means no local tools. all_tools() asks the server for its tools and returns them in function-call format, so the names live under ["function"]["name"]. You could pass this tool_node to a graph as the tool node.
agent.py
from client import build_client, require_api_keyIt reuses the helpers from client.py, which is why the script is run from the repo root with its folder importable.
agent = ReactAgent(
model="claude-sonnet-5-5",
system_prompt=[{"role": "system", "content": "Use the Xquik tools to answer."}],
client=build_client(require_api_key()),
)
app = agent.compile()
result = await app.ainvoke(
{"messages": [Message.text_message("Which Xquik tools are available to you?")]},
config={"thread_id": "xquik-demo", "recursion_limit": 10},
)
print("assistant:", result["messages"][-1].text())
await app.aclose()client= replaces tools=. compile() with no arguments uses the default in-memory checkpointer. aclose() releases the graph when done.
Full code
client.py
"""Discover Xquik tools through the 10xGraph MCP adapter.
Run: XQUIK_API_KEY=... python examples/mcp/xquik/client.py
"""
import asyncio
import os
from fastmcp import Client
from tenxgraph.core.graph import ToolNode
MCP_URL = "https://xquik.com/mcp"
def require_api_key() -> str:
"""Read the Xquik API key without embedding it in source."""
api_key = os.getenv("XQUIK_API_KEY", "").strip()
if not api_key:
raise RuntimeError("Set XQUIK_API_KEY before running this example")
return api_key
def build_client(api_key: str) -> Client:
"""Build a Streamable HTTP client for the remote Xquik MCP server."""
return Client(
{
"mcpServers": {
"xquik": {
"url": MCP_URL,
"transport": "streamable-http",
"headers": {"x-api-key": api_key},
}
}
}
)
async def main() -> None:
"""Load the remote tool schemas through 10xGraph."""
tool_node = ToolNode([], client=build_client(require_api_key()))
tools = await tool_node.all_tools()
names = sorted(tool["function"]["name"] for tool in tools)
print(f"Available Xquik tools: {', '.join(names)}")
if __name__ == "__main__":
asyncio.run(main())agent.py
"""Give a ReactAgent the Xquik MCP tools.
Reuses build_client() from client.py. Run from the repo root:
XQUIK_API_KEY=... ANTHROPIC_API_KEY=... python examples/mcp/xquik/agent.py
"""
import asyncio
from client import build_client, require_api_key
from dotenv import load_dotenv
from tenxgraph.core.state import Message
from tenxgraph.prebuilt.agent import ReactAgent
load_dotenv()
async def main() -> None:
agent = ReactAgent(
model="claude-sonnet-5-5",
system_prompt=[{"role": "system", "content": "Use the Xquik tools to answer."}],
client=build_client(require_api_key()),
)
app = agent.compile()
result = await app.ainvoke(
{"messages": [Message.text_message("Which Xquik tools are available to you?")]},
config={"thread_id": "xquik-demo", "recursion_limit": 10},
)
print("assistant:", result["messages"][-1].text())
await app.aclose()
if __name__ == "__main__":
asyncio.run(main())Source on GitHub: examples/mcp/xquik
Next steps
- MCP overview
- GitHub MCP for a bearer token example.
- Tools for local Python tools.
Frequently asked questions
- How does the example authenticate?
- It sends the XQUIK_API_KEY environment variable in the x-api-key header. Xquik also supports OAuth 2.1 for MCP clients that handle it.
- Can I use the tools in an agent?
- Yes. Pass the same client to ReactAgent(client=...), as agent.py does with claude-sonnet-5-5.