Reef
Reef is the door in front of your MCP servers. An agent connects once, with its Trellis grant token, and sees only the tools its grant allows. Every call it makes is decided by Trellis's three checks and written to the Trellis ledger before anything is forwarded.
Package: reef-mcp. It depends on trellisd and runs Trellis in the same
process.
pip install reef-mcp
reef demo the-door
What it does
| A persona-based gateway | Reef | |
|---|---|---|
| Tool list | A fixed bundle per persona | Built per request from what the grant allows |
| A tool outside the grant | Listed, then fails | Never listed; a call is denied at the door |
| Downstream credentials | A secret per server, often the agent's | Per server: the person's own token (obo), the agent's own (agent), or a service credential only Reef holds (brokered) |
| Masks and row filters | The server's problem | Applied by Reef to the result, and passed to the server in _meta so it can push them down |
| Audit | Per server, if at all | Every list and call in one hash-chained ledger |
On tools/list, Reef runs the three checks for every tool it fronts (without a ledger
entry each) and writes one tools.listed event naming what it showed and what it hid.
On tools/call:
- Trellis decides. The decision event is written first; if it can't be, the answer is a deny.
- A deny returns the check that refused and who to ask: the contract's owner, the agent's owner, or the person who gave the grant. Reef records that it blocked the call, and nothing reaches the server.
- Reef gets the credential the server's mode calls for. The ledger records the exchange, never the token.
- Reef writes the enforcement event, and forwards only once that write succeeds.
- It masks columns and filters rows in the result, and writes the outcome before the agent sees it. A result it can't record, or can't apply the obligations to, is held back.
trellisd trace <event> shows a decision together with what the door did with it.
Configure
reef.yaml lists the servers behind Reef:
reef:
servers:
ledger:
url: https://ledger.internal/mcp
credential: obo # the person's own token, exchanged at their IdP
audience: ledger-mcp
tools:
journal_entries: {action: query}
post_adjustment: {action: write}
hr:
url: https://hr.internal/mcp
credential: brokered # a service credential Reef holds
credential_env: REEF_HR_TOKEN
tools:
headcount: {action: read}
payroll: {action: read}
Each tool's address is mcp://<server>/<tool> unless it names another resource. A
Trellis contract binds that address, so the contract says what the tool is, who may use it
and what gets masked. A tool no contract binds is denied and never listed; a tool the
server offers and reef.yaml doesn't name is hidden.
Agents see each tool as <server>_<tool>, a name every MCP client accepts.
reef serve --config reef.yaml --trellis trellis/ --db postgresql://... \
--key trellis.key --trellis-port 8180
Agents get their grant token from Trellis's token endpoint (POST /token) and send it
to Reef as Authorization: Bearer <grant token>. --trellis-port serves that endpoint
from Reef's own process, which obo mode needs: the person's sign-in is held in memory
only, so the endpoint that takes it and the door that uses it must be one process.
For trying it out, reef sample ledger|hr runs the sample MCP servers, and
quickstart/ runs the whole thing with docker compose up.
Limits in v0.1
- Trellis runs inside Reef. A Reef in front of a remote Trellis, over AuthZEN, comes later.
- Reef applies masks and row filters to results shaped as rows: a list of objects, or an object holding one. Any other shape, when there's something to apply, is held back.
- The person's sign-in is held in memory for obo mode, so a restart means signing in again.
Metadata
Release files for reef-mcp 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| reef_mcp-0.1.0.tar.gz | 35.4 kB | Without provenance | Details for reef_mcp-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| reef_mcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for reef_mcp-0.1.0-py3-none-any.whl |
Total release size: 71.6 kB
Release files / reef_mcp-0.1.0.tar.gz
| Download URL | reef_mcp-0.1.0.tar.gz |
|---|---|
| Size | 35.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b19f30d30f31436963571d6ec12e4bff98f222c18825a40ca474ed821dca6d07
|
|
BLAKE2b-256 checksum How to use checksums |
dd459ce58b8f832d16a98e7351ad6573055df1328cfc7a9a747780819d88e8f1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / reef_mcp-0.1.0-py3-none-any.whl
| Download URL | reef_mcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 36.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e1ad39c39475f14adb42935e12f124d1bc4c9e6d8bea3d3730fb7a7569a1f6d1
|
|
BLAKE2b-256 checksum How to use checksums |
6666daba18df8675f5010c102f5008a11da4387693714324a4ba9e24658b197a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Security for reef-mcp 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.