Search docs

Search the Vexo developer documentation

Get the ring

Ecosystem

MCP Marketplace

Publish a context server so agents can use Vexo data, with the wearer holding the keys.

Vexo ring in graphite on a dark background
vexo mcp · consented context for agents

What an MCP server sees

A marketplace server is a standard MCP server with one difference: every tool call arrives with a wearer-scoped token, vx_user_9f2k…, minted from a live grant. Your server never holds credentials of its own for a wearer. If the grant covers the scope, the call succeeds. If it does not, the platform rejects it before your handler runs.

Three tool types are exposed to agents. You implement the handlers, Vexo enforces the scope boundary around them.

NameTypeDescription
context.readtoolOne-shot read of a derived metric window the wearer has granted, for example the last 24 hours of HRV. Agents call it, get typed JSON, and the read is logged to the wearer's activity feed.
context.subscribetoolA live stream of granted signals for the duration of an agent session. Closes with code 4403 the moment the wearer revokes, mid-message if necessary.
context.summarizetoolA server-side rollup, for example "sleep quality this week: declining". Your code shapes the summary, Vexo enforces that only granted families feed it.

Every invocation is logged to the wearer's activity feed with the tool name and scope used.

Scaffold a server

  1. Scaffold the project

    One command creates a typed project with the manifest, a sample tool, and a simulated wearer for local runs.

    npx @vexoring/create-mcp sleep-coach
    
    # ✔ Scaffolded sleep-coach/
    #   vexo.mcp.ts        tool definitions
    #   mcp.manifest.json  scopes, retention, pricing
    #   .env.example       VEXO_CLIENT_ID, VEXO_APP_TOKEN
  2. Define tools

    Tools live in vexo.mcp.ts. Each declares the scopes it needs, an input schema, and a handler that receives a wearer-scoped SDK client.

    Tool definitions
    vexo.mcp.ts
    import { defineServer, tool } from "@vexoring/create-mcp";
    import { z } from "zod";
    
    export default defineServer({
      name: "sleep-coach",
    
      tools: [
        tool({
          name: "context.read",
          description: "Read the wearer's sleep and HRV window.",
          scopes: ["biometrics:hrv", "biometrics:temp"],
          input: z.object({
            window: z.enum(["24h", "7d", "30d"]).default("7d"),
          }),
          async handler({ window }, { vexo }) {
            const hrv = await vexo.biometrics.read("hrv", { window });
            return { window, hrv: hrv.summary }; // e.g. { median: 61, trend: "up" }
          },
        }),
    
        tool({
          name: "context.summarize",
          description: "Plain-language sleep readiness for this morning.",
          scopes: ["biometrics:hrv"],
          async handler(_, { vexo }) {
            const night = await vexo.biometrics.read("hrv", { window: "24h" });
            return {
              readiness: night.summary.median > 55 ? "recovered" : "take it easy",
            };
          },
        }),
      ],
    });
  3. Run locally

    vexo dev serves the MCP endpoint with a simulated wearer whose grants you can toggle, so you can test revocation without a physical ring.

    vexo dev
    
    # ▸ sleep-coach listening on http://localhost:7823/mcp
    # ▸ 2 tools registered: context.read, context.summarize
    # ▸ scopes in manifest: biometrics:hrv, biometrics:temp
    # ▸ simulated wearer "test-wearer-01" granted all scopes

Manifest reference

The manifest is your public contract. It is rendered word for word on the wearer's grant screen and checked against your code at review time, so write it as the promise it is.

mcp.manifest.json
{
  "name": "sleep-coach",
  "version": "1.2.0",
  "description": "Morning readiness summaries from overnight HRV and skin temperature.",
  "scopes": ["biometrics:hrv", "biometrics:temp"],
  "dataRetention": {
    "policy": "ephemeral",
    "maxSeconds": 0
  },
  "pricing": {
    "model": "per-call",
    "amountUsd": 0.002
  },
  "endpoints": {
    "mcp": "https://sleep-coach.yourapp.com/mcp"
  }
}

Manifest fields

NameTypeDescription
namerequiredstringUnique slug in the marketplace, lowercase with hyphens. Shown to wearers on the grant screen exactly as written.
scopesrequiredstring[]Every scope your tools reference, and nothing more. A tool that requests a scope missing from this list fails to register.
dataRetentionrequiredobjectDeclared policy: ephemeral, session, or stored with maxSeconds. Wearers see it verbatim, and review checks your code against it.
pricingobjectper-call, subscription, or free. Billed to the calling agent's owner, never to the wearer.Default: free

Changing scopes or dataRetention in a new version triggers re-review and re-consent from every wearer.

Review and publish

POST/v1/marketplace/servers

Submit with vexo publish or the endpoint above. Review usually takes two business days and holds three bars: scope minimality, every scope in the manifest must be exercised by a tool. Retention honesty, your code must match the declared dataRetention policy. Plain language, descriptions must say what the server does in words a wearer can act on.

Revenue

Paid servers bill the calling agent's owner per call or per month, set in the manifest's pricing block. Vexo takes 15 percent, pays out monthly at a 25 dollar minimum, and never charges the wearer. Usage and earnings live in the developer dashboard next to your consent metrics, because in this marketplace the two rise together.

Ship something people would consent to twice.