180 lines
7.6 KiB
Markdown
180 lines
7.6 KiB
Markdown
---
|
|
name: ctxd-client
|
|
description: Use when an LLM agent needs to read or update project context via the Context Dossier (CTXD) daemon. Covers OAuth authentication, MCP tool discovery, read-only and write endpoints, and the workflow for keeping project context current.
|
|
version: 1.0.0
|
|
author: Hermes Agent
|
|
license: MIT
|
|
platforms:
|
|
- linux
|
|
- macos
|
|
metadata:
|
|
hermes:
|
|
tags:
|
|
- context-management
|
|
- ctxd
|
|
- mcp-client
|
|
- oauth
|
|
- project-context
|
|
related_skills:
|
|
- project-context-management
|
|
- native-mcp
|
|
---
|
|
|
|
# CTXD Client — LLM Agent Guide
|
|
|
|
Use when an LLM agent (Claude Desktop, Codex CLI, Hermes, custom harness) needs to read or update project context stored in Context Dossier (CTXD).
|
|
|
|
## Overview
|
|
|
|
CTXD is a single source of truth for multi-harness project context. It exposes:
|
|
|
|
- **Public MCP** (`/mcp`) — OAuth read + write (scope-gated) on the public host
|
|
- **Hermes / automation** — same `http://<lan>:9091/mcp` with `CTXD_API_KEY` (full tool surface)
|
|
|
|
Public host: `https://ctxd.cubecraftlabs.com` (OAuth + MCP + landing page + dashboard).
|
|
|
|
## Connection URLs
|
|
|
|
| Surface | URL | Auth |
|
|
|---------|-----|------|
|
|
| Public OAuth MCP (read + write) | `https://ctxd.cubecraftlabs.com/mcp` | OAuth `ctxd.read` and/or `ctxd.write` |
|
|
| Legacy aliases | `/readonly/mcp`, `/oauth/mcp` | Same behavior as `/mcp` for OAuth |
|
|
| OAuth discovery | `https://ctxd.cubecraftlabs.com/.well-known/oauth-authorization-server` | Public |
|
|
| DCR registration | `POST https://ctxd.cubecraftlabs.com/oauth/register` | Public |
|
|
| Landing page | `https://ctxd.cubecraftlabs.com/` | Public |
|
|
|
|
## OAuth Flow
|
|
|
|
1. **Discover** the authorization server metadata at `/.well-known/oauth-authorization-server`
|
|
2. **Register** a client via `POST /oauth/register` (DCR) with your redirect URI
|
|
3. **Authorize** — open `/oauth/authorize` in a browser; an admin must approve
|
|
4. **Exchange** the authorization code for tokens at `POST /oauth/token`
|
|
5. **Use** the access token as `Authorization: Bearer <token>` on MCP connections (Streamable HTTP for read; SSE for write — see Connection URLs)
|
|
|
|
### Scopes
|
|
|
|
| Scope | Grants |
|
|
|-------|--------|
|
|
| `ctxd.read` | `list_projects`, `get_project_context`, `search_context`, `get_project_tags`, `list_files`, `get_file`, `get_client_guide` |
|
|
| `ctxd.write` | `update_file`, `set_project_tags`, `sync_to_project`, `get_client_guide` |
|
|
|
|
Request both scopes for full read+write in **one connector**: `scope=ctxd.read ctxd.write`
|
|
|
|
**Admin:** In the Web UI → Admin → OAuth clients, set **allowed scopes** per client (create form or **scopes** on an existing row). Tokens cannot exceed what the client is allowed, even if the user requests more at authorize time.
|
|
|
|
### Redirect URIs by Platform
|
|
|
|
| Platform | Redirect URI |
|
|
|----------|-------------|
|
|
| Claude Desktop | `https://claude.ai/api/mcp/auth_callback` |
|
|
| Claude Code | `http://localhost:5555/oauth/callback` |
|
|
| Codex CLI | `http://localhost:7777/oauth/callback` |
|
|
| Custom | Your app's documented OAuth callback |
|
|
|
|
### Token Lifetime
|
|
|
|
Access tokens expire per server config (default ~1 hour). Refresh tokens are issued alongside access tokens. Use `POST /oauth/token` with `grant_type=refresh_token` to rotate.
|
|
|
|
## MCP Tools
|
|
|
|
### First Call — Always
|
|
|
|
| Tool | Description |
|
|
|------|-------------|
|
|
| `get_client_guide` | Return the locked LLM-CLIENT.MD guide. **Call this first in every session.** No arguments. Covers OAuth, MCP tools, read/write endpoints, version-checked updates, and error handling. |
|
|
|
|
The guide lives in the `ctxd-docs` project as `LLM-CLIENT.MD`. It is **locked** — cannot be updated or deleted by any MCP/API client. If you need the guide updated, ask an admin to edit it via the Web UI.
|
|
|
|
### Read-only tools (require `ctxd.read` on the same connector)
|
|
|
|
| Tool | Description |
|
|
|------|-------------|
|
|
| `list_projects` | All projects with version numbers |
|
|
| `get_project_context` | Compiled markdown of all context files for a project |
|
|
| `search_context` | FTS5 full-text search across all projects |
|
|
| `get_project_tags` | Metadata tags for a project |
|
|
| `list_files` | All context files in a project (multi-file mode) |
|
|
| `get_file` | Single file with metadata header |
|
|
|
|
### Write tools (require `ctxd.write` on the same connector)
|
|
|
|
| Tool | Description |
|
|
|------|-------------|
|
|
| `update_file` | Update a single context file with optimistic version checking |
|
|
| `set_project_tags` | Replace all metadata tags for a project |
|
|
| `sync_to_project` | Write CONTEXT.MD as AGENTS.md + symlinks to project root |
|
|
|
|
## Workflow: Reading Context
|
|
|
|
```
|
|
1. get_client_guide() → read the locked client guide first
|
|
2. list_projects() → find the project slug
|
|
3. get_project_context(project_id) → read compiled context
|
|
or list_files() + get_file() → read individual files
|
|
```
|
|
|
|
The compiled view returns all files concatenated with `## FILENAME` headers and a metadata block at the top.
|
|
|
|
## Workflow: Updating Context
|
|
|
|
```
|
|
1. get_file(project_id, file_path) → get current content + version
|
|
2. update_file(project_id, file_path, content, base_version)
|
|
→ base_version must match current version (optimistic locking)
|
|
→ returns {"ok": true, "version": N+1} or {"ok": false, "error": "version_conflict"}
|
|
3. On conflict: re-read, merge, retry
|
|
```
|
|
|
|
### What to Update
|
|
|
|
- **CONTEXT.MD** — canonical project overview (synced as AGENTS.md to repos)
|
|
- **DECISIONS.MD** — architecture decisions, rationale
|
|
- **RUNBOOKS.MD** — deploy, troubleshoot, operate procedures
|
|
- **PROMPTS.MD** — project-specific prompts for different harnesses
|
|
- **GLOSSARY.MD** — project-specific terms, acronyms
|
|
|
|
### What NOT to Put in Context
|
|
|
|
- Session progress logs (use session_search or audit trail)
|
|
- Temporary TODO state
|
|
- Single-session debugging notes
|
|
- Secrets, keys, tokens
|
|
|
|
## Locked Files
|
|
|
|
| File | Protection |
|
|
|------|-----------|
|
|
| `CONTEXT.MD` | Cannot delete — canonical synced file |
|
|
| `LLM-CLIENT.MD` | Cannot update or delete — locked client guide |
|
|
|
|
Both return `403 cannot_update_locked` on PUT and `400 cannot_delete_context` on DELETE.
|
|
|
|
## Discipline
|
|
|
|
1. **Call `get_client_guide()` first** in every session
|
|
2. **Read context at the start of every session** for the project you're working on
|
|
3. **Update context immediately** when a durable fact changes — not "next session"
|
|
4. **Use `base_version`** to avoid overwriting concurrent edits
|
|
5. **Don't put session progress in project context** — that's what session history is for
|
|
|
|
## Error Handling
|
|
|
|
| Error | Meaning | Action |
|
|
|-------|---------|--------|
|
|
| `version_conflict` | Someone else updated the file | Re-read, merge, retry with new `base_version` |
|
|
| `not_found` | Project or file doesn't exist | Check slug spelling; create project via Web UI |
|
|
| `invalid_grant` | OAuth token expired or wrong scope | Refresh token or re-authorize with correct scope |
|
|
| `forbidden` | Wrong scope for the tool | Request `ctxd.write` for write tools; `ctxd.read` for read tools (same MCP URL) |
|
|
| `cannot_delete_context` | Tried to delete CONTEXT.MD or LLM-CLIENT.MD | Protected file — update content instead |
|
|
| `cannot_update_locked` | Tried to update LLM-CLIENT.MD | Locked guide — ask admin to update via Web UI |
|
|
|
|
## Verification Checklist
|
|
|
|
- [ ] OAuth client registered with correct redirect URI
|
|
- [ ] Admin approved the authorization (browser session or approval key)
|
|
- [ ] Access token obtained with `ctxd.read` (and `ctxd.write` for updates)
|
|
- [ ] `get_client_guide` returns the LLM client guide
|
|
- [ ] `list_projects` returns expected projects
|
|
- [ ] `get_project_context` returns compiled markdown with metadata header
|
|
- [ ] `update_file` succeeds with correct `base_version`
|
|
- [ ] Audit log shows the write operation |