Skip to content

Using Purple8 with MCP Agents

Purple8 ships a first-party MCP server out of the box. One command exposes the full REST API as typed tools that any MCP-compatible client — Claude Desktop, Cursor, or your own agent loop — can discover and call via JSON-RPC 2.0 over stdio.

What MCP is (the 30-second version)

The Model Context Protocol is an open standard (originally from Anthropic, now widely adopted) that lets an AI agent discover and call tools through a uniform JSON-RPC 2.0 interface over stdio or HTTP-SSE.

From the agent's perspective, a tool is just a named function with a JSON Schema for its inputs. The agent decides when to call it; the MCP server executes the real work and returns a text result. The agent has no direct access to your database or API — it only sees what the tool returns.

Architecture

MCP Client (Claude Desktop / Cursor / custom agent)
  │  JSON-RPC 2.0 (stdio)

purple8-graph mcp-server  ← ships with the package, pip install "purple8-graph[mcp]"
  │  REST + API-Key / JWT

Purple8 Secure Server (http://localhost:8010)

Quick start — native MCP server

Step 1 — install the MCP extra

bash
pip install "purple8-graph[mcp]"

Step 2 — start the server

With an API key (recommended for persistent servers):

bash
purple8-graph mcp-server \
    --url     http://localhost:8010 \
    --api-key YOUR_API_KEY

With username / password (JWT, re-authenticated automatically on expiry):

bash
purple8-graph mcp-server \
    --url      http://localhost:8010 \
    --username admin \
    --password changeme
FlagRequiredDefaultDescription
--urlBase URL of the running Purple8 server
--api-key✅ (or --username)Long-lived API key (X-API-Key header)
--username✅ (or --api-key)Admin username for JWT login
--passwordif --username setAdmin password for JWT login
--timeout30sHTTP request timeout in seconds

Step 3 — connect Claude Desktop

Add this to ~/.claude/claude_desktop_config.json:

json
{
  "mcpServers": {
    "purple8": {
      "command": "purple8-graph",
      "args": [
        "mcp-server",
        "--url", "http://localhost:8010",
        "--api-key", "YOUR_API_KEY"
      ]
    }
  }
}

Restart Claude Desktop — the 13 Purple8 tools will appear in the tool chooser immediately.

Step 3 (alternative) — connect a custom Python agent

python
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

params = StdioServerParameters(
    command="purple8-graph",
    args=["mcp-server", "--url", "http://localhost:8010", "--api-key", "YOUR_API_KEY"],
)

async def run():
    async with stdio_client(params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()

            # Hybrid search
            result = await session.call_tool("hybrid_search", {
                "query_text": "enterprise contracts expiring Q3 2026",
                "label": "Contract",
                "k": 5,
            })
            print(result.content)

            # Ask a natural-language question
            answer = await session.call_tool("rag_query", {
                "question": "Which accounts have open critical tickets right now?",
            })
            print(answer.content)

asyncio.run(run())

Tools exposed by the native server

All 13 tools are available out of the box — no wrapper code needed.

Tool nameMethodPathWhat it does
graph_queryPOST/queryArbitrary Cypher
vector_searchPOST/search/vectorHNSW nearest-neighbour
hybrid_searchPOST/search/hybridVector + graph combined
rag_queryPOST/rag/queryNL question → LLM answer
traversePOST/traverseGraph walk from a node
add_nodePOST/nodesInsert a node
get_nodeGET/nodes/{id}Fetch a node
ingest_textPOST/ingest/preview + /ingest/commitExtract entities from text
journey_startPOST/v1/journeys/{type}/instancesStart a Journey Engine instance
journey_advancePOST/v1/journeys/instances/{id}/advanceAdvance to next stage
journey_statusGET/v1/journeys/instances/{id}Full audit trail
pagerankGET/algorithms/pagerankTop-K influential nodes
communitiesGET/algorithms/communitiesLouvain community detection

Authentication details

ApproachHowWhen to use
API key--api-key YOUR_KEYLong-running servers, CI/CD
JWT--username + --password (auto-refreshed on 401)Per-session auth, scoped permissions

Building your own wrapper (advanced)

If you need custom tool names, filtered results, or want to embed the MCP logic inside a larger service, you can write a thin wrapper directly against the REST API instead of using the native server.

Install dependencies

bash
pip install mcp httpx

Minimal wrapper

python
# purple8_mcp.py  —  custom wrapper, only if you need non-standard tool names/logic
import asyncio, json, httpx
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent

BASE_URL = "http://localhost:8010"
HEADERS  = {"X-API-Key": "YOUR_API_KEY"}
server   = Server("purple8-graph-custom")

@server.list_tools()
async def list_tools() -> list[Tool]:
    return [
        Tool(
            name="hybrid_search",
            description="Semantic + graph search over the Purple8 knowledge graph.",
            inputSchema={
                "type": "object",
                "properties": {
                    "query_text": {"type": "string"},
                    "label":      {"type": "string"},
                    "k":          {"type": "integer", "default": 10},
                },
                "required": ["query_text"],
            },
        ),
        # add more tools as needed — see the tools table above
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    async with httpx.AsyncClient(headers=HEADERS, timeout=30) as client:
        if name == "hybrid_search":
            r = await client.post(f"{BASE_URL}/search/hybrid", json=arguments)
        else:
            return [TextContent(type="text", text=f"Unknown tool: {name}")]
        r.raise_for_status()
        return [TextContent(type="text", text=json.dumps(r.json(), indent=2))]

async def main():
    async with stdio_server() as (read, write):
        await server.run(read, write, server.create_initialization_options())

if __name__ == "__main__":
    asyncio.run(main())

See Also

Purple8 Graph is proprietary software. All rights reserved.