Jarvis Docs
API Reference

Public MCP Edge

Reference for the public machine-to-machine MCP surface

Public MCP Edge

Phase 13.5 keeps the public MCP edge as a real public execution surface while adding deployment parity across development, hosted, and local-tunnel backends. External clients can:

  • discover public-safe agent entries with ortho.agents.v1.list
  • invoke approved public agents with ortho.agents.v1.invoke
  • read public-safe runtime posture with ortho.system.v1.info
  • poll long-running public work with tasks/get and tasks/result

The web host remains transport-thin. It authenticates, validates, and delegates into the canonical public runtime rather than acting as a second execution harness.

Endpoints

EndpointMethodPurpose
/mcpPOSTStreamable HTTP MCP transport with JSON-RPC framing for initialize, tools/list, tools/call, tasks/get, and tasks/result
/.well-known/oauth-protected-resource/mcpGETProtected Resource Metadata for the public MCP resource
/.well-known/oauth-authorization-server/mcpGETAuthorization Server Metadata for the public MCP resource

Deployment parity

Phase 13.5 preserves one public MCP contract across all supported deployment backends:

  • development uses the app-hosted runtime directly
  • local_tunnel forwards only already-admitted public calls into the local runtime
  • hosted resolves the request into a tenant-local hosted runtime

Clients do not switch endpoints, tools, auth posture, or task semantics when the backend changes. The only public-safe deployment distinction surfaced to callers is server.backendMode in ortho.system.v1.info, which can be development, local_tunnel, or hosted.

Admission posture

  • /mcp requires OAuth bearer posture before any tool mapping, task lookup, or runtime dispatch.
  • Admission validates request schema, bearer presence, token validity, audience, origin, and scopes.
  • External callers are represented as ExternalClient subjects at the boundary.
  • Public tool names stay namespaced as ortho.* and map once onto the canonical flat internal capability surface.
  • Agent invoke scopes are binding-aware: ortho.agents.v1.invoke always requires ortho.agents.invoke, plus any requested memory-tier scopes derived from the binding payload.
  • The public edge remains the only authority for auth, quota, rate-limit, and audit posture even when the selected backend is local_tunnel or hosted.

Phase 13.5 availability

tools/list returns only the intersection of caller scopes and current-phase-enabled public mappings.

Enabled tools

Public namePurposeRequired scopeTask support
ortho.memory.v1.putAppend or supersede one source-local STM/LTM entrytier-specific write scopenone
ortho.memory.v1.getFetch one source-local STM/LTM entrytier-specific read scopenone
ortho.memory.v1.searchSearch source-local STM/LTM entriestier-specific read scopenone
ortho.memory.v1.deleteSoft-delete one source-local STM/LTM entrytier-specific delete scopenone
ortho.memory.v1.compactRun external-only summarize or extract_facts compactionstrategy-derived write scopeoptional
ortho.agents.v1.listDiscover public-safe agent catalog entriesortho.system.readnone
ortho.agents.v1.invokeInvoke an approved public agentortho.agents.invoke plus any binding-derived memory scopesoptional
ortho.system.v1.infoRead public-safe runtime metadataortho.system.readnone

The tool list and request/response shapes remain the same across development, local_tunnel, and hosted backends.

Public agents

Phase 13.4 continues to expose public-safe agent aliases instead of leaking internal runtime IDs.

Current catalog entries:

Agent IDPurposeInput modesMemory binding
engineering.workflowStructured engineering-orchestration requeststext, packet, jsonsupported (ltm read, stm write)

Example ortho.agents.v1.list response:

{
  "jsonrpc": "2.0",
  "id": "rpc-list-agents-1",
  "result": {
    "agents": [
      {
        "agentId": "engineering.workflow",
        "title": "Engineering Workflow",
        "description": "A public-safe orchestration agent for structured engineering tasks.",
        "inputModes": ["text", "packet", "json"],
        "memoryBinding": {
          "supported": true,
          "readTiers": ["stm", "ltm"],
          "writeTiers": ["stm"]
        },
        "execution": {
          "taskSupport": "optional",
          "asyncThreshold": "long_running_only"
        }
      }
    ]
  }
}

Task methods

When a public invoke is accepted into the async path, the edge returns a task handle and clients poll via the MCP task methods.

tasks/get

{
  "jsonrpc": "2.0",
  "id": "rpc-task-get-1",
  "method": "tasks/get",
  "params": {
    "taskId": "550e8400-e29b-41d4-a716-446655440100"
  }
}

Example result:

