Work context, packaged for LLMs
UCP is an open format that turns a sprawling issue thread into a small, verifiable package your agent can load: facts, decisions, conflicts, hashed sources.
15× smaller, with decisions, conflicts and provenance intact.
Install
Run the whole toolchain as one self-hosted service, or pick the piece you need.
One container: REST API on /v1, MCP over Streamable HTTP on /mcp.
docker run --rm -p 8080:8080 -e GITHUB_TOKEN=ghp_yourtoken \
ghcr.io/ucpcore/ucp-server:latestSame server, no Docker. The PyPI package is ucpcore-server; the command is ucp-server.
uvx --from ucpcore-server ucp-serverThe CLI generator, the stdio MCP server, and the Python library.
pip install ucp-gen # ucp-gen github owner/repo#42, ucp-gen jira KEY-1pip install ucp-mcp # serve packages to agents over stdiopip install pyucp # import ucp: models, validation, renderingTypes, validation and canonical rendering for TypeScript.
npm install @ucpcore/coreGenerate a package from a real issue
By default no LLM is involved: the structure alone carries the facts, decisions and timeline. Decorations go to stderr; stdout stays pure JSON, so piping is always safe.
Works on any public GitHub issue or Jira ticket.
Every claim cites its sources; every source carries a sha256 hash.
The output validates against the schema before it is written.
Connect Cursor or Claude Code in 60 seconds
MCP is the pipe. UCP is what flows through it. Start the server, point your agent at it, done.
Start the server
Generates and caches packages on demand.
docker run --rm -p 8080:8080 \
-e GITHUB_TOKEN=ghp_yourtoken \
ghcr.io/ucpcore/ucp-server:latestAdd it to mcp.json
Cursor and Claude Code speak Streamable HTTP natively.
{
"mcpServers": {
"ucp": { "url": "http://localhost:8080/mcp" }
}
}Your agent now has generate_context,
list_contexts, get_context,
get_context_markdown, and submit_usage_receipt.
Ask it to load context for
owner/repo#123 or PROJ-123. Prefer plain HTTP?
The same server exposes POST /v1/generate and
POST /v1/receipt.
Deploying beyond localhost? Set
UCP_SERVER_API_KEY and send it as a Bearer
header — see the MCP reference.
Close the loop with Usage Receipts
Most context formats are one-way: producer ships a package, the agent reads it, and nobody learns what actually helped. UCP adds a Usage Receipt — a small JSON object that records which claims were cited, which were ignored, and how the task ended. The reference server uses that signal to warm-rank the next package for your team.
Step 1
Generate
Server assembles a UCP with ranked must_know
Step 2
Agent works
Cursor, Sidebar, or any MCP client uses cited claims
Step 3
Submit receipt
Claim ids only — no claim text, privacy-safe
Step 4
Warm rank
Cited claims gain salience; noise drops
Step 5
Next package
Same task, sharper ordering for your team
mk-1, mk-3 — used in the fix
mk-2 — not relevant this sprint
{ "receipt_version": "0.1.0", "package_id": "urn:uuid:7f9c…", "consumer": { "type": "mcp" }, "claims_cited": ["mk-1", "mk-3"], "claims_ignored": ["mk-2"], "gaps_needed": ["rate-limit docs"], "outcome": "task_completed" }
Salience delta
Measured on real issues
Same token estimator on both sides (~4 chars/token). "Raw thread" is the text you would otherwise paste into the model: title, body, comments, linked-PR bodies.
| Issue | Comments | Raw thread | UCP |
|---|---|---|---|
| microsoft/vscode#519 | first 200 of 596 | ~18,500 | ~1,200 |
| rust-lang/rust#158622 | 12 | ~4,450 | ~1,450 |
| pallets/flask#5961 | 4 | ~800 | ~700 |
| pallets/flask#5948 | 0 | ~500 | ~330 |
The win grows with thread size: a decade-long discussion collapses ~15× while keeping decisions, conflicts and provenance. On small issues the token count is similar, but the package is still structured, hashed and audience-aware. Reproduce with tools/benchmark_context.py; generated with ucp-gen 0.3.1, 2026-07-06.
What --llm adds
One call to any OpenAI-compatible endpoint extracts what exists only in prose. Guarantees hold: the package stays schema-valid, hallucinated citations are dropped, and if the endpoint is down you get the structural package with a warning.
On vscode#519, the enriched package records the dispute over whether Electron or VS Code's hard-coded styles are to blame, both positions citing specific hashed comments.
The request is not on the roadmap. Stated only in prose across a decade of comments, invisible to every structured GitHub field.
What's inside a package
One JSON document. Every consumer, human or model, gets the same predictable sections.
A canonical rendering algorithm turns any package into
a deterministic prompt. Under a token budget, salience defines
the truncation order (each claim MAY carry salience_method:
producer, graph, ranking, or llm).
Sources carry content_hash (sha256); consumers revalidate with
since + context_diff when the upstream changes.
A claim without sources is schema-invalid.