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
| Parameter | Type |
|---|---|
options | McpToolServerOptions |
Returns
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
| Parameter | Type |
|---|---|
message | unknown |
signal | AbortSignal |
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
| Parameter | Type |
|---|---|
options | OpenToolBridgeOptions |
Returns
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
| Parameter | Type |
|---|---|
signal | AbortSignal |
Returns
Promise<{ catalogHash: string; executionId: string; tools: object[]; version: "1"; }>
Implementation of
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
| Parameter | Type |
|---|---|
invocation | McpToolInvocation |
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; }>
Implementation of
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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
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 |
options | { executionId: string; signal?: AbortSignal; } |
options.executionId | string |
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
| Parameter | Type |
|---|---|
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? | { 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
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-now"></a> now | readonly | string | mcp/src/bridge.ts:33 |
<a id="property-traceid"></a> traceId | readonly | string | mcp/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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-externaldirect"></a> externalDirect? | readonly | readonly string[] | MCP servers the harness was configured with independently. | mcp/src/policy.ts:24 |
<a id="property-harnesslocal"></a> harnessLocal? | readonly | readonly string[] | The harness's own tools, which SharedOS never sees. | mcp/src/policy.ts:22 |
<a id="property-managedmcp"></a> managedMcp? | readonly | readonly 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
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-contents"></a> contents | readonly | string | mcp/src/harness-config.ts:39 |
<a id="property-filename"></a> filename | readonly | string | mcp/src/harness-config.ts:38 |
<a id="property-harness"></a> harness | readonly | string | mcp/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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-name"></a> name? | readonly | string | The server name the harness will namespace its aliases under. | mcp/src/harness-config.ts:28 |
<a id="property-timeoutsec"></a> timeoutSec? | readonly | number | Per-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? | readonly | string | Bearer token for a sandboxed or remote harness. | mcp/src/harness-config.ts:32 |
<a id="property-url"></a> url | readonly | string | The Streamable HTTP endpoint the turn-scoped bridge is serving. | mcp/src/harness-config.ts:26 |
JsonRpcErrorBody
Defined in: mcp/src/protocol.ts:61
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-code"></a> code | readonly | number | mcp/src/protocol.ts:62 |
<a id="property-data"></a> data? | readonly | unknown | mcp/src/protocol.ts:64 |
<a id="property-message"></a> message | readonly | string | mcp/src/protocol.ts:63 |
JsonRpcFailure
Defined in: mcp/src/protocol.ts:73
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-error"></a> error | readonly | JsonRpcErrorBody | mcp/src/protocol.ts:76 |
<a id="property-id"></a> id | readonly | string | number | null | mcp/src/protocol.ts:75 |
<a id="property-jsonrpc"></a> jsonrpc | readonly | "2.0" | mcp/src/protocol.ts:74 |
JsonRpcSuccess
Defined in: mcp/src/protocol.ts:67
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-id-1"></a> id | readonly | string | number | mcp/src/protocol.ts:69 |
<a id="property-jsonrpc-1"></a> jsonrpc | readonly | "2.0" | mcp/src/protocol.ts:68 |
<a id="property-result"></a> result | readonly | unknown | mcp/src/protocol.ts:70 |
KernelToolBridgeOptions
Defined in: mcp/src/bridge.ts:167
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-context"></a> context | readonly | object | The trusted context. Never built from anything the harness sent. | mcp/src/bridge.ts:170 |
context.actor | public | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } | - | contracts/dist/access.d.ts:144 |
context.authority | public | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } | - | contracts/dist/access.d.ts:157 |
context.enabledToolNamespaces | public | string[] | - | contracts/dist/access.d.ts:170 |
context.namespaceId | public | string | - | contracts/dist/access.d.ts:141 |
context.now | public | string | - | contracts/dist/access.d.ts:171 |
context.owner | public | { kind: "human"; userId: string; } | { agentId: string; kind: "agent"; } | { conversationId: string; kind: "group"; } | { kind: "service"; serviceId: string; } | - | contracts/dist/access.d.ts:128 |
context.purpose | public | string | - | contracts/dist/access.d.ts:142 |
context.traceId | public | string | - | contracts/dist/access.d.ts:143 |
<a id="property-executionid"></a> executionId | readonly | string | - | mcp/src/bridge.ts:171 |
<a id="property-kernel"></a> kernel | readonly | BridgeKernel | - | mcp/src/bridge.ts:168 |
McpServerInfo
Defined in: mcp/src/server.ts:58
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-name-1"></a> name | readonly | string | mcp/src/server.ts:59 |
<a id="property-version"></a> version | readonly | string | mcp/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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-alias"></a> alias? | readonly | string | The name the harness actually sent, when it was not the canonical one. | mcp/src/server.ts:40 |
<a id="property-arguments"></a> arguments | readonly | JsonObject | - | mcp/src/server.ts:38 |
<a id="property-callid"></a> callId | readonly | string | - | mcp/src/server.ts:35 |
<a id="property-tool"></a> tool | readonly | string | The 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
| Parameter | Type |
|---|---|
signal | AbortSignal |
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
| Parameter | Type |
|---|---|
invocation | McpToolInvocation |
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; }>
McpToolServerOptions
Defined in: mcp/src/server.ts:63
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-createid"></a> createId? | readonly | () => string | Mints the SharedOS call id for one tools/call. | mcp/src/server.ts:69 |
<a id="property-instructions"></a> instructions? | readonly | string | Guidance handed to the client at initialize time. | mcp/src/server.ts:67 |
<a id="property-invoker"></a> invoker | readonly | McpToolInvoker | - | mcp/src/server.ts:64 |
<a id="property-serverinfo"></a> serverInfo? | readonly | McpServerInfo | - | mcp/src/server.ts:65 |
<a id="property-spans"></a> spans? | readonly | SpanSink | Where 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
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-context-1"></a> context | readonly | BridgeTurnContext | - | mcp/src/bridge.ts:45 |
<a id="property-executionid-1"></a> executionId | readonly | string | - | mcp/src/bridge.ts:44 |
<a id="property-host"></a> host | readonly | BridgeToolInvoker | - | mcp/src/bridge.ts:48 |
<a id="property-step"></a> step? | readonly | number | Position 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> tools | readonly | readonly 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
| Property | Modifier | Type | Defined in |
|---|---|---|---|
<a id="property-alias-1"></a> alias | readonly | string | mcp/src/bridge.ts:38 |
<a id="property-at"></a> at | readonly | string | mcp/src/bridge.ts:40 |
<a id="property-tool-1"></a> tool | readonly | string | mcp/src/bridge.ts:39 |
VerifyExecutionTokenOptions
Defined in: mcp/src/token.ts:76
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
<a id="property-expect"></a> expect? | readonly | Partial<{ 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> now | readonly | string | The instant to judge expiry against. RFC 3339. | mcp/src/token.ts:78 |
Type Aliases
CallToolParams
CallToolParams =
z.infer<typeofCallToolParamsSchema>>
Defined in: mcp/src/protocol.ts:117
ExecutionTokenClaims
ExecutionTokenClaims =
z.infer<typeofExecutionTokenClaimsSchema>>
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<typeofInitializeParamsSchema>>
Defined in: mcp/src/protocol.ts:108
JsonRpcId
JsonRpcId =
z.infer<typeofJsonRpcIdSchema>>
Defined in: mcp/src/protocol.ts:37
JsonRpcNotification
JsonRpcNotification =
z.infer<typeofJsonRpcNotificationSchema>>
Defined in: mcp/src/protocol.ts:59
JsonRpcRequest
JsonRpcRequest =
z.infer<typeofJsonRpcRequestSchema>>
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
constCallToolParamsSchema: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
constExecutionTokenClaimsSchema: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
constInitializeParamsSchema: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
constJSON_RPC_INTERNAL_ERROR:-32603=-32_603
Defined in: mcp/src/protocol.ts:34
JSON_RPC_INVALID_PARAMS
constJSON_RPC_INVALID_PARAMS:-32602=-32_602
Defined in: mcp/src/protocol.ts:33
JSON_RPC_INVALID_REQUEST
constJSON_RPC_INVALID_REQUEST:-32600=-32_600
Defined in: mcp/src/protocol.ts:31
JSON_RPC_METHOD_NOT_FOUND
constJSON_RPC_METHOD_NOT_FOUND:-32601=-32_601
Defined in: mcp/src/protocol.ts:32
JSON_RPC_PARSE_ERROR
constJSON_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
constJsonRpcIdSchema:ZodUnion<[ZodString,ZodNumber]>
Defined in: mcp/src/protocol.ts:36
JsonRpcNotificationSchema
constJsonRpcNotificationSchema: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
constJsonRpcRequestSchema: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
constLATEST_MCP_PROTOCOL_VERSION:"2025-06-18"="2025-06-18"
Defined in: mcp/src/protocol.ts:21
MCP_HARNESS_IDS
constMCP_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
constMCP_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
constSHAREDOS_MCP_SERVER_NAME:"sharedos"="sharedos"
Defined in: mcp/src/server.ts:83
SUPPORTED_MCP_PROTOCOL_VERSIONS
constSUPPORTED_MCP_PROTOCOL_VERSIONS: readonlystring[]
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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
policy | { externalDirect: string[]; harnessLocal: string[]; managedMcp: string[]; mode: "strict" | "hybrid"; } |
policy.externalDirect | string[] |
policy.harnessLocal | string[] |
policy.managedMcp | string[] |
policy.mode | "strict" | "hybrid" |
publishedNames | readonly string[] |
tool | string |
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
| Parameter | Type |
|---|---|
connection | HarnessMcpConnection |
Returns
claudeCodeMcpConfig()
claudeCodeMcpConfig(
connection):JsonObject
Defined in: mcp/src/harness-config.ts:93
Claude Code's .mcp.json.
Parameters
| Parameter | Type |
|---|---|
connection | HarnessMcpConnection |
Returns
codexMcpConfig()
codexMcpConfig(
connection):string
Defined in: mcp/src/harness-config.ts:83
Codex's config.toml fragment: codexMcpServerSettings as a table.
Parameters
| Parameter | Type |
|---|---|
connection | HarnessMcpConnection |
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
| Parameter | Type |
|---|---|
connection | HarnessMcpConnection |
Returns
readonly readonly [string, string][]
declareToolPolicy()
declareToolPolicy(
options?):object
Defined in: mcp/src/policy.ts:27
Parameters
| Parameter | Type |
|---|---|
options | DeclareToolPolicyOptions |
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
| Parameter | Type |
|---|---|
connection | HarnessMcpConnection |
Returns
string
harnessMcpConfigFile()
harnessMcpConfigFile(
harness,connection):HarnessMcpConfigFile
Defined in: mcp/src/harness-config.ts:216
Every emitter above, addressed by harness id.
Parameters
| Parameter | Type |
|---|---|
harness | "codex" | "claude-code" | "deepseek" | "pi" |
connection | HarnessMcpConnection |
Returns
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
| Parameter | Type |
|---|---|
serverName | string |
tool | string |
Returns
string
jsonRpcError()
jsonRpcError(
id,code,message,data?):JsonRpcFailure
Defined in: mcp/src/protocol.ts:85
Parameters
| Parameter | Type |
|---|---|
id | string | number | null |
code | number |
message | string |
data? | unknown |
Returns
jsonRpcResult()
jsonRpcResult(
id,result):JsonRpcSuccess
Defined in: mcp/src/protocol.ts:81
Parameters
| Parameter | Type |
|---|---|
id | string | number |
result | unknown |
Returns
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
| Parameter | Type |
|---|---|
options | KernelToolBridgeOptions |
Returns
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
| Parameter | Type | Description |
|---|---|---|
claims | { actor: string; catalogHash: string; executionId: string; expiresAt: string; namespaceId: string; } | - |
claims.actor | string | The acting principal as canonicalActor renders it: <kind>:<id>, for example agent:a-1. Compared by equality, never parsed back. |
claims.catalogHash | string | - |
claims.executionId | string | - |
claims.expiresAt | string | RFC 3339. A token with no expiry is not issued. |
claims.namespaceId | string | - |
secret | string | - |
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
| Parameter | Type |
|---|---|
requested | string | undefined |
Returns
string
openToolBridge()
openToolBridge(
options):SharedOSToolBridge
Defined in: mcp/src/bridge.ts:150
Open a turn-scoped bridge over the execution envelope.
Parameters
| Parameter | Type |
|---|---|
options | OpenToolBridgeOptions |
Returns
parseToolPolicy()
parseToolPolicy(
value):object
Defined in: mcp/src/policy.ts:37
Parameters
| Parameter | Type |
|---|---|
value | unknown |
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
| Parameter | Type |
|---|---|
connection | HarnessMcpConnection |
Returns
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
| Parameter | Type |
|---|---|
tools | readonly object[] |
exposed | string |
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
| Parameter | Type |
|---|---|
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
toMcpTool()
toMcpTool(
tool):JsonObject
Defined in: mcp/src/server.ts:274
One published tool in MCP's own shape.
Parameters
| Parameter | Type |
|---|---|
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.description | string |
tool.inputSchema | JsonObject |
tool.metadata? | { namespace?: string; source?: string; } |
tool.metadata.namespace? | string |
tool.metadata.source? | string |
tool.name | string |
tool.outputSchema? | JsonObject |
Returns
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
| Parameter | Type |
|---|---|
policy | { externalDirect: string[]; harnessLocal: string[]; managedMcp: string[]; mode: "strict" | "hybrid"; } |
policy.externalDirect | string[] |
policy.harnessLocal | string[] |
policy.managedMcp | string[] |
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
| Parameter | Type |
|---|---|
token | string |
secret | string |
options | VerifyExecutionTokenOptions |
Returns
Promise<ExecutionTokenVerification>