Mycelio is the binary layer agents use instead of HTTP+JSON. One persistent connection gives an agent two things: FETCH any public URL as clean Markdown (~30× fewer tokens than raw HTML), and ROUTE calls into signed vendor manifests without touching their docs. Every response is Ed25519-signed by the directory.
myc://mycelio.prowl.world:4242
100 tests · Apache 2.0
v0 — no major agent runtime speaks this yet
Point Mycelio at any public URL. The daemon fetches it, extracts the main content as Markdown locally with trafilatura, falls back to Jina Reader for SPAs and PDFs when needed, and returns it inside a signed binary envelope. No API key. No SDK on the vendor's side. Cached 24 hours.
curl https://mycelio.prowl.world/r/<any-url># pip install mycelio
import asyncio
from mycelio import MycelioClient
ROOT_PUBKEY = bytes.fromhex(
"23f6ebbc8faddb7ee8c9dedf2ef8e81057fb7d0bbace6ba26523452ef739c20c"
)
async def main():
async with MycelioClient.connect(
"mycelio.prowl.world", 4242, root_pubkey=ROOT_PUBKEY,
) as cli:
page = await cli.fetch("https://news.ycombinator.com")
print(page.content[:400])
print(f"\n→ {len(page.affordances)} affordances extracted")
asyncio.run(main())
The response carries clean Markdown and a list of typed affordances (links, forms) the agent can act on — relative URLs are already resolved against the page. SPAs and PDFs that trafilatura can't parse fall through to Jina Reader transparently.
Measured against news.ycombinator.com on 2026-05-23. Numbers vary by page — content-heavy docs sites compress harder; static landing pages compress less. The shape holds: clean Markdown is dramatically smaller than the HTML it came from.
The whole invoke path is built around one artifact: a small signed file that points at the HTTP API the vendor already serves. Here's a representative Mycelio manifest, decoded into a readable form:
# stripe-payments.myc · 412 bytes signed
service: stripe.com
title: Stripe Payments API
backend: https://api.stripe.com/v1
auth: bearer-token (Authorization header)
endpoints:
- op: charge
method: POST /charges
in: { amount: int, currency: str, source: str }
out: { id: str, status: str }
- op: refund
method: POST /refunds
in: { charge_id: str, amount: int }
out: { id: str, status: str }
signatures:
vendor: ed25519:9f8a3d...
directory: ed25519:1b4c7e...
Wire-encoded as binary frames it's 412 bytes. You sign it with your Ed25519 key. The directory co-signs it with the root key. Your HTTP backend stays untouched — Mycelio just describes how it can be reached. No SDK, no server to run, no integration to maintain.
This is v0. The reference daemon runs at
myc://mycelio.prowl.world:4242. The Python SDK is on
PyPI. 100 tests pass end-to-end. The wire format is stable enough to
build against.
Shipped: spec v0, binary frame codec, TLS support,
async daemon, vendor manifests with Ed25519 dual signing,
INSPECT, ROUTE, and FETCH
verbs working end-to-end (FETCH with affordance extraction + Jina
fallback). Next:
Prowl Design — auto-generate
signed manifests from your existing OpenAPI.
But to be straight with you, the things this is not yet:
The FETCH side dodges the chicken-and-egg — it works on
any URL on the public web from day one, no vendor adoption required.
That's why we shipped it first.
What we're betting on: as agents move from "tool-loop inside an IDE" to "autonomous, calling thousands of APIs a session," the chicken-and-egg flips. The only protocol that can scale to "every SaaS on the internet" is one where the vendor implements nothing — because the long tail of vendors will not deploy bespoke servers per agent runtime. If that thesis is right, this becomes the layer for it.
If the thesis is wrong: the directory's HTTP API still works, your existing OpenAPI still works, and you can ignore Mycelio. Taking the protocol bet costs you a manifest file you can sign in five minutes and revoke any time.
MCP and Mycelio operate at different layers and we think they're complementary, not competitive. MCP shines when the agent operator already chose your tool — the user installed your MCP server, the agent is in a tool-loop, parameters are known. Mycelio is for the layer before that: public discovery and invocation across services the agent didn't know about at startup.
That said, the technical trade-offs differ in places that matter:
DISCOVER)
We're not trying to replace MCP for tool-use inside agent runtimes, A2A for agent-to-agent messaging, or OpenAI's function-calling for proprietary tool syntax. Mycelio sits one layer earlier: public discovery and signature-rooted invocation for backends that already speak HTTP.
The full composition — discover services, fetch a page, invoke an op — happens in one TCP connection. No extra TLS handshakes between verbs, one signature chain, one auth context:
async with MycelioClient.connect(
"mycelio.prowl.world", 4242, root_pubkey=ROOT_PUBKEY,
) as cli:
# 1. find payment APIs
matches = await cli.discover(query="payment", min_score=80)
# 2. read a candidate's site to evaluate it
page = await cli.fetch(f"https://{matches.results[0].name}")
if "x402" in page.content.lower():
# 3. pull the manifest and invoke it
m = await cli.inspect(matches.results[0].service_id)
resp = await cli.route(m, "charge", {"amount": 500, "currency": "usd"})
print(resp.json())
DISCOVER + FETCH + INSPECT +
ROUTE in one session. End-to-end signature verification.
Full demos in
examples/.
Wire spec:
protocol-v0.md.
Seven verbs are implemented end-to-end today; four are reserved in the spec for future use. Reserved doesn't mean "coming soon" — it means "the byte is allocated so an implementation can grow into it later without breaking compatibility."
Manifest format: manifest-v0.md
Mycelio is Apache 2.0. The wire spec, frame codec, Python SDK, and reference daemon all live in the public GitHub repo. Implementations in Go, Rust, JS are welcome.
The honest part: right now there's only one directory
running Mycelio in production, and that's
Prowl. The daemon at
myc://mycelio.prowl.world:4242 is Prowl's. The Ed25519
root key that co-signs every manifest is Prowl's. The spec doesn't
assume one operator, but until someone else stands one up, "Mycelio"
and "Prowl's binary protocol" mean the same thing in practice. We'd
rather say that out loud than pretend otherwise.
Lock-in worry: your manifest can be served by any future directory, your existing HTTP API is the source of truth that survives any of this, and you can revoke at any time.
cli.fetch(url) to read the web in ~700 tokens per page instead of 20,000. The Python SDK is on PyPI: pip install mycelio.