SharedOS API v0.1.0-alpha.3


SharedOS API / @aicoo/sharedos-mcp

@aicoo/sharedos-mcp

The SharedOS permission-filtered tool catalogue, served to external harnesses as a Model Context Protocol server.

npm install @aicoo/sharedos-mcp@next
Harness configuration declares a CONNECTION.
SharedOS declares the TOOLS.
SharedOS capabilities declare the AUTHORITY.
RuntimeHost is the only EXECUTION path.

This is the other half of the harness story. @aicoo/sharedos-adapters puts SharedOS in the model provider's seat and owns the turn loop; this package lets a vendor CLI keep its own loop and whatever model it is configured with, and connect to SharedOS as a tool server. Both converge on RuntimeHost.invokeTool, so neither adds a second permission path.

import { McpToolServer, openToolBridge } from "@aicoo/sharedos-mcp";
import { createStreamableHttpMcpServer } from "@aicoo/sharedos-mcp/node";

// Inside RuntimePlugin.run(request, host, signal):
const bridge = openToolBridge({
  executionId: request.executionId,
  context: { traceId: request.context.traceId, now: request.context.now },
  tools: request.tools, // already permission-filtered by the envelope
  host, // RuntimeHost: every call is re-authorized
});
const http = await createStreamableHttpMcpServer({
  server: new McpToolServer({ invoker: bridge }),
});
try {
  // ... point the harness at http.url ...
} finally {
  bridge.close();
  await http.close();
}

One name

ToolDefinition.name  =  SharedOS canonical tool ID  =  raw MCP Tool.name

There is no second identity in the published catalogue. A harness alias (mcp__sharedos__files_read) is presentation: it is recorded on the bridge for diagnosis, never on the ToolCall, so it cannot reach an authorization decision.

What crosses the boundary

PublishedToolDefinition carries name, description, inputSchema, outputSchema, MCP annotation hints, and catalogue provenance. It carries no requiredCapability, no resolveRequirement, no grants, no issuing authority, no namespace settings, no credentials, and no handler references.

The omission is load-bearing. Authorization is resource + action + context resolved from the arguments at call time, so two calls to one published tool routinely need different authority.

Refusals are results

A SharedOS denial comes back as an MCP tool error (isError: true), never as a transport error. A JSON-RPC error means the request could not be processed; a denial is a processed request whose answer is "no", and a harness needs to be able to report it and carry on. denied and failed stay distinguishable in the payload and in _meta["sharedos/status"].

Per turn, never global

The bridge is opened for one AccessContext, exposed for one turn, and torn down with it. A harness process that outlives its turn finds a shut door rather than a catalogue resolved for a turn that has ended.

Catalogue hashes

catalogHash = SHA-256(canonical JSON(tools sorted by canonical name))

Field participation is fixed by CATALOG_HASH_FIELDS, so two implementations cannot both claim to compute it and disagree. Two harnesses whose hashes match were served the same semantic tool set; two whose hashes differ cannot be compared until that is explained.

Full design: MCP toolshare and ADR 0014.

SharedOS is currently an 0.x prerelease.

Classes

McpToolServer

Defined in: mcp/src/server.ts:114

SharedOS's catalogue and authorization broker, spoken as MCP.

The server is transport-agnostic on purpose: it turns one JSON-RPC message into one JSON-RPC response, and knows nothing about stdio, HTTP, sessions, or processes. That is what lets the same translation be exercised deterministically in a unit test and then serve a live CLI without changing the code under test.

It holds no policy. Every tools/call is handed to the invoker, which puts it through RuntimeHost.invokeTool and the kernel; the server never decides that a call should be refused, and never decides that one should be allowed. Its one substantive job is translation, and the translation rule that matters is that a SharedOS refusal is a tool result, never a transport error -- see toCallToolResult.

Constructors

Constructor

new McpToolServer(options): McpToolServer

Defined in: mcp/src/server.ts:123

Parameters
ParameterType
optionsMcpToolServerOptions
Returns

McpToolServer

Accessors

initialized
Get Signature

get initialized(): boolean

Defined in: mcp/src/server.ts:136

Returns

boolean

protocolVersion
Get Signature

get protocolVersion(): string | undefined

Defined in: mcp/src/server.ts:132

The revision agreed with this client, once initialize has been answered.

Returns

string | undefined

Methods

handle()

handle(message, signal): Promise<JsonRpcResponse | undefined>>

Defined in: mcp/src/server.ts:147

Handle one JSON-RPC message.

Returns undefined for a notification, which is what JSON-RPC requires: a notification has no id and therefore no addressable reply, including when it is malformed.

Parameters
ParameterType
messageunknown
signalAbortSignal
Returns

Promise<JsonRpcResponse | undefined>


SharedOSToolBridge

Defined in: mcp/src/bridge.ts:72

A turn-scoped MCP tool broker.

The lifecycle is the whole design. ContextToolProvider exists so one user's MCP catalogue never mutates a registry shared with concurrent users, and this carries that invariant across the harness boundary: the catalogue is computed for one AccessContext, exposed for the length of one turn, and torn down with it. There is no long-lived SharedOS MCP server holding a union of every user's tools, because such a server would have to re-derive who is asking on every call, and would be wrong once.

After close, the bridge answers nothing. A harness process that outlives its turn -- and they do, on cancellation and on timeout -- finds a door that is shut rather than one that still opens onto a turn that has ended.

Implements

Constructors

Constructor

new SharedOSToolBridge(options): SharedOSToolBridge

Defined in: mcp/src/bridge.ts:82

Parameters
ParameterType
optionsOpenToolBridgeOptions
Returns

SharedOSToolBridge

