@axiom-lattice/protocols 6.2.0 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +7 -0
- package/dist/index.d.mts +134 -11
- package/dist/index.d.ts +134 -11
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/McpAppShareProtocol.ts +29 -0
- package/src/McpUiProtocol.ts +13 -0
- package/src/MenuProtocol.ts +2 -0
- package/src/OpenProtocol.ts +27 -1
- package/src/SandboxResourceProtocol.ts +91 -15
- package/src/__tests__/McpUiProtocol.toolName.test.ts +26 -0
- package/src/index.ts +1 -0
package/package.json
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { McpUiRef } from "./McpUiProtocol";
|
|
2
|
+
|
|
3
|
+
/** Public-facing description of a shared MCP App. */
|
|
4
|
+
export interface McpAppShareBootstrap {
|
|
5
|
+
title: string | null;
|
|
6
|
+
visibility: "public" | "password";
|
|
7
|
+
app: {
|
|
8
|
+
kind: "plugin" | "mcp";
|
|
9
|
+
toolName?: string;
|
|
10
|
+
ref: McpUiRef;
|
|
11
|
+
/** Initial arguments re-executed on every open. */
|
|
12
|
+
toolInput?: Record<string, unknown>;
|
|
13
|
+
/** Fresh tool result produced for this bootstrap. */
|
|
14
|
+
toolResult?: unknown;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Share card payload rendered inside an MCP App. */
|
|
19
|
+
export interface ShareCardData {
|
|
20
|
+
token: string;
|
|
21
|
+
/** Relative gateway path; the host resolves it against its origin. */
|
|
22
|
+
path: string;
|
|
23
|
+
/** Optional absolute URL from a deployment-level public base URL. */
|
|
24
|
+
url?: string;
|
|
25
|
+
title: string;
|
|
26
|
+
visibility: "public" | "password";
|
|
27
|
+
password?: string;
|
|
28
|
+
warnings?: string[];
|
|
29
|
+
}
|
package/src/McpUiProtocol.ts
CHANGED
|
@@ -25,6 +25,8 @@ export type McpUiRef =
|
|
|
25
25
|
resourceUri: string;
|
|
26
26
|
displayMode: McpUiDisplayMode;
|
|
27
27
|
title?: string;
|
|
28
|
+
/** Tool that produced the UI resource (1..128 chars), when known. */
|
|
29
|
+
toolName?: string;
|
|
28
30
|
/**
|
|
29
31
|
* Retained only for backward compatibility with pre-unification
|
|
30
32
|
* messages; no longer emitted. Rich tool results now travel via
|
|
@@ -38,6 +40,8 @@ export type McpUiRef =
|
|
|
38
40
|
resource: string;
|
|
39
41
|
displayMode: McpUiDisplayMode;
|
|
40
42
|
title?: string;
|
|
43
|
+
/** Tool that produced the UI resource (1..128 chars), when known. */
|
|
44
|
+
toolName?: string;
|
|
41
45
|
/** Opaque HMAC-signed run/connection scope (1..4096 chars); never contains secrets. */
|
|
42
46
|
scope?: string;
|
|
43
47
|
};
|
|
@@ -54,6 +58,7 @@ export interface McpUiResourcePayload {
|
|
|
54
58
|
|
|
55
59
|
const MODES: McpUiDisplayMode[] = ["inline", "fullscreen", "pip"];
|
|
56
60
|
const MAX_MCP_UI_SCOPE_LENGTH = 4096;
|
|
61
|
+
const MAX_MCP_UI_TOOL_NAME_LENGTH = 128;
|
|
57
62
|
const isObj = (v: unknown): v is Record<string, unknown> => typeof v === "object" && v !== null;
|
|
58
63
|
|
|
59
64
|
/** Type guard for a parsed `McpUiRef`. */
|
|
@@ -68,6 +73,12 @@ export function parseMcpUiRef(value: unknown): McpUiRef | null {
|
|
|
68
73
|
? (value.displayMode as McpUiDisplayMode)
|
|
69
74
|
: "inline";
|
|
70
75
|
const title = typeof value.title === "string" ? value.title : undefined;
|
|
76
|
+
const toolName =
|
|
77
|
+
typeof value.toolName === "string" &&
|
|
78
|
+
value.toolName.length > 0 &&
|
|
79
|
+
value.toolName.length <= MAX_MCP_UI_TOOL_NAME_LENGTH
|
|
80
|
+
? value.toolName
|
|
81
|
+
: undefined;
|
|
71
82
|
if (value.kind === "mcp" && typeof value.serverKey === "string" && typeof value.resourceUri === "string") {
|
|
72
83
|
return {
|
|
73
84
|
kind: "mcp",
|
|
@@ -75,6 +86,7 @@ export function parseMcpUiRef(value: unknown): McpUiRef | null {
|
|
|
75
86
|
resourceUri: value.resourceUri,
|
|
76
87
|
displayMode,
|
|
77
88
|
...(title ? { title } : {}),
|
|
89
|
+
...(toolName ? { toolName } : {}),
|
|
78
90
|
...(value.structuredContent !== undefined ? { structuredContent: value.structuredContent } : {}),
|
|
79
91
|
};
|
|
80
92
|
}
|
|
@@ -89,6 +101,7 @@ export function parseMcpUiRef(value: unknown): McpUiRef | null {
|
|
|
89
101
|
resource: value.resource,
|
|
90
102
|
displayMode,
|
|
91
103
|
...(title ? { title } : {}),
|
|
104
|
+
...(toolName ? { toolName } : {}),
|
|
92
105
|
...(scope ? { scope } : {}),
|
|
93
106
|
};
|
|
94
107
|
}
|
package/src/MenuProtocol.ts
CHANGED
|
@@ -44,6 +44,7 @@ export type McpAppMenuConfig =
|
|
|
44
44
|
resourceUri: string;
|
|
45
45
|
displayMode?: McpUiDisplayMode;
|
|
46
46
|
title?: string;
|
|
47
|
+
toolName?: string;
|
|
47
48
|
toolInput?: Record<string, unknown>;
|
|
48
49
|
toolResult?: unknown;
|
|
49
50
|
ui?: ToolCallUi;
|
|
@@ -54,6 +55,7 @@ export type McpAppMenuConfig =
|
|
|
54
55
|
resource: string;
|
|
55
56
|
displayMode?: McpUiDisplayMode;
|
|
56
57
|
title?: string;
|
|
58
|
+
toolName?: string;
|
|
57
59
|
/** Signed scope copied from the ref so a pinned App can keep calling. */
|
|
58
60
|
scope?: string;
|
|
59
61
|
toolInput?: Record<string, unknown>;
|
package/src/OpenProtocol.ts
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
* capability invocation). See docs/superpowers/specs/2026-09-07-open-platform-api-design.md.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
/** Resource constraints attached to a grant (domain-specific). */
|
|
7
|
+
export interface OpenGrantSelector {
|
|
8
|
+
/** Sandbox self-binding, set only on server-minted sandbox tokens. */
|
|
9
|
+
sandbox?: "self";
|
|
10
|
+
/**
|
|
11
|
+
* Connection keys of this domain's connection type (the plugin type).
|
|
12
|
+
* Absent/empty keeps the legacy connect-all behavior.
|
|
13
|
+
*/
|
|
14
|
+
connections?: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
6
17
|
/** Authorization grant: default-deny; a grant covers one capability domain. */
|
|
7
18
|
export interface OpenGrant {
|
|
8
19
|
domain: string;
|
|
@@ -11,7 +22,7 @@ export interface OpenGrant {
|
|
|
11
22
|
* Absent/empty = every action in the domain.
|
|
12
23
|
*/
|
|
13
24
|
items?: string[];
|
|
14
|
-
selector?:
|
|
25
|
+
selector?: OpenGrantSelector;
|
|
15
26
|
}
|
|
16
27
|
|
|
17
28
|
/** Execution context synthesized from a verified credential — never from the caller. */
|
|
@@ -20,6 +31,8 @@ export interface OpenExecutionContext {
|
|
|
20
31
|
projectId: string;
|
|
21
32
|
/** Addressing only, not an authorization dimension (see design §6.2). */
|
|
22
33
|
workspaceId?: string;
|
|
34
|
+
/** Connection keys pinned by the covering grant (plugin domains only). */
|
|
35
|
+
connectionKeys?: string[];
|
|
23
36
|
/** Synthesized run identity (mirrors the Agent path's runConfig; plugin tools resolve their own connections). */
|
|
24
37
|
runConfig: Record<string, unknown>;
|
|
25
38
|
}
|
|
@@ -67,6 +80,15 @@ export interface OpenCatalogItem {
|
|
|
67
80
|
annotations?: { readOnlyHint: boolean; destructiveHint: boolean };
|
|
68
81
|
}
|
|
69
82
|
|
|
83
|
+
/** A tenant connection selectable for a connection-backed plugin domain. */
|
|
84
|
+
export interface OpenCatalogConnection {
|
|
85
|
+
/** Connection key, stable within `(tenantId, domain type)`. */
|
|
86
|
+
key: string;
|
|
87
|
+
/** Human-readable connection name. */
|
|
88
|
+
name: string;
|
|
89
|
+
description?: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
70
92
|
export interface OpenCatalogDomain {
|
|
71
93
|
domain: string;
|
|
72
94
|
label: string;
|
|
@@ -76,6 +98,10 @@ export interface OpenCatalogDomain {
|
|
|
76
98
|
/** How grant items are chosen: per-action or per-instance. */
|
|
77
99
|
itemKind: "action" | "instance";
|
|
78
100
|
items: OpenCatalogItem[];
|
|
101
|
+
/** True when this domain's tools resolve tenant connections. */
|
|
102
|
+
connectionBacked?: boolean;
|
|
103
|
+
/** Tenant connections selectable for this domain (connection-backed only). */
|
|
104
|
+
connections?: OpenCatalogConnection[];
|
|
79
105
|
}
|
|
80
106
|
|
|
81
107
|
/** Full grantable capability catalog for a tenant (drives the key picker). */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { OpenGrant } from "./OpenProtocol";
|
|
2
|
+
import type { McpUiDisplayMode } from "./McpUiProtocol";
|
|
2
3
|
/**
|
|
3
4
|
* SandboxResourceProtocol
|
|
4
5
|
*
|
|
@@ -7,6 +8,9 @@ import type { OpenGrant } from "./OpenProtocol";
|
|
|
7
8
|
* and file resolution types for the sandbox lattice.
|
|
8
9
|
*/
|
|
9
10
|
|
|
11
|
+
/** Discriminator for the kind of resource a share points at. */
|
|
12
|
+
export type ShareKind = "file" | "mcpApp";
|
|
13
|
+
|
|
10
14
|
/** Sandbox resource location — project-grained, provider-agnostic. */
|
|
11
15
|
export interface ResourceAddress {
|
|
12
16
|
volume: string;
|
|
@@ -21,10 +25,40 @@ export interface ResourceResolver {
|
|
|
21
25
|
/** Visibility level for resource shares. */
|
|
22
26
|
export type ShareVisibility = "public" | "password" | "internal";
|
|
23
27
|
|
|
24
|
-
/**
|
|
25
|
-
export interface
|
|
28
|
+
/** Live target of the MCP App a share points at. */
|
|
29
|
+
export interface McpAppShareApp {
|
|
30
|
+
/** Where the App comes from. */
|
|
31
|
+
kind: "plugin" | "mcp";
|
|
32
|
+
/** Initial invocation tool; required for tool shares, optional for invocation shares. */
|
|
33
|
+
toolName?: string;
|
|
34
|
+
displayMode?: McpUiDisplayMode;
|
|
35
|
+
title?: string;
|
|
36
|
+
/** Plugin-sourced Apps. */
|
|
37
|
+
pluginType?: string;
|
|
38
|
+
resource?: string;
|
|
39
|
+
/** HMAC-signed scope; persisted on the share record, never emitted in bootstrap. */
|
|
40
|
+
scope?: string;
|
|
41
|
+
/** MCP-server-sourced Apps. */
|
|
42
|
+
serverKey?: string;
|
|
43
|
+
resourceUri?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Initial tool arguments. Stored so a shared link can re-run the tool on
|
|
46
|
+
* every open; the tool result itself is never persisted.
|
|
47
|
+
*/
|
|
48
|
+
toolInput?: Record<string, unknown>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** App share target stored in the reuse of the `address` column. */
|
|
52
|
+
export interface McpAppShareTarget {
|
|
53
|
+
kind: "mcpApp";
|
|
54
|
+
app: McpAppShareApp;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Share target: either a file location or an App target. */
|
|
58
|
+
export type ShareTarget = ResourceAddress | McpAppShareTarget;
|
|
59
|
+
|
|
60
|
+
interface ShareRecordBase {
|
|
26
61
|
token: string;
|
|
27
|
-
address: ResourceAddress;
|
|
28
62
|
title: string | null;
|
|
29
63
|
createdBy: string;
|
|
30
64
|
tenantId: string;
|
|
@@ -44,8 +78,26 @@ export interface ShareRecord {
|
|
|
44
78
|
version: number;
|
|
45
79
|
}
|
|
46
80
|
|
|
47
|
-
/**
|
|
48
|
-
export interface
|
|
81
|
+
/** Persisted record of a file share within a project. */
|
|
82
|
+
export interface FileShareRecord extends ShareRecordBase {
|
|
83
|
+
kind: "file";
|
|
84
|
+
address: ResourceAddress;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Persisted record of an MCP App share within a project. */
|
|
88
|
+
export interface McpAppShareRecord extends ShareRecordBase {
|
|
89
|
+
kind: "mcpApp";
|
|
90
|
+
address: McpAppShareTarget;
|
|
91
|
+
/** App shares V1 do not support `internal`. */
|
|
92
|
+
visibility: "public" | "password";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Persisted record of a resource share within a project. */
|
|
96
|
+
export type ShareRecord = FileShareRecord | McpAppShareRecord;
|
|
97
|
+
|
|
98
|
+
/** Client-provided payload for creating a new file share. */
|
|
99
|
+
export interface CreateFileShareRequest {
|
|
100
|
+
kind?: "file";
|
|
49
101
|
resourcePath: string;
|
|
50
102
|
assistantId?: string;
|
|
51
103
|
visibility?: ShareVisibility;
|
|
@@ -57,25 +109,49 @@ export interface CreateShareRequest {
|
|
|
57
109
|
openGrants?: OpenGrant[];
|
|
58
110
|
}
|
|
59
111
|
|
|
112
|
+
/** Client-provided payload for creating a new MCP App share. */
|
|
113
|
+
export interface CreateMcpAppShareRequest {
|
|
114
|
+
kind: "mcpApp";
|
|
115
|
+
app: McpAppShareApp;
|
|
116
|
+
title?: string;
|
|
117
|
+
/** Required: `public` or `password`; there is no default. */
|
|
118
|
+
visibility: "public" | "password";
|
|
119
|
+
password?: string;
|
|
120
|
+
expiresAt?: string;
|
|
121
|
+
maxAccess?: number;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Client-provided payload for creating a new resource share. */
|
|
125
|
+
export type CreateShareRequest =
|
|
126
|
+
| CreateFileShareRequest
|
|
127
|
+
| CreateMcpAppShareRequest;
|
|
128
|
+
|
|
60
129
|
/** Response returned to clients after a share is created. */
|
|
61
130
|
export interface ShareResult {
|
|
62
131
|
token: string;
|
|
63
132
|
url: string;
|
|
64
133
|
}
|
|
65
134
|
|
|
135
|
+
/** Mutable fields of a persisted share record. */
|
|
136
|
+
export interface ShareRecordPatch {
|
|
137
|
+
title?: string;
|
|
138
|
+
expiresAt?: Date | null;
|
|
139
|
+
maxAccess?: number | null;
|
|
140
|
+
revoked?: boolean;
|
|
141
|
+
visibility?: ShareVisibility;
|
|
142
|
+
passwordHash?: string | null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Store insert shape for a new share record. */
|
|
146
|
+
export type CreateShareRecord =
|
|
147
|
+
| Omit<FileShareRecord, "accessCount" | "createdAt" | "version">
|
|
148
|
+
| Omit<McpAppShareRecord, "accessCount" | "createdAt" | "version">;
|
|
149
|
+
|
|
66
150
|
/** Store interface for persisting and querying resource shares. */
|
|
67
151
|
export interface SharedResourceStore {
|
|
68
152
|
findByToken(token: string): Promise<ShareRecord | null>;
|
|
69
|
-
create(record:
|
|
70
|
-
update(
|
|
71
|
-
token: string,
|
|
72
|
-
patch: Partial<
|
|
73
|
-
Pick<
|
|
74
|
-
ShareRecord,
|
|
75
|
-
"title" | "expiresAt" | "maxAccess" | "revoked" | "visibility" | "passwordHash"
|
|
76
|
-
>
|
|
77
|
-
>,
|
|
78
|
-
): Promise<void>;
|
|
153
|
+
create(record: CreateShareRecord): Promise<ShareRecord>;
|
|
154
|
+
update(token: string, patch: ShareRecordPatch): Promise<void>;
|
|
79
155
|
listByUser(tenantId: string, userId: string): Promise<ShareRecord[]>;
|
|
80
156
|
incrementAccess(token: string): Promise<void>;
|
|
81
157
|
atomicIncrementAccess(token: string): Promise<boolean>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { parseMcpUiRef } from "../McpUiProtocol";
|
|
2
|
+
|
|
3
|
+
describe("McpUiRef toolName", () => {
|
|
4
|
+
it("preserves toolName", () => {
|
|
5
|
+
const ref = parseMcpUiRef({
|
|
6
|
+
kind: "plugin",
|
|
7
|
+
pluginType: "demo",
|
|
8
|
+
resource: "ui/app.html",
|
|
9
|
+
displayMode: "inline",
|
|
10
|
+
toolName: "render_report",
|
|
11
|
+
scope: "abc",
|
|
12
|
+
});
|
|
13
|
+
expect(ref?.toolName).toBe("render_report");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("parses legacy refs without toolName", () => {
|
|
17
|
+
const ref = parseMcpUiRef({
|
|
18
|
+
kind: "mcp",
|
|
19
|
+
serverKey: "demo",
|
|
20
|
+
resourceUri: "ui://demo/app",
|
|
21
|
+
displayMode: "inline",
|
|
22
|
+
});
|
|
23
|
+
expect(ref).not.toBeNull();
|
|
24
|
+
expect(ref?.toolName).toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
});
|