Architecture · deep dive

How ctxlayer works

One Worker on Cloudflare's edge serves the MCP surface, the collaborative editor, and the governed proxy. Its sharpest trick: it injects your curated docs and skills straight into tool calling, so agents follow your conventions without being told.

1 · System overview

One deployable unit on the edge

ctxlayer is a single Cloudflare Worker. It hosts the MCP server, the OAuth provider, the SPA and its backend, and the realtime collaboration endpoint — backed by Cloudflare's storage and AI primitives. Per-session state lives in a Durable Object; each document gets its own. There is nothing else to run.

MCP clients Claude · Cursor · agents Browser onboard · edit docs CLOUDFLARE WORKER — GLOBAL EDGE /mcp · /sse MCP server OAuth provider sign-in + tokens /api · SPA onboarding app + assets /collab DocRoomDO · Yjs McpSessionDO per session: identity · tool registry · upstream clients Queue consumers usage → D1 · reindex → Vectorize BINDINGS D1 · KV · R2 · Vectorize · Workers AI · Queues Upstream MCP Notion · Linear Figma · internal stdio upstreams BYO bridge → HTTP /mcp /api · /collab proxy + sealed creds

MCP clients hit /mcp; the browser hits the SPA and the collab socket. Per-session state and the upstream proxy live in McpSessionDO. Stdio upstreams join as ordinary HTTP via a bring-your-own bridge.

Identity is resolved once, at the edge, and pinned to the session as { user, role }. From there the session object builds a per-user view of the world: the tools that user is allowed to call, the upstreams they've connected, and the org docs and skills attached to each. Credentials for upstreams are decrypted only inside that session, never logged, and sealed with AES-GCM at rest.

2 · Context injection into tool calling

The right playbook, delivered at the moment of the call

This is what makes ctxlayer more than a proxy. When it assembles the tool list for a session, it weaves pointers to your curated skills and docs into the tools themselves. The agent reads them as it decides what to do — then pulls the full playbook on demand, only when it needs it.

1 Curate & attach admin links a skill or doc to an upstream or a single tool 2 Session init McpSessionDO builds this user's tool registry 3 Inject context pointers woven into: • each tool's description • the MCP server instructions WHAT THE AGENT RECEIVES [Linear] Create an issue. [ctxlayer] Org convention applies — consult skill `linear-triage`, doc `linear-practices` before using this tool. 4 Agent sees tools enriched tool list arrives at the client 5 Fetch on demand agent calls get_skill / get_doc when needed 6 Call the tool convention applied · proxied · usage recorded injects then, at runtime ↓

Pointers are injected once, when the tool list is built. The agent fetches the actual skill or doc body only if it decides to act on the tool — context arrives just in time, not all at once.

There are two injection points. Per-tool attachments append a short, first-party suffix to that tool's description — [ctxlayer] Org convention applies — consult skill … / doc … before using this tool. Whole-upstream attachments are added to the MCP server's instructions, so the agent reads the org playbook before its very first call to that service:

MCP server instructions (excerpt)
**Org playbooks attached to your upstreams — read these BEFORE
the first call to the named upstream's tools:**
- `linear`:  consult doc `linear-practices` (get_doc) before using its tools.
- `driver`:  consult skill `driverai-planning` (get_skill) first.

ctxlayer injects pointers, not payloads. Inlining every doc would bloat the tool list and burn context the agent may never use; a pointer lets the agent pull only the playbook it actually needs, exactly when it needs it. The pointers are org-curated, first-party strings — kept cleanly separate from upstream tool descriptions, which are treated as untrusted input, sanitised of control characters, and truncated so the binding guidance always survives.

3 · Skills lifecycle

Procedural playbooks, authored once and reused everywhere

A skill is a Markdown playbook that encodes the conventions a raw tool schema can't show — which team IDs to use, which status names are valid, how to format a title, when to prefer one tool over another. Skills are authored, published, attached, and then surfaced to every agent over MCP.

1 Author / draft in the admin editor or via CLI draft-skill (local claude -p) 2 Publish review the draft, then promote draft → published 3 Attach to an upstream, or to a single tool (tool_name) 4 Surface over MCP list_skills get_skill + skill resources 5 Consume agent loads on demand — or pull into the IDE ctxlayer pull

Skills are reference material an agent fetches when relevant — not auto-loaded. The same published skill can back the injected pointers from section 2, or be pulled into a developer's local editor with ctxlayer pull.

Authoring can start from scratch in the admin editor, or from the CLI: ctxlayer draft-skill <upstream> pulls the org context for that service, runs your local Claude Code to draft the playbook, and posts it back as a draft for review. Once published and attached, the skill becomes discoverable over MCP through list_skills and retrievable via get_skill (or its mcp://ctxlayer/skills/{slug} resource). Attachments carry an attached_to list, so the same skill can apply org-wide to an upstream or narrowly to one tool — which is exactly what feeds the injection in section 2.

4 · Docs & search pipeline

Edited by people, searched by agents

The curated library is editable in a Notion-style collaborative editor and searchable by every agent. Behind a save, ctxlayer snapshots the document, embeds it, and makes it retrievable by meaning — so an agent finds the right passage without anyone wiring up a search index.

GitHub repos git-sync mirror 1 Edit collaborative editor (BlockNote · Yjs) in DocRoomDO 2 Persist snapshot → R2 revision → D1 enqueue reindex 3 Chunk ~512-token chunks 64 overlap, heading-aware 4 Embed Workers AI bge-base-en 768-dim vectors 5 Vectorize upsert keyed {docId}:{idx} cosine index Agent search_docs · get_doc semantic query

A save snapshots and embeds the doc; a query embeds the question and matches by meaning. Docs are open-read org-wide — tags shape what search returns, they don't gate access.

Edits sync in realtime through a per-document Durable Object and are debounced into snapshots; each save writes a revision and enqueues a reindex job. The consumer renders the blocks to Markdown, chunks them heading-aware, embeds each chunk with Workers AI, and upserts the vectors into Vectorize keyed by chunk. At query time, search_docs embeds the question and returns the closest passages — and Markdown mirrored from GitHub repos flows through the very same pipeline, so code-adjacent docs are searchable too.

That's the whole machine.

One Worker, your context injected where it counts. Run it yourself or let us host it.