Accessors

aliases
Get Signature

get aliases(): readonly ToolAliasRecord[]

Defined in: mcp/src/bridge.ts:98

Names the harness rewrote, in the order they were seen.

Carried here rather than on the ToolCall so it is structurally impossible for an alias to reach the kernel. A host that wants the diagnostic detail in its execution record reads it from the bridge afterwards; nothing on the authorization path can read it at all.

Returns

readonly ToolAliasRecord[]

closed
Get Signature

get closed(): boolean

Defined in: mcp/src/bridge.ts:102

Returns

boolean

Methods

catalog()

catalog(signal): Promise<{ catalogHash: string; executionId: string; tools: object[]; version: "1"; }>

Defined in: mcp/src/bridge.ts:106

The permission-filtered catalogue for this session.

Parameters
ParameterType
signalAbortSignal
Returns

Promise<{ catalogHash: string; executionId: string; tools: object[]; version: "1"; }>

Implementation of

McpToolInvoker.catalog

close()

close(): void

Defined in: mcp/src/bridge.ts:135

Returns

void

invoke()

invoke(invocation, signal): Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>

Defined in: mcp/src/bridge.ts:115

One call, re-authorized against the arguments actually presented.

Parameters
ParameterType
invocationMcpToolInvocation
signalAbortSignal
Returns

Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>

Implementation of

McpToolInvoker.invoke

Interfaces

BridgeKernel

Defined in: mcp/src/bridge.ts:155

The kernel surface a bridge needs when it is not running inside a turn.

Methods

invokeTool()

invokeTool(context, call, options?): Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>