{
  "jsonrpc": "2.0",
  "id": "rpc-task-get-1",
  "result": {
    "taskId": "550e8400-e29b-41d4-a716-446655440100",
    "toolName": "ortho.agents.v1.invoke",
    "subjectNamespace": "app:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
    "canonicalRunId": "550e8400-e29b-41d4-a716-446655440101",
    "status": "running",
    "submittedAt": "2026-03-14T00:00:00.000Z",
    "updatedAt": "2026-03-14T00:00:01.000Z"
  }
}

tasks/result

{
  "jsonrpc": "2.0",
  "id": "rpc-task-result-1",
  "method": "tasks/result",
  "params": {
    "taskId": "550e8400-e29b-41d4-a716-446655440100"
  }
}

Example terminal result:

{
  "jsonrpc": "2.0",
  "id": "rpc-task-result-1",
  "result": {
    "taskId": "550e8400-e29b-41d4-a716-446655440100",
    "status": "completed",
    "result": {
      "runId": "550e8400-e29b-41d4-a716-446655440101",
      "outputs": [
        {
          "type": "text",
          "text": "Structured public result..."
        }
      ]
    }
  }
}

MCP examples

The examples below use a concrete namespace shape. Replace the bearer token and namespace with values derived for your client.

Authorization: Bearer eyJhbGciOi...
Namespace: app:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Endpoint: POST /mcp

initialize

{
  "jsonrpc": "2.0",
  "id": "rpc-init-1",
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-11-25",
    "clientInfo": {
      "name": "example-client",
      "version": "1.0.0"
    }
  }
}
{
  "jsonrpc": "2.0",
  "id": "rpc-init-1",
  "result": {
    "protocolVersion": "2025-11-25",
    "serverInfo": {
      "name": "Nous Public MCP",
      "version": "0.0.1"
    },
    "capabilities": {
      "tools": {
        "listChanged": false
      },
      "tasks": {}
    }
  }
}

tools/list

{
  "jsonrpc": "2.0",
  "id": "rpc-tools-1",
  "method": "tools/list",
  "params": {}
}

Example result for a token with ortho.system.read but not ortho.agents.invoke:

{
  "jsonrpc": "2.0",
  "id": "rpc-tools-1",
  "result": {
    "tools": [
      {
        "name": "ortho.agents.v1.list",
        "version": "1.0.0",
        "description": "Public MCP tool ortho.agents.v1.list.",
        "capabilities": ["external"],
        "permissionScope": "external",
        "inputSchema": {},
        "outputSchema": {}
      },
      {
        "name": "ortho.system.v1.info",
        "version": "1.0.0",
        "description": "Public MCP tool ortho.system.v1.info.",
        "capabilities": ["external"],
        "permissionScope": "external",
        "inputSchema": {},
        "outputSchema": {}
      }
    ]
  }
}

ortho.agents.v1.invoke

{
  "jsonrpc": "2.0",
  "id": "rpc-invoke-1",
  "method": "tools/call",
  "params": {
    "name": "ortho.agents.v1.invoke",
    "arguments": {
      "agentId": "engineering.workflow",
      "input": {
        "type": "text",
        "text": "Summarize the current public invoke contract."
      },
      "memory": {
        "namespace": "app:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
        "readTiers": ["ltm"],
        "writeTiers": ["stm"]
      },
      "executionMode": "async",
      "idempotencyKey": "invoke-engineering-workflow-001"
    }
  }
}

Async acceptance example:

{
  "jsonrpc": "2.0",
  "id": "rpc-invoke-1",
  "result": {
    "mode": "task",
    "task": {
      "taskId": "550e8400-e29b-41d4-a716-446655440100",
      "status": "queued",
      "runId": "550e8400-e29b-41d4-a716-446655440101"
    }
  }
}

Synchronous completion example for executionMode: "sync" when the run finishes within the sync threshold:

{
  "jsonrpc": "2.0",
  "id": "rpc-invoke-2",
  "result": {
    "mode": "completed",
    "runId": "550e8400-e29b-41d4-a716-446655440102",
    "outputs": [
      {
        "type": "text",
        "text": "Public agents can return inline results when the request completes within the sync threshold."
      }
    ]
  }
}

ortho.system.v1.info

