Embabel Hub exposes resources relating to the Embabel Agent Framework, such as documentation, relevant blogs and other content, and up-to-the-minute API information.
This is exposed in two ways:
- Via a chatbot for the Embabel Hub front end
- Via an MCP server for integration with Claude Desktop, Claude Code and other MCP clients
curl -X POST http://localhost:1337/api/v1/data/load-referencesGo to the Neo Browser at http://localhost:7474/browser/
Log in with username neo4j and password brahmsian (or your custom password if you set one).
To delete all data run the following query:
MATCH (n:ContentElement)
DETACH DELETE nStarting the server will expose MCP tools on http://localhost:1337/sse.
An easy way to verify the tools are exposed and experiment with calling them is by running the MCP inspector:
npx @modelcontextprotocol/inspectorWithin the inspector UI, connect to http://localhost:1337/sse.
Add this stanza to claude_desktop_config.json:
{
"mcpServers": {
"embabel-dev": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://localhost:1337/sse",
"--transport",
"sse-only"
]
},
...
}See Connect Local Servers for detailed documentation.
If you're using Claude Code, adding the Embabel MCP server will powerfully augment its capabilities for working on Embabel applications and helping you learn Embabel.
claude mcp add embabel --transport sse http://localhost:1337/sseWithin the Claude Code shell, type /mcp to test the connection. Choose the number of the embabel server to check its
status.
Start via claude --debug to see more logging.
See Claude Code MCP documentation for further information.
By default, Claude Code asks for confirmation before running MCP tools. When you accept a tool with "Yes, don't ask
again", Claude Code saves that permission to your local .claude/settings.local.json file (which is auto-ignored by
git).
Note: Wildcards do not work for MCP tool permissions. Each tool must be approved individually or listed explicitly in your settings.
Tool naming: By default, guide.toolPrefix is empty, so MCP tools are exposed with their original names (e.g.,
mcp__embabel__docs_vectorSearch). You can set a custom prefix in your application configuration to namespace your
tools.
See Claude Code Permission Modes for detailed documentation on how permissions work.
The backend supports any client via WebSocket (for real-time chat) and REST (for authentication).
Endpoint: ws://localhost:1337/ws
Uses STOMP protocol over WebSocket with SockJS fallback. Any STOMP client library works (e.g., @stomp/stompjs for JavaScript, stomp.py for Python).
Authentication: Pass an optional JWT token as a query parameter:
ws://localhost:1337/ws?token=<JWT>
If no token is provided, an anonymous user is created automatically.
| Direction | Destination | Purpose |
|---|---|---|
| Subscribe | /user/queue/messages |
Receive chat responses |
| Subscribe | /user/queue/status |
Receive typing/status updates |
| Publish | /app/chat.sendToJesse |
Send message to AI bot |
| Publish | /app/presence.ping |
Keep-alive (send every 30s) |
Sending a message:
{ "body": "your message here" }Receiving a message:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"content": "response text",
"userId": "bot:jesse",
"userName": "Jesse",
"timestamp": "2025-12-16T10:30:00Z"
}Receiving a status update:
{
"fromUserId": "bot:jesse",
"status": "typing"
}CORS is open (*), no special headers required beyond Content-Type: application/json.
Register:
POST /api/hub/register
{
"userDisplayName": "Jane Doe",
"username": "jane",
"userEmail": "jane@example.com",
"password": "secret",
"passwordConfirmation": "secret"
}
Login:
POST /api/hub/login
{ "username": "jane", "password": "secret" }
Response:
{ "token": "eyJhbG...", "userId": "...", "username": "jane", ... }
List Personas:
GET /api/hub/personas
Update Persona (requires auth):
PUT /api/hub/persona/mine
Authorization: Bearer <JWT>
{ "persona": "persona_name" }
import { Client } from '@stomp/stompjs';
import SockJS from 'sockjs-client';
const client = new Client({
webSocketFactory: () => new SockJS('http://localhost:1337/ws'),
onConnect: () => {
// Subscribe to responses
client.subscribe('/user/queue/messages', (frame) => {
const message = JSON.parse(frame.body);
console.log('Received:', message.content);
});
// Send a message
client.publish({
destination: '/app/chat.sendToJesse',
body: JSON.stringify({ body: 'Hello!' })
});
}
});
client.activate();Run with Docker Compose:
docker compose up| Variable | Default | Description |
|---|---|---|
NEO4J_VERSION |
2025.10.1-community-bullseye |
Neo4j Docker image tag |
NEO4J_USERNAME |
neo4j |
Neo4j username |
NEO4J_PASSWORD |
brahmsian |
Neo4j password |
OPENAI_API_KEY |
(required) | OpenAI API key |
DISCORD_TOKEN |
(optional) | Discord bot token |
Example:
NEO4J_PASSWORD=mysecretpassword OPENAI_API_KEY=sk-... docker compose upSometimes (for example if your IDE crashes) you will be left with an orphaned server process and won't be able to restart. To kill the server:
lsof -ti:1337 | xargs kill -9
