AI Resources

MCP

OKE serves MCP on :6535 so agents can operate a running app, and apps consume external MCP servers as allowlisted tools on the same fx.call path.

Two directions, same execution model

MCP is a surface of the model, not the model itself.

Two genuinely distinct things share the protocol in OKE:

  1. Gate Element (MCP Provider role): Your app exposes Flows as MCP tools on port 6535 (or via mcp.tool() + OAuth 2.1 Authorization Server) so external AI agents (Claude, ChatGPT) can read the Manifest and call declared Flows.
  2. AI Element (MCP Client role): Your app consumes external MCP tool servers via ai.mcpServer(...), routing tool calls through fx.call inside prompts and agents.

OKE does not create separate security models for users, operators, and agents. They enter the same execution model through different triggers and planes.

The server on 6535 speaks JSON-RPC over HTTP (MCP protocol 2024-11-05), requires a Bearer token even on localhost, and never forwards that token upstream — adapters receive structured operator ids instead.

The one rule

MCP inherits the operator's capability and can never exceed it. Server-level controls alone are exactly where the confused-deputy problem lives, so access descends to the tool, the operation, and each parameter.

Read tools

Default-safe — they return inert data envelopes, never live handles:

ToolReturnsScope (any of)
oke.manifest.getThe current Manifest cataloguemcp:manifest:read · console:manifest:read
oke.schema.getIn/out/error schemas for one flow (flowId)mcp:schema:read · console:manifest:read
oke.effects.getDeclared effects for one flow (flowId)mcp:effects:read · console:manifest:read
oke.traces.listRecent runs (limit ≤ 200, optional flowId)mcp:traces:read · console:runs:read
oke.traces.getOne run/trace record (runId)mcp:traces:read · console:runs:read

Write tools — confirmed, every single call

Two actions are write-class, and each call needs a fresh, single-use confirmation — there is no session-level consent cache to leak:

ToolDoesScope (any of)
oke.action.invokeInvoke a flow by id (sensitive)mcp:action:invoke · console:flows:invoke
oke.action.structural_proposePropose a structural diff — reviewable, not appliedmcp:action:structural · console:structural:propose

Request a confirmation token

oke.action.confirm with the target tool, the exact args, and a human reason — it returns a single-use token.

Call the write tool

Pass the token as confirmToken plus the phrase CONFIRM in confirmation. Token, phrase, args, and principal must all match what was confirmed.

The token dies

Consumed tokens cannot be replayed; the next write needs a new confirmation. A mismatch fails with write tool requires fresh human confirmation and the confirmVia hint.

Structural changes arrive as diffs

oke.action.structural_propose is how an agent suggests a file change: it takes title, relativePath, and contents, and produces a reviewable diff for a human — it is never applied to the tree. This is the boundary that lets an agent propose boldly while a human stays the one who merges.

The security model

LayerEnforcement
AuthenticationBearer session token required — even on 127.0.0.1
Scope inheritanceconsole:* / mcp:* expand to every declared tool scope
Per-tool ACLEach tool declares required scopes + read/write class
Per-parameter rulesmaxLength, enum allow-lists, forbidden parameters
Token hygieneCaller token never forwarded — structured operator ids only
ConfirmationSingle-use, per call, phrase + token + args bound

Docs MCP — a second, docs-only server

oke dev also boots okengine-docs-mcp on port 6536 — the same protocol, but exposing the documentation itself instead of a live Manifest. It is how an agent answers "how do I … in OKE?" from the real pages rather than its training data.

FactValue
Port6536 (moves upward when busy)
AuthNone — public documentation, read-only
EndpointPOST http://127.0.0.1:6536/mcp
HealthGET http://127.0.0.1:6536/health
Toolsoke.docs.search · oke.docs.get
{
  "mcpServers": {
    "okengine-docs": { "url": "http://127.0.0.1:6536/mcp" }
  }
}

The docs content ships inside the okengine package, so the index your agent searches is exactly the version you have installed. If the surface cannot boot (missing content, busy port), oke dev prints Docs MCP skipped — … and continues — docs search never takes your dev session down.

Consume — ai.mcpServer

Your app can call other MCP servers. Those tools are not a second loop — they join fx.ask / ai.agent the same way a Flow tool does.

export const github = ai.mcpServer("github", {
  url: "https://mcp.example/github",
  auth: { bearer: githubToken },
  tools: ["create_issue"], // required allowlist
});

await fx.ask(triage, input, { tools: [github.tool("create_issue")] });
RuleMeaning
Allowlisttools is required. Extra names from tools/list are dropped.
Capabilitymcp:<server>/<tool> on effects.calls — undeclared throws OKE1007.
Transporturl (Streamable HTTP) or command + args (stdio). Not both.
CancelHTTP aborts the fetch / SSE stream. stdio sends notifications/cancelled then kills the process.

Console draws each declared server as one AI node on the flow graph; Units chips read Call github → create_issue; traces label the effect MCP call. There is no separate MCP page or connect UI.

Learn more

  • Agent contracts — what agents are taught about the system they operate
  • Flow — the effects the MCP reads back

Next

On this page