MCP Server
Quick start#
The MCP server is opt-in and disabled by default — set AXIODB_MCP=true on the same container you already run for the GUI/TCP server:
docker run -d \
--name axiodb-server \
-e AXIODB_GUI=true \
-e AXIODB_MCP=true \
-p 27018:27018 \
-p 27019:27019 \
-p 27020:27020 \
-v axiodb-data:/app \
theankansaha/axiodb
# Ports:
# 27018 - HTTP GUI Dashboard
# 27019 - TCP Remote Access (AxioDBCloud)
# 27020 - MCP Server (Streamable HTTP, path /mcp)AXIODB_MCP=true only has something to serve once RBAC is seeded — that requires AXIODB_GUI=true (the default) or AXIODB_TCP=true + AXIODB_TCP_AUTH=true.
Register with your AI tool#
Register the endpoint (http://localhost:27020/mcp) with whichever client you use — Claude Code (claude mcp add --transport http axiodb http://localhost:27020/mcp), Cursor, Windsurf, OpenAI Codex CLI, opencode, GitHub Copilot CLI, or Google Antigravity all support the same Streamable HTTP transport with minor config-file differences.
Real login, real RBAC#
Every tool except axiodb_login requires a sessionId. Call axiodb_login first with the seeded default account (admin/admin, same as the GUI) or any other RBAC user, and every subsequent call is checked against that logged-in user's actual role — a View-role session gets a real 403 on write tools, exactly like the GUI would. Nothing is gated by a static container environment variable.
// axiodb_login({ username: "admin", password: "admin" })
{
"statusCode": 200,
"data": {
"sessionId": "a1b2c3...",
"role": "Super Admin",
"permissions": ["db:view", "db:create", "..."],
"mustChangePassword": true
}
}Sessions live in server memory only with a 24h sliding TTL — call axiodb_logout when done rather than waiting it out. The same login rate limiter as the GUI/TCP login applies (5 failed attempts / 15 min lockout).
32 tools, mirroring the HTTP control server 1:1#
Every MCP tool maps to the exact same controller and permission check as its HTTP route counterpart — nothing was reimplemented, so behavior never drifts between the GUI and the MCP surface.
| Group | Permission scope | Tools |
|---|---|---|
| Session | none — login is the gate | axiodb_login, axiodb_logout, axiodb_whoami, axiodb_change_own_password |
| Database | db:view/create/delete |
axiodb_create_database, axiodb_delete_database, axiodb_database_exists, axiodb_get_instance_info |
| Collection | collection:view/create/delete |
axiodb_create_collection, axiodb_delete_collection, axiodb_collection_exists, axiodb_get_collection_info |
| Documents | document:view/query/create/update/delete/aggregate |
axiodb_insert_document, axiodb_insert_many_documents, axiodb_query_documents, axiodb_update_document, axiodb_delete_document, axiodb_total_documents, axiodb_aggregate |
| Index | index:view/create/delete |
axiodb_create_index, axiodb_drop_index, axiodb_list_indexes |
| Dashboard | dashboard:view |
axiodb_get_dashboard_stats |
| Users | Super Admin only | axiodb_list_users, axiodb_create_user, axiodb_update_user_role, axiodb_reset_user_password, axiodb_delete_user |
| Roles | Super Admin only | axiodb_list_roles, axiodb_create_role, axiodb_delete_role, axiodb_list_permissions |
Out of scope by design: transactions and database export/import are not exposed as MCP tools.
Human in the loop on destructive tools#
Nine tools destroy or overwrite existing state, and each one asks a human before it runs — through your MCP client's own confirmation prompt. Declining, cancelling, or leaving the box unchecked aborts with 409 and the operation never reaches the database. Inserts, creates, and index builds are never prompted — they only ever add.
Agent: axiodb_delete_collection({ sessionId, dbName: "shop", collectionName: "orders" })
-> your MCP client prompts YOU:
"Delete the collection 'orders' from database 'shop'? This cannot be undone." [ ] Confirm
Declined -> { "statusCode": 409, "message": "Aborted: not confirmed by a human reviewer." }
Confirmed -> collection deletedEvery tool also ships MCP annotations (readOnlyHint, destructiveHint, idempotentHint) so clients can auto-approve reads while holding writes for review. For an agent that must never write, hand it a View-role login — that's enforced server-side in RBAC and needs no client cooperation.
Example: insert and query from an agent#
1. axiodb_login({ username: "admin", password: "admin" }) -> sessionId
2. axiodb_create_database({ sessionId, name: "shop" })
3. axiodb_create_collection({ sessionId, dbName: "shop", collectionName: "orders" })
4. axiodb_insert_document({ sessionId, dbName: "shop", collectionName: "orders",
document: { customer: "Alice", total: 49.99, status: "paid" } })
5. axiodb_query_documents({ sessionId, dbName: "shop", collectionName: "orders",
query: { status: "paid" } })Security notes#
- Every tool is permission-checked against the caller's actual role on every call, not just at login.
- An invalid, expired, or missing
sessionIdis rejected before it reaches a database operation. - Expose port 27020 only to trusted networks and agents — the MCP server carries the same authority as the GUI, just a different transport.