Hierarchical context store for AI agents — workspace → group → project → context. Serves markdown / yaml / json / txt via REST and MCP.
workspace (slug)
└── group (slug)
└── project (slug)
└── context (slug) ─── actual contentNon-leaf levels carry their own index_md so agents can drill in quickly. The server bumps children_updated_at on every descendant change; agents poll /api/stale to know which indexes to regenerate.
claude mcp add --transport http -s user agent-guideline \ https://dev-agent-guideline.skylinklabs.ai/api/mcp \ -H "X-API-Key:<YOUR_API_KEY>"
The admin panel has a “Install as MCP” button that copies this command with the current host and your key already filled in. 13 tools are exposed:list_workspaces · fetch_index · fetch_context · list_children · list_stale · get_tree · put_index · upsert_workspace · upsert_group · upsert_project · upsert_context · delete_node · search
Every /api/* endpoint (except /api/health) requires the API key from the API_KEY env var. Send it as:
X-API-Key: <key> # or Authorization: Bearer <key>
Return rendered index_md or raw leaf content with the correct Content-Type.
| Method | Endpoint | Returns |
|---|---|---|
GET | /api/w/{ws} | workspace index_md |
GET | /api/w/{ws}/{g} | group index_md |
GET | /api/w/{ws}/{g}/{p} | project index_md |
GET | /api/w/{ws}/{g}/{p}/{ctx} | leaf content |
Response headers: X-Index-Stale, X-Index-Updated-At,X-Children-Updated-At. Add ?format=json to get the row instead.
| Method | Endpoint | Purpose |
|---|---|---|
GET/POST | /api/workspaces | list / create workspace |
GET/PUT/DELETE | /api/workspaces/{ws} | one workspace |
PUT | /api/workspaces/{ws}/index | replace index_md |
GET | /api/workspaces/{ws}/children | list groups |
GET/POST | /api/workspaces/{ws}/groups | list / create group |
GET/PUT/DELETE | /api/workspaces/{ws}/groups/{g} | one group |
PUT | /api/workspaces/{ws}/groups/{g}/index | replace index_md |
GET | /api/workspaces/{ws}/groups/{g}/children | list projects |
GET/POST | /api/workspaces/{ws}/groups/{g}/projects | list / create project |
GET/PUT/DELETE | /api/workspaces/{ws}/groups/{g}/projects/{p} | one project |
PUT | /api/workspaces/{ws}/groups/{g}/projects/{p}/index | replace index_md |
GET | /api/workspaces/{ws}/groups/{g}/projects/{p}/children | list contexts |
GET/POST | /api/workspaces/{ws}/groups/{g}/projects/{p}/contexts | list / create context |
GET/PUT/DELETE | /api/workspaces/{ws}/groups/{g}/projects/{p}/contexts/{ctx} | one context |
| Method | Endpoint | Purpose |
|---|---|---|
GET | /api/health | DB health (no auth required) |
POST | /api/init | create/upgrade tables + triggers |
GET | /api/stale | nodes whose index_md is out of date |
GET | /api/tree | nested JSON hierarchy (?workspace=, ?depth=, ?brief=) |
POST | /api/mcp | MCP JSON-RPC endpoint |
The flat /api/contexts/... routes still work for old clients. Reads prefer the new ag_contexts table and fall back to the legacy flat table. Writes still land in the legacy table — run the migration (npm run db:migrate:apply) to promote them into the new hierarchy.