mikoriza/0.1-mock

The mycelium spec

Mikoriza turns Stellar apps into a shared capability pool. Alliance is not a slogan. If the app only has a UI, it is not in the mycelium. If the app exposes WebMCP tools, it is a node.

v0 mock · treat as live

00

Overview

Other agents call the node. That is the whole protocol. Humans keep the page. Agents get the tools. Same session, same state, same chain actions.

not a node

Landing page. Chat wrapper. DOM scrape. A button with no verb behind it.

a node

Live origin. WebMCP tools. describe_node returns the handshake. Domain verbs actually hit the chain.

  1. 1 · join a live alliance
  2. 2 · enter the check-in code
  3. 3 · copy the builder prompt
  4. 4 · graft the app you ship

01

Protocol

Current version is mikoriza/0.1-mock. The network is mocked. The graft is local. Follow it as if it were already live.

versionmikoriza/0.1-mock
transportWebMCP in the page. No backend MCP server for page actions — the page is the server.
allianceistanbul-2026 | organizma
identityHTTPS origin + stable tool names + handshake JSON

Required tools on every mikoriza node, plus the domain tools of whatever you actually built:

  • describe_nodeidentity

    App name, one-line purpose, alliance id, origin, protocol version. Returns the mycelium handshake.

  • list_capabilitiesindex

    Names + descriptions of tools this page currently exposes. The pool reads this, not the DOM.

02

WebMCP

On every live page of the app, register tools against document.modelContext or navigator.modelContext. Feature-detect. Do not assume the flag is on.

registerTool

const ctx = document.modelContext ?? navigator.modelContext
if (ctx?.registerTool) {
  await ctx.registerTool({
    name,
    description,
    inputSchema,   // JSON Schema
    annotations,   // readOnlyHint / destructiveHint
    execute,       // in-page, same session as the UI
  }, { signal })
}

execute runs in-page and uses the user's session. Return structured JSON or { content: [{ type: "text", text }] }. Fail loud — return an error object, do not throw into the void.

Pass AbortSignal so the tools drop on unmount. Keep names stable across reloads.

03

Capabilities

Each tool is a verb the app can actually perform. Never a CSS class. Never a screenshot of a button.

capability

{
  name: "quote_swap",           // stable snake_case verb
  description: "Quote a swap",  // what an agent can DO
  inputSchema: {
    type: "object",
    properties: { /* typed fields */ },
    required: [/* no mystery bags */]
  },
  annotations: { readOnlyHint: true },
  execute: async (input) => {
    // same logic the UI uses
    return { content: [{ type: "text", text: JSON.stringify(result) }] }
  }
}
fieldrule
nameStable snake_case verb: quote_swap, send_payment, mint_subtoken.
descriptionWhat an agent can do. Not what the button looks like.
inputSchemaJSON Schema. Required fields listed. No mystery bags.
annotationsreadOnlyHint, destructiveHint, idempotentHint, openWorldHint.
executeCall the same logic the UI uses. Same session, same chain.

04

Handshake

Until the network exists, the graft is local. describe_node returns this payload. If twenty teams at a hackathon do that, we do not have twenty demos. We have one Stellar capability pool with twenty hyphae.

describe_node

{
  "protocol": "mikoriza/0.1-mock",
  "alliance": "<istanbul-2026 | organizma>",
  "app": "<what we shipped>",
  "origin": "<https origin of the live UI>",
  "tools": ["describe_node", "list_capabilities", "..."]
}

05

Alliances

An alliance is a live mycelium you graft onto. Joining one locks the builder prompt until the check-in code is entered. Switching alliances relocks it.

describe_node.alliance must be the joined id. Istanbul grafts onto this weekend's event. Organizma is treated as a live capability node, not a landing page.

06

This node

mikoriza itself is a node. The landing page registers four WebMCP tools on mount, using refs so join/unlock state is live without re-registering. Tools abort on unmount.

  • list_alliancesreadOnlyHint · idempotentHint

    List live alliances a builder can join. Includes join/unlock state of this tab.

    in { }

    out { protocol, selected, unlocked, alliances: [{ id, name, kicker, blurb, meta, href, live, joined }] }

  • join_alliance

    Join an alliance. Selecting a different alliance relocks the prompt. Unknown ids fail loud.

    in { id: "istanbul-2026" | "organizma" }

    out { joined: { id, name }, next: "Call unlock_prompt with the alliance code…" }

  • unlock_prompt

    Code is issued at check-in. Wrong code leaves the prompt locked. No alliance → fail closed.

    in { code: string }

    out { unlocked, alliance, protocol, prompt }

  • get_mikoriza_promptreadOnlyHint · idempotentHint

    Return the unlocked builder prompt for the joined alliance. Fails closed if still locked.

    in { }

    out prompt string, or a lock/join error

The unlocked prompt is PROMPT + alliance context. Agents can drive the same join → unlock → copy loop the UI exposes.

07

Graft

Ship a real Stellar integration, then expose it. Whatever we build must be callable by another agent on the same machine, in the same tab, without DOM scraping.

  1. 01Ship a real Stellar integration, then expose it. A tool with no chain behind it is copy, not capability.
  2. 02Prefer read tools first (quote, balance, lookup), then writes (sign, submit, mint). Mark writes with destructiveHint.
  3. 03Keep tool names stable across reloads. The pool cannot grow if every refresh renames the verbs.
  4. 04If WebMCP is missing in the browser, still write the tools behind a helper so they light up when the flag is on.
  5. 05Feature-detect. HTTPS. Pass AbortSignal so tools drop on unmount.
  6. 06Do not wrap the app in a chatbot. Do not replace the UI. Humans keep the page. Agents get the tools.

08

Raven

Use Stellar Raven MCP for every Stellar protocol, ecosystem, funding, SDK, or API fact. Do not guess. Tools: search, execute.

~/.cursor/mcp.json

{
  "mcpServers": {
    "stellar-raven": {
      "url": "https://raven.stellar.org/mcp"
    }
  }
}

Endpoint: https://raven.stellar.org/mcp. Classify the claim, search the right family (stellarDocs / scout / lumenloop / skills), never guess operation ids, write one execute script, read payloads under .data, treat soft-empty as inconclusive.