{
  "jsonrpc": "2.0",
  "id": "rpc-system-1",
  "method": "tools/call",
  "params": {
    "name": "ortho.system.v1.info",
    "arguments": {}
  }
}
{
  "jsonrpc": "2.0",
  "id": "rpc-system-1",
  "result": {
    "server": {
      "name": "Andre Hosted Nous",
      "phase": "phase-13.5",
      "backendMode": "hosted",
      "protocolVersion": "2025-11-25"
    },
    "features": {
      "publicAgents": true,
      "publicSystemInfo": true,
      "publicTasks": true,
      "publicCompactAsync": true
    },
    "limits": {
      "maxInvokeInputBytes": 8192,
      "maxSearchTopK": 50,
      "maxTaskPollWindowSeconds": 300
    },
    "quotas": {
      "invokePerMinute": 10,
      "compactPerMinute": 10
    },
    "tasks": {
      "supportedMethods": ["tasks/get", "tasks/result"],
      "toolSupport": {
        "ortho.agents.v1.invoke": "optional",
        "ortho.memory.v1.compact": "optional"
      }
    }
  }
}

The response shape stays the same across backends. Only public-safe deployment details such as server.name, server.phase, and server.backendMode vary.

Carried-forward memory examples

ortho.memory.v1.put supersede with idempotencyKey

Use mode: "supersede" when the new record replaces an existing one. The gateway writes the new record, marks the predecessor as superseded, and treats the idempotencyKey as the replay key for safe retries.

{
  "jsonrpc": "2.0",
  "id": "rpc-put-1",
  "method": "tools/call",
  "params": {
    "name": "ortho.memory.v1.put",
    "arguments": {
      "namespace": "app:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
      "tier": "stm",
      "content": "Use Tuesday morning for supplier follow-up.",
      "mode": "supersede",
      "supersedesEntryId": "entry-previous",
      "tags": ["crm", "follow-up"],
      "metadata": {
        "source": "public-mcp-example"
      },
      "idempotencyKey": "put-follow-up-002"
    }
  }
}

ortho.memory.v1.compact with extract_facts

extract_facts is the carried-forward fact-extraction strategy. It derives durable LTM facts from the selected STM window while preserving the source-local public-memory boundary.

{
  "jsonrpc": "2.0",
  "id": "rpc-compact-1",
  "method": "tools/call",
  "params": {
    "name": "ortho.memory.v1.compact",
    "arguments": {
      "namespace": "app:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
      "sourceTier": "stm",
      "strategy": "extract_facts",
      "maxEntries": 10,
      "idempotencyKey": "compact-facts-001"
    }
  }
}

Error behavior

Common public reject reasons in Phase 13.5:

Reject reasonMeaning
scope_insufficientThe bearer token does not include the scope required by the request or its memory binding posture.
namespace_unauthorizedThe request namespace or memory binding namespace does not match the namespace derived from the validated client identity.
memory_binding_forbiddenThe requested binding tiers are not allowed for the selected public agent.
agent_not_availableThe requested public agent alias is not allowlisted for this surface.
task_not_foundThe task does not exist for the requesting subject.
task_not_readyThe task exists but its terminal result is not available yet.
request_schema_invalidThe JSON-RPC request or tool arguments failed schema validation.
source_quarantinedThe source is quarantined or purged for durable mutation paths.
quota_exceededThe request exceeds the namespace + token quota window.
rate_limitedThe namespace + token has exceeded the allowed request rate for the tool.
deployment_not_resolvedThe public host did not map to a known development, hosted, or tunnel deployment target.
tunnel_envelope_invalidThe forwarded tunnel request failed signature, binding, or expiry validation.
tunnel_replay_detectedA tunnel nonce was already consumed and the request was rejected as a replay.

Operator configuration

Phase 13.5 adds deployment-seeding environment variables for hosted and local-tunnel routing:

VariablePurpose
NOUS_PUBLIC_BASE_URLBase URL used by the OAuth discovery documents for the public MCP edge.
NOUS_PUBLIC_MCP_HOSTED_BINDINGS_JSONSeeded hosted tenant bindings used to map a public host or user handle to a hosted backend.
NOUS_PUBLIC_MCP_TUNNEL_SESSIONS_JSONSeeded tunnel sessions used to map a public host or user handle to a local-tunnel backend.

See Configuration Schema for the accepted JSON shapes.

Runtime boundary

The public MCP edge is not a public-only business-logic stack. The host accepts HTTP and JSON-RPC traffic, the public gateway owns admission and audit posture, and admitted calls flow into the canonical gateway/runtime seam.

  • local_tunnel does not expose a raw local MCP server; it forwards only already-admitted public calls into the local runtime.
  • hosted resolves requests into tenant-local runtime state rather than proxying through shared mutable storage.
  • Long-running public work is projected through subject-scoped task records rather than a second status model.
  • Phase 13.5 still does not add any public promoted-tier tool or public path into internal-only promoted storage.

On this page