Defined in: mcp/src/bridge.ts:160

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespaces?string[]
context.namespaceId?string
context.now?string
context.owner?{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purpose?string
context.traceId?string
call?{ arguments: JsonObject; id: string; requestedAt: string; tool: string; traceId: string; }
call.arguments?JsonObject
call.id?string
call.requestedAt?string
call.tool?string
call.traceId?string
options?{ signal?: AbortSignal; }
options.signal?AbortSignal
Returns

Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>

listPublishedTools()

listPublishedTools(context, options): Promise<{ catalogHash: string; executionId: string; tools: object[]; version: "1"; }>

Defined in: mcp/src/bridge.ts:156

Parameters
ParameterType
context{ actor: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; authority: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; enabledToolNamespaces: string[]; namespaceId: string; now: string; owner: { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }; purpose: string; traceId: string; }
context.actor{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.authority{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.enabledToolNamespacesstring[]
context.namespaceIdstring
context.nowstring
context.owner{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }
context.purposestring
context.traceIdstring
options{ executionId: string; signal?: AbortSignal; }
options.executionIdstring
options.signal?AbortSignal
Returns

Promise<{ catalogHash: string; executionId: string; tools: object[]; version: "1"; }>


BridgeToolInvoker

Defined in: mcp/src/bridge.ts:26

The effectful surface a bridge is allowed to reach.

Structurally satisfied by RuntimeHost, which is the intended binding: a bridge opened inside a turn puts every tools/call through the execution envelope, so the call is counted against the turn's budgets, checked against the effective catalogue, and re-authorized by the kernel -- the same path a native runtime's calls take, with no second enforcement path added for MCP.

Declared structurally rather than imported so this package does not depend on the runtime package. The dependency would be harmless; the absence is the point, because it makes it impossible for a bridge to reach any part of the turn machinery other than the one method that re-authorizes.

Methods

invokeTool()

invokeTool(call, options?): Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>

Defined in: mcp/src/bridge.ts:27

Parameters
ParameterType
call{ arguments: JsonObject; id: string; requestedAt: string; tool: string; traceId: string; }
call.argumentsJsonObject
call.id?string
call.requestedAt?string
call.tool?string
call.traceId?string
options?{ step?: number; }
options.step?number
Returns

Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>


BridgeTurnContext

Defined in: mcp/src/bridge.ts:31

What the bridge needs of the turn's sanitised context: identity, not authority.

Properties

PropertyModifierTypeDefined in
<a id="property-now"></a> nowreadonlystringmcp/src/bridge.ts:33
<a id="property-traceid"></a> traceIdreadonlystringmcp/src/bridge.ts:32

DeclareToolPolicyOptions

Defined in: mcp/src/policy.ts:17

What a run's tool surface actually was.

A conformance result reads very differently depending on the answer. "The kernel refused every violation" means one thing when the managed catalogue was the only way to have an effect, and almost nothing when the harness also had a shell. The policy is declared per run so a reader never has to infer which of those they are looking at, and parseToolPolicy refuses the combination that would let a run claim the first while being the second.

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-externaldirect"></a> externalDirect?readonlyreadonly string[]MCP servers the harness was configured with independently.mcp/src/policy.ts:24
<a id="property-harnesslocal"></a> harnessLocal?readonlyreadonly string[]The harness's own tools, which SharedOS never sees.mcp/src/policy.ts:22
<a id="property-managedmcp"></a> managedMcp?readonlyreadonly string[]SharedOS MCP endpoints. Defaults to the one this package serves.mcp/src/policy.ts:20
<a id="property-mode"></a> mode?readonly"strict" | "hybrid"-mcp/src/policy.ts:18

HarnessMcpConfigFile

Defined in: mcp/src/harness-config.ts:36

One generated file: what to write, and what a harness expects it to be called.

Properties

PropertyModifierTypeDefined in
<a id="property-contents"></a> contentsreadonlystringmcp/src/harness-config.ts:39
<a id="property-filename"></a> filenamereadonlystringmcp/src/harness-config.ts:38
<a id="property-harness"></a> harnessreadonlystringmcp/src/harness-config.ts:37

HarnessMcpConnection

Defined in: mcp/src/harness-config.ts:24

Harness configuration, which declares a CONNECTION and nothing else.

This is the architectural rule the whole boundary rests on, and it is worth stating where the files are generated:

Harness configuration declares a CONNECTION.
SharedOS declares the TOOLS.
SharedOS capabilities declare the AUTHORITY.
RuntimeHost is the only EXECUTION path.

So every emitter here produces a few lines naming a URL. None of them enumerate tools, and none of them can: the catalogue is resolved per turn from the access context, and a file on disk cannot know who is asking. A harness setting that looks like authorization -- Codex's enabled_tools, Claude's allowedTools -- is defense in depth and UX policy over a catalogue SharedOS already filtered, never the thing that decides.

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-name"></a> name?readonlystringThe server name the harness will namespace its aliases under.mcp/src/harness-config.ts:28
<a id="property-timeoutsec"></a> timeoutSec?readonlynumberPer-call timeout in the emitted config. Set by nothing today; see docs/open-items.md.mcp/src/harness-config.ts:30
<a id="property-token"></a> token?readonlystringBearer token for a sandboxed or remote harness.mcp/src/harness-config.ts:32
<a id="property-url"></a> urlreadonlystringThe Streamable HTTP endpoint the turn-scoped bridge is serving.mcp/src/harness-config.ts:26

JsonRpcErrorBody

Defined in: mcp/src/protocol.ts:61

Properties

PropertyModifierTypeDefined in
<a id="property-code"></a> codereadonlynumbermcp/src/protocol.ts:62
<a id="property-data"></a> data?readonlyunknownmcp/src/protocol.ts:64
<a id="property-message"></a> messagereadonlystringmcp/src/protocol.ts:63

JsonRpcFailure

Defined in: mcp/src/protocol.ts:73

Properties

PropertyModifierTypeDefined in
<a id="property-error"></a> errorreadonlyJsonRpcErrorBodymcp/src/protocol.ts:76
<a id="property-id"></a> idreadonlystring | number | nullmcp/src/protocol.ts:75
<a id="property-jsonrpc"></a> jsonrpcreadonly"2.0"mcp/src/protocol.ts:74

JsonRpcSuccess

Defined in: mcp/src/protocol.ts:67

Properties

PropertyModifierTypeDefined in
<a id="property-id-1"></a> idreadonlystring | numbermcp/src/protocol.ts:69
<a id="property-jsonrpc-1"></a> jsonrpcreadonly"2.0"mcp/src/protocol.ts:68
<a id="property-result"></a> resultreadonlyunknownmcp/src/protocol.ts:70

KernelToolBridgeOptions

Defined in: mcp/src/bridge.ts:167

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-context"></a> contextreadonlyobjectThe trusted context. Never built from anything the harness sent.mcp/src/bridge.ts:170
context.actorpublic{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-contracts/dist/access.d.ts:144
context.authoritypublic{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-contracts/dist/access.d.ts:157
context.enabledToolNamespacespublicstring[]-contracts/dist/access.d.ts:170
context.namespaceIdpublicstring-contracts/dist/access.d.ts:141
context.nowpublicstring-contracts/dist/access.d.ts:171
context.ownerpublic{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }-contracts/dist/access.d.ts:128
context.purposepublicstring-contracts/dist/access.d.ts:142
context.traceIdpublicstring-contracts/dist/access.d.ts:143
<a id="property-executionid"></a> executionIdreadonlystring-mcp/src/bridge.ts:171
<a id="property-kernel"></a> kernelreadonlyBridgeKernel-mcp/src/bridge.ts:168

McpServerInfo

Defined in: mcp/src/server.ts:58

Properties

PropertyModifierTypeDefined in
<a id="property-name-1"></a> namereadonlystringmcp/src/server.ts:59
<a id="property-version"></a> versionreadonlystringmcp/src/server.ts:60

McpToolInvocation

Defined in: mcp/src/server.ts:34

One tools/call, after the exposed name has been mapped back to canonical.

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-alias"></a> alias?readonlystringThe name the harness actually sent, when it was not the canonical one.mcp/src/server.ts:40
<a id="property-arguments"></a> argumentsreadonlyJsonObject-mcp/src/server.ts:38
<a id="property-callid"></a> callIdreadonlystring-mcp/src/server.ts:35
<a id="property-tool"></a> toolreadonlystringThe canonical SharedOS tool name, or the raw one when it matched nothing.mcp/src/server.ts:37

McpToolInvoker

Defined in: mcp/src/server.ts:51

What the MCP surface is allowed to do, and the only thing it is allowed to do.

Discovery and invocation, nothing else. There is no method here for reading grants, resolving authority, or listing what a call would need: the server is a projection and a doorway, and every question about authority is answered on the other side of it.

Methods

catalog()

catalog(signal): Promise<{ catalogHash: string; executionId: string; tools: object[]; version: "1"; }>

Defined in: mcp/src/server.ts:53

The permission-filtered catalogue for this session.

Parameters
ParameterType
signalAbortSignal
Returns

Promise<{ catalogHash: string; executionId: string; tools: object[]; version: "1"; }>

invoke()

invoke(invocation, signal): Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>

Defined in: mcp/src/server.ts:55

One call, re-authorized against the arguments actually presented.

Parameters
ParameterType
invocationMcpToolInvocation
signalAbortSignal
Returns

Promise<{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }>


McpToolServerOptions

Defined in: mcp/src/server.ts:63

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-createid"></a> createId?readonly() => stringMints the SharedOS call id for one tools/call.mcp/src/server.ts:69
<a id="property-instructions"></a> instructions?readonlystringGuidance handed to the client at initialize time.mcp/src/server.ts:67
<a id="property-invoker"></a> invokerreadonlyMcpToolInvoker-mcp/src/server.ts:64
<a id="property-serverinfo"></a> serverInfo?readonlyMcpServerInfo-mcp/src/server.ts:65
<a id="property-spans"></a> spans?readonlySpanSinkWhere the cost of answering one frame is reported. This is the span that bounds enforcement over the toolshare path: it opens when a frame arrives here and closes when the response leaves, so the model's own thinking time is outside it by construction rather than by subtraction. What is also outside it, and cannot be brought in, is the vendor CLI's own tool router -- that code runs before a frame reaches this server and SharedOS never sees it.mcp/src/server.ts:80

OpenToolBridgeOptions

Defined in: mcp/src/bridge.ts:43

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-context-1"></a> contextreadonlyBridgeTurnContext-mcp/src/bridge.ts:45
<a id="property-executionid-1"></a> executionIdreadonlystring-mcp/src/bridge.ts:44
<a id="property-host"></a> hostreadonlyBridgeToolInvoker-mcp/src/bridge.ts:48
<a id="property-step"></a> step?readonlynumberPosition in the harness's own loop, when the transport can report one. Neither caller passes it today, so an MCP-mediated call declares no step and is bounded by maxToolCalls alone; see docs/open-items.md.mcp/src/bridge.ts:54
<a id="property-tools"></a> toolsreadonlyreadonly object[]The permission-filtered catalogue this turn resolved.mcp/src/bridge.ts:47

ToolAliasRecord

Defined in: mcp/src/bridge.ts:37

One harness-side rewrite, kept for diagnosis and never for authorization.

Properties

PropertyModifierTypeDefined in
<a id="property-alias-1"></a> aliasreadonlystringmcp/src/bridge.ts:38
<a id="property-at"></a> atreadonlystringmcp/src/bridge.ts:40
<a id="property-tool-1"></a> toolreadonlystringmcp/src/bridge.ts:39

VerifyExecutionTokenOptions

Defined in: mcp/src/token.ts:76

Properties

PropertyModifierTypeDescriptionDefined in
<a id="property-expect"></a> expect?readonlyPartial<{ actor: string; catalogHash: string; executionId: string; expiresAt: string; namespaceId: string; }>Claims the session already knows, each of which must match exactly.mcp/src/token.ts:80
<a id="property-now-1"></a> nowreadonlystringThe instant to judge expiry against. RFC 3339.mcp/src/token.ts:78

Type Aliases

CallToolParams

CallToolParams = z.infer<typeof CallToolParamsSchema>>

Defined in: mcp/src/protocol.ts:117


ExecutionTokenClaims

ExecutionTokenClaims = z.infer<typeof ExecutionTokenClaimsSchema>>

Defined in: mcp/src/token.ts:34


ExecutionTokenRejection

ExecutionTokenRejection = "malformed" | "signature_mismatch" | "expired" | "claims_mismatch"

Defined in: mcp/src/token.ts:48


ExecutionTokenVerification

ExecutionTokenVerification = { claims: ExecutionTokenClaims; valid: true; } | { reason: ExecutionTokenRejection; valid: false; }

Defined in: mcp/src/token.ts:51


InitializeParams

InitializeParams = z.infer<typeof InitializeParamsSchema>>

Defined in: mcp/src/protocol.ts:108


JsonRpcId

JsonRpcId = z.infer<typeof JsonRpcIdSchema>>

Defined in: mcp/src/protocol.ts:37


JsonRpcNotification

JsonRpcNotification = z.infer<typeof JsonRpcNotificationSchema>>

Defined in: mcp/src/protocol.ts:59


JsonRpcRequest

JsonRpcRequest = z.infer<typeof JsonRpcRequestSchema>>

Defined in: mcp/src/protocol.ts:47


JsonRpcResponse

JsonRpcResponse = JsonRpcSuccess | JsonRpcFailure

Defined in: mcp/src/protocol.ts:79


McpHarnessId

McpHarnessId = typeof MCP_HARNESS_IDS[number]

Defined in: mcp/src/harness-config.ts:213

Variables

CallToolParamsSchema

const CallToolParamsSchema: ZodObject<{ _meta: ZodOptional<ZodRecord<ZodString, ZodUnknown>>>>; arguments: ZodOptional<ZodRecord<ZodString, ZodUnknown>>>>; name: ZodString; }, "passthrough", ZodTypeAny, objectOutputType<{ _meta: ZodOptional<ZodRecord<ZodString, ZodUnknown>>>>; arguments: ZodOptional<ZodRecord<ZodString, ZodUnknown>>>>; name: ZodString; }, ZodTypeAny, "passthrough">>, objectInputType<{ _meta: ZodOptional<ZodRecord<ZodString, ZodUnknown>>>>; arguments: ZodOptional<ZodRecord<ZodString, ZodUnknown>>>>; name: ZodString; }, ZodTypeAny, "passthrough">>>>

Defined in: mcp/src/protocol.ts:110


ExecutionTokenClaimsSchema

const ExecutionTokenClaimsSchema: ZodObject<{ actor: ZodString; catalogHash: ZodString; executionId: ZodString; expiresAt: ZodString; namespaceId: ZodString; }, "strict", ZodTypeAny, { actor: string; catalogHash: string; executionId: string; expiresAt: string; namespaceId: string; }, { actor: string; catalogHash: string; executionId: string; expiresAt: string; namespaceId: string; }>

Defined in: mcp/src/token.ts:20

What a short-lived execution token asserts.

It identifies a broker session and nothing more. There are deliberately no grants, no capabilities, and no authority in these claims: a token is a way to find the right turn-scoped bridge, not a bearer of permission. Whoever presents it still gets exactly the catalogue that turn's AccessContext resolved, and every call it makes is still authorized from the trusted grant source at the moment of the call.

catalogHash is bound in so a token cannot be replayed against a session that is serving a different tool set -- the case where a stale sandbox reconnects after the catalogue changed, and would otherwise call tools it was never shown.


InitializeParamsSchema

const InitializeParamsSchema: ZodObject<{ capabilities: ZodOptional<ZodRecord<ZodString, ZodUnknown>>>>; clientInfo: ZodOptional<ZodObject<{ name: ZodOptional<ZodString>>; version: ZodOptional<ZodString>>; }, "passthrough", ZodTypeAny, objectOutputType<{ name: ZodOptional<ZodString>>; version: ZodOptional<ZodString>>; }, ZodTypeAny, "passthrough">>, objectInputType<{ name: ZodOptional<ZodString>>; version: ZodOptional<ZodString>>; }, ZodTypeAny, "passthrough">>>>>>; protocolVersion: ZodOptional<ZodString>>; }, "passthrough", ZodTypeAny, objectOutputType<{ capabilities: ZodOptional<ZodRecord<ZodString, ZodUnknown>>>>; clientInfo: ZodOptional<ZodObject<{ name: ZodOptional<ZodString>>; version: ZodOptional<ZodString>>; }, "passthrough", ZodTypeAny, objectOutputType<{ name: ZodOptional<ZodString>>; version: ZodOptional<ZodString>>; }, ZodTypeAny, "passthrough">>, objectInputType<{ name: ZodOptional<ZodString>>; version: ZodOptional<ZodString>>; }, ZodTypeAny, "passthrough">>>>>>; protocolVersion: ZodOptional<ZodString>>; }, ZodTypeAny, "passthrough">>, objectInputType<{ capabilities: ZodOptional<ZodRecord<ZodString, ZodUnknown>>>>; clientInfo: ZodOptional<ZodObject<{ name: ZodOptional<ZodString>>; version: ZodOptional<ZodString>>; }, "passthrough", ZodTypeAny, objectOutputType<{ name: ZodOptional<ZodString>>; version: ZodOptional<ZodString>>; }, ZodTypeAny, "passthrough">>, objectInputType<{ name: ZodOptional<ZodString>>; version: ZodOptional<ZodString>>; }, ZodTypeAny, "passthrough">>>>>>; protocolVersion: ZodOptional<ZodString>>; }, ZodTypeAny, "passthrough">>>>

Defined in: mcp/src/protocol.ts:98


JSON_RPC_INTERNAL_ERROR

const JSON_RPC_INTERNAL_ERROR: -32603 = -32_603

Defined in: mcp/src/protocol.ts:34


JSON_RPC_INVALID_PARAMS

const JSON_RPC_INVALID_PARAMS: -32602 = -32_602

Defined in: mcp/src/protocol.ts:33


JSON_RPC_INVALID_REQUEST

const JSON_RPC_INVALID_REQUEST: -32600 = -32_600

Defined in: mcp/src/protocol.ts:31


JSON_RPC_METHOD_NOT_FOUND

const JSON_RPC_METHOD_NOT_FOUND: -32601 = -32_601

Defined in: mcp/src/protocol.ts:32


JSON_RPC_PARSE_ERROR

const JSON_RPC_PARSE_ERROR: -32700 = -32_700

Defined in: mcp/src/protocol.ts:30

JSON-RPC 2.0 error codes.

These are for messages that could not be processed at all. A SharedOS refusal is never one of them: a denial is a processed request whose answer is no, and it returns as a tool result. See toCallToolResult.


JsonRpcIdSchema

const JsonRpcIdSchema: ZodUnion<[ZodString, ZodNumber]>

Defined in: mcp/src/protocol.ts:36


JsonRpcNotificationSchema

const JsonRpcNotificationSchema: ZodEffects<ZodObject<{ jsonrpc: ZodLiteral<"2.0">>; method: ZodString; params: ZodOptional<ZodUnknown>>; }, "passthrough", ZodTypeAny, objectOutputType<{ jsonrpc: ZodLiteral<"2.0">>; method: ZodString; params: ZodOptional<ZodUnknown>>; }, ZodTypeAny, "passthrough">>, objectInputType<{ jsonrpc: ZodLiteral<"2.0">>; method: ZodString; params: ZodOptional<ZodUnknown>>; }, ZodTypeAny, "passthrough">>>>, objectOutputType<{ jsonrpc: ZodLiteral<"2.0">>; method: ZodString; params: ZodOptional<ZodUnknown>>; }, ZodTypeAny, "passthrough">>, objectInputType<{ jsonrpc: ZodLiteral<"2.0">>; method: ZodString; params: ZodOptional<ZodUnknown>>; }, ZodTypeAny, "passthrough">>>>

Defined in: mcp/src/protocol.ts:49


JsonRpcRequestSchema

const JsonRpcRequestSchema: ZodObject<{ id: ZodUnion<[ZodString, ZodNumber]>; jsonrpc: ZodLiteral<"2.0">>; method: ZodString; params: ZodOptional<ZodUnknown>>; }, "passthrough", ZodTypeAny, objectOutputType<{ id: ZodUnion<[ZodString, ZodNumber]>; jsonrpc: ZodLiteral<"2.0">>; method: ZodString; params: ZodOptional<ZodUnknown>>; }, ZodTypeAny, "passthrough">>, objectInputType<{ id: ZodUnion<[ZodString, ZodNumber]>; jsonrpc: ZodLiteral<"2.0">>; method: ZodString; params: ZodOptional<ZodUnknown>>; }, ZodTypeAny, "passthrough">>>>

Defined in: mcp/src/protocol.ts:39


LATEST_MCP_PROTOCOL_VERSION

const LATEST_MCP_PROTOCOL_VERSION: "2025-06-18" = "2025-06-18"

Defined in: mcp/src/protocol.ts:21


MCP_HARNESS_IDS

const MCP_HARNESS_IDS: readonly ["codex", "claude-code", "deepseek", "pi"]

Defined in: mcp/src/harness-config.ts:212

The harnesses this package emits a connection for, by id.


MCP_SERVER_VERSION

const MCP_SERVER_VERSION: "0.1.0-alpha.3" = "0.1.0-alpha.3"

Defined in: mcp/src/server.ts:92

The version a server built without serverInfo reports in initialize.

It names the build a harness connected to, so it is kept equal to the synchronized package version by the release gate, like every other version constant that reaches a record or a wire.


SHAREDOS_MCP_SERVER_NAME

const SHAREDOS_MCP_SERVER_NAME: "sharedos" = "sharedos"

Defined in: mcp/src/server.ts:83


SUPPORTED_MCP_PROTOCOL_VERSIONS

const SUPPORTED_MCP_PROTOCOL_VERSIONS: readonly string[]

Defined in: mcp/src/protocol.ts:15

Protocol revisions this server speaks, newest first.

Functions

canonicalActor()

canonicalActor(address): string

Defined in: mcp/src/token.ts:44

The one string form of an address a token carries as its actor.

<kind>:<id>, from the same [kind, id] pair addressPath derives for a recipient-scoped grant, so the two never spell an address differently. It is a label for equality, not an encoding: nothing parses it back into an Address, and a token is matched on the exact string it was minted with.

Parameters

ParameterType
address{ kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; }

Returns

string


classifyTool()

classifyTool(policy, publishedNames, tool): "managed" | "harness_local" | "external_direct" | undefined

Defined in: mcp/src/policy.ts:61

Which class a tool the harness called belongs to.

managed is decided by presence in the published catalogue rather than by the policy's own lists, because the catalogue is the fact and the policy is the declaration. A name in neither is undefined: an unclassified tool, which is a gap in the declaration and is reported as one rather than being quietly counted as harness-local.

Parameters

ParameterType
policy{ externalDirect: string[]; harnessLocal: string[]; managedMcp: string[]; mode: "strict" | "hybrid"; }
policy.externalDirectstring[]
policy.harnessLocalstring[]
policy.managedMcpstring[]
policy.mode"strict" | "hybrid"
publishedNamesreadonly string[]
toolstring

Returns

"managed" | "harness_local" | "external_direct" | undefined


claudeAgentSdkMcpOptions()

claudeAgentSdkMcpOptions(connection): JsonObject

Defined in: mcp/src/harness-config.ts:117

Claude Agent SDK options for a non-interactive evaluation.

allowedTools auto-approves the SharedOS server, which is the correct setting precisely because it is not an authorization decision: Claude separates tool availability from permission prompting, and prompting a human for a run with no human in it would stall the eval rather than secure it. What secures it is that every one of those calls is re-authorized by the kernel.

Parameters

ParameterType
connectionHarnessMcpConnection

Returns

JsonObject


claudeCodeMcpConfig()

claudeCodeMcpConfig(connection): JsonObject

Defined in: mcp/src/harness-config.ts:93

Claude Code's .mcp.json.

Parameters

ParameterType
connectionHarnessMcpConnection

Returns

JsonObject


codexMcpConfig()

codexMcpConfig(connection): string

Defined in: mcp/src/harness-config.ts:83

Codex's config.toml fragment: codexMcpServerSettings as a table.

Parameters

ParameterType
connectionHarnessMcpConnection

Returns

string


codexMcpServerSettings()

codexMcpServerSettings(connection): readonly readonly [string, string][]

Defined in: mcp/src/harness-config.ts:67

The settings a Codex MCP server entry carries, as key and TOML value.

One list serves both forms Codex accepts -- the [mcp_servers.<name>] table codexMcpConfig emits, and the -c mcp_servers.<name>.<key>=<value> overrides a launch passes -- so the two cannot disagree. bearer_token, present only when the connection carries one, belongs to the file alone: a launch keeps it off the command line.

required = true is deliberate. A Codex run whose SharedOS server failed to start should not quietly continue with only its own tools -- that run would look like a harness that declined to use the catalogue, which is a different finding entirely.

default_tools_approval_mode = "approve" is the same decision as Claude Code's --allowedTools, and not an authorization one. Codex gates MCP calls itself, and its default mode, auto, decides from the tool's readOnlyHint: read-only tools run, everything else asks a human. A run with no human then refuses every write inside Codex, with the kernel never consulted. approve is scoped to this one server, leaves Codex's shell sandbox alone, and hands the decision to the only thing that should be making it: RuntimeHost.invokeTool, which re-authorizes every call.

Parameters

ParameterType
connectionHarnessMcpConnection

Returns

readonly readonly [string, string][]


declareToolPolicy()

declareToolPolicy(options?): object

Defined in: mcp/src/policy.ts:27

Parameters

ParameterType
optionsDeclareToolPolicyOptions

Returns

object

externalDirect

externalDirect: string[]

harnessLocal

harnessLocal: string[]

managedMcp

managedMcp: string[]

mode

mode: "strict" | "hybrid"


deepseekMcpConfig()

deepseekMcpConfig(connection): string

Defined in: mcp/src/harness-config.ts:149

DeepSeek Harness's plugin patch overlay.

A dsh profile composes an ordered stack of plugin-bundle patch layers, and a --patch overlay is the last one. Its entries are id-targeted: a bare id: entry overrides a plugin already in the tree, and only an insert: entry adds one. Getting that backwards fails quietly -- dsh warns patch: entry "..." not found on stderr and boots without the plugin, which downstream reads as a harness that declined to use the catalogue rather than as a misconfigured one.

The plugin itself must already be installed into the profile (dsh plugin --profile <name> add @deepseek-ai/dsh-mcp-client). A patch activates a plugin; it does not fetch one.

@deepseek-ai/dsh-mcp-client then performs tools/list, converts the schemas, and registers each result through ctx.tools.register(). Nothing in this file describes a tool, for the same reason as the others.

failOnStartupError is set for the same reason Codex's server is required: a run that quietly continued with only the harness's own tools would look like a harness that declined to use the catalogue, which is a different finding.

Parameters

ParameterType
connectionHarnessMcpConnection

Returns

string


harnessMcpConfigFile()

harnessMcpConfigFile(harness, connection): HarnessMcpConfigFile

Defined in: mcp/src/harness-config.ts:216

Every emitter above, addressed by harness id.

Parameters

ParameterType
harness"codex" | "claude-code" | "deepseek" | "pi"
connectionHarnessMcpConnection

Returns

HarnessMcpConfigFile


harnessToolAlias()

harnessToolAlias(serverName, tool): string

Defined in: mcp/src/harness-config.ts:255

The harness-facing alias a tool is likely to appear under.

mcp__<serverName>__<rawName> is the shape Claude Code, Codex, and DeepSeek Harness all use, so it is the one assumed here. It is still only an approximation: DeepSeek normalises the raw name to [A-Za-z0-9_-] and, when that changes the name -- which it does for every dotted SharedOS name -- appends a deterministic hash so two tools can never collapse into one alias.

Which is exactly why nothing may authorize against this. The alias is recorded so a vendor transcript can be read back to a canonical name, and SharedOS maps a name it receives back to the catalogue rather than trusting a reconstruction.

Parameters

ParameterType
serverNamestring
toolstring

Returns

string


jsonRpcError()

jsonRpcError(id, code, message, data?): JsonRpcFailure

Defined in: mcp/src/protocol.ts:85

Parameters

ParameterType
idstring | number | null
codenumber
messagestring
data?unknown

Returns

JsonRpcFailure


jsonRpcResult()

jsonRpcResult(id, result): JsonRpcSuccess

Defined in: mcp/src/protocol.ts:81

Parameters

ParameterType
idstring | number
resultunknown

Returns

JsonRpcSuccess


kernelToolBridge()

kernelToolBridge(options): McpToolInvoker

Defined in: mcp/src/bridge.ts:185

A bridge that goes straight to the kernel, for a host serving MCP outside a turn.

Every kernel guarantee still holds: discovery is filtered, and each call is re-authorized against the arguments presented. What is absent is the envelope -- no step or tool-call budget, and no execution event stream -- so a turn's evidence cannot be assembled from a session served this way. Use openToolBridge inside a turn; use this to expose a catalogue to a long-running harness the host is supervising by other means.

Parameters

ParameterType
optionsKernelToolBridgeOptions

Returns

McpToolInvoker


mintExecutionToken()

mintExecutionToken(claims, secret): Promise<string>>

Defined in: mcp/src/token.ts:63

Sign one execution token.

HMAC-SHA256 over the canonical JSON of the claims, through Web Crypto so this stays host-neutral. The secret is the host's; SharedOS neither generates nor stores it, because a broker that mints its own signing key has no way to be revoked by the host that deployed it.

Parameters

ParameterTypeDescription
claims{ actor: string; catalogHash: string; executionId: string; expiresAt: string; namespaceId: string; }-
claims.actorstringThe acting principal as canonicalActor renders it: <kind>:<id>, for example agent:a-1. Compared by equality, never parsed back.
claims.catalogHashstring-
claims.executionIdstring-
claims.expiresAtstringRFC 3339. A token with no expiry is not issued.
claims.namespaceIdstring-
secretstring-

Returns

Promise<string>


negotiateProtocolVersion()

negotiateProtocolVersion(requested): string

Defined in: mcp/src/protocol.ts:127

Negotiate a protocol revision.

A client asking for a revision this server knows gets that revision back, which is what keeps an older harness working. A client asking for one it does not know is answered with the newest supported revision rather than an error, per the MCP negotiation rule: the client then decides whether it can proceed.

Parameters

ParameterType
requestedstring | undefined

Returns

string


openToolBridge()

openToolBridge(options): SharedOSToolBridge

Defined in: mcp/src/bridge.ts:150

Open a turn-scoped bridge over the execution envelope.

Parameters

ParameterType
optionsOpenToolBridgeOptions

Returns

SharedOSToolBridge


parseToolPolicy()

parseToolPolicy(value): object

Defined in: mcp/src/policy.ts:37

Parameters

ParameterType
valueunknown

Returns

object

externalDirect

externalDirect: string[]

harnessLocal

harnessLocal: string[]

managedMcp

managedMcp: string[]

mode

mode: "strict" | "hybrid"


piMcpConfig()

piMcpConfig(connection): JsonObject

Defined in: mcp/src/harness-config.ts:195

Pi's .mcp.json, read by an MCP extension.

Pi ships no MCP client. Reaching an MCP server therefore requires an extension, and which extension is a host choice rather than something SharedOS mandates -- pi-mcp-adapter is the one this repository is exercised against, and anything with the same job would serve. The file shape below is that adapter's, which happens to be Claude Code's shape with its own lifecycle and timeout keys.

The effect is not identical to a native client, and the difference is worth knowing when reading a Pi column. The adapter registers a single mcp proxy tool and discovers the catalogue behind it on demand, so Pi's model calls mcp({tool: "files.read", ...}) rather than files.read, and the harness-facing surface is one tool wide.

None of that reaches SharedOS: what arrives at the bridge is an ordinary tools/call naming the canonical tool, authorized exactly like any other. Which is the point of keeping the harness-facing alias out of authorization.

lifecycle: "eager" connects at startup rather than on first use, so the catalogue is fetched inside the turn that opened the bridge rather than at some later moment the turn may already have closed.

Parameters

ParameterType
connectionHarnessMcpConnection

Returns

JsonObject


resolveCanonicalName()

resolveCanonicalName(tools, exposed): string

Defined in: mcp/src/server.ts:315

Map an exposed name back to the canonical SharedOS tool ID.

The canonical name is what SharedOS published, so an exact match is the ordinary case. The portable form is accepted too, because a transport that cannot carry a dot will have rewritten it, and refusing the rewrite would turn a transport limitation into a permission failure.

Anything else is returned unchanged rather than rejected here. A guess at a tool that was never published has to reach the kernel to be refused and recorded: resolving it to undefined in the adapter would erase the attempt, and an attempted violation that leaves no trace is the one outcome this boundary must not produce. Resolution can only ever select a tool already in the permission-filtered catalogue, so it can never widen authority.

Parameters

ParameterType
toolsreadonly object[]
exposedstring

Returns

string


toCallToolResult()

toCallToolResult(result, published?): JsonObject

Defined in: mcp/src/server.ts:342

A SharedOS ToolResult as an MCP CallToolResult.

The rule that matters: a refusal is a tool error, never a transport error. A JSON-RPC error means the request could not be processed, and a harness that receives one has no reason to believe anything about its authority -- most retry, some abandon the turn. A denial is a processed request with an answer, and the answer is "no". Reporting it as isError: true is what lets a harness learn it was refused, tell the user, and carry on to its next call.

denied and failed stay distinguishable in the payload. They mean different things -- policy refused this, versus the tool broke -- and collapsing them would make a denial rate uncountable from the evidence.

Parameters

ParameterType
result{ callId: string; completedAt: string; metadata?: JsonObject; output: JsonValue; status: "succeeded"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "denied"; tool: string; } | { callId: string; completedAt: string; error: { code: string; details?: JsonObject; message: string; retryable?: boolean; }; metadata?: JsonObject; status: "failed"; tool: string; }
published?{ annotations?: { destructiveHint?: boolean; idempotentHint?: boolean; openWorldHint?: boolean; readOnlyHint?: boolean; }; description: string; inputSchema: JsonObject; metadata?: { namespace?: string; source?: string; }; name: string; outputSchema?: JsonObject; }
published.annotations?{ destructiveHint?: boolean; idempotentHint?: boolean; openWorldHint?: boolean; readOnlyHint?: boolean; }
published.annotations.destructiveHint?boolean
published.annotations.idempotentHint?boolean
published.annotations.openWorldHint?boolean
published.annotations.readOnlyHint?boolean
published.description?string
published.inputSchema?JsonObject
published.metadata?{ namespace?: string; source?: string; }
published.metadata.namespace?string
published.metadata.source?string
published.name?string
published.outputSchema?JsonObject

Returns

JsonObject


toMcpTool()

toMcpTool(tool): JsonObject

Defined in: mcp/src/server.ts:274

One published tool in MCP's own shape.

Parameters

ParameterType
tool{ annotations?: { destructiveHint?: boolean; idempotentHint?: boolean; openWorldHint?: boolean; readOnlyHint?: boolean; }; description: string; inputSchema: JsonObject; metadata?: { namespace?: string; source?: string; }; name: string; outputSchema?: JsonObject; }
tool.annotations?{ destructiveHint?: boolean; idempotentHint?: boolean; openWorldHint?: boolean; readOnlyHint?: boolean; }
tool.annotations.destructiveHint?boolean
tool.annotations.idempotentHint?boolean
tool.annotations.openWorldHint?boolean
tool.annotations.readOnlyHint?boolean
tool.descriptionstring
tool.inputSchemaJsonObject
tool.metadata?{ namespace?: string; source?: string; }
tool.metadata.namespace?string
tool.metadata.source?string
tool.namestring
tool.outputSchema?JsonObject

Returns

JsonObject


toolPolicyHash()

toolPolicyHash(policy): Promise<string>>

Defined in: mcp/src/policy.ts:79

A content identifier for the declared policy, for the run's policyHash.

Parameters

ParameterType
policy{ externalDirect: string[]; harnessLocal: string[]; managedMcp: string[]; mode: "strict" | "hybrid"; }
policy.externalDirectstring[]
policy.harnessLocalstring[]
policy.managedMcpstring[]
policy.mode"strict" | "hybrid"

Returns

Promise<string>


verifyExecutionToken()

verifyExecutionToken(token, secret, options): Promise<ExecutionTokenVerification>>

Defined in: mcp/src/token.ts:92

Verify a token, then check it against what the session already knows.

Order matters: the signature is checked before the claims are trusted for anything, including for deciding whether they are worth checking. The comparison is constant-time, and a mismatch of any kind is reported as a refusal rather than thrown, so a bad token produces a clean 401 instead of an exception path that a caller might handle differently from a denial.

Parameters

ParameterType
tokenstring
secretstring
optionsVerifyExecutionTokenOptions

Returns

Promise<ExecutionTokenVerification>