@agent-native/core 0.22.7 → 0.22.8
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/dist/agent/engine/builder-gateway-headers.d.ts +1 -1
- package/dist/agent/engine/builder-gateway-headers.d.ts.map +1 -1
- package/dist/agent/engine/builder-gateway-headers.js +1 -3
- package/dist/agent/engine/builder-gateway-headers.js.map +1 -1
- package/dist/agent/engine/translate-anthropic.d.ts +2 -0
- package/dist/agent/engine/translate-anthropic.d.ts.map +1 -1
- package/dist/agent/engine/translate-anthropic.js +71 -9
- package/dist/agent/engine/translate-anthropic.js.map +1 -1
- package/dist/client/mcp-apps/McpAppRenderer.js +6 -1
- package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -0
- package/dist/index.browser.js.map +1 -1
- package/dist/mcp/builtin-tools.d.ts.map +1 -1
- package/dist/mcp/builtin-tools.js +7 -4
- package/dist/mcp/builtin-tools.js.map +1 -1
- package/dist/mcp/embed-app.js +1 -1
- package/dist/mcp/embed-app.js.map +1 -1
- package/docs/content/actions.md +20 -20
- package/docs/content/external-agents.md +19 -14
- package/docs/content/mcp-protocol.md +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export declare function getAgentNativeCorePackageVersion(): string;
|
|
3
3
|
/**
|
|
4
4
|
* Version string for `x-client-version`: npm version plus a short git SHA when
|
|
5
|
-
* available from
|
|
5
|
+
* available from allowlisted deploy env vars.
|
|
6
6
|
*/
|
|
7
7
|
export declare function getBuilderGatewayClientVersion(): string;
|
|
8
8
|
/** Stable request headers for Builder LLM gateway attribution in logs. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder-gateway-headers.d.ts","sourceRoot":"","sources":["../../../src/agent/engine/builder-gateway-headers.ts"],"names":[],"mappings":"AAMA,gBAAgB;AAChB,wBAAgB,gCAAgC,IAAI,MAAM,CAezD;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"builder-gateway-headers.d.ts","sourceRoot":"","sources":["../../../src/agent/engine/builder-gateway-headers.ts"],"names":[],"mappings":"AAMA,gBAAgB;AAChB,wBAAgB,gCAAgC,IAAI,MAAM,CAezD;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,IAAI,MAAM,CAOvD;AAED,0EAA0E;AAC1E,wBAAgB,+BAA+B,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKxE"}
|
|
@@ -23,13 +23,11 @@ export function getAgentNativeCorePackageVersion() {
|
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Version string for `x-client-version`: npm version plus a short git SHA when
|
|
26
|
-
* available from
|
|
26
|
+
* available from allowlisted deploy env vars.
|
|
27
27
|
*/
|
|
28
28
|
export function getBuilderGatewayClientVersion() {
|
|
29
29
|
const v = getAgentNativeCorePackageVersion();
|
|
30
30
|
const sha = process.env.VERCEL_GIT_COMMIT_SHA?.trim() ||
|
|
31
|
-
process.env.GITHUB_SHA?.trim() ||
|
|
32
|
-
process.env.CI_COMMIT_SHA?.trim() ||
|
|
33
31
|
process.env.AGENT_NATIVE_BUILD_SHA?.trim() ||
|
|
34
32
|
"";
|
|
35
33
|
return sha.length >= 7 ? `${v}+${sha.slice(0, 7)}` : v;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder-gateway-headers.js","sourceRoot":"","sources":["../../../src/agent/engine/builder-gateway-headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,IAAI,iBAAiB,GAAkB,IAAI,CAAC;AAE5C,gBAAgB;AAChB,MAAM,UAAU,gCAAgC;IAC9C,IAAI,iBAAiB,KAAK,IAAI;QAAE,OAAO,iBAAiB,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;QAC5D,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;QACpD,iBAAiB;YACf,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;gBACvD,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,SAAS,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB,GAAG,SAAS,CAAC;IAChC,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,8BAA8B;IAC5C,MAAM,CAAC,GAAG,gCAAgC,EAAE,CAAC;IAC7C,MAAM,GAAG,GACP,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,EAAE;QACzC,OAAO,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"builder-gateway-headers.js","sourceRoot":"","sources":["../../../src/agent/engine/builder-gateway-headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,IAAI,iBAAiB,GAAkB,IAAI,CAAC;AAE5C,gBAAgB;AAChB,MAAM,UAAU,gCAAgC;IAC9C,IAAI,iBAAiB,KAAK,IAAI;QAAE,OAAO,iBAAiB,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;QAC5D,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;QACpD,iBAAiB;YACf,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;gBACvD,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,SAAS,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB,GAAG,SAAS,CAAC;IAChC,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,8BAA8B;IAC5C,MAAM,CAAC,GAAG,gCAAgC,EAAE,CAAC;IAC7C,MAAM,GAAG,GACP,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,EAAE;QACzC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,IAAI,EAAE;QAC1C,EAAE,CAAC;IACL,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,+BAA+B;IAC7C,OAAO;QACL,eAAe,EAAE,oBAAoB;QACrC,kBAAkB,EAAE,8BAA8B,EAAE;KACrD,CAAC;AACJ,CAAC","sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\n\nlet cachedCoreVersion: string | null = null;\n\n/** @internal */\nexport function getAgentNativeCorePackageVersion(): string {\n if (cachedCoreVersion !== null) return cachedCoreVersion;\n try {\n const here = path.dirname(fileURLToPath(import.meta.url));\n const pkgPath = path.resolve(here, \"../../../package.json\");\n const raw = fs.readFileSync(pkgPath, \"utf-8\");\n const pkg = JSON.parse(raw) as { version?: string };\n cachedCoreVersion =\n typeof pkg.version === \"string\" && pkg.version.length > 0\n ? pkg.version\n : \"unknown\";\n } catch {\n cachedCoreVersion = \"unknown\";\n }\n return cachedCoreVersion;\n}\n\n/**\n * Version string for `x-client-version`: npm version plus a short git SHA when\n * available from allowlisted deploy env vars.\n */\nexport function getBuilderGatewayClientVersion(): string {\n const v = getAgentNativeCorePackageVersion();\n const sha =\n process.env.VERCEL_GIT_COMMIT_SHA?.trim() ||\n process.env.AGENT_NATIVE_BUILD_SHA?.trim() ||\n \"\";\n return sha.length >= 7 ? `${v}+${sha.slice(0, 7)}` : v;\n}\n\n/** Stable request headers for Builder LLM gateway attribution in logs. */\nexport function getBuilderGatewayRequestHeaders(): Record<string, string> {\n return {\n \"x-client-name\": \"@agent-native/core\",\n \"x-client-version\": getBuilderGatewayClientVersion(),\n };\n}\n"]}
|
|
@@ -33,6 +33,8 @@ export declare function unmatchedToolResultReplayText(part: {
|
|
|
33
33
|
/**
|
|
34
34
|
* Ensure every `tool-result` has a non-empty `toolName` and `toolInput` string,
|
|
35
35
|
* using the matching assistant `tool-call` in the same conversation.
|
|
36
|
+
* Assistant `tool-call` blocks without an immediately following result get a
|
|
37
|
+
* synthetic interrupted result so replayed history stays provider-protocol safe.
|
|
36
38
|
* Orphan tool-results (no resolvable tool name) become `text` notes so nothing
|
|
37
39
|
* is silently dropped from replayed history.
|
|
38
40
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate-anthropic.d.ts","sourceRoot":"","sources":["../../../src/agent/engine/translate-anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,WAAW,EACZ,MAAM,YAAY,CAAC;AAMpB,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC,IAAI,CAMtE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC,IAAI,EAAE,CAE5E;AAMD,wDAAwD;AACxD,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOtE;AAED,qFAAqF;AACrF,eAAO,MAAM,mCAAmC,4DACW,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,MAAM,CAiBT;
|
|
1
|
+
{"version":3,"file":"translate-anthropic.d.ts","sourceRoot":"","sources":["../../../src/agent/engine/translate-anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,WAAW,EACZ,MAAM,YAAY,CAAC;AAMpB,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC,IAAI,CAMtE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC,IAAI,EAAE,CAE5E;AAMD,wDAAwD;AACxD,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOtE;AAED,qFAAqF;AACrF,eAAO,MAAM,mCAAmC,4DACW,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,MAAM,CAiBT;AAgBD;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,aAAa,EAAE,GACxB,aAAa,EAAE,CA8IjB;AAMD,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,aAAa,EAClB,IAAI,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,GAClC,SAAS,CAAC,YAAY,CAMxB;AAED,yFAAyF;AACzF,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,aAAa,EAAE,GACxB,SAAS,CAAC,YAAY,EAAE,CAG1B;AAED;;;GAGG;AACH,wBAAgB,uCAAuC,CACrD,QAAQ,EAAE,aAAa,EAAE,GACxB,SAAS,CAAC,YAAY,EAAE,CAK1B;AAgFD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,SAAS,CAAC,YAAY,EAAE,GAChC,iBAAiB,EAAE,CA0BrB;AAMD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,GAAG,GAAG,WAAW,EAAE,CAoBtE;AAMD,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,OAAY,EACvB,OAAO,UAAQ,GACd,iBAAiB,CASnB"}
|
|
@@ -65,44 +65,77 @@ export function unmatchedToolResultReplayText(part) {
|
|
|
65
65
|
const err = part.isError ? " isError=true" : "";
|
|
66
66
|
return `${UNMATCHED_TOOL_RESULT_REPLAY_PREFIX} [tool_use_id=${part.toolCallId}${err}] ${body}`;
|
|
67
67
|
}
|
|
68
|
+
function interruptedToolResultPart(part) {
|
|
69
|
+
return {
|
|
70
|
+
type: "tool-result",
|
|
71
|
+
toolCallId: part.id,
|
|
72
|
+
toolName: part.name,
|
|
73
|
+
toolInput: stringifyToolUseInputForGateway(part.input),
|
|
74
|
+
content: "Interrupted before this tool returned a result.",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
68
77
|
/**
|
|
69
78
|
* Ensure every `tool-result` has a non-empty `toolName` and `toolInput` string,
|
|
70
79
|
* using the matching assistant `tool-call` in the same conversation.
|
|
80
|
+
* Assistant `tool-call` blocks without an immediately following result get a
|
|
81
|
+
* synthetic interrupted result so replayed history stays provider-protocol safe.
|
|
71
82
|
* Orphan tool-results (no resolvable tool name) become `text` notes so nothing
|
|
72
83
|
* is silently dropped from replayed history.
|
|
73
84
|
*/
|
|
74
85
|
export function backfillEngineMessagesToolResults(messages) {
|
|
75
|
-
// Walk messages in order.
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
//
|
|
86
|
+
// Walk messages in order. User tool-result blocks are valid only when they
|
|
87
|
+
// answer the immediately preceding assistant tool-call turn. This prevents
|
|
88
|
+
// older tool-results from being backfilled with later, unrelated tool-calls
|
|
89
|
+
// when ids are reused (e.g. `continuation_tc_1` reset across adapter
|
|
90
|
+
// recreations).
|
|
80
91
|
const toolUseById = new Map();
|
|
81
92
|
const out = [];
|
|
93
|
+
let pendingToolUses = [];
|
|
94
|
+
const flushInterruptedToolResults = () => {
|
|
95
|
+
if (pendingToolUses.length === 0)
|
|
96
|
+
return;
|
|
97
|
+
out.push({
|
|
98
|
+
role: "user",
|
|
99
|
+
content: pendingToolUses.map(interruptedToolResultPart),
|
|
100
|
+
});
|
|
101
|
+
pendingToolUses = [];
|
|
102
|
+
};
|
|
82
103
|
for (const msg of messages) {
|
|
83
104
|
if (msg.role === "assistant") {
|
|
105
|
+
flushInterruptedToolResults();
|
|
84
106
|
for (const part of msg.content) {
|
|
85
107
|
if (part.type === "tool-call") {
|
|
86
108
|
toolUseById.set(part.id, { name: part.name, input: part.input });
|
|
87
109
|
}
|
|
88
110
|
}
|
|
89
111
|
out.push(msg);
|
|
112
|
+
pendingToolUses = msg.content
|
|
113
|
+
.filter((part) => part.type === "tool-call")
|
|
114
|
+
.map((part) => ({
|
|
115
|
+
id: part.id,
|
|
116
|
+
name: part.name,
|
|
117
|
+
input: part.input,
|
|
118
|
+
}));
|
|
90
119
|
continue;
|
|
91
120
|
}
|
|
92
121
|
if (msg.role !== "user") {
|
|
122
|
+
flushInterruptedToolResults();
|
|
93
123
|
out.push(msg);
|
|
94
124
|
continue;
|
|
95
125
|
}
|
|
96
126
|
const newContent = [];
|
|
127
|
+
const pendingById = new Map(pendingToolUses.map((part) => [part.id, part]));
|
|
128
|
+
const matchedPendingToolResults = new Map();
|
|
97
129
|
for (const part of msg.content) {
|
|
98
130
|
if (part.type !== "tool-result") {
|
|
99
131
|
newContent.push(part);
|
|
100
132
|
continue;
|
|
101
133
|
}
|
|
102
134
|
const lookup = toolUseById.get(part.toolCallId);
|
|
135
|
+
const pendingLookup = pendingById.get(part.toolCallId);
|
|
103
136
|
const toolName = typeof part.toolName === "string" && part.toolName.trim().length > 0
|
|
104
137
|
? part.toolName
|
|
105
|
-
:
|
|
138
|
+
: pendingLookup?.name;
|
|
106
139
|
if (!toolName?.trim()) {
|
|
107
140
|
const id = typeof part.toolCallId === "string"
|
|
108
141
|
? part.toolCallId.trim()
|
|
@@ -119,17 +152,45 @@ export function backfillEngineMessagesToolResults(messages) {
|
|
|
119
152
|
});
|
|
120
153
|
continue;
|
|
121
154
|
}
|
|
155
|
+
if (pendingToolUses.length > 0 && !pendingLookup) {
|
|
156
|
+
const id = typeof part.toolCallId === "string"
|
|
157
|
+
? part.toolCallId.trim()
|
|
158
|
+
: part.toolCallId != null
|
|
159
|
+
? String(part.toolCallId).trim()
|
|
160
|
+
: "";
|
|
161
|
+
newContent.push({
|
|
162
|
+
type: "text",
|
|
163
|
+
text: unmatchedToolResultReplayText({
|
|
164
|
+
toolCallId: id.length > 0 ? id : "(missing)",
|
|
165
|
+
content: part.content,
|
|
166
|
+
isError: part.isError,
|
|
167
|
+
}),
|
|
168
|
+
});
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
122
171
|
const toolInput = typeof part.toolInput === "string" && part.toolInput.length > 0
|
|
123
172
|
? part.toolInput
|
|
124
|
-
: stringifyToolUseInputForGateway(lookup?.input);
|
|
125
|
-
|
|
173
|
+
: stringifyToolUseInputForGateway(pendingLookup?.input ?? lookup?.input);
|
|
174
|
+
const filled = {
|
|
126
175
|
type: "tool-result",
|
|
127
176
|
toolCallId: part.toolCallId,
|
|
128
177
|
toolName,
|
|
129
178
|
toolInput,
|
|
130
179
|
content: part.content,
|
|
131
180
|
...(part.isError ? { isError: true } : {}),
|
|
132
|
-
}
|
|
181
|
+
};
|
|
182
|
+
if (pendingLookup) {
|
|
183
|
+
matchedPendingToolResults.set(part.toolCallId, filled);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
newContent.push(filled);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (pendingToolUses.length > 0) {
|
|
190
|
+
const pairedResults = pendingToolUses.map((part) => matchedPendingToolResults.get(part.id) ??
|
|
191
|
+
interruptedToolResultPart(part));
|
|
192
|
+
newContent.unshift(...pairedResults);
|
|
193
|
+
pendingToolUses = [];
|
|
133
194
|
}
|
|
134
195
|
if (newContent.length === 0) {
|
|
135
196
|
out.push({
|
|
@@ -145,6 +206,7 @@ export function backfillEngineMessagesToolResults(messages) {
|
|
|
145
206
|
}
|
|
146
207
|
out.push({ role: "user", content: newContent });
|
|
147
208
|
}
|
|
209
|
+
flushInterruptedToolResults();
|
|
148
210
|
return out;
|
|
149
211
|
}
|
|
150
212
|
// ---------------------------------------------------------------------------
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate-anthropic.js","sourceRoot":"","sources":["../../../src/agent/engine/translate-anthropic.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Translation helpers between the AgentEngine normalized types and\n * @anthropic-ai/sdk's wire types.\n *\n * AnthropicEngine does very little translation because the framework's\n * EngineMessage / EngineTool shapes were modeled on Anthropic's types.\n * The main differences are: camelCase vs snake_case, and that\n * Anthropic uses `input_schema` while we use `inputSchema`.\n *\n * Builder's Gemini-backed gateway requires `tool_name` and `tool_input` on\n * every `tool_result` block. Use `engineMessagesToBuilderGatewayAnthropic` for\n * that path. The native Anthropic API keeps the strict `tool_result` shape\n * (`engineMessagesToAnthropic`).\n */\n\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n EngineTool,\n EngineMessage,\n EngineContentPart,\n EngineEvent,\n} from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// EngineTool → Anthropic.Tool\n// ---------------------------------------------------------------------------\n\nexport function engineToolToAnthropic(tool: EngineTool): Anthropic.Tool {\n return {\n name: tool.name,\n description: tool.description,\n input_schema: tool.inputSchema as Anthropic.Tool[\"input_schema\"],\n };\n}\n\nexport function engineToolsToAnthropic(tools: EngineTool[]): Anthropic.Tool[] {\n return tools.map(engineToolToAnthropic);\n}\n\n// ---------------------------------------------------------------------------\n// Tool result backfill (Gemini / Builder gateway)\n// ---------------------------------------------------------------------------\n\n/** JSON.stringify for tool_use inputs; never throws. */\nexport function stringifyToolUseInputForGateway(input: unknown): string {\n try {\n if (input === undefined || input === null) return \"{}\";\n return JSON.stringify(input);\n } catch {\n return \"{}\";\n }\n}\n\n/** Same lead-in as structured-history replay when a tool_result cannot be paired. */\nexport const UNMATCHED_TOOL_RESULT_REPLAY_PREFIX =\n \"(Omitted unmatched tool results from replayed history.)\";\n\n/**\n * Human/LLM-visible note when a tool_result cannot be matched to a tool_use\n * (replay from DB, or malformed engine history). Preserves tool_use_id and\n * a truncated payload instead of silently dropping the turn.\n */\nexport function unmatchedToolResultReplayText(part: {\n toolCallId: string;\n content: unknown;\n isError?: boolean;\n}): string {\n const max = 2000;\n let body =\n typeof part.content === \"string\"\n ? part.content\n : part.content === undefined || part.content === null\n ? \"\"\n : (() => {\n try {\n return JSON.stringify(part.content);\n } catch {\n return String(part.content);\n }\n })();\n if (body.length > max) body = `${body.slice(0, max)}…`;\n const err = part.isError ? \" isError=true\" : \"\";\n return `${UNMATCHED_TOOL_RESULT_REPLAY_PREFIX} [tool_use_id=${part.toolCallId}${err}] ${body}`;\n}\n\n/**\n * Ensure every `tool-result` has a non-empty `toolName` and `toolInput` string,\n * using the matching assistant `tool-call` in the same conversation.\n * Orphan tool-results (no resolvable tool name) become `text` notes so nothing\n * is silently dropped from replayed history.\n */\nexport function backfillEngineMessagesToolResults(\n messages: EngineMessage[],\n): EngineMessage[] {\n // Walk messages in order. For each user message, only consider tool-calls\n // from assistant messages that appeared earlier in the conversation. This\n // prevents an older tool-result from being backfilled with a later,\n // unrelated tool-call when ids are reused (e.g. `continuation_tc_1` reset\n // across adapter recreations).\n const toolUseById = new Map<string, { name: string; input: unknown }>();\n const out: EngineMessage[] = [];\n\n for (const msg of messages) {\n if (msg.role === \"assistant\") {\n for (const part of msg.content) {\n if (part.type === \"tool-call\") {\n toolUseById.set(part.id, { name: part.name, input: part.input });\n }\n }\n out.push(msg);\n continue;\n }\n if (msg.role !== \"user\") {\n out.push(msg);\n continue;\n }\n const newContent: EngineContentPart[] = [];\n for (const part of msg.content) {\n if (part.type !== \"tool-result\") {\n newContent.push(part);\n continue;\n }\n const lookup = toolUseById.get(part.toolCallId);\n const toolName =\n typeof part.toolName === \"string\" && part.toolName.trim().length > 0\n ? part.toolName\n : lookup?.name;\n if (!toolName?.trim()) {\n const id =\n typeof part.toolCallId === \"string\"\n ? part.toolCallId.trim()\n : part.toolCallId != null\n ? String(part.toolCallId).trim()\n : \"\";\n newContent.push({\n type: \"text\",\n text: unmatchedToolResultReplayText({\n toolCallId: id.length > 0 ? id : \"(missing)\",\n content: part.content,\n isError: part.isError,\n }),\n });\n continue;\n }\n const toolInput =\n typeof part.toolInput === \"string\" && part.toolInput.length > 0\n ? part.toolInput\n : stringifyToolUseInputForGateway(lookup?.input);\n newContent.push({\n type: \"tool-result\",\n toolCallId: part.toolCallId,\n toolName,\n toolInput,\n content: part.content,\n ...(part.isError ? { isError: true } : {}),\n });\n }\n if (newContent.length === 0) {\n out.push({\n role: \"user\",\n content: [\n {\n type: \"text\",\n text: UNMATCHED_TOOL_RESULT_REPLAY_PREFIX,\n },\n ],\n });\n continue;\n }\n out.push({ role: \"user\", content: newContent });\n }\n\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// EngineMessage → Anthropic.MessageParam\n// ---------------------------------------------------------------------------\n\nexport function engineMessageToAnthropic(\n msg: EngineMessage,\n opts?: { builderGateway?: boolean },\n): Anthropic.MessageParam {\n const builderGateway = opts?.builderGateway === true;\n return {\n role: msg.role,\n content: msg.content.map((p) => enginePartToAnthropic(p, builderGateway)),\n };\n}\n\n/** Messages for the Anthropic HTTP API (strict schema — no extra tool_result fields). */\nexport function engineMessagesToAnthropic(\n messages: EngineMessage[],\n): Anthropic.MessageParam[] {\n const normalized = backfillEngineMessagesToolResults(messages);\n return normalized.map((m) => engineMessageToAnthropic(m));\n}\n\n/**\n * Messages for the Builder LLM gateway (Gemini-backed). Same Anthropic-shaped\n * envelope, but every `tool_result` includes `tool_name` and `tool_input`.\n */\nexport function engineMessagesToBuilderGatewayAnthropic(\n messages: EngineMessage[],\n): Anthropic.MessageParam[] {\n const normalized = backfillEngineMessagesToolResults(messages);\n return normalized.map((m) =>\n engineMessageToAnthropic(m, { builderGateway: true }),\n );\n}\n\nfunction enginePartToAnthropic(\n part: EngineContentPart,\n builderGateway: boolean,\n): Anthropic.ContentBlockParam {\n switch (part.type) {\n case \"text\":\n return { type: \"text\", text: part.text };\n\n case \"image\":\n return {\n type: \"image\",\n source: {\n type: \"base64\",\n media_type: part.mediaType,\n data: part.data,\n },\n };\n\n case \"file\":\n if (part.mediaType === \"application/pdf\") {\n return {\n type: \"document\",\n source: {\n type: \"base64\",\n media_type: \"application/pdf\",\n data: part.data,\n },\n ...(part.filename ? { title: part.filename } : {}),\n } as any;\n }\n return {\n type: \"text\",\n text: `[Attached file: ${part.filename ?? \"attachment\"} (${part.mediaType})]`,\n };\n\n case \"tool-call\":\n return {\n type: \"tool_use\",\n id: part.id,\n name: part.name,\n input: part.input as Record<string, unknown>,\n } as any; // tool_use is a ContentBlockParam in Anthropic SDK\n\n case \"tool-result\": {\n if (builderGateway) {\n const tool_name = part.toolName.trim();\n const tool_input = part.toolInput;\n return {\n type: \"tool_result\",\n tool_use_id: part.toolCallId,\n tool_name,\n tool_input,\n content: part.content,\n ...(part.isError ? { is_error: true } : {}),\n } as any;\n }\n return {\n type: \"tool_result\",\n tool_use_id: part.toolCallId,\n content: part.content,\n ...(part.isError ? { is_error: true } : {}),\n } as any;\n }\n\n case \"thinking\":\n // Anthropic thinking blocks — pass through with signature for context window continuity\n return {\n type: \"thinking\",\n thinking: part.text,\n signature: part.signature ?? \"\",\n } as any;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Anthropic.ContentBlock → EngineContentPart (from final message)\n// ---------------------------------------------------------------------------\n\nexport function anthropicContentToEngine(\n content: Anthropic.ContentBlock[],\n): EngineContentPart[] {\n return content\n .map((block) => {\n if (block.type === \"text\") {\n return { type: \"text\" as const, text: block.text };\n }\n if (block.type === \"tool_use\") {\n return {\n type: \"tool-call\" as const,\n id: block.id,\n name: block.name,\n input: block.input,\n };\n }\n if ((block as any).type === \"thinking\") {\n const b = block as any;\n return {\n type: \"thinking\" as const,\n text: b.thinking ?? \"\",\n signature: b.signature,\n };\n }\n // Unknown block type — skip\n return { type: \"text\" as const, text: \"\" };\n })\n .filter((p) => !(p.type === \"text\" && p.text === \"\"));\n}\n\n// ---------------------------------------------------------------------------\n// Anthropic stream chunk → EngineEvent\n// ---------------------------------------------------------------------------\n\n/**\n * Translate an Anthropic stream chunk into zero or more EngineEvents.\n * Called in a loop as chunks arrive from client.messages.stream().\n */\nexport function anthropicChunkToEngineEvents(chunk: any): EngineEvent[] {\n const events: EngineEvent[] = [];\n\n if (chunk.type === \"content_block_delta\") {\n if (chunk.delta?.type === \"text_delta\") {\n events.push({ type: \"text-delta\", text: chunk.delta.text });\n } else if (chunk.delta?.type === \"thinking_delta\") {\n events.push({ type: \"thinking-delta\", text: chunk.delta.thinking ?? \"\" });\n } else if (chunk.delta?.type === \"signature_delta\") {\n // Signature arrives after thinking — emit as a thinking-delta with empty text\n // but carry the signature for the caller to store\n events.push({\n type: \"thinking-delta\",\n text: \"\",\n signature: chunk.delta.signature,\n });\n }\n }\n\n return events;\n}\n\n// ---------------------------------------------------------------------------\n// Build tool_result blocks to append to messages after tool dispatch\n// ---------------------------------------------------------------------------\n\nexport function buildToolResultPart(\n toolCallId: string,\n toolName: string,\n content: string,\n toolInput: unknown = {},\n isError = false,\n): EngineContentPart {\n return {\n type: \"tool-result\",\n toolCallId,\n toolName,\n toolInput: stringifyToolUseInputForGateway(toolInput),\n content,\n ...(isError ? { isError } : {}),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"translate-anthropic.js","sourceRoot":"","sources":["../../../src/agent/engine/translate-anthropic.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Translation helpers between the AgentEngine normalized types and\n * @anthropic-ai/sdk's wire types.\n *\n * AnthropicEngine does very little translation because the framework's\n * EngineMessage / EngineTool shapes were modeled on Anthropic's types.\n * The main differences are: camelCase vs snake_case, and that\n * Anthropic uses `input_schema` while we use `inputSchema`.\n *\n * Builder's Gemini-backed gateway requires `tool_name` and `tool_input` on\n * every `tool_result` block. Use `engineMessagesToBuilderGatewayAnthropic` for\n * that path. The native Anthropic API keeps the strict `tool_result` shape\n * (`engineMessagesToAnthropic`).\n */\n\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n EngineTool,\n EngineMessage,\n EngineContentPart,\n EngineEvent,\n} from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// EngineTool → Anthropic.Tool\n// ---------------------------------------------------------------------------\n\nexport function engineToolToAnthropic(tool: EngineTool): Anthropic.Tool {\n return {\n name: tool.name,\n description: tool.description,\n input_schema: tool.inputSchema as Anthropic.Tool[\"input_schema\"],\n };\n}\n\nexport function engineToolsToAnthropic(tools: EngineTool[]): Anthropic.Tool[] {\n return tools.map(engineToolToAnthropic);\n}\n\n// ---------------------------------------------------------------------------\n// Tool result backfill (Gemini / Builder gateway)\n// ---------------------------------------------------------------------------\n\n/** JSON.stringify for tool_use inputs; never throws. */\nexport function stringifyToolUseInputForGateway(input: unknown): string {\n try {\n if (input === undefined || input === null) return \"{}\";\n return JSON.stringify(input);\n } catch {\n return \"{}\";\n }\n}\n\n/** Same lead-in as structured-history replay when a tool_result cannot be paired. */\nexport const UNMATCHED_TOOL_RESULT_REPLAY_PREFIX =\n \"(Omitted unmatched tool results from replayed history.)\";\n\n/**\n * Human/LLM-visible note when a tool_result cannot be matched to a tool_use\n * (replay from DB, or malformed engine history). Preserves tool_use_id and\n * a truncated payload instead of silently dropping the turn.\n */\nexport function unmatchedToolResultReplayText(part: {\n toolCallId: string;\n content: unknown;\n isError?: boolean;\n}): string {\n const max = 2000;\n let body =\n typeof part.content === \"string\"\n ? part.content\n : part.content === undefined || part.content === null\n ? \"\"\n : (() => {\n try {\n return JSON.stringify(part.content);\n } catch {\n return String(part.content);\n }\n })();\n if (body.length > max) body = `${body.slice(0, max)}…`;\n const err = part.isError ? \" isError=true\" : \"\";\n return `${UNMATCHED_TOOL_RESULT_REPLAY_PREFIX} [tool_use_id=${part.toolCallId}${err}] ${body}`;\n}\n\nfunction interruptedToolResultPart(part: {\n id: string;\n name: string;\n input: unknown;\n}): EngineContentPart {\n return {\n type: \"tool-result\",\n toolCallId: part.id,\n toolName: part.name,\n toolInput: stringifyToolUseInputForGateway(part.input),\n content: \"Interrupted before this tool returned a result.\",\n };\n}\n\n/**\n * Ensure every `tool-result` has a non-empty `toolName` and `toolInput` string,\n * using the matching assistant `tool-call` in the same conversation.\n * Assistant `tool-call` blocks without an immediately following result get a\n * synthetic interrupted result so replayed history stays provider-protocol safe.\n * Orphan tool-results (no resolvable tool name) become `text` notes so nothing\n * is silently dropped from replayed history.\n */\nexport function backfillEngineMessagesToolResults(\n messages: EngineMessage[],\n): EngineMessage[] {\n // Walk messages in order. User tool-result blocks are valid only when they\n // answer the immediately preceding assistant tool-call turn. This prevents\n // older tool-results from being backfilled with later, unrelated tool-calls\n // when ids are reused (e.g. `continuation_tc_1` reset across adapter\n // recreations).\n const toolUseById = new Map<string, { name: string; input: unknown }>();\n const out: EngineMessage[] = [];\n let pendingToolUses: Array<{ id: string; name: string; input: unknown }> = [];\n\n const flushInterruptedToolResults = () => {\n if (pendingToolUses.length === 0) return;\n out.push({\n role: \"user\",\n content: pendingToolUses.map(interruptedToolResultPart),\n });\n pendingToolUses = [];\n };\n\n for (const msg of messages) {\n if (msg.role === \"assistant\") {\n flushInterruptedToolResults();\n for (const part of msg.content) {\n if (part.type === \"tool-call\") {\n toolUseById.set(part.id, { name: part.name, input: part.input });\n }\n }\n out.push(msg);\n pendingToolUses = msg.content\n .filter(\n (part): part is Extract<EngineContentPart, { type: \"tool-call\" }> =>\n part.type === \"tool-call\",\n )\n .map((part) => ({\n id: part.id,\n name: part.name,\n input: part.input,\n }));\n continue;\n }\n if (msg.role !== \"user\") {\n flushInterruptedToolResults();\n out.push(msg);\n continue;\n }\n const newContent: EngineContentPart[] = [];\n const pendingById = new Map(\n pendingToolUses.map((part) => [part.id, part] as const),\n );\n const matchedPendingToolResults = new Map<string, EngineContentPart>();\n for (const part of msg.content) {\n if (part.type !== \"tool-result\") {\n newContent.push(part);\n continue;\n }\n const lookup = toolUseById.get(part.toolCallId);\n const pendingLookup = pendingById.get(part.toolCallId);\n const toolName =\n typeof part.toolName === \"string\" && part.toolName.trim().length > 0\n ? part.toolName\n : pendingLookup?.name;\n if (!toolName?.trim()) {\n const id =\n typeof part.toolCallId === \"string\"\n ? part.toolCallId.trim()\n : part.toolCallId != null\n ? String(part.toolCallId).trim()\n : \"\";\n newContent.push({\n type: \"text\",\n text: unmatchedToolResultReplayText({\n toolCallId: id.length > 0 ? id : \"(missing)\",\n content: part.content,\n isError: part.isError,\n }),\n });\n continue;\n }\n if (pendingToolUses.length > 0 && !pendingLookup) {\n const id =\n typeof part.toolCallId === \"string\"\n ? part.toolCallId.trim()\n : part.toolCallId != null\n ? String(part.toolCallId).trim()\n : \"\";\n newContent.push({\n type: \"text\",\n text: unmatchedToolResultReplayText({\n toolCallId: id.length > 0 ? id : \"(missing)\",\n content: part.content,\n isError: part.isError,\n }),\n });\n continue;\n }\n const toolInput =\n typeof part.toolInput === \"string\" && part.toolInput.length > 0\n ? part.toolInput\n : stringifyToolUseInputForGateway(\n pendingLookup?.input ?? lookup?.input,\n );\n const filled: EngineContentPart = {\n type: \"tool-result\",\n toolCallId: part.toolCallId,\n toolName,\n toolInput,\n content: part.content,\n ...(part.isError ? { isError: true } : {}),\n };\n if (pendingLookup) {\n matchedPendingToolResults.set(part.toolCallId, filled);\n } else {\n newContent.push(filled);\n }\n }\n if (pendingToolUses.length > 0) {\n const pairedResults = pendingToolUses.map(\n (part) =>\n matchedPendingToolResults.get(part.id) ??\n interruptedToolResultPart(part),\n );\n newContent.unshift(...pairedResults);\n pendingToolUses = [];\n }\n if (newContent.length === 0) {\n out.push({\n role: \"user\",\n content: [\n {\n type: \"text\",\n text: UNMATCHED_TOOL_RESULT_REPLAY_PREFIX,\n },\n ],\n });\n continue;\n }\n out.push({ role: \"user\", content: newContent });\n }\n\n flushInterruptedToolResults();\n\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// EngineMessage → Anthropic.MessageParam\n// ---------------------------------------------------------------------------\n\nexport function engineMessageToAnthropic(\n msg: EngineMessage,\n opts?: { builderGateway?: boolean },\n): Anthropic.MessageParam {\n const builderGateway = opts?.builderGateway === true;\n return {\n role: msg.role,\n content: msg.content.map((p) => enginePartToAnthropic(p, builderGateway)),\n };\n}\n\n/** Messages for the Anthropic HTTP API (strict schema — no extra tool_result fields). */\nexport function engineMessagesToAnthropic(\n messages: EngineMessage[],\n): Anthropic.MessageParam[] {\n const normalized = backfillEngineMessagesToolResults(messages);\n return normalized.map((m) => engineMessageToAnthropic(m));\n}\n\n/**\n * Messages for the Builder LLM gateway (Gemini-backed). Same Anthropic-shaped\n * envelope, but every `tool_result` includes `tool_name` and `tool_input`.\n */\nexport function engineMessagesToBuilderGatewayAnthropic(\n messages: EngineMessage[],\n): Anthropic.MessageParam[] {\n const normalized = backfillEngineMessagesToolResults(messages);\n return normalized.map((m) =>\n engineMessageToAnthropic(m, { builderGateway: true }),\n );\n}\n\nfunction enginePartToAnthropic(\n part: EngineContentPart,\n builderGateway: boolean,\n): Anthropic.ContentBlockParam {\n switch (part.type) {\n case \"text\":\n return { type: \"text\", text: part.text };\n\n case \"image\":\n return {\n type: \"image\",\n source: {\n type: \"base64\",\n media_type: part.mediaType,\n data: part.data,\n },\n };\n\n case \"file\":\n if (part.mediaType === \"application/pdf\") {\n return {\n type: \"document\",\n source: {\n type: \"base64\",\n media_type: \"application/pdf\",\n data: part.data,\n },\n ...(part.filename ? { title: part.filename } : {}),\n } as any;\n }\n return {\n type: \"text\",\n text: `[Attached file: ${part.filename ?? \"attachment\"} (${part.mediaType})]`,\n };\n\n case \"tool-call\":\n return {\n type: \"tool_use\",\n id: part.id,\n name: part.name,\n input: part.input as Record<string, unknown>,\n } as any; // tool_use is a ContentBlockParam in Anthropic SDK\n\n case \"tool-result\": {\n if (builderGateway) {\n const tool_name = part.toolName.trim();\n const tool_input = part.toolInput;\n return {\n type: \"tool_result\",\n tool_use_id: part.toolCallId,\n tool_name,\n tool_input,\n content: part.content,\n ...(part.isError ? { is_error: true } : {}),\n } as any;\n }\n return {\n type: \"tool_result\",\n tool_use_id: part.toolCallId,\n content: part.content,\n ...(part.isError ? { is_error: true } : {}),\n } as any;\n }\n\n case \"thinking\":\n // Anthropic thinking blocks — pass through with signature for context window continuity\n return {\n type: \"thinking\",\n thinking: part.text,\n signature: part.signature ?? \"\",\n } as any;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Anthropic.ContentBlock → EngineContentPart (from final message)\n// ---------------------------------------------------------------------------\n\nexport function anthropicContentToEngine(\n content: Anthropic.ContentBlock[],\n): EngineContentPart[] {\n return content\n .map((block) => {\n if (block.type === \"text\") {\n return { type: \"text\" as const, text: block.text };\n }\n if (block.type === \"tool_use\") {\n return {\n type: \"tool-call\" as const,\n id: block.id,\n name: block.name,\n input: block.input,\n };\n }\n if ((block as any).type === \"thinking\") {\n const b = block as any;\n return {\n type: \"thinking\" as const,\n text: b.thinking ?? \"\",\n signature: b.signature,\n };\n }\n // Unknown block type — skip\n return { type: \"text\" as const, text: \"\" };\n })\n .filter((p) => !(p.type === \"text\" && p.text === \"\"));\n}\n\n// ---------------------------------------------------------------------------\n// Anthropic stream chunk → EngineEvent\n// ---------------------------------------------------------------------------\n\n/**\n * Translate an Anthropic stream chunk into zero or more EngineEvents.\n * Called in a loop as chunks arrive from client.messages.stream().\n */\nexport function anthropicChunkToEngineEvents(chunk: any): EngineEvent[] {\n const events: EngineEvent[] = [];\n\n if (chunk.type === \"content_block_delta\") {\n if (chunk.delta?.type === \"text_delta\") {\n events.push({ type: \"text-delta\", text: chunk.delta.text });\n } else if (chunk.delta?.type === \"thinking_delta\") {\n events.push({ type: \"thinking-delta\", text: chunk.delta.thinking ?? \"\" });\n } else if (chunk.delta?.type === \"signature_delta\") {\n // Signature arrives after thinking — emit as a thinking-delta with empty text\n // but carry the signature for the caller to store\n events.push({\n type: \"thinking-delta\",\n text: \"\",\n signature: chunk.delta.signature,\n });\n }\n }\n\n return events;\n}\n\n// ---------------------------------------------------------------------------\n// Build tool_result blocks to append to messages after tool dispatch\n// ---------------------------------------------------------------------------\n\nexport function buildToolResultPart(\n toolCallId: string,\n toolName: string,\n content: string,\n toolInput: unknown = {},\n isError = false,\n): EngineContentPart {\n return {\n type: \"tool-result\",\n toolCallId,\n toolName,\n toolInput: stringifyToolUseInputForGateway(toolInput),\n content,\n ...(isError ? { isError } : {}),\n };\n}\n"]}
|
|
@@ -5,7 +5,7 @@ import { IconAlertTriangle, IconLoader2 } from "@tabler/icons-react";
|
|
|
5
5
|
import { agentNativePath } from "../api-path.js";
|
|
6
6
|
import { cn } from "../utils.js";
|
|
7
7
|
const DEFAULT_IFRAME_HEIGHT = 360;
|
|
8
|
-
const MAX_IFRAME_HEIGHT =
|
|
8
|
+
const MAX_IFRAME_HEIGHT = 900;
|
|
9
9
|
const SANDBOX_FLAGS = "allow-scripts allow-forms allow-popups";
|
|
10
10
|
export function McpAppRenderer({ app, className }) {
|
|
11
11
|
const iframeRef = useRef(null);
|
|
@@ -168,6 +168,11 @@ function sanitizeCspSource(value) {
|
|
|
168
168
|
const source = value.trim();
|
|
169
169
|
if (!source || source.includes("'") || /[\s;]/.test(source))
|
|
170
170
|
return null;
|
|
171
|
+
if (source === "https:")
|
|
172
|
+
return source;
|
|
173
|
+
if (/^http:\/\/(?:localhost|127\.0\.0\.1|\[::1\]):\*$/i.test(source)) {
|
|
174
|
+
return source;
|
|
175
|
+
}
|
|
171
176
|
if (/^https:\/\/\*\.[a-z0-9.-]+(?::\d+)?$/i.test(source))
|
|
172
177
|
return source;
|
|
173
178
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpAppRenderer.js","sourceRoot":"","sources":["../../../src/client/mcp-apps/McpAppRenderer.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,EACL,SAAS,EACT,oBAAoB,EACpB,mBAAmB,GAGpB,MAAM,2CAA2C,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAEjC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAC9B,MAAM,aAAa,GAAG,wCAAwC,CAAC;AAa/D,MAAM,UAAU,cAAc,CAAC,EAAE,GAAG,EAAE,SAAS,EAAuB;IACpE,MAAM,SAAS,GAAG,MAAM,CAA2B,IAAI,CAAC,CAAC;IACzD,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAC;IAC5D,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,MAAM,oBAAoB,GAAG,OAAO,CAClC,GAAG,EAAE,CAAC,0BAA0B,CAAC,MAAM,CAAC,WAAW,CAAC,EACpD,CAAC,MAAM,CAAC,WAAW,CAAC,CACrB,CAAC;IACF,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EACxD,CAAC,YAAY,EAAE,GAAG,CAAC,CACpB,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,eAAe,CAAC,IAAI,CAAC,CAAC;QACtB,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChB,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;QACjC,IAAI,CAAC,MAAM,EAAE,aAAa,IAAI,CAAC,MAAM,IAAI,YAAY,KAAK,MAAM;YAAE,OAAO;QAEzE,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,IAAI,EACJ,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,EAC1C;YACE,SAAS,EAAE,EAAE;YACb,WAAW,EAAE,EAAE;YACf,eAAe,EAAE,EAAE;YACnB,OAAO,EAAE,EAAE;YACX,OAAO,EAAE;gBACP,WAAW,EAAE,oBAAoB;gBACjC,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,EAAE;aACtB;SACF,EACD;YACE,WAAW,EAAE,gBAAgB,CAAC,GAAG,CAAQ;SAC1C,CACF,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,YAAY,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE;YAC/D,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACnE,OAAO;YACT,CAAC;YACD,SAAS,CACP,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAClE,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE;YAC1C,IAAI,MAAM;gBAAE,OAAO;YACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,KAAK,MAAM,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;YACxD,KAAK,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,UAA4B,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE;YAC5D,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;gBACnE,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YAClC,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,UAAU,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACpC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YACtD,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,qBAAqB,CAAC,CAAC;YAClD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,MAAM,CAAC,UAAU,GAAG,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,EAAE;YAC/D,MAAM,QAAQ,GAAG,2BAA2B,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACjE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,eAAe,CAAC,8CAA8C,CAAC,CAAC;YACzE,CAAC;YACD,IAAI,CAAC;gBACH,OAAO,MAAM,kBAAkB,CAAiB,WAAW,EAAE;oBAC3D,QAAQ,EAAE,GAAG,CAAC,QAAQ;oBACtB,QAAQ;oBACR,SAAS,EACP,aAAa,IAAI,OAAO,aAAa,KAAK,QAAQ;wBAChD,CAAC,CAAC,aAAa;wBACf,CAAC,CAAC,EAAE;iBACT,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO,eAAe,CAAC,GAAG,EAAE,OAAO,IAAI,2BAA2B,CAAC,CAAC;YACtE,CAAC;QACH,CAAC,CAAC;QACD,MAAc,CAAC,WAAW,GAAG,KAAK,IAAI,EAAE,CACvC,kBAAkB,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,cAAc,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CACxC,kBAAkB,CAAC,eAAe,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;QACvE,MAAM,CAAC,eAAe,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;QACzD,MAAM,CAAC,uBAAuB,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,CAAC,CAAC;QACzE,MAAM,CAAC,cAAc,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,SAAS,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,MAAM,CAAC,oBAAoB,GAAG,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAE/C,MAAM,SAAS,GAAG,IAAI,oBAAoB,CACxC,MAAM,CAAC,aAAa,EACpB,MAAM,CAAC,aAAa,CACrB,CAAC;QACF,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,GAAQ,EAAE,EAAE;YAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,QAAQ,CAAC,GAAG,EAAE,OAAO,IAAI,+BAA+B,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,MAAM,GAAG,IAAI,CAAC;YACd,QAAQ,CAAC,KAAK,CAAC,CAAC;YAChB,KAAK,MAAM;iBACR,gBAAgB,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;iBACtC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;iBACtB,OAAO,CAAC,GAAG,EAAE;gBACZ,KAAM,MAAc,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC1D,CAAC,CAAC,CAAC;QACP,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAElE,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,oCAAoC,EAAE,SAAS,CAAC,aACjE,KAAC,iBAAiB,IAAC,IAAI,EAAE,EAAE,GAAI,EAC/B,iEAAgD,IAC5C,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,eAAe,EACf,MAAM,CAAC,aAAa,KAAK,KAAK,IAAI,sBAAsB,EACxD,SAAS,CACV,aAEA,CAAC,KAAK,IAAI,CAAC,KAAK,IAAI,CACnB,eAAK,SAAS,EAAC,wBAAwB,aACrC,KAAC,WAAW,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,yBAAyB,GAAG,EAC7D,6CAA4B,IACxB,CACP,EACA,KAAK,IAAI,CACR,eAAK,SAAS,EAAC,sBAAsB,aACnC,KAAC,iBAAiB,IAAC,IAAI,EAAE,EAAE,GAAI,EAC/B,yBAAO,KAAK,GAAQ,IAChB,CACP,EACD,iBACE,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,GAAG,CAAC,gBAAgB,EAC9C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,mBAAmB,CAAC,oBAAoB,CAAC,EAChD,KAAK,EAAE,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,GACrC,IACE,CACP,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,GAAuB;IAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC;IACjC,MAAM,EAAE,GACN,IAAI,EAAE,EAAE,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChE,CAAC,CAAE,IAAI,CAAC,EAAqB;QAC7B,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,gBAAgB,CACvB,QAAqD;IAErD,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC,IAAI,CAAC;IAC5D,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACjD,IAAI,CAAC;QACH,IAAI,OAAO,IAAI,KAAK,UAAU;YAAE,OAAO,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,WAAiD;IAEjD,OAAO,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAiC;IAC9D,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,kBAAkB,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IACrD,OAAO;QACL,oBAAoB;QACpB,YAAY,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;QACrD,oBAAoB;QACpB,eAAe,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;QAC9D,sBAAsB,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;QACzE,wBAAwB,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;QAC3E,iBAAiB,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;QACpE,4BAA4B,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;QAC/E,6BAA6B,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;QAChF,aAAa,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;KAC3D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,MAA4B;IACtD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,EAAE,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,MAAM;YAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACtC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACzE,IAAI,uCAAuC,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IACxE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC;QACjD,IACE,GAAG,CAAC,QAAQ,KAAK,OAAO;YACxB,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EACxD,CAAC;YACD,OAAO,GAAG,CAAC,MAAM,CAAC;QACpB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,GAAW;IAC1C,MAAM,IAAI,GAAG,uDAAuD,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;IAC7F,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,OAAO,CACjB,gBAAgB,EAChB,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,OAAO,SAAS,IAAI,SAAS,CAC9C,CAAC;IACJ,CAAC;IACD,OAAO,8BAA8B,IAAI,gBAAgB,IAAI,gBAAgB,CAAC;AAChF,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAuB;IAC/C,MAAM,IAAI,GACR,OAAO,MAAM,KAAK,WAAW;QAC3B,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC;QAC5C,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3E,MAAM,KAAK,GACT,OAAO,QAAQ,KAAK,WAAW;QAC/B,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;YAClD,MAAM,CAAC,UAAU,EAAE,CAAC,8BAA8B,CAAC,CAAC,OAAO,CAAC;QAC5D,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,OAAO,CAAC;IACd,OAAO;QACL,QAAQ,EAAE,GAAG,CAAC,IAAI;YAChB,CAAC,CAAC;gBACE,IAAI,EAAE;oBACJ,IAAI,EAAE,GAAG,CAAC,gBAAgB;oBAC1B,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW;oBACjC,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI;wBACnC,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE,EAAE;qBACf;oBACD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACrD;aACF;YACH,CAAC,CAAC,SAAS;QACb,KAAK;QACL,WAAW,EAAE,QAAQ;QACrB,qBAAqB,EAAE,CAAC,QAAQ,CAAC;QACjC,QAAQ,EAAE,KAAK;QACf,SAAS,EAAE,cAAc;QACzB,MAAM,EAAE,OAAO,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;QACzE,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ;QAC1D,mBAAmB,EAAE;YACnB,SAAS,EAAE,iBAAiB;YAC5B,QAAQ,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;SACxE;QACD,MAAM,EAAE;YACN,SAAS,EAAE;gBACT,4BAA4B,EAAE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;gBAC5D,8BAA8B,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBACzD,sBAAsB,EAAE,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;gBACtD,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;gBAC9D,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;gBACpD,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC,IAAI,0BAA0B;gBAClE,aAAa,EACX,MAAM,CAAC,aAAa,CAAC;oBACrB,gDAAgD;gBAClD,oBAAoB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,KAAK;aAClD;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7C,CAAC;AAED,SAAS,2BAA2B,CAClC,QAAgB,EAChB,OAAe;IAEf,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,MAAM,GAAG,QAAQ,QAAQ,IAAI,CAAC;IACpC,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,QAAsD,EACtD,IAA6B;IAE7B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,eAAe,CAAC,2BAA2B,QAAQ,EAAE,CAAC,EACtD;QACE,MAAM,EAAE,MAAM;QACd,WAAW,EAAE,aAAa;QAC1B,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CACF,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,OAAO,GAAG,2BAA2B,QAAQ,CAAC,MAAM,GAAG,CAAC;QAC5D,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,OAAO,IAAI,EAAE,KAAK,KAAK,QAAQ;gBAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAC;AACtC,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACtC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC;QACtD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAa;IACtC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,OAAO,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC","sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n AppBridge,\n PostMessageTransport,\n buildAllowAttribute,\n type McpUiResourceCsp,\n type McpUiResourcePermissions,\n} from \"@modelcontextprotocol/ext-apps/app-bridge\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { IconAlertTriangle, IconLoader2 } from \"@tabler/icons-react\";\nimport type { AgentMcpAppPayload } from \"../../mcp-client/app-result.js\";\nimport { agentNativePath } from \"../api-path.js\";\nimport { cn } from \"../utils.js\";\n\nconst DEFAULT_IFRAME_HEIGHT = 360;\nconst MAX_IFRAME_HEIGHT = 720;\nconst SANDBOX_FLAGS = \"allow-scripts allow-forms allow-popups\";\n\nexport interface McpAppRendererProps {\n app: AgentMcpAppPayload;\n className?: string;\n}\n\ntype ResourceUiMeta = {\n csp?: McpUiResourceCsp;\n permissions?: McpUiResourcePermissions;\n prefersBorder?: boolean;\n};\n\nexport function McpAppRenderer({ app, className }: McpAppRendererProps) {\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n const [loadedSrcDoc, setLoadedSrcDoc] = useState<string | null>(null);\n const [height, setHeight] = useState(DEFAULT_IFRAME_HEIGHT);\n const [error, setError] = useState<string | null>(null);\n const [ready, setReady] = useState(false);\n const resourceHtml = app.resource ? htmlFromResource(app.resource) : \"\";\n const uiMeta = useMemo(() => resourceUiMeta(app), [app]);\n const supportedPermissions = useMemo(\n () => supportedMcpAppPermissions(uiMeta.permissions),\n [uiMeta.permissions],\n );\n const csp = buildMcpAppCsp(uiMeta.csp);\n const srcDoc = useMemo(\n () => (resourceHtml ? injectCsp(resourceHtml, csp) : \"\"),\n [resourceHtml, csp],\n );\n\n useEffect(() => {\n setLoadedSrcDoc(null);\n setReady(false);\n setError(null);\n }, [srcDoc]);\n\n useEffect(() => {\n const iframe = iframeRef.current;\n if (!iframe?.contentWindow || !srcDoc || loadedSrcDoc !== srcDoc) return;\n\n let closed = false;\n const bridge = new AppBridge(\n null,\n { name: \"Agent Native\", version: \"1.0.0\" },\n {\n openLinks: {},\n serverTools: {},\n serverResources: {},\n logging: {},\n sandbox: {\n permissions: supportedPermissions,\n csp: uiMeta.csp ?? {},\n },\n },\n {\n hostContext: buildHostContext(app) as any,\n },\n );\n\n bridge.addEventListener(\"sizechange\", ({ height: nextHeight }) => {\n if (typeof nextHeight !== \"number\" || !Number.isFinite(nextHeight)) {\n return;\n }\n setHeight(\n Math.min(MAX_IFRAME_HEIGHT, Math.max(220, Math.ceil(nextHeight))),\n );\n });\n bridge.addEventListener(\"initialized\", () => {\n if (closed) return;\n setReady(true);\n void bridge.sendToolInput({ arguments: app.toolInput });\n void bridge.sendToolResult(app.toolResult as CallToolResult);\n });\n bridge.addEventListener(\"loggingmessage\", ({ level, data }) => {\n if (level === \"error\" || level === \"critical\" || level === \"alert\") {\n console.warn(\"[mcp-app]\", data);\n }\n });\n bridge.onopenlink = async ({ url }) => {\n if (!isSafeExternalUrl(url)) return { isError: true };\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n return {};\n };\n bridge.oncalltool = async ({ name, arguments: toolArguments }) => {\n const toolName = normalizeSameServerToolName(app.serverId, name);\n if (!toolName) {\n return errorToolResult(\"Cross-server MCP App tool calls are blocked.\");\n }\n try {\n return await postMcpAppEndpoint<CallToolResult>(\"call-tool\", {\n serverId: app.serverId,\n toolName,\n arguments:\n toolArguments && typeof toolArguments === \"object\"\n ? toolArguments\n : {},\n });\n } catch (err: any) {\n return errorToolResult(err?.message ?? \"MCP App tool call failed.\");\n }\n };\n (bridge as any).onlisttools = async () =>\n postMcpAppEndpoint(\"list-tools\", { serverId: app.serverId });\n bridge.onreadresource = async ({ uri }) =>\n postMcpAppEndpoint(\"read-resource\", { serverId: app.serverId, uri });\n bridge.onlistresources = async () => ({ resources: [] });\n bridge.onlistresourcetemplates = async () => ({ resourceTemplates: [] });\n bridge.ondownloadfile = async () => ({ isError: true });\n bridge.onmessage = async () => ({ isError: true });\n bridge.onupdatemodelcontext = async () => ({});\n\n const transport = new PostMessageTransport(\n iframe.contentWindow,\n iframe.contentWindow,\n );\n setReady(false);\n setError(null);\n bridge.connect(transport).catch((err: any) => {\n if (!closed) {\n setError(err?.message ?? \"Failed to initialize MCP App.\");\n }\n });\n\n return () => {\n closed = true;\n setReady(false);\n void bridge\n .teardownResource({}, { timeout: 500 })\n .catch(() => undefined)\n .finally(() => {\n void (bridge as any).close?.().catch?.(() => undefined);\n });\n };\n }, [app, loadedSrcDoc, srcDoc, supportedPermissions, uiMeta.csp]);\n\n if (!resourceHtml) {\n return (\n <div className={cn(\"agent-mcp-app agent-mcp-app--error\", className)}>\n <IconAlertTriangle size={15} />\n <span>MCP App resource was not available.</span>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n \"agent-mcp-app\",\n uiMeta.prefersBorder === false && \"agent-mcp-app--flush\",\n className,\n )}\n >\n {!ready && !error && (\n <div className=\"agent-mcp-app__loading\">\n <IconLoader2 size={14} className=\"agent-conversation-spin\" />\n <span>Loading MCP App</span>\n </div>\n )}\n {error && (\n <div className=\"agent-mcp-app__error\">\n <IconAlertTriangle size={15} />\n <span>{error}</span>\n </div>\n )}\n <iframe\n ref={iframeRef}\n title={app.tool?.title ?? app.originalToolName}\n srcDoc={srcDoc}\n sandbox={SANDBOX_FLAGS}\n allow={buildAllowAttribute(supportedPermissions)}\n style={{ height }}\n onLoad={() => setLoadedSrcDoc(srcDoc)}\n />\n </div>\n );\n}\n\nfunction resourceUiMeta(app: AgentMcpAppPayload): ResourceUiMeta {\n const meta = app.resource?._meta;\n const ui =\n meta?.ui && typeof meta.ui === \"object\" && !Array.isArray(meta.ui)\n ? (meta.ui as ResourceUiMeta)\n : {};\n return ui;\n}\n\nfunction htmlFromResource(\n resource: NonNullable<AgentMcpAppPayload[\"resource\"]>,\n): string {\n if (typeof resource.text === \"string\") return resource.text;\n if (typeof resource.blob !== \"string\") return \"\";\n try {\n if (typeof atob !== \"function\") return \"\";\n return atob(resource.blob);\n } catch {\n return \"\";\n }\n}\n\nexport function supportedMcpAppPermissions(\n permissions: McpUiResourcePermissions | undefined,\n): McpUiResourcePermissions {\n return permissions?.clipboardWrite ? { clipboardWrite: {} } : {};\n}\n\nexport function buildMcpAppCsp(csp: McpUiResourceCsp | undefined): string {\n const connect = sanitizeCspSources(csp?.connectDomains);\n const resources = sanitizeCspSources(csp?.resourceDomains);\n const frames = sanitizeCspSources(csp?.frameDomains);\n const base = sanitizeCspSources(csp?.baseUriDomains);\n return [\n \"default-src 'none'\",\n `base-uri ${base.length ? base.join(\" \") : \"'none'\"}`,\n \"form-action 'none'\",\n `connect-src ${connect.length ? connect.join(\" \") : \"'none'\"}`,\n `img-src data: blob:${resources.length ? ` ${resources.join(\" \")}` : \"\"}`,\n `media-src data: blob:${resources.length ? ` ${resources.join(\" \")}` : \"\"}`,\n `font-src data:${resources.length ? ` ${resources.join(\" \")}` : \"\"}`,\n `style-src 'unsafe-inline'${resources.length ? ` ${resources.join(\" \")}` : \"\"}`,\n `script-src 'unsafe-inline'${resources.length ? ` ${resources.join(\" \")}` : \"\"}`,\n `frame-src ${frames.length ? frames.join(\" \") : \"'none'\"}`,\n ].join(\"; \");\n}\n\nfunction sanitizeCspSources(values: string[] | undefined): string[] {\n const out: string[] = [];\n for (const value of values ?? []) {\n const source = sanitizeCspSource(value);\n if (source) out.push(source);\n }\n return [...new Set(out)];\n}\n\nfunction sanitizeCspSource(value: string): string | null {\n const source = value.trim();\n if (!source || source.includes(\"'\") || /[\\s;]/.test(source)) return null;\n if (/^https:\\/\\/\\*\\.[a-z0-9.-]+(?::\\d+)?$/i.test(source)) return source;\n try {\n const url = new URL(source);\n if (url.protocol === \"https:\") return url.origin;\n if (\n url.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\", \"::1\"].includes(url.hostname)\n ) {\n return url.origin;\n }\n } catch {\n return null;\n }\n return null;\n}\n\nfunction injectCsp(html: string, csp: string): string {\n const meta = `<meta http-equiv=\"Content-Security-Policy\" content=\"${escapeAttribute(csp)}\">`;\n if (/<head\\b[^>]*>/i.test(html)) {\n return html.replace(/<head\\b[^>]*>/i, (head) => `${head}${meta}`);\n }\n if (/<html\\b[^>]*>/i.test(html)) {\n return html.replace(\n /<html\\b[^>]*>/i,\n (htmlTag) => `${htmlTag}<head>${meta}</head>`,\n );\n }\n return `<!doctype html><html><head>${meta}</head><body>${html}</body></html>`;\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\");\n}\n\nfunction buildHostContext(app: AgentMcpAppPayload) {\n const root =\n typeof window !== \"undefined\"\n ? getComputedStyle(document.documentElement)\n : null;\n const cssVar = (name: string) => root?.getPropertyValue(name).trim() || \"\";\n const theme =\n typeof document !== \"undefined\" &&\n (document.documentElement.classList.contains(\"dark\") ||\n window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches)\n ? \"dark\"\n : \"light\";\n return {\n toolInfo: app.tool\n ? {\n tool: {\n name: app.originalToolName,\n description: app.tool.description,\n inputSchema: app.tool.inputSchema ?? {\n type: \"object\",\n properties: {},\n },\n ...(app.tool._meta ? { _meta: app.tool._meta } : {}),\n },\n }\n : undefined,\n theme,\n displayMode: \"inline\",\n availableDisplayModes: [\"inline\"],\n platform: \"web\",\n userAgent: \"agent-native\",\n locale: typeof navigator !== \"undefined\" ? navigator.language : undefined,\n timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n containerDimensions: {\n maxHeight: MAX_IFRAME_HEIGHT,\n maxWidth: typeof window !== \"undefined\" ? window.innerWidth : undefined,\n },\n styles: {\n variables: {\n \"--color-background-primary\": hslVar(cssVar(\"--background\")),\n \"--color-background-secondary\": hslVar(cssVar(\"--muted\")),\n \"--color-text-primary\": hslVar(cssVar(\"--foreground\")),\n \"--color-text-secondary\": hslVar(cssVar(\"--muted-foreground\")),\n \"--color-border-primary\": hslVar(cssVar(\"--border\")),\n \"--font-sans\": cssVar(\"--font-sans\") || \"ui-sans-serif, system-ui\",\n \"--font-mono\":\n cssVar(\"--font-mono\") ||\n \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n \"--border-radius-md\": cssVar(\"--radius\") || \"8px\",\n },\n },\n };\n}\n\nfunction hslVar(value: string): string | undefined {\n return value ? `hsl(${value})` : undefined;\n}\n\nfunction normalizeSameServerToolName(\n serverId: string,\n rawName: string,\n): string | null {\n if (!rawName.trim()) return null;\n const prefix = `mcp__${serverId}__`;\n if (rawName.startsWith(\"mcp__\")) {\n return rawName.startsWith(prefix) ? rawName.slice(prefix.length) : null;\n }\n return rawName;\n}\n\nasync function postMcpAppEndpoint<T>(\n endpoint: \"call-tool\" | \"list-tools\" | \"read-resource\",\n body: Record<string, unknown>,\n): Promise<T> {\n const response = await fetch(\n agentNativePath(`/_agent-native/mcp/apps/${endpoint}`),\n {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n },\n );\n if (!response.ok) {\n let message = `MCP App request failed (${response.status})`;\n try {\n const json = await response.json();\n if (typeof json?.error === \"string\") message = json.error;\n } catch {\n // ignore\n }\n throw new Error(message);\n }\n return (await response.json()) as T;\n}\n\nfunction errorToolResult(message: string): CallToolResult {\n return {\n content: [{ type: \"text\", text: `Error: ${message}` }],\n isError: true,\n };\n}\n\nfunction isSafeExternalUrl(value: string): boolean {\n try {\n const url = new URL(value);\n return url.protocol === \"http:\" || url.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"McpAppRenderer.js","sourceRoot":"","sources":["../../../src/client/mcp-apps/McpAppRenderer.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n AppBridge,\n PostMessageTransport,\n buildAllowAttribute,\n type McpUiResourceCsp,\n type McpUiResourcePermissions,\n} from \"@modelcontextprotocol/ext-apps/app-bridge\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { IconAlertTriangle, IconLoader2 } from \"@tabler/icons-react\";\nimport type { AgentMcpAppPayload } from \"../../mcp-client/app-result.js\";\nimport { agentNativePath } from \"../api-path.js\";\nimport { cn } from \"../utils.js\";\n\nconst DEFAULT_IFRAME_HEIGHT = 360;\nconst MAX_IFRAME_HEIGHT = 900;\nconst SANDBOX_FLAGS = \"allow-scripts allow-forms allow-popups\";\n\nexport interface McpAppRendererProps {\n app: AgentMcpAppPayload;\n className?: string;\n}\n\ntype ResourceUiMeta = {\n csp?: McpUiResourceCsp;\n permissions?: McpUiResourcePermissions;\n prefersBorder?: boolean;\n};\n\nexport function McpAppRenderer({ app, className }: McpAppRendererProps) {\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n const [loadedSrcDoc, setLoadedSrcDoc] = useState<string | null>(null);\n const [height, setHeight] = useState(DEFAULT_IFRAME_HEIGHT);\n const [error, setError] = useState<string | null>(null);\n const [ready, setReady] = useState(false);\n const resourceHtml = app.resource ? htmlFromResource(app.resource) : \"\";\n const uiMeta = useMemo(() => resourceUiMeta(app), [app]);\n const supportedPermissions = useMemo(\n () => supportedMcpAppPermissions(uiMeta.permissions),\n [uiMeta.permissions],\n );\n const csp = buildMcpAppCsp(uiMeta.csp);\n const srcDoc = useMemo(\n () => (resourceHtml ? injectCsp(resourceHtml, csp) : \"\"),\n [resourceHtml, csp],\n );\n\n useEffect(() => {\n setLoadedSrcDoc(null);\n setReady(false);\n setError(null);\n }, [srcDoc]);\n\n useEffect(() => {\n const iframe = iframeRef.current;\n if (!iframe?.contentWindow || !srcDoc || loadedSrcDoc !== srcDoc) return;\n\n let closed = false;\n const bridge = new AppBridge(\n null,\n { name: \"Agent Native\", version: \"1.0.0\" },\n {\n openLinks: {},\n serverTools: {},\n serverResources: {},\n logging: {},\n sandbox: {\n permissions: supportedPermissions,\n csp: uiMeta.csp ?? {},\n },\n },\n {\n hostContext: buildHostContext(app) as any,\n },\n );\n\n bridge.addEventListener(\"sizechange\", ({ height: nextHeight }) => {\n if (typeof nextHeight !== \"number\" || !Number.isFinite(nextHeight)) {\n return;\n }\n setHeight(\n Math.min(MAX_IFRAME_HEIGHT, Math.max(220, Math.ceil(nextHeight))),\n );\n });\n bridge.addEventListener(\"initialized\", () => {\n if (closed) return;\n setReady(true);\n void bridge.sendToolInput({ arguments: app.toolInput });\n void bridge.sendToolResult(app.toolResult as CallToolResult);\n });\n bridge.addEventListener(\"loggingmessage\", ({ level, data }) => {\n if (level === \"error\" || level === \"critical\" || level === \"alert\") {\n console.warn(\"[mcp-app]\", data);\n }\n });\n bridge.onopenlink = async ({ url }) => {\n if (!isSafeExternalUrl(url)) return { isError: true };\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n return {};\n };\n bridge.oncalltool = async ({ name, arguments: toolArguments }) => {\n const toolName = normalizeSameServerToolName(app.serverId, name);\n if (!toolName) {\n return errorToolResult(\"Cross-server MCP App tool calls are blocked.\");\n }\n try {\n return await postMcpAppEndpoint<CallToolResult>(\"call-tool\", {\n serverId: app.serverId,\n toolName,\n arguments:\n toolArguments && typeof toolArguments === \"object\"\n ? toolArguments\n : {},\n });\n } catch (err: any) {\n return errorToolResult(err?.message ?? \"MCP App tool call failed.\");\n }\n };\n (bridge as any).onlisttools = async () =>\n postMcpAppEndpoint(\"list-tools\", { serverId: app.serverId });\n bridge.onreadresource = async ({ uri }) =>\n postMcpAppEndpoint(\"read-resource\", { serverId: app.serverId, uri });\n bridge.onlistresources = async () => ({ resources: [] });\n bridge.onlistresourcetemplates = async () => ({ resourceTemplates: [] });\n bridge.ondownloadfile = async () => ({ isError: true });\n bridge.onmessage = async () => ({ isError: true });\n bridge.onupdatemodelcontext = async () => ({});\n\n const transport = new PostMessageTransport(\n iframe.contentWindow,\n iframe.contentWindow,\n );\n setReady(false);\n setError(null);\n bridge.connect(transport).catch((err: any) => {\n if (!closed) {\n setError(err?.message ?? \"Failed to initialize MCP App.\");\n }\n });\n\n return () => {\n closed = true;\n setReady(false);\n void bridge\n .teardownResource({}, { timeout: 500 })\n .catch(() => undefined)\n .finally(() => {\n void (bridge as any).close?.().catch?.(() => undefined);\n });\n };\n }, [app, loadedSrcDoc, srcDoc, supportedPermissions, uiMeta.csp]);\n\n if (!resourceHtml) {\n return (\n <div className={cn(\"agent-mcp-app agent-mcp-app--error\", className)}>\n <IconAlertTriangle size={15} />\n <span>MCP App resource was not available.</span>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n \"agent-mcp-app\",\n uiMeta.prefersBorder === false && \"agent-mcp-app--flush\",\n className,\n )}\n >\n {!ready && !error && (\n <div className=\"agent-mcp-app__loading\">\n <IconLoader2 size={14} className=\"agent-conversation-spin\" />\n <span>Loading MCP App</span>\n </div>\n )}\n {error && (\n <div className=\"agent-mcp-app__error\">\n <IconAlertTriangle size={15} />\n <span>{error}</span>\n </div>\n )}\n <iframe\n ref={iframeRef}\n title={app.tool?.title ?? app.originalToolName}\n srcDoc={srcDoc}\n sandbox={SANDBOX_FLAGS}\n allow={buildAllowAttribute(supportedPermissions)}\n style={{ height }}\n onLoad={() => setLoadedSrcDoc(srcDoc)}\n />\n </div>\n );\n}\n\nfunction resourceUiMeta(app: AgentMcpAppPayload): ResourceUiMeta {\n const meta = app.resource?._meta;\n const ui =\n meta?.ui && typeof meta.ui === \"object\" && !Array.isArray(meta.ui)\n ? (meta.ui as ResourceUiMeta)\n : {};\n return ui;\n}\n\nfunction htmlFromResource(\n resource: NonNullable<AgentMcpAppPayload[\"resource\"]>,\n): string {\n if (typeof resource.text === \"string\") return resource.text;\n if (typeof resource.blob !== \"string\") return \"\";\n try {\n if (typeof atob !== \"function\") return \"\";\n return atob(resource.blob);\n } catch {\n return \"\";\n }\n}\n\nexport function supportedMcpAppPermissions(\n permissions: McpUiResourcePermissions | undefined,\n): McpUiResourcePermissions {\n return permissions?.clipboardWrite ? { clipboardWrite: {} } : {};\n}\n\nexport function buildMcpAppCsp(csp: McpUiResourceCsp | undefined): string {\n const connect = sanitizeCspSources(csp?.connectDomains);\n const resources = sanitizeCspSources(csp?.resourceDomains);\n const frames = sanitizeCspSources(csp?.frameDomains);\n const base = sanitizeCspSources(csp?.baseUriDomains);\n return [\n \"default-src 'none'\",\n `base-uri ${base.length ? base.join(\" \") : \"'none'\"}`,\n \"form-action 'none'\",\n `connect-src ${connect.length ? connect.join(\" \") : \"'none'\"}`,\n `img-src data: blob:${resources.length ? ` ${resources.join(\" \")}` : \"\"}`,\n `media-src data: blob:${resources.length ? ` ${resources.join(\" \")}` : \"\"}`,\n `font-src data:${resources.length ? ` ${resources.join(\" \")}` : \"\"}`,\n `style-src 'unsafe-inline'${resources.length ? ` ${resources.join(\" \")}` : \"\"}`,\n `script-src 'unsafe-inline'${resources.length ? ` ${resources.join(\" \")}` : \"\"}`,\n `frame-src ${frames.length ? frames.join(\" \") : \"'none'\"}`,\n ].join(\"; \");\n}\n\nfunction sanitizeCspSources(values: string[] | undefined): string[] {\n const out: string[] = [];\n for (const value of values ?? []) {\n const source = sanitizeCspSource(value);\n if (source) out.push(source);\n }\n return [...new Set(out)];\n}\n\nfunction sanitizeCspSource(value: string): string | null {\n const source = value.trim();\n if (!source || source.includes(\"'\") || /[\\s;]/.test(source)) return null;\n if (source === \"https:\") return source;\n if (/^http:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\]):\\*$/i.test(source)) {\n return source;\n }\n if (/^https:\\/\\/\\*\\.[a-z0-9.-]+(?::\\d+)?$/i.test(source)) return source;\n try {\n const url = new URL(source);\n if (url.protocol === \"https:\") return url.origin;\n if (\n url.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\", \"::1\"].includes(url.hostname)\n ) {\n return url.origin;\n }\n } catch {\n return null;\n }\n return null;\n}\n\nfunction injectCsp(html: string, csp: string): string {\n const meta = `<meta http-equiv=\"Content-Security-Policy\" content=\"${escapeAttribute(csp)}\">`;\n if (/<head\\b[^>]*>/i.test(html)) {\n return html.replace(/<head\\b[^>]*>/i, (head) => `${head}${meta}`);\n }\n if (/<html\\b[^>]*>/i.test(html)) {\n return html.replace(\n /<html\\b[^>]*>/i,\n (htmlTag) => `${htmlTag}<head>${meta}</head>`,\n );\n }\n return `<!doctype html><html><head>${meta}</head><body>${html}</body></html>`;\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\");\n}\n\nfunction buildHostContext(app: AgentMcpAppPayload) {\n const root =\n typeof window !== \"undefined\"\n ? getComputedStyle(document.documentElement)\n : null;\n const cssVar = (name: string) => root?.getPropertyValue(name).trim() || \"\";\n const theme =\n typeof document !== \"undefined\" &&\n (document.documentElement.classList.contains(\"dark\") ||\n window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches)\n ? \"dark\"\n : \"light\";\n return {\n toolInfo: app.tool\n ? {\n tool: {\n name: app.originalToolName,\n description: app.tool.description,\n inputSchema: app.tool.inputSchema ?? {\n type: \"object\",\n properties: {},\n },\n ...(app.tool._meta ? { _meta: app.tool._meta } : {}),\n },\n }\n : undefined,\n theme,\n displayMode: \"inline\",\n availableDisplayModes: [\"inline\"],\n platform: \"web\",\n userAgent: \"agent-native\",\n locale: typeof navigator !== \"undefined\" ? navigator.language : undefined,\n timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n containerDimensions: {\n maxHeight: MAX_IFRAME_HEIGHT,\n maxWidth: typeof window !== \"undefined\" ? window.innerWidth : undefined,\n },\n styles: {\n variables: {\n \"--color-background-primary\": hslVar(cssVar(\"--background\")),\n \"--color-background-secondary\": hslVar(cssVar(\"--muted\")),\n \"--color-text-primary\": hslVar(cssVar(\"--foreground\")),\n \"--color-text-secondary\": hslVar(cssVar(\"--muted-foreground\")),\n \"--color-border-primary\": hslVar(cssVar(\"--border\")),\n \"--font-sans\": cssVar(\"--font-sans\") || \"ui-sans-serif, system-ui\",\n \"--font-mono\":\n cssVar(\"--font-mono\") ||\n \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n \"--border-radius-md\": cssVar(\"--radius\") || \"8px\",\n },\n },\n };\n}\n\nfunction hslVar(value: string): string | undefined {\n return value ? `hsl(${value})` : undefined;\n}\n\nfunction normalizeSameServerToolName(\n serverId: string,\n rawName: string,\n): string | null {\n if (!rawName.trim()) return null;\n const prefix = `mcp__${serverId}__`;\n if (rawName.startsWith(\"mcp__\")) {\n return rawName.startsWith(prefix) ? rawName.slice(prefix.length) : null;\n }\n return rawName;\n}\n\nasync function postMcpAppEndpoint<T>(\n endpoint: \"call-tool\" | \"list-tools\" | \"read-resource\",\n body: Record<string, unknown>,\n): Promise<T> {\n const response = await fetch(\n agentNativePath(`/_agent-native/mcp/apps/${endpoint}`),\n {\n method: \"POST\",\n credentials: \"same-origin\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n },\n );\n if (!response.ok) {\n let message = `MCP App request failed (${response.status})`;\n try {\n const json = await response.json();\n if (typeof json?.error === \"string\") message = json.error;\n } catch {\n // ignore\n }\n throw new Error(message);\n }\n return (await response.json()) as T;\n}\n\nfunction errorToolResult(message: string): CallToolResult {\n return {\n content: [{ type: \"text\", text: `Error: ${message}` }],\n isError: true,\n };\n}\n\nfunction isSafeExternalUrl(value: string): boolean {\n try {\n const url = new URL(value);\n return url.protocol === \"http:\" || url.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n"]}
|
package/dist/index.browser.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ export { sendToAgentChat, useAgentChatGenerating, useDevMode, useSendToAgentChat
|
|
|
2
2
|
export { agentChat } from "./shared/index.js";
|
|
3
3
|
export { parseArgs, camelCaseArgs } from "./scripts/parse-args.js";
|
|
4
4
|
export { defineAction, AgentActionStopError, isAgentActionStopError, type ActionHttpConfig, type AgentActionStopOptions, MCP_APP_EXTENSION_ID, MCP_APP_MIME_TYPE, MCP_APP_RESOURCE_URI_META_KEY, type ActionMcpAppConfig, type ActionMcpAppCsp, type ActionMcpAppHtmlBuilder, type ActionMcpAppPermissions, type ActionMcpAppResourceConfig, type ActionMcpAppResourceMeta, } from "./action.js";
|
|
5
|
+
export { embedApp, MCP_APP_REQUEST_ORIGIN_CSP_SOURCE, type EmbedAppOptions, } from "./mcp/embed-app.js";
|
|
5
6
|
//# sourceMappingURL=index.browser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,UAAU,EACV,EAAE,EACF,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,GACjB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAG9C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGnE,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,oBAAoB,EACpB,iBAAiB,EACjB,6BAA6B,EAC7B,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,GAC9B,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,UAAU,EACV,EAAE,EACF,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,GACjB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAG9C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGnE,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,oBAAoB,EACpB,iBAAiB,EACjB,6BAA6B,EAC7B,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,QAAQ,EACR,iCAAiC,EACjC,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC"}
|
package/dist/index.browser.js
CHANGED
|
@@ -7,4 +7,5 @@ export { agentChat } from "./shared/index.js";
|
|
|
7
7
|
export { parseArgs, camelCaseArgs } from "./scripts/parse-args.js";
|
|
8
8
|
// defineAction — used by template actions, no Node.js deps
|
|
9
9
|
export { defineAction, AgentActionStopError, isAgentActionStopError, MCP_APP_EXTENSION_ID, MCP_APP_MIME_TYPE, MCP_APP_RESOURCE_URI_META_KEY, } from "./action.js";
|
|
10
|
+
export { embedApp, MCP_APP_REQUEST_ORIGIN_CSP_SOURCE, } from "./mcp/embed-app.js";
|
|
10
11
|
//# sourceMappingURL=index.browser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,SAAS;AACT,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,UAAU,EACV,EAAE,EACF,cAAc,GAIf,MAAM,mBAAmB,CAAC;AAE3B,sBAAsB;AACtB,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,8DAA8D;AAC9D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAEnE,2DAA2D;AAC3D,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,EAGtB,oBAAoB,EACpB,iBAAiB,EACjB,6BAA6B,GAO9B,MAAM,aAAa,CAAC","sourcesContent":["// Browser-safe entry — only client & shared exports (no Node/Express/chokidar).\n\n// Client\nexport {\n sendToAgentChat,\n useAgentChatGenerating,\n useDevMode,\n useSendToAgentChat,\n CodeRequiredDialog,\n useDbSync,\n useFileWatcher,\n useSession,\n cn,\n ApiKeySettings,\n type AgentChatMessage,\n type CodeRequiredDialogProps,\n type AuthSession,\n} from \"./client/index.js\";\n\n// Shared (isomorphic)\nexport { agentChat } from \"./shared/index.js\";\n\n// Pure utilities (no Node.js deps — safe for browser and SSR)\nexport { parseArgs, camelCaseArgs } from \"./scripts/parse-args.js\";\n\n// defineAction — used by template actions, no Node.js deps\nexport {\n defineAction,\n AgentActionStopError,\n isAgentActionStopError,\n type ActionHttpConfig,\n type AgentActionStopOptions,\n MCP_APP_EXTENSION_ID,\n MCP_APP_MIME_TYPE,\n MCP_APP_RESOURCE_URI_META_KEY,\n type ActionMcpAppConfig,\n type ActionMcpAppCsp,\n type ActionMcpAppHtmlBuilder,\n type ActionMcpAppPermissions,\n type ActionMcpAppResourceConfig,\n type ActionMcpAppResourceMeta,\n} from \"./action.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,SAAS;AACT,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,UAAU,EACV,EAAE,EACF,cAAc,GAIf,MAAM,mBAAmB,CAAC;AAE3B,sBAAsB;AACtB,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,8DAA8D;AAC9D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAEnE,2DAA2D;AAC3D,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,sBAAsB,EAGtB,oBAAoB,EACpB,iBAAiB,EACjB,6BAA6B,GAO9B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,QAAQ,EACR,iCAAiC,GAElC,MAAM,oBAAoB,CAAC","sourcesContent":["// Browser-safe entry — only client & shared exports (no Node/Express/chokidar).\n\n// Client\nexport {\n sendToAgentChat,\n useAgentChatGenerating,\n useDevMode,\n useSendToAgentChat,\n CodeRequiredDialog,\n useDbSync,\n useFileWatcher,\n useSession,\n cn,\n ApiKeySettings,\n type AgentChatMessage,\n type CodeRequiredDialogProps,\n type AuthSession,\n} from \"./client/index.js\";\n\n// Shared (isomorphic)\nexport { agentChat } from \"./shared/index.js\";\n\n// Pure utilities (no Node.js deps — safe for browser and SSR)\nexport { parseArgs, camelCaseArgs } from \"./scripts/parse-args.js\";\n\n// defineAction — used by template actions, no Node.js deps\nexport {\n defineAction,\n AgentActionStopError,\n isAgentActionStopError,\n type ActionHttpConfig,\n type AgentActionStopOptions,\n MCP_APP_EXTENSION_ID,\n MCP_APP_MIME_TYPE,\n MCP_APP_RESOURCE_URI_META_KEY,\n type ActionMcpAppConfig,\n type ActionMcpAppCsp,\n type ActionMcpAppHtmlBuilder,\n type ActionMcpAppPermissions,\n type ActionMcpAppResourceConfig,\n type ActionMcpAppResourceMeta,\n} from \"./action.js\";\nexport {\n embedApp,\n MCP_APP_REQUEST_ORIGIN_CSP_SOURCE,\n type EmbedAppOptions,\n} from \"./mcp/embed-app.js\";\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtin-tools.d.ts","sourceRoot":"","sources":["../../src/mcp/builtin-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAGhE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"builtin-tools.d.ts","sourceRoot":"","sources":["../../src/mcp/builtin-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAGhE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAsrBnD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,WAAW,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAChC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAS7B"}
|
|
@@ -212,10 +212,12 @@ function listAppsTool(config, requestMeta) {
|
|
|
212
212
|
// ---------------------------------------------------------------------------
|
|
213
213
|
function openAppTool(config) {
|
|
214
214
|
return {
|
|
215
|
-
tool: tool("Build a deep link that opens an app at a specific view/record
|
|
215
|
+
tool: tool("Build a deep link that opens an app at a specific view/record or " +
|
|
216
|
+
"focused route/component. No side " +
|
|
216
217
|
"effects — returns a URL the user can click to land in the running UI. " +
|
|
217
218
|
"Set embed:true when a UI-capable MCP host should render the live app " +
|
|
218
|
-
|
|
219
|
+
"or focused route/component inline. After calling, surface the returned " +
|
|
220
|
+
'"Open in … →" link to the user.', {
|
|
219
221
|
app: { type: "string", description: "App id, e.g. 'mail'" },
|
|
220
222
|
view: {
|
|
221
223
|
type: "string",
|
|
@@ -223,7 +225,7 @@ function openAppTool(config) {
|
|
|
223
225
|
},
|
|
224
226
|
path: {
|
|
225
227
|
type: "string",
|
|
226
|
-
description: "Optional app route to open directly, e.g. '/extensions/abc'
|
|
228
|
+
description: "Optional app route to open directly, e.g. '/extensions/abc', '/adhoc/q2', or '/chart?panel=...'. Must be same-origin relative.",
|
|
227
229
|
},
|
|
228
230
|
params: {
|
|
229
231
|
type: "object",
|
|
@@ -231,7 +233,7 @@ function openAppTool(config) {
|
|
|
231
233
|
},
|
|
232
234
|
embed: {
|
|
233
235
|
type: "boolean",
|
|
234
|
-
description: "Render the full app inline in MCP Apps when the host supports it.",
|
|
236
|
+
description: "Render the full app or focused route/component inline in MCP Apps when the host supports it.",
|
|
235
237
|
},
|
|
236
238
|
chrome: {
|
|
237
239
|
type: "string",
|
|
@@ -304,6 +306,7 @@ function openAppTool(config) {
|
|
|
304
306
|
description: "Render the requested app route inline.",
|
|
305
307
|
iframeTitle: "Agent Native app",
|
|
306
308
|
openLabel: "Open app",
|
|
309
|
+
height: 900,
|
|
307
310
|
}),
|
|
308
311
|
},
|
|
309
312
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtin-tools.js","sourceRoot":"","sources":["../../src/mcp/builtin-tools.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generic cross-app MCP tools — a stable verb set every external agent gets\n * regardless of which template it is talking to.\n *\n * These are merged into the MCP action registry by\n * `createMCPServerForRequest` (see `build-server.ts`). **Precedence: template\n * actions win.** If a template defines an action named `list_apps` /\n * `open_app` / `ask_app` / `create_workspace_app` / `list_templates`, the\n * template's `ActionEntry` overwrites the builtin of the same name. This is\n * the same template-over-framework precedence `autoDiscoverActions` uses.\n *\n * | Tool | Side effects | Returns |\n * | --------------------- | ------------ | ---------------------------------------- |\n * | `list_apps` | none | `{ apps: [{ id, url, running }] }` |\n * | `open_app` | none | `{ url }` (+ deep-link `link`) |\n * | `create_embed_session`| ticket mint | `{ startUrl }` for MCP App iframes |\n * | `ask_app` | agent loop | `{ app, routedVia, response }` |\n * | `create_workspace_app`| scaffolds | `{ name, url, port, deepLink }` (+ link) |\n *\n * `open_app` / `create_workspace_app` return an **absolute** URL on the\n * *target* app's origin when it differs from this app (so a workspace link\n * lands in the right app), and a relative path for the same app / standalone.\n * `ask_app` routes to a *different* workspace app over A2A when possible and\n * reports `routedVia: \"a2a\"`; otherwise it answers locally\n * (`routedVia: \"local\"`) and never falsely claims cross-app delegation.\n * | `list_templates` | none | `{ templates: [...] }` (allow-list only) |\n *\n * Node-only at call time (workspace resolution + scaffolding use `fs`), but\n * the module has no top-level Node imports so it bundles fine alongside\n * `mountMCP` — the Node bits are dynamically imported inside `run()`.\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport { buildDeepLink } from \"../server/deep-link.js\";\nimport { getConfiguredAppBasePath } from \"../server/app-base-path.js\";\nimport type { MCPConfig } from \"./build-server.js\";\nimport { fetchOrgApps, type OrgApp } from \"./org-directory.js\";\nimport { embedApp } from \"./embed-app.js\";\n\nimport type { ActionTool } from \"../agent/types.js\";\n\n/** Flat map of param name → JSON-schema property. */\ntype Params = Record<\n string,\n { type: string; description?: string; enum?: string[] }\n>;\n\n/**\n * Build an `ActionTool`. `parameters` is wrapped in the\n * `{ type:\"object\", properties, required }` shape `createMCPServerForRequest`\n * forwards verbatim as the MCP tool `inputSchema`.\n */\nfunction tool(\n description: string,\n parameters?: Params,\n required?: string[],\n): ActionTool {\n if (!parameters) return { description };\n return {\n description,\n parameters: {\n type: \"object\",\n properties: parameters,\n ...(required && required.length ? { required } : {}),\n },\n };\n}\n\n/**\n * The canonical app id this MCP server is mounted for. `MCPConfig.appId` is\n * authoritative; fall back to lowercasing `name` (which is the capitalized\n * app id at every call site) for back-compat with configs that predate the\n * `appId` field.\n */\nfunction currentAppId(config: MCPConfig): string {\n return (config.appId || config.name || \"app\").toLowerCase();\n}\n\nconst CONTROL_CHARS = new RegExp(\"[\\\\u0000-\\\\u001f\\\\u007f]\");\n\nfunction safeAppPath(raw: unknown): string | null {\n if (typeof raw !== \"string\" || !raw.trim()) return null;\n const value = raw.trim();\n if (CONTROL_CHARS.test(value)) return null;\n if (!value.startsWith(\"/\")) return null;\n if (value.startsWith(\"//\") || value.startsWith(\"/\\\\\")) return null;\n if (/^\\/[a-z][a-z0-9+.-]*:/i.test(value)) return null;\n return value;\n}\n\nfunction appendParamsToPath(\n path: string,\n params: Record<string, string | number | boolean> | undefined,\n): string {\n if (!params || Object.keys(params).length === 0) return path;\n const url = new URL(path, \"http://agent-native.invalid\");\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, String(value));\n }\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nfunction viewToAppPath(view: string): string | null {\n const value = view.trim();\n if (!value) return null;\n return safeAppPath(value.startsWith(\"/\") ? value : `/${value}`);\n}\n\nfunction withConfiguredBasePath(path: string): string {\n const base = getConfiguredAppBasePath();\n if (!base || path === base || path.startsWith(`${base}/`)) return path;\n return `${base}${path}`;\n}\n\n/**\n * Resolve the absolute origin of a *target* workspace app (e.g.\n * `http://127.0.0.1:8101`) so cross-app deep links / A2A calls point at the\n * right app instead of the current request's origin. Reuses the same\n * workspace resolution `list_apps` / the stdio proxy use.\n *\n * Returns `null` when:\n * - the target is the current app (caller should keep relative behavior),\n * - there is no workspace info (standalone / single app), or\n * - the target app is unknown.\n */\nasync function resolveTargetAppOrigin(\n config: MCPConfig,\n targetAppId: string,\n): Promise<{ origin: string; id: string } | null> {\n const target = targetAppId.trim().toLowerCase();\n if (!target || target === currentAppId(config)) return null;\n try {\n const { resolveWorkspace } = await import(\"./workspace-resolve.js\");\n const ws = await resolveWorkspace();\n if (!ws.isWorkspace) return null;\n const match = ws.apps.find((a) => a.id.toLowerCase() === target);\n if (!match) return null;\n return { origin: match.url, id: match.id };\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// list_apps\n// ---------------------------------------------------------------------------\n\nfunction listAppsTool(\n config: MCPConfig,\n requestMeta?: { origin?: string },\n): ActionEntry {\n return {\n tool: tool(\n \"List the workspace apps and their URLs. Use this to discover which \" +\n \"apps exist before opening or asking one. In a single-app project \" +\n \"this returns just that app. When an org directory is configured \" +\n \"this also includes the org's deployed sibling apps.\",\n ),\n readOnly: true,\n parallelSafe: true,\n run: async () => {\n const { resolveWorkspace } = await import(\"./workspace-resolve.js\");\n const ws = await resolveWorkspace();\n\n // The MCP request is served BY the current app, so it is provably\n // reachable at the inbound request origin — that beats a guessed\n // `PORT || 5173` probe (which reports the wrong URL + `running:false`\n // whenever the dev server picked a non-default port, e.g. `agent-\n // native dev` on :8080). For the entry that IS this app (the sole\n // entry when single-app, or the id matching `config.appId` in a\n // workspace) prefer the live origin; other workspace apps keep their\n // probed values.\n const liveOrigin = requestMeta?.origin?.replace(/\\/+$/, \"\") || \"\";\n let livePort = 0;\n if (liveOrigin) {\n try {\n const u = new URL(liveOrigin);\n livePort = Number(u.port) || (u.protocol === \"https:\" ? 443 : 80);\n } catch {\n livePort = 0;\n }\n }\n const selfId = (config.appId ?? \"\").toLowerCase();\n const isSelf = (id: string) =>\n !!liveOrigin &&\n (!ws.isWorkspace || (!!selfId && id.toLowerCase() === selfId));\n\n interface AppEntry {\n id: string;\n url: string;\n port: number | undefined;\n running: boolean;\n source: \"workspace\" | \"org-directory\";\n }\n\n const apps: AppEntry[] = ws.apps.map((a) =>\n isSelf(a.id)\n ? {\n id: a.id,\n url: liveOrigin,\n port: (livePort || a.port) as number | undefined,\n running: true,\n source: \"workspace\" as const,\n }\n : {\n id: a.id,\n url: a.url,\n port: a.port as number | undefined,\n running: a.running,\n source: \"workspace\" as const,\n },\n );\n const seenIds = new Set(apps.map((a) => a.id.toLowerCase()));\n const seenOrigins = new Set(apps.map((a) => a.url.replace(/\\/+$/, \"\")));\n\n // Merge the org directory's deployed sibling apps. Inactive (no env)\n // or any failure ⇒ fetchOrgApps() returns [] and this is a no-op, so\n // the existing local/workspace behavior is preserved exactly.\n const orgApps = await fetchOrgApps({\n selfId: currentAppId(config),\n }).catch(() => [] as OrgApp[]);\n for (const oa of orgApps) {\n const idKey = oa.id.toLowerCase();\n const originKey = oa.url.replace(/\\/+$/, \"\");\n // Dedupe by id OR origin — a workspace app already listed wins.\n if (seenIds.has(idKey) || seenOrigins.has(originKey)) continue;\n seenIds.add(idKey);\n seenOrigins.add(originKey);\n apps.push({\n id: oa.id,\n url: oa.url,\n port: undefined,\n running: true,\n source: \"org-directory\",\n });\n }\n\n return {\n workspace: ws.isWorkspace,\n gatewayUrl: ws.gatewayUrl,\n apps,\n };\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// open_app\n// ---------------------------------------------------------------------------\n\nfunction openAppTool(config: MCPConfig): ActionEntry {\n return {\n tool: tool(\n \"Build a deep link that opens an app at a specific view/record. No side \" +\n \"effects — returns a URL the user can click to land in the running UI. \" +\n \"Set embed:true when a UI-capable MCP host should render the live app \" +\n 'inline. After calling, surface the returned \"Open in … →\" link to the user.',\n {\n app: { type: \"string\", description: \"App id, e.g. 'mail'\" },\n view: {\n type: \"string\",\n description:\n \"Target view, e.g. 'inbox' (maps to navigate command). Optional when path is provided.\",\n },\n path: {\n type: \"string\",\n description:\n \"Optional app route to open directly, e.g. '/extensions/abc' or '/dashboards/q2'. Must be same-origin relative.\",\n },\n params: {\n type: \"object\",\n description:\n \"Optional record-focus / filter params, e.g. { threadId: 'abc' }\",\n },\n embed: {\n type: \"boolean\",\n description:\n \"Render the full app inline in MCP Apps when the host supports it.\",\n },\n chrome: {\n type: \"string\",\n enum: [\"full\", \"minimal\"],\n description:\n \"Embed chrome preference for compatible app routes. Defaults to full.\",\n },\n },\n [\"app\"],\n ),\n readOnly: true,\n parallelSafe: true,\n run: async (args: Record<string, any>) => {\n const app = String(args.app ?? \"\").trim();\n const view = String(args.view ?? \"\").trim();\n const path = safeAppPath(args.path);\n if (!app || (!view && !path)) {\n throw new Error(\"open_app requires 'app' and either 'view' or 'path'.\");\n }\n let params: Record<string, string | number | boolean> | undefined;\n const raw = args.params;\n if (raw && typeof raw === \"object\") {\n params = raw as Record<string, string | number | boolean>;\n } else if (typeof raw === \"string\" && raw.trim()) {\n try {\n params = JSON.parse(raw);\n } catch {\n params = undefined;\n }\n }\n const embed = args.embed === true;\n const directViewPath = embed && view ? viewToAppPath(view) : null;\n const relUrl = path\n ? appendParamsToPath(path, params)\n : directViewPath\n ? appendParamsToPath(directViewPath, params)\n : buildDeepLink({ app, view, params });\n const sameAppUrl =\n path || directViewPath ? withConfiguredBasePath(relUrl) : relUrl;\n\n // Cross-app target in a workspace: resolve the TARGET app's origin and\n // return an absolute URL. Otherwise the MCP layer would prefix the\n // relative path with the CURRENT request origin, landing the user in\n // the wrong app (e.g. open_app({app:\"calendar\"}) served from Mail).\n // Same-app / standalone keeps the relative path (current behavior).\n const targetApp = await resolveTargetAppOrigin(config, app);\n const url = targetApp\n ? `${targetApp.origin.replace(/\\/+$/, \"\")}${relUrl}`\n : sameAppUrl;\n\n return {\n app,\n ...(view ? { view } : {}),\n ...(path ? { path } : {}),\n url,\n embed,\n };\n },\n link: ({ result }) => {\n if (!result || typeof result !== \"object\") return null;\n const r = result as { url?: string; app?: string; view?: string };\n if (!r.url) return null;\n return {\n url: r.url,\n label: `Open ${r.app ?? \"app\"}`,\n view: r.view,\n };\n },\n mcpApp: {\n resource: embedApp({\n title: \"Open app\",\n description: \"Render the requested app route inline.\",\n iframeTitle: \"Agent Native app\",\n openLabel: \"Open app\",\n }),\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// create_embed_session\n// ---------------------------------------------------------------------------\n\nfunction createEmbedSessionTool(requestMeta?: {\n origin?: string;\n}): ActionEntry {\n return {\n tool: {\n ...tool(\n \"MCP Apps helper: create a one-time browser embed session for a same-origin app URL. Usually called by an MCP App iframe, not directly by the model.\",\n {\n url: {\n type: \"string\",\n description:\n \"Same-origin absolute URL or app-relative path to embed.\",\n },\n path: {\n type: \"string\",\n description: \"Same-origin app-relative path to embed.\",\n },\n chrome: {\n type: \"string\",\n enum: [\"full\", \"minimal\"],\n description: \"Embed chrome preference. Defaults to full.\",\n },\n },\n ),\n _meta: { ui: { visibility: [\"app\"] } },\n } as ActionTool,\n // Minting a browser session lets the iframe operate the real app as the\n // caller, so OAuth callers must have mcp:write rather than only mcp:read.\n readOnly: false,\n parallelSafe: true,\n run: async (args: Record<string, any>) => {\n const { getRequestContext } =\n await import(\"../server/request-context.js\");\n const ctx = getRequestContext();\n const ownerEmail = ctx?.userEmail?.trim();\n if (!ownerEmail) {\n throw new Error(\n \"create_embed_session requires an authenticated MCP caller.\",\n );\n }\n\n const { normalizeEmbedTargetPath, createEmbedSessionTicket } =\n await import(\"../server/embed-session.js\");\n const { buildEmbedStartPath } = await import(\"../server/embed-route.js\");\n const rawTarget =\n typeof args.url === \"string\" && args.url.trim()\n ? args.url\n : typeof args.path === \"string\"\n ? args.path\n : \"\";\n const targetPath = normalizeEmbedTargetPath(\n rawTarget,\n requestMeta?.origin,\n );\n if (!targetPath) {\n throw new Error(\n \"create_embed_session can only embed same-origin app-relative URLs.\",\n );\n }\n\n const ticket = await createEmbedSessionTicket({\n ownerEmail,\n orgId: ctx?.orgId,\n targetPath,\n scope: typeof args.chrome === \"string\" ? args.chrome : null,\n });\n const startPath = buildEmbedStartPath(ticket.ticket);\n const startUrl = requestMeta?.origin\n ? new URL(startPath, requestMeta.origin).toString()\n : startPath;\n return {\n startUrl,\n targetPath,\n expiresAt: ticket.expiresAt,\n };\n },\n };\n}\n\n/**\n * Route an `ask_app` message to a *different* app's agent over A2A. Shared by\n * the workspace-resolved path and the org-directory-resolved path so the A2A\n * call logic is not duplicated. `origin` is the target app's A2A base\n * (workspace dev origin or the directory's `a2aUrl`); `id` is reported back.\n *\n * Throws on failure so the caller can be honest — it never falls back to this\n * app's agent and pretends it was the target.\n */\nasync function routeAskOverA2A(\n origin: string,\n id: string,\n message: string,\n): Promise<{ app: string; routedVia: \"a2a\"; response: string }> {\n const { callAgent } = await import(\"../a2a/client.js\");\n const { resolveA2ACallerAuth } = await import(\"../a2a/caller-auth.js\");\n // The MCP handler runs inside `runWithRequestContext`, so this is the\n // verified caller identity and org scope. Reuse the same auth resolver as\n // org-directory discovery so the directory lookup and actual A2A call are\n // scoped the same way.\n const auth = await resolveA2ACallerAuth();\n const response = await callAgent(origin, message, {\n apiKey: auth.apiKey,\n userEmail: auth.userEmail,\n orgDomain: auth.orgDomain,\n orgSecret: auth.orgSecret,\n // Bound the wait — cross-app A2A polls async by default.\n timeoutMs: 5 * 60_000,\n });\n return { app: id, routedVia: \"a2a\", response };\n}\n\n// ---------------------------------------------------------------------------\n// ask_app\n// ---------------------------------------------------------------------------\n\nfunction askAppTool(config: MCPConfig): ActionEntry {\n return {\n tool: tool(\n \"Send a natural-language message to an app's AI agent and get its \" +\n \"response. Use for complex, multi-step tasks needing the agent's \" +\n \"reasoning and full app context. In a single-app project the 'app' \" +\n \"param is optional (defaults to this app). When 'app' names a \" +\n \"different workspace app it is routed there over A2A; the result's \" +\n \"'routedVia' field reports whether it ran cross-app or locally.\",\n {\n app: {\n type: \"string\",\n description: \"App id to route to (optional in a single-app project)\",\n },\n message: {\n type: \"string\",\n description: \"The message to send to the app's agent\",\n },\n },\n [\"message\"],\n ),\n run: async (args: Record<string, any>) => {\n const message = String(args.message ?? \"\").trim();\n if (!message) throw new Error(\"ask_app requires a 'message'.\");\n const requestedApp = String(args.app ?? \"\").trim();\n const selfId = currentAppId(config);\n\n // Cross-app: the caller named a *different* workspace app. Route the\n // message to THAT app's agent over A2A (its `/_agent-native/a2a`\n // endpoint runs the real agent loop with JWT identity) rather than\n // silently answering from this app's agent and claiming delegation.\n const targetApp = await resolveTargetAppOrigin(config, requestedApp);\n if (targetApp) {\n try {\n return await routeAskOverA2A(targetApp.origin, targetApp.id, message);\n } catch (err: any) {\n // Be honest: routing was attempted and failed — do NOT fall back to\n // this app's agent and pretend it was the target.\n throw new Error(\n `Failed to route ask_app to \"${targetApp.id}\" via A2A: ` +\n `${err?.message ?? err}`,\n );\n }\n }\n\n // Not a known local/workspace app — try the org directory. When a\n // directory is configured and the requested app is one of the org's\n // deployed sibling apps, route to it over A2A (same path as above,\n // against its `a2aUrl`). Inactive directory / any failure ⇒ orgApps is\n // [] and this is skipped, preserving the exact local-only behavior.\n if (requestedApp && requestedApp.toLowerCase() !== selfId) {\n const orgApps = await fetchOrgApps({ selfId }).catch(\n () => [] as OrgApp[],\n );\n const dirMatch = orgApps.find(\n (a) => a.id === requestedApp.toLowerCase(),\n );\n if (dirMatch) {\n try {\n return await routeAskOverA2A(dirMatch.a2aUrl, dirMatch.id, message);\n } catch (err: any) {\n throw new Error(\n `Failed to route ask_app to \"${dirMatch.id}\" via A2A ` +\n `(org directory): ${err?.message ?? err}`,\n );\n }\n }\n }\n\n // Same app (or no workspace / unknown target): answer locally with this\n // app's own ask-agent handler — the same entry point the HTTP MCP mount\n // + A2A use, so there is no second agent runner.\n if (!config.askAgent) {\n throw new Error(\n \"This app does not expose an agent (no ask-agent handler).\",\n );\n }\n\n // If the caller named an app we couldn't route to (unknown id, or no\n // workspace), say so honestly instead of claiming we reached it.\n const unresolved =\n !!requestedApp && requestedApp.toLowerCase() !== selfId;\n const response = await config.askAgent(message);\n return {\n app: selfId,\n routedVia: \"local\",\n ...(unresolved\n ? {\n note:\n `Requested app \"${requestedApp}\" is not a reachable workspace ` +\n `app; answered with this app (\"${selfId}\") instead.`,\n }\n : {}),\n response,\n };\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// list_templates\n// ---------------------------------------------------------------------------\n\nfunction listTemplatesTool(): ActionEntry {\n return {\n tool: tool(\n \"List the first-party templates that can be scaffolded into a workspace \" +\n \"(allow-listed templates only).\",\n ),\n readOnly: true,\n parallelSafe: true,\n run: async () => {\n const { visibleTemplates } = await import(\"../cli/templates-meta.js\");\n return {\n templates: visibleTemplates().map((t) => ({\n name: t.name,\n label: t.label,\n hint: t.hint,\n })),\n };\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// create_workspace_app\n// ---------------------------------------------------------------------------\n\nfunction createWorkspaceAppTool(): ActionEntry {\n return {\n tool: tool(\n \"Scaffold a new app into the current workspace from an allow-listed \" +\n \"template, then return a deep link to open it. Idempotent: if an app \" +\n \"with that name already exists it is reused. After calling, surface \" +\n 'the returned \"Open … →\" link to the user.',\n {\n name: {\n type: \"string\",\n description: \"New app id (directory under apps/), e.g. 'mymail'\",\n },\n template: {\n type: \"string\",\n description:\n \"Template to scaffold from — must be allow-listed (see list_templates)\",\n },\n },\n [\"name\", \"template\"],\n ),\n run: async (args: Record<string, any>) => {\n const name = String(args.name ?? \"\").trim();\n const template = String(args.template ?? \"\").trim();\n if (!name || !template) {\n throw new Error(\n \"create_workspace_app requires both 'name' and 'template'.\",\n );\n }\n\n // Enforce the strict public template allow-list. The authoritative,\n // dependency-free source inside @agent-native/core is cli/templates-meta\n // (kept in sync with packages/shared-app-config/templates.ts; CI guard).\n const { visibleTemplates } = await import(\"../cli/templates-meta.js\");\n const allowed = new Set(visibleTemplates().map((t) => t.name));\n if (!allowed.has(template)) {\n throw new Error(\n `Template \"${template}\" is not allow-listed. Allowed: ${[...allowed]\n .sort()\n .join(\", \")}`,\n );\n }\n\n const { findWorkspaceRoot, resolveWorkspace } =\n await import(\"./workspace-resolve.js\");\n const fs = await import(\"node:fs\");\n const path = await import(\"node:path\");\n\n const root = findWorkspaceRoot(process.cwd());\n if (!root) {\n throw new Error(\n \"Not inside a workspace. create_workspace_app only works in a \" +\n \"multi-app workspace (run from the workspace root).\",\n );\n }\n\n const appDir = path.join(root, \"apps\", name);\n const alreadyExisted = fs.existsSync(appDir);\n\n if (!alreadyExisted) {\n // Reuse the CLI scaffolder directly (no second `agent-native`\n // subprocess). `addAppToWorkspace(name, { template })` takes the\n // non-interactive single-template path when name + one template are\n // given. Run it from the workspace root so detectWorkspace resolves.\n const prevCwd = process.cwd();\n try {\n process.chdir(root);\n const { addAppToWorkspace } = await import(\"../cli/create.js\");\n await addAppToWorkspace(name, { template, noInstall: true });\n } finally {\n try {\n process.chdir(prevCwd);\n } catch {\n // best-effort cwd restore\n }\n }\n }\n\n // The workspace gateway auto-detects new apps/* dirs (fs.watch +\n // 2s sync) and lazily boots the dev server on first request, so we\n // don't spawn vite ourselves — opening the deep link warms it. Resolve\n // the port the gateway will use so we can report it.\n const ws = await resolveWorkspace(root);\n const appInfo = ws.apps.find((a) => a.id === name);\n const port = appInfo?.port;\n // The scaffolded app is always a *different* app from the host MCP\n // server, so anchor the deep link to the new app's own origin. A\n // relative path would otherwise be prefixed with the current request\n // origin and land on the wrong app. Fall back to the relative path\n // only if the gateway hasn't reported the new app's URL yet.\n const relDeepLink = buildDeepLink({ app: name, view: \"home\" });\n const deepLink = appInfo?.url\n ? `${appInfo.url.replace(/\\/+$/, \"\")}${relDeepLink}`\n : relDeepLink;\n\n return {\n name,\n template,\n created: !alreadyExisted,\n reused: alreadyExisted,\n port,\n url: appInfo?.url,\n gatewayUrl: ws.gatewayUrl,\n deepLink,\n };\n },\n link: ({ result }) => {\n if (!result || typeof result !== \"object\") return null;\n const r = result as { deepLink?: string; name?: string };\n if (!r.deepLink) return null;\n return {\n url: r.deepLink,\n label: `Open ${r.name ?? \"app\"}`,\n view: \"home\",\n };\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Registry\n// ---------------------------------------------------------------------------\n\n/**\n * Build the generic cross-app builtin tool registry. Called by\n * `createMCPServerForRequest`; the result is merged UNDER the config's\n * actions so template actions of the same name win.\n */\nexport function getBuiltinCrossAppTools(\n config: MCPConfig,\n requestMeta?: { origin?: string },\n): Record<string, ActionEntry> {\n return {\n list_apps: listAppsTool(config, requestMeta),\n open_app: openAppTool(config),\n create_embed_session: createEmbedSessionTool(requestMeta),\n ask_app: askAppTool(config),\n create_workspace_app: createWorkspaceAppTool(),\n list_templates: listTemplatesTool(),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"builtin-tools.js","sourceRoot":"","sources":["../../src/mcp/builtin-tools.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generic cross-app MCP tools — a stable verb set every external agent gets\n * regardless of which template it is talking to.\n *\n * These are merged into the MCP action registry by\n * `createMCPServerForRequest` (see `build-server.ts`). **Precedence: template\n * actions win.** If a template defines an action named `list_apps` /\n * `open_app` / `ask_app` / `create_workspace_app` / `list_templates`, the\n * template's `ActionEntry` overwrites the builtin of the same name. This is\n * the same template-over-framework precedence `autoDiscoverActions` uses.\n *\n * | Tool | Side effects | Returns |\n * | --------------------- | ------------ | ---------------------------------------- |\n * | `list_apps` | none | `{ apps: [{ id, url, running }] }` |\n * | `open_app` | none | `{ url }` (+ deep-link `link`) |\n * | `create_embed_session`| ticket mint | `{ startUrl }` for MCP App iframes |\n * | `ask_app` | agent loop | `{ app, routedVia, response }` |\n * | `create_workspace_app`| scaffolds | `{ name, url, port, deepLink }` (+ link) |\n *\n * `open_app` / `create_workspace_app` return an **absolute** URL on the\n * *target* app's origin when it differs from this app (so a workspace link\n * lands in the right app), and a relative path for the same app / standalone.\n * `ask_app` routes to a *different* workspace app over A2A when possible and\n * reports `routedVia: \"a2a\"`; otherwise it answers locally\n * (`routedVia: \"local\"`) and never falsely claims cross-app delegation.\n * | `list_templates` | none | `{ templates: [...] }` (allow-list only) |\n *\n * Node-only at call time (workspace resolution + scaffolding use `fs`), but\n * the module has no top-level Node imports so it bundles fine alongside\n * `mountMCP` — the Node bits are dynamically imported inside `run()`.\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport { buildDeepLink } from \"../server/deep-link.js\";\nimport { getConfiguredAppBasePath } from \"../server/app-base-path.js\";\nimport type { MCPConfig } from \"./build-server.js\";\nimport { fetchOrgApps, type OrgApp } from \"./org-directory.js\";\nimport { embedApp } from \"./embed-app.js\";\n\nimport type { ActionTool } from \"../agent/types.js\";\n\n/** Flat map of param name → JSON-schema property. */\ntype Params = Record<\n string,\n { type: string; description?: string; enum?: string[] }\n>;\n\n/**\n * Build an `ActionTool`. `parameters` is wrapped in the\n * `{ type:\"object\", properties, required }` shape `createMCPServerForRequest`\n * forwards verbatim as the MCP tool `inputSchema`.\n */\nfunction tool(\n description: string,\n parameters?: Params,\n required?: string[],\n): ActionTool {\n if (!parameters) return { description };\n return {\n description,\n parameters: {\n type: \"object\",\n properties: parameters,\n ...(required && required.length ? { required } : {}),\n },\n };\n}\n\n/**\n * The canonical app id this MCP server is mounted for. `MCPConfig.appId` is\n * authoritative; fall back to lowercasing `name` (which is the capitalized\n * app id at every call site) for back-compat with configs that predate the\n * `appId` field.\n */\nfunction currentAppId(config: MCPConfig): string {\n return (config.appId || config.name || \"app\").toLowerCase();\n}\n\nconst CONTROL_CHARS = new RegExp(\"[\\\\u0000-\\\\u001f\\\\u007f]\");\n\nfunction safeAppPath(raw: unknown): string | null {\n if (typeof raw !== \"string\" || !raw.trim()) return null;\n const value = raw.trim();\n if (CONTROL_CHARS.test(value)) return null;\n if (!value.startsWith(\"/\")) return null;\n if (value.startsWith(\"//\") || value.startsWith(\"/\\\\\")) return null;\n if (/^\\/[a-z][a-z0-9+.-]*:/i.test(value)) return null;\n return value;\n}\n\nfunction appendParamsToPath(\n path: string,\n params: Record<string, string | number | boolean> | undefined,\n): string {\n if (!params || Object.keys(params).length === 0) return path;\n const url = new URL(path, \"http://agent-native.invalid\");\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, String(value));\n }\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nfunction viewToAppPath(view: string): string | null {\n const value = view.trim();\n if (!value) return null;\n return safeAppPath(value.startsWith(\"/\") ? value : `/${value}`);\n}\n\nfunction withConfiguredBasePath(path: string): string {\n const base = getConfiguredAppBasePath();\n if (!base || path === base || path.startsWith(`${base}/`)) return path;\n return `${base}${path}`;\n}\n\n/**\n * Resolve the absolute origin of a *target* workspace app (e.g.\n * `http://127.0.0.1:8101`) so cross-app deep links / A2A calls point at the\n * right app instead of the current request's origin. Reuses the same\n * workspace resolution `list_apps` / the stdio proxy use.\n *\n * Returns `null` when:\n * - the target is the current app (caller should keep relative behavior),\n * - there is no workspace info (standalone / single app), or\n * - the target app is unknown.\n */\nasync function resolveTargetAppOrigin(\n config: MCPConfig,\n targetAppId: string,\n): Promise<{ origin: string; id: string } | null> {\n const target = targetAppId.trim().toLowerCase();\n if (!target || target === currentAppId(config)) return null;\n try {\n const { resolveWorkspace } = await import(\"./workspace-resolve.js\");\n const ws = await resolveWorkspace();\n if (!ws.isWorkspace) return null;\n const match = ws.apps.find((a) => a.id.toLowerCase() === target);\n if (!match) return null;\n return { origin: match.url, id: match.id };\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// list_apps\n// ---------------------------------------------------------------------------\n\nfunction listAppsTool(\n config: MCPConfig,\n requestMeta?: { origin?: string },\n): ActionEntry {\n return {\n tool: tool(\n \"List the workspace apps and their URLs. Use this to discover which \" +\n \"apps exist before opening or asking one. In a single-app project \" +\n \"this returns just that app. When an org directory is configured \" +\n \"this also includes the org's deployed sibling apps.\",\n ),\n readOnly: true,\n parallelSafe: true,\n run: async () => {\n const { resolveWorkspace } = await import(\"./workspace-resolve.js\");\n const ws = await resolveWorkspace();\n\n // The MCP request is served BY the current app, so it is provably\n // reachable at the inbound request origin — that beats a guessed\n // `PORT || 5173` probe (which reports the wrong URL + `running:false`\n // whenever the dev server picked a non-default port, e.g. `agent-\n // native dev` on :8080). For the entry that IS this app (the sole\n // entry when single-app, or the id matching `config.appId` in a\n // workspace) prefer the live origin; other workspace apps keep their\n // probed values.\n const liveOrigin = requestMeta?.origin?.replace(/\\/+$/, \"\") || \"\";\n let livePort = 0;\n if (liveOrigin) {\n try {\n const u = new URL(liveOrigin);\n livePort = Number(u.port) || (u.protocol === \"https:\" ? 443 : 80);\n } catch {\n livePort = 0;\n }\n }\n const selfId = (config.appId ?? \"\").toLowerCase();\n const isSelf = (id: string) =>\n !!liveOrigin &&\n (!ws.isWorkspace || (!!selfId && id.toLowerCase() === selfId));\n\n interface AppEntry {\n id: string;\n url: string;\n port: number | undefined;\n running: boolean;\n source: \"workspace\" | \"org-directory\";\n }\n\n const apps: AppEntry[] = ws.apps.map((a) =>\n isSelf(a.id)\n ? {\n id: a.id,\n url: liveOrigin,\n port: (livePort || a.port) as number | undefined,\n running: true,\n source: \"workspace\" as const,\n }\n : {\n id: a.id,\n url: a.url,\n port: a.port as number | undefined,\n running: a.running,\n source: \"workspace\" as const,\n },\n );\n const seenIds = new Set(apps.map((a) => a.id.toLowerCase()));\n const seenOrigins = new Set(apps.map((a) => a.url.replace(/\\/+$/, \"\")));\n\n // Merge the org directory's deployed sibling apps. Inactive (no env)\n // or any failure ⇒ fetchOrgApps() returns [] and this is a no-op, so\n // the existing local/workspace behavior is preserved exactly.\n const orgApps = await fetchOrgApps({\n selfId: currentAppId(config),\n }).catch(() => [] as OrgApp[]);\n for (const oa of orgApps) {\n const idKey = oa.id.toLowerCase();\n const originKey = oa.url.replace(/\\/+$/, \"\");\n // Dedupe by id OR origin — a workspace app already listed wins.\n if (seenIds.has(idKey) || seenOrigins.has(originKey)) continue;\n seenIds.add(idKey);\n seenOrigins.add(originKey);\n apps.push({\n id: oa.id,\n url: oa.url,\n port: undefined,\n running: true,\n source: \"org-directory\",\n });\n }\n\n return {\n workspace: ws.isWorkspace,\n gatewayUrl: ws.gatewayUrl,\n apps,\n };\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// open_app\n// ---------------------------------------------------------------------------\n\nfunction openAppTool(config: MCPConfig): ActionEntry {\n return {\n tool: tool(\n \"Build a deep link that opens an app at a specific view/record or \" +\n \"focused route/component. No side \" +\n \"effects — returns a URL the user can click to land in the running UI. \" +\n \"Set embed:true when a UI-capable MCP host should render the live app \" +\n \"or focused route/component inline. After calling, surface the returned \" +\n '\"Open in … →\" link to the user.',\n {\n app: { type: \"string\", description: \"App id, e.g. 'mail'\" },\n view: {\n type: \"string\",\n description:\n \"Target view, e.g. 'inbox' (maps to navigate command). Optional when path is provided.\",\n },\n path: {\n type: \"string\",\n description:\n \"Optional app route to open directly, e.g. '/extensions/abc', '/adhoc/q2', or '/chart?panel=...'. Must be same-origin relative.\",\n },\n params: {\n type: \"object\",\n description:\n \"Optional record-focus / filter params, e.g. { threadId: 'abc' }\",\n },\n embed: {\n type: \"boolean\",\n description:\n \"Render the full app or focused route/component inline in MCP Apps when the host supports it.\",\n },\n chrome: {\n type: \"string\",\n enum: [\"full\", \"minimal\"],\n description:\n \"Embed chrome preference for compatible app routes. Defaults to full.\",\n },\n },\n [\"app\"],\n ),\n readOnly: true,\n parallelSafe: true,\n run: async (args: Record<string, any>) => {\n const app = String(args.app ?? \"\").trim();\n const view = String(args.view ?? \"\").trim();\n const path = safeAppPath(args.path);\n if (!app || (!view && !path)) {\n throw new Error(\"open_app requires 'app' and either 'view' or 'path'.\");\n }\n let params: Record<string, string | number | boolean> | undefined;\n const raw = args.params;\n if (raw && typeof raw === \"object\") {\n params = raw as Record<string, string | number | boolean>;\n } else if (typeof raw === \"string\" && raw.trim()) {\n try {\n params = JSON.parse(raw);\n } catch {\n params = undefined;\n }\n }\n const embed = args.embed === true;\n const directViewPath = embed && view ? viewToAppPath(view) : null;\n const relUrl = path\n ? appendParamsToPath(path, params)\n : directViewPath\n ? appendParamsToPath(directViewPath, params)\n : buildDeepLink({ app, view, params });\n const sameAppUrl =\n path || directViewPath ? withConfiguredBasePath(relUrl) : relUrl;\n\n // Cross-app target in a workspace: resolve the TARGET app's origin and\n // return an absolute URL. Otherwise the MCP layer would prefix the\n // relative path with the CURRENT request origin, landing the user in\n // the wrong app (e.g. open_app({app:\"calendar\"}) served from Mail).\n // Same-app / standalone keeps the relative path (current behavior).\n const targetApp = await resolveTargetAppOrigin(config, app);\n const url = targetApp\n ? `${targetApp.origin.replace(/\\/+$/, \"\")}${relUrl}`\n : sameAppUrl;\n\n return {\n app,\n ...(view ? { view } : {}),\n ...(path ? { path } : {}),\n url,\n embed,\n };\n },\n link: ({ result }) => {\n if (!result || typeof result !== \"object\") return null;\n const r = result as { url?: string; app?: string; view?: string };\n if (!r.url) return null;\n return {\n url: r.url,\n label: `Open ${r.app ?? \"app\"}`,\n view: r.view,\n };\n },\n mcpApp: {\n resource: embedApp({\n title: \"Open app\",\n description: \"Render the requested app route inline.\",\n iframeTitle: \"Agent Native app\",\n openLabel: \"Open app\",\n height: 900,\n }),\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// create_embed_session\n// ---------------------------------------------------------------------------\n\nfunction createEmbedSessionTool(requestMeta?: {\n origin?: string;\n}): ActionEntry {\n return {\n tool: {\n ...tool(\n \"MCP Apps helper: create a one-time browser embed session for a same-origin app URL. Usually called by an MCP App iframe, not directly by the model.\",\n {\n url: {\n type: \"string\",\n description:\n \"Same-origin absolute URL or app-relative path to embed.\",\n },\n path: {\n type: \"string\",\n description: \"Same-origin app-relative path to embed.\",\n },\n chrome: {\n type: \"string\",\n enum: [\"full\", \"minimal\"],\n description: \"Embed chrome preference. Defaults to full.\",\n },\n },\n ),\n _meta: { ui: { visibility: [\"app\"] } },\n } as ActionTool,\n // Minting a browser session lets the iframe operate the real app as the\n // caller, so OAuth callers must have mcp:write rather than only mcp:read.\n readOnly: false,\n parallelSafe: true,\n run: async (args: Record<string, any>) => {\n const { getRequestContext } =\n await import(\"../server/request-context.js\");\n const ctx = getRequestContext();\n const ownerEmail = ctx?.userEmail?.trim();\n if (!ownerEmail) {\n throw new Error(\n \"create_embed_session requires an authenticated MCP caller.\",\n );\n }\n\n const { normalizeEmbedTargetPath, createEmbedSessionTicket } =\n await import(\"../server/embed-session.js\");\n const { buildEmbedStartPath } = await import(\"../server/embed-route.js\");\n const rawTarget =\n typeof args.url === \"string\" && args.url.trim()\n ? args.url\n : typeof args.path === \"string\"\n ? args.path\n : \"\";\n const targetPath = normalizeEmbedTargetPath(\n rawTarget,\n requestMeta?.origin,\n );\n if (!targetPath) {\n throw new Error(\n \"create_embed_session can only embed same-origin app-relative URLs.\",\n );\n }\n\n const ticket = await createEmbedSessionTicket({\n ownerEmail,\n orgId: ctx?.orgId,\n targetPath,\n scope: typeof args.chrome === \"string\" ? args.chrome : null,\n });\n const startPath = buildEmbedStartPath(ticket.ticket);\n const startUrl = requestMeta?.origin\n ? new URL(startPath, requestMeta.origin).toString()\n : startPath;\n return {\n startUrl,\n targetPath,\n expiresAt: ticket.expiresAt,\n };\n },\n };\n}\n\n/**\n * Route an `ask_app` message to a *different* app's agent over A2A. Shared by\n * the workspace-resolved path and the org-directory-resolved path so the A2A\n * call logic is not duplicated. `origin` is the target app's A2A base\n * (workspace dev origin or the directory's `a2aUrl`); `id` is reported back.\n *\n * Throws on failure so the caller can be honest — it never falls back to this\n * app's agent and pretends it was the target.\n */\nasync function routeAskOverA2A(\n origin: string,\n id: string,\n message: string,\n): Promise<{ app: string; routedVia: \"a2a\"; response: string }> {\n const { callAgent } = await import(\"../a2a/client.js\");\n const { resolveA2ACallerAuth } = await import(\"../a2a/caller-auth.js\");\n // The MCP handler runs inside `runWithRequestContext`, so this is the\n // verified caller identity and org scope. Reuse the same auth resolver as\n // org-directory discovery so the directory lookup and actual A2A call are\n // scoped the same way.\n const auth = await resolveA2ACallerAuth();\n const response = await callAgent(origin, message, {\n apiKey: auth.apiKey,\n userEmail: auth.userEmail,\n orgDomain: auth.orgDomain,\n orgSecret: auth.orgSecret,\n // Bound the wait — cross-app A2A polls async by default.\n timeoutMs: 5 * 60_000,\n });\n return { app: id, routedVia: \"a2a\", response };\n}\n\n// ---------------------------------------------------------------------------\n// ask_app\n// ---------------------------------------------------------------------------\n\nfunction askAppTool(config: MCPConfig): ActionEntry {\n return {\n tool: tool(\n \"Send a natural-language message to an app's AI agent and get its \" +\n \"response. Use for complex, multi-step tasks needing the agent's \" +\n \"reasoning and full app context. In a single-app project the 'app' \" +\n \"param is optional (defaults to this app). When 'app' names a \" +\n \"different workspace app it is routed there over A2A; the result's \" +\n \"'routedVia' field reports whether it ran cross-app or locally.\",\n {\n app: {\n type: \"string\",\n description: \"App id to route to (optional in a single-app project)\",\n },\n message: {\n type: \"string\",\n description: \"The message to send to the app's agent\",\n },\n },\n [\"message\"],\n ),\n run: async (args: Record<string, any>) => {\n const message = String(args.message ?? \"\").trim();\n if (!message) throw new Error(\"ask_app requires a 'message'.\");\n const requestedApp = String(args.app ?? \"\").trim();\n const selfId = currentAppId(config);\n\n // Cross-app: the caller named a *different* workspace app. Route the\n // message to THAT app's agent over A2A (its `/_agent-native/a2a`\n // endpoint runs the real agent loop with JWT identity) rather than\n // silently answering from this app's agent and claiming delegation.\n const targetApp = await resolveTargetAppOrigin(config, requestedApp);\n if (targetApp) {\n try {\n return await routeAskOverA2A(targetApp.origin, targetApp.id, message);\n } catch (err: any) {\n // Be honest: routing was attempted and failed — do NOT fall back to\n // this app's agent and pretend it was the target.\n throw new Error(\n `Failed to route ask_app to \"${targetApp.id}\" via A2A: ` +\n `${err?.message ?? err}`,\n );\n }\n }\n\n // Not a known local/workspace app — try the org directory. When a\n // directory is configured and the requested app is one of the org's\n // deployed sibling apps, route to it over A2A (same path as above,\n // against its `a2aUrl`). Inactive directory / any failure ⇒ orgApps is\n // [] and this is skipped, preserving the exact local-only behavior.\n if (requestedApp && requestedApp.toLowerCase() !== selfId) {\n const orgApps = await fetchOrgApps({ selfId }).catch(\n () => [] as OrgApp[],\n );\n const dirMatch = orgApps.find(\n (a) => a.id === requestedApp.toLowerCase(),\n );\n if (dirMatch) {\n try {\n return await routeAskOverA2A(dirMatch.a2aUrl, dirMatch.id, message);\n } catch (err: any) {\n throw new Error(\n `Failed to route ask_app to \"${dirMatch.id}\" via A2A ` +\n `(org directory): ${err?.message ?? err}`,\n );\n }\n }\n }\n\n // Same app (or no workspace / unknown target): answer locally with this\n // app's own ask-agent handler — the same entry point the HTTP MCP mount\n // + A2A use, so there is no second agent runner.\n if (!config.askAgent) {\n throw new Error(\n \"This app does not expose an agent (no ask-agent handler).\",\n );\n }\n\n // If the caller named an app we couldn't route to (unknown id, or no\n // workspace), say so honestly instead of claiming we reached it.\n const unresolved =\n !!requestedApp && requestedApp.toLowerCase() !== selfId;\n const response = await config.askAgent(message);\n return {\n app: selfId,\n routedVia: \"local\",\n ...(unresolved\n ? {\n note:\n `Requested app \"${requestedApp}\" is not a reachable workspace ` +\n `app; answered with this app (\"${selfId}\") instead.`,\n }\n : {}),\n response,\n };\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// list_templates\n// ---------------------------------------------------------------------------\n\nfunction listTemplatesTool(): ActionEntry {\n return {\n tool: tool(\n \"List the first-party templates that can be scaffolded into a workspace \" +\n \"(allow-listed templates only).\",\n ),\n readOnly: true,\n parallelSafe: true,\n run: async () => {\n const { visibleTemplates } = await import(\"../cli/templates-meta.js\");\n return {\n templates: visibleTemplates().map((t) => ({\n name: t.name,\n label: t.label,\n hint: t.hint,\n })),\n };\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// create_workspace_app\n// ---------------------------------------------------------------------------\n\nfunction createWorkspaceAppTool(): ActionEntry {\n return {\n tool: tool(\n \"Scaffold a new app into the current workspace from an allow-listed \" +\n \"template, then return a deep link to open it. Idempotent: if an app \" +\n \"with that name already exists it is reused. After calling, surface \" +\n 'the returned \"Open … →\" link to the user.',\n {\n name: {\n type: \"string\",\n description: \"New app id (directory under apps/), e.g. 'mymail'\",\n },\n template: {\n type: \"string\",\n description:\n \"Template to scaffold from — must be allow-listed (see list_templates)\",\n },\n },\n [\"name\", \"template\"],\n ),\n run: async (args: Record<string, any>) => {\n const name = String(args.name ?? \"\").trim();\n const template = String(args.template ?? \"\").trim();\n if (!name || !template) {\n throw new Error(\n \"create_workspace_app requires both 'name' and 'template'.\",\n );\n }\n\n // Enforce the strict public template allow-list. The authoritative,\n // dependency-free source inside @agent-native/core is cli/templates-meta\n // (kept in sync with packages/shared-app-config/templates.ts; CI guard).\n const { visibleTemplates } = await import(\"../cli/templates-meta.js\");\n const allowed = new Set(visibleTemplates().map((t) => t.name));\n if (!allowed.has(template)) {\n throw new Error(\n `Template \"${template}\" is not allow-listed. Allowed: ${[...allowed]\n .sort()\n .join(\", \")}`,\n );\n }\n\n const { findWorkspaceRoot, resolveWorkspace } =\n await import(\"./workspace-resolve.js\");\n const fs = await import(\"node:fs\");\n const path = await import(\"node:path\");\n\n const root = findWorkspaceRoot(process.cwd());\n if (!root) {\n throw new Error(\n \"Not inside a workspace. create_workspace_app only works in a \" +\n \"multi-app workspace (run from the workspace root).\",\n );\n }\n\n const appDir = path.join(root, \"apps\", name);\n const alreadyExisted = fs.existsSync(appDir);\n\n if (!alreadyExisted) {\n // Reuse the CLI scaffolder directly (no second `agent-native`\n // subprocess). `addAppToWorkspace(name, { template })` takes the\n // non-interactive single-template path when name + one template are\n // given. Run it from the workspace root so detectWorkspace resolves.\n const prevCwd = process.cwd();\n try {\n process.chdir(root);\n const { addAppToWorkspace } = await import(\"../cli/create.js\");\n await addAppToWorkspace(name, { template, noInstall: true });\n } finally {\n try {\n process.chdir(prevCwd);\n } catch {\n // best-effort cwd restore\n }\n }\n }\n\n // The workspace gateway auto-detects new apps/* dirs (fs.watch +\n // 2s sync) and lazily boots the dev server on first request, so we\n // don't spawn vite ourselves — opening the deep link warms it. Resolve\n // the port the gateway will use so we can report it.\n const ws = await resolveWorkspace(root);\n const appInfo = ws.apps.find((a) => a.id === name);\n const port = appInfo?.port;\n // The scaffolded app is always a *different* app from the host MCP\n // server, so anchor the deep link to the new app's own origin. A\n // relative path would otherwise be prefixed with the current request\n // origin and land on the wrong app. Fall back to the relative path\n // only if the gateway hasn't reported the new app's URL yet.\n const relDeepLink = buildDeepLink({ app: name, view: \"home\" });\n const deepLink = appInfo?.url\n ? `${appInfo.url.replace(/\\/+$/, \"\")}${relDeepLink}`\n : relDeepLink;\n\n return {\n name,\n template,\n created: !alreadyExisted,\n reused: alreadyExisted,\n port,\n url: appInfo?.url,\n gatewayUrl: ws.gatewayUrl,\n deepLink,\n };\n },\n link: ({ result }) => {\n if (!result || typeof result !== \"object\") return null;\n const r = result as { deepLink?: string; name?: string };\n if (!r.deepLink) return null;\n return {\n url: r.deepLink,\n label: `Open ${r.name ?? \"app\"}`,\n view: \"home\",\n };\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Registry\n// ---------------------------------------------------------------------------\n\n/**\n * Build the generic cross-app builtin tool registry. Called by\n * `createMCPServerForRequest`; the result is merged UNDER the config's\n * actions so template actions of the same name win.\n */\nexport function getBuiltinCrossAppTools(\n config: MCPConfig,\n requestMeta?: { origin?: string },\n): Record<string, ActionEntry> {\n return {\n list_apps: listAppsTool(config, requestMeta),\n open_app: openAppTool(config),\n create_embed_session: createEmbedSessionTool(requestMeta),\n ask_app: askAppTool(config),\n create_workspace_app: createWorkspaceAppTool(),\n list_templates: listTemplatesTool(),\n };\n}\n"]}
|
package/dist/mcp/embed-app.js
CHANGED
|
@@ -13,7 +13,7 @@ export function embedApp(options = {}) {
|
|
|
13
13
|
const openLabel = options.openLabel ?? "Open in app";
|
|
14
14
|
const startToolName = options.startToolName ?? "create_embed_session";
|
|
15
15
|
const embedByDefault = options.embedByDefault !== false;
|
|
16
|
-
const height = Math.max(320, Math.min(
|
|
16
|
+
const height = Math.max(320, Math.min(900, options.height ?? 900));
|
|
17
17
|
return {
|
|
18
18
|
title,
|
|
19
19
|
...(options.description ? { description: options.description } : {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embed-app.js","sourceRoot":"","sources":["../../src/mcp/embed-app.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAClB,mEAAmE,CAAC;AAEtE,MAAM,CAAC,MAAM,iCAAiC,GAAG,gBAAgB,CAAC;AAalE,SAAS,IAAI,CAAC,KAAyB;IACrC,OAAO,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,QAAQ,CACtB,UAA2B,EAAE;IAE7B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC;IAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,kBAAkB,CAAC;IAC9D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,aAAa,CAAC;IACrD,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,sBAAsB,CAAC;IACtE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,KAAK,KAAK,CAAC;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC;IAEnE,OAAO;QACL,KAAK;QACL,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,IAAI,EAAE,GAAG,EAAE,CAAC;;;;;;;;;oDASoC,MAAM;;;;;;+CAMX,MAAM,GAAG,EAAE;oDACN,MAAM,GAAG,EAAE;iEACE,MAAM,GAAG,EAAE;;;;gBAI5D,IAAI,CAAC,KAAK,CAAC;uBACJ,IAAI,CAAC,WAAW,CAAC;qBACnB,IAAI,CAAC,SAAS,CAAC;qBACf,IAAI,CAAC,aAAa,CAAC;wBAChB,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;;;;sCAIZ,IAAI,CAAC,KAAK,CAAC;;mDAEE,IAAI,CAAC,SAAS,CAAC;;;;;;;;2BAQvC,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwHjC;QACJ,GAAG,EAAE;YACH,cAAc,EAAE,CAAC,gBAAgB,CAAC;YAClC,eAAe,EAAE,CAAC,gBAAgB,CAAC;YACnC,YAAY,EAAE;gBACZ,iCAAiC;gBACjC,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;aAChC;SACF;QACD,aAAa,EAAE,KAAK;KACrB,CAAC;AACJ,CAAC","sourcesContent":["import type { ActionMcpAppResourceConfig } from \"../action.js\";\n\nconst MCP_APP_IMPORT =\n \"https://esm.sh/@modelcontextprotocol/ext-apps@1.7.2/app-with-deps\";\n\nexport const MCP_APP_REQUEST_ORIGIN_CSP_SOURCE = \"$requestOrigin\";\n\nexport interface EmbedAppOptions {\n title?: string;\n description?: string;\n iframeTitle?: string;\n openLabel?: string;\n embedByDefault?: boolean;\n startToolName?: string;\n frameDomains?: string[];\n height?: number;\n}\n\nfunction attr(value: string | undefined): string {\n return String(value ?? \"\")\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nexport function embedApp(\n options: EmbedAppOptions = {},\n): ActionMcpAppResourceConfig {\n const title = options.title ?? \"Open app\";\n const iframeTitle = options.iframeTitle ?? \"Agent Native app\";\n const openLabel = options.openLabel ?? \"Open in app\";\n const startToolName = options.startToolName ?? \"create_embed_session\";\n const embedByDefault = options.embedByDefault !== false;\n const height = Math.max(320, Math.min(
|
|
1
|
+
{"version":3,"file":"embed-app.js","sourceRoot":"","sources":["../../src/mcp/embed-app.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAClB,mEAAmE,CAAC;AAEtE,MAAM,CAAC,MAAM,iCAAiC,GAAG,gBAAgB,CAAC;AAalE,SAAS,IAAI,CAAC,KAAyB;IACrC,OAAO,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,QAAQ,CACtB,UAA2B,EAAE;IAE7B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC;IAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,kBAAkB,CAAC;IAC9D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,aAAa,CAAC;IACrD,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,sBAAsB,CAAC;IACtE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,KAAK,KAAK,CAAC;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC;IAEnE,OAAO;QACL,KAAK;QACL,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,IAAI,EAAE,GAAG,EAAE,CAAC;;;;;;;;;oDASoC,MAAM;;;;;;+CAMX,MAAM,GAAG,EAAE;oDACN,MAAM,GAAG,EAAE;iEACE,MAAM,GAAG,EAAE;;;;gBAI5D,IAAI,CAAC,KAAK,CAAC;uBACJ,IAAI,CAAC,WAAW,CAAC;qBACnB,IAAI,CAAC,SAAS,CAAC;qBACf,IAAI,CAAC,aAAa,CAAC;wBAChB,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;;;;sCAIZ,IAAI,CAAC,KAAK,CAAC;;mDAEE,IAAI,CAAC,SAAS,CAAC;;;;;;;;2BAQvC,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwHjC;QACJ,GAAG,EAAE;YACH,cAAc,EAAE,CAAC,gBAAgB,CAAC;YAClC,eAAe,EAAE,CAAC,gBAAgB,CAAC;YACnC,YAAY,EAAE;gBACZ,iCAAiC;gBACjC,GAAG,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;aAChC;SACF;QACD,aAAa,EAAE,KAAK;KACrB,CAAC;AACJ,CAAC","sourcesContent":["import type { ActionMcpAppResourceConfig } from \"../action.js\";\n\nconst MCP_APP_IMPORT =\n \"https://esm.sh/@modelcontextprotocol/ext-apps@1.7.2/app-with-deps\";\n\nexport const MCP_APP_REQUEST_ORIGIN_CSP_SOURCE = \"$requestOrigin\";\n\nexport interface EmbedAppOptions {\n title?: string;\n description?: string;\n iframeTitle?: string;\n openLabel?: string;\n embedByDefault?: boolean;\n startToolName?: string;\n frameDomains?: string[];\n height?: number;\n}\n\nfunction attr(value: string | undefined): string {\n return String(value ?? \"\")\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nexport function embedApp(\n options: EmbedAppOptions = {},\n): ActionMcpAppResourceConfig {\n const title = options.title ?? \"Open app\";\n const iframeTitle = options.iframeTitle ?? \"Agent Native app\";\n const openLabel = options.openLabel ?? \"Open in app\";\n const startToolName = options.startToolName ?? \"create_embed_session\";\n const embedByDefault = options.embedByDefault !== false;\n const height = Math.max(320, Math.min(900, options.height ?? 900));\n\n return {\n title,\n ...(options.description ? { description: options.description } : {}),\n html: () => `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style>\n :root { color-scheme: light dark; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; background: Canvas; color: CanvasText; }\n * { box-sizing: border-box; }\n body { margin: 0; }\n .shell { display: grid; gap: 8px; min-height: ${height}px; padding: 0; }\n .bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 36px; padding: 6px 8px; border-bottom: 1px solid color-mix(in srgb, CanvasText 12%, Canvas); }\n .title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; font-weight: 700; color: color-mix(in srgb, CanvasText 72%, Canvas); }\n .actions { display: flex; align-items: center; gap: 6px; }\n button { min-height: 28px; border: 1px solid color-mix(in srgb, CanvasText 14%, Canvas); border-radius: 7px; background: Canvas; color: CanvasText; cursor: pointer; font: inherit; font-size: 12px; font-weight: 700; padding: 0 9px; }\n button:disabled { opacity: .55; cursor: default; }\n .stage { position: relative; min-height: ${height - 44}px; }\n iframe { display: block; width: 100%; height: ${height - 44}px; border: 0; background: Canvas; }\n .message { display: grid; place-items: center; min-height: ${height - 44}px; padding: 18px; color: color-mix(in srgb, CanvasText 62%, Canvas); font-size: 13px; line-height: 1.45; text-align: center; }\n </style>\n</head>\n<body\n data-title=\"${attr(title)}\"\n data-iframe-title=\"${attr(iframeTitle)}\"\n data-open-label=\"${attr(openLabel)}\"\n data-start-tool=\"${attr(startToolName)}\"\n data-embed-default=\"${embedByDefault ? \"1\" : \"0\"}\"\n>\n <main class=\"shell\">\n <div class=\"bar\">\n <div class=\"title\" data-title>${attr(title)}</div>\n <div class=\"actions\">\n <button type=\"button\" data-open disabled>${attr(openLabel)}</button>\n </div>\n </div>\n <section class=\"stage\" data-stage>\n <div class=\"message\">Preparing app</div>\n </section>\n </main>\n <script type=\"module\">\n import { App } from \"${MCP_APP_IMPORT}\";\n\n const app = new App({ name: \"Agent Native Embed\", version: \"1.0.0\" }, {});\n const body = document.body;\n const stage = document.querySelector(\"[data-stage]\");\n const titleEl = document.querySelector(\"[data-title]\");\n const openButton = document.querySelector(\"[data-open]\");\n const startTool = body.dataset.startTool || \"create_embed_session\";\n const embedByDefault = body.dataset.embedDefault !== \"0\";\n let toolInput = {};\n let openUrl = \"\";\n let startedFor = \"\";\n\n function esc(value) {\n return String(value ?? \"\")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n }\n\n function parseJson(value, fallback) {\n if (value && typeof value === \"object\") return value;\n if (typeof value !== \"string\" || !value.trim()) return fallback;\n try { return JSON.parse(value); } catch { return fallback; }\n }\n\n function parseToolResult(params) {\n if (!params) return {};\n if (params.structuredContent && typeof params.structuredContent === \"object\") {\n return params.structuredContent;\n }\n const parts = Array.isArray(params.content) ? params.content : [];\n const textPart = parts.find((part) => part && part.type === \"text\" && typeof part.text === \"string\");\n return parseJson(textPart ? textPart.text : \"\", {});\n }\n\n function openLinkFrom(params, data) {\n const metaUrl = params && params._meta && params._meta[\"agent-native/openLink\"]\n ? params._meta[\"agent-native/openLink\"].webUrl\n : \"\";\n return metaUrl || data.url || data.deepLink || data.openUrl || \"\";\n }\n\n function wantsEmbed() {\n if (toolInput.embed === false) return false;\n if (toolInput.embed === true) return true;\n return embedByDefault;\n }\n\n function setMessage(message) {\n stage.innerHTML = '<div class=\"message\">' + esc(message) + '</div>';\n }\n\n function renderFrame(src) {\n const frame = document.createElement(\"iframe\");\n frame.title = body.dataset.iframeTitle || \"Agent Native app\";\n frame.src = src;\n frame.allow = \"clipboard-read; clipboard-write\";\n stage.replaceChildren(frame);\n }\n\n async function launchEmbed() {\n if (!openUrl) {\n setMessage(\"Open link was not available.\");\n return;\n }\n if (!wantsEmbed()) {\n setMessage(\"Ready to open.\");\n return;\n }\n if (startedFor === openUrl) return;\n startedFor = openUrl;\n setMessage(\"Loading app\");\n try {\n const result = await app.callServerTool({\n name: startTool,\n arguments: {\n url: openUrl,\n chrome: typeof toolInput.chrome === \"string\" ? toolInput.chrome : \"full\"\n }\n });\n const data = parseToolResult(result);\n if (!data.startUrl) {\n startedFor = \"\";\n setMessage(data.error || \"This app can be opened, but not embedded from this MCP server.\");\n return;\n }\n renderFrame(data.startUrl);\n } catch (err) {\n startedFor = \"\";\n setMessage(err && err.message ? err.message : \"Could not launch embedded app.\");\n }\n }\n\n function updateOpenButton() {\n openButton.disabled = !openUrl;\n openButton.onclick = () => {\n if (openUrl) void app.openLink({ url: openUrl });\n };\n }\n\n function updateTitle(data) {\n const label = data.label || data.app || data.view || body.dataset.title || \"App\";\n titleEl.textContent = String(label);\n }\n\n app.ontoolinput = (params) => {\n toolInput = params.arguments || {};\n };\n app.ontoolresult = (params) => {\n const data = parseToolResult(params);\n openUrl = openLinkFrom(params, data);\n updateTitle(data);\n updateOpenButton();\n void launchEmbed();\n };\n await app.connect();\n </script>\n</body>\n</html>`,\n csp: {\n connectDomains: [\"https://esm.sh\"],\n resourceDomains: [\"https://esm.sh\"],\n frameDomains: [\n MCP_APP_REQUEST_ORIGIN_CSP_SOURCE,\n ...(options.frameDomains ?? []),\n ],\n },\n prefersBorder: false,\n };\n}\n"]}
|
package/docs/content/actions.md
CHANGED
|
@@ -154,9 +154,26 @@ If your app is an [A2A](/docs/a2a-protocol) peer, other agent-native apps discov
|
|
|
154
154
|
|
|
155
155
|
With MCP enabled, your actions show up in the framework's MCP server at `/_agent-native/mcp`. Any MCP client — Claude, ChatGPT custom MCP apps, Claude Desktop/Code, Cursor, Codex, etc. — can connect and see them as tools. See [MCP Protocol](/docs/mcp-protocol).
|
|
156
156
|
|
|
157
|
-
For UI-capable MCP hosts, actions can also attach an optional MCP Apps resource
|
|
157
|
+
For UI-capable MCP hosts, actions can also attach an optional MCP Apps resource.
|
|
158
|
+
Use the shared full-app embed helper when the action needs an inline experience.
|
|
159
|
+
MCP Apps should embed the real React route; do not hand-write a separate plain
|
|
160
|
+
HTML product UI.
|
|
161
|
+
|
|
162
|
+
The pattern is the same focused link we already return for external agents:
|
|
163
|
+
the action exposes the operation, `link` points at the route with the right URL
|
|
164
|
+
or deep-link params, and `embedApp()` uses that same target as the inline app.
|
|
165
|
+
This works for draft emails, filtered inboxes, calendar event drafts, full
|
|
166
|
+
dashboards, saved analyses, extension routes, decks, design editors, and any
|
|
167
|
+
other state the app can load from a route.
|
|
168
|
+
|
|
169
|
+
When a whole app surface is too much, embed a narrow route that renders a real
|
|
170
|
+
shared React component instead. For example, Analytics can render `/chart` with
|
|
171
|
+
a compact `SqlPanel` URL payload so the MCP host shows one live chart while the
|
|
172
|
+
implementation still reuses the dashboard chart component.
|
|
158
173
|
|
|
159
174
|
```ts
|
|
175
|
+
import { embedApp } from "@agent-native/core";
|
|
176
|
+
|
|
160
177
|
export default defineAction({
|
|
161
178
|
description: "Create an email draft for review.",
|
|
162
179
|
schema: z.object({ body: z.string() }),
|
|
@@ -166,31 +183,14 @@ export default defineAction({
|
|
|
166
183
|
url: "/_agent-native/open?app=mail&view=inbox",
|
|
167
184
|
}),
|
|
168
185
|
mcpApp: {
|
|
169
|
-
resource: {
|
|
170
|
-
title: "Review draft",
|
|
171
|
-
html: '<!doctype html><html><body><main id="app"></main></body></html>',
|
|
172
|
-
csp: { connectDomains: ["https://mail.agent-native.com"] },
|
|
173
|
-
},
|
|
186
|
+
resource: embedApp({ title: "Review draft", openLabel: "Open in Mail" }),
|
|
174
187
|
},
|
|
175
188
|
});
|
|
176
189
|
```
|
|
177
190
|
|
|
178
191
|
This advertises the MCP Apps extension (`io.modelcontextprotocol/ui`), exposes the HTML via MCP resources, and includes both current and legacy UI resource metadata for compatible hosts. Keep `link` as the fallback for CLI and non-UI MCP clients; see [External Agents](/docs/external-agents#mcp-apps).
|
|
179
192
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
```ts
|
|
183
|
-
import { embedApp } from "@agent-native/core/mcp";
|
|
184
|
-
|
|
185
|
-
export default defineAction({
|
|
186
|
-
// ...description, schema, run, link...
|
|
187
|
-
mcpApp: {
|
|
188
|
-
resource: embedApp({ title: "Open dashboard" }),
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
The helper launches the action's `link` target through `/_agent-native/embed/start` with a short-lived browser session, so routes such as dashboards, filtered inboxes, drafts, and extension pages can reuse the app's React components directly.
|
|
193
|
+
The helper launches the action's `link` target through `/_agent-native/embed/start` with a short-lived browser session, so routes such as full dashboards, filtered inboxes, drafts, and extension pages can reuse the app's React components directly.
|
|
194
194
|
|
|
195
195
|
## Standard actions {#standard-actions}
|
|
196
196
|
|
|
@@ -102,7 +102,7 @@ Use Agent-Native Analytics to generate a weekly conversion-rate bar chart and sh
|
|
|
102
102
|
Use Agent-Native Mail to draft a short follow-up email to me, but do not send it.
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
In hosts that support MCP Apps, Analytics can render
|
|
105
|
+
In hosts that support MCP Apps, Analytics can render real dashboard and analysis routes inline, and Mail can render the real compose UI inline for draft review. In hosts that do not render MCP Apps, the same tool call still returns a deep link such as **Open draft in Mail →** or **Open dashboard in Analytics →**.
|
|
106
106
|
|
|
107
107
|
## Advanced setup: local agents {#connect}
|
|
108
108
|
|
|
@@ -279,31 +279,36 @@ List/search actions point at a record-focused view the same way — e.g. calenda
|
|
|
279
279
|
|
|
280
280
|
## Authoring: optional MCP Apps UI {#mcp-apps}
|
|
281
281
|
|
|
282
|
-
For hosts that support the MCP Apps extension, an action can also advertise an inline
|
|
282
|
+
For hosts that support the MCP Apps extension, an action can also advertise an inline UI resource with `mcpApp`. This is a progressive enhancement for flows where the external agent should hand the user an interactive surface instead of only text — for example reviewing an email draft, editing a calendar invite, or choosing between generated dashboard variants.
|
|
283
|
+
|
|
284
|
+
Use the real React app with `embedApp()` whenever the user needs UI. The mental model is simple: the action's `link` target is also the MCP App embed target. Expose the operation as a normal action/tool, return a focused deep link with `link`, and add `mcpApp.resource = embedApp(...)` so capable hosts load that same route inline instead of opening a new tab.
|
|
285
|
+
|
|
286
|
+
That means full-app embeds can do anything the route can do once opened: review or edit an email draft, show a filtered inbox/search, open a calendar event or event draft, load an extension page, inspect a full analytics dashboard or saved analysis, continue a deck in the Slides editor, or open a Design project/editor. Prefer URL/deep-link params and the existing `/_agent-native/open` navigation/app-state bridge over inventing a second state protocol for MCP Apps.
|
|
287
|
+
|
|
288
|
+
On rare occasions the right target is a focused app route that renders one shared React component instead of the whole app shell. Analytics' `/chart` route is the model: it takes a compact `SqlPanel` payload in the URL and renders the same chart component the dashboard uses. This is still an app embed, not a plain HTML MCP App. Expose or call it through a normal action / `open_app({ path, embed: true })`, keep the URL deterministic, and let `embedApp()` render that route inline.
|
|
289
|
+
|
|
290
|
+
Do not hand-write one-off plain HTML MCP Apps for product UI; if the action needs a custom surface, add or reuse a real app route/component first and embed that route.
|
|
283
291
|
|
|
284
292
|
```ts
|
|
293
|
+
import { embedApp } from "@agent-native/core";
|
|
294
|
+
|
|
285
295
|
export default defineAction({
|
|
286
296
|
// ...description, schema, run, link...
|
|
287
297
|
mcpApp: {
|
|
288
|
-
resource: {
|
|
298
|
+
resource: embedApp({
|
|
289
299
|
title: "Review draft",
|
|
290
|
-
description: "
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
csp: { connectDomains: ["https://mail.agent-native.com"] },
|
|
296
|
-
prefersBorder: true,
|
|
297
|
-
},
|
|
300
|
+
description: "Open the generated draft in the real Mail compose UI.",
|
|
301
|
+
iframeTitle: "Agent-Native Mail",
|
|
302
|
+
openLabel: "Open in Mail",
|
|
303
|
+
frameDomains: ["https:", "http://localhost:*", "http://127.0.0.1:*"],
|
|
304
|
+
}),
|
|
298
305
|
},
|
|
299
306
|
});
|
|
300
307
|
```
|
|
301
308
|
|
|
302
309
|
The MCP server advertises extension `io.modelcontextprotocol/ui`, adds `_meta.ui.resourceUri` plus `_meta["ui/resourceUri"]` to `tools/list`, and exposes the HTML through `resources/list` + `resources/read` using MIME `text/html;profile=mcp-app`. The stdio proxy forwards those resource handlers from the live app, so desktop and CLI clients see the same resources as HTTP clients.
|
|
303
310
|
|
|
304
|
-
Keep the existing `link` builder even when adding `mcpApp`. CLI-only clients, older hosts, and any host that does not render MCP Apps will ignore the UI metadata and still need the `"Open in … →"` link.
|
|
305
|
-
|
|
306
|
-
For heavyweight authenticated workflows, reuse the real React app instead of rebuilding a plain-HTML mini UI. Core exports `embedApp()` from `@agent-native/core/mcp` and `@agent-native/core`; attach it to an action that already has a `link` builder. The embedded MCP App calls the app-only `create_embed_session` helper, exchanges a one-time SQL ticket at `/_agent-native/embed/start`, and loads the target route in an iframe with a short-lived browser session plus a bearer fallback for same-origin fetches. `open_app({ app, path, embed: true })` is the generic escape hatch for routes such as dashboards, filtered inboxes, calendar draft views, and extension pages.
|
|
311
|
+
Keep the existing `link` builder even when adding `mcpApp`. CLI-only clients, older hosts, and any host that does not render MCP Apps will ignore the UI metadata and still need the `"Open in … →"` link. `embedApp()` uses that link as its launch target, calls the app-only `create_embed_session` helper, exchanges a one-time SQL ticket at `/_agent-native/embed/start`, and loads the target route in an iframe with a short-lived browser session plus a bearer fallback for same-origin fetches. `open_app({ app, path, embed: true })` is the generic escape hatch for routes such as full dashboards, filtered inboxes, calendar draft views, analyses, and extension pages, and should be used liberally when the full app is the clearest review/edit surface.
|
|
307
312
|
|
|
308
313
|
### The `link` contract {#link-contract}
|
|
309
314
|
|
|
@@ -72,7 +72,7 @@ POST https://your-app.example.com/_agent-native/mcp
|
|
|
72
72
|
|
|
73
73
|
The server supports the standard MCP handshake: `initialize` → `initialized` → `tools/list` → `tools/call`.
|
|
74
74
|
|
|
75
|
-
If an action declares `mcpApp`, the server also advertises the official MCP Apps extension (`io.modelcontextprotocol/ui`) and supports `resources/list`, `resources/templates/list`, and `resources/read` for the app
|
|
75
|
+
If an action declares `mcpApp`, the server also advertises the official MCP Apps extension (`io.modelcontextprotocol/ui`) and supports `resources/list`, `resources/templates/list`, and `resources/read` for the app resource. Hosts that render MCP Apps can show the UI inline; hosts that do not can still call the tool and use the deep-link fallback. Product UIs should use `embedApp()` so the inline surface is the real React app route, or a focused route that renders a shared React component such as an Analytics chart, not a separate plain HTML implementation. The current official extension matrix includes Claude, Claude Desktop, VS Code GitHub Copilot, Goose, Postman, MCPJam, ChatGPT, and Cursor; host support varies by version and plan, so use the [External Agents MCP Apps notes](/docs/external-agents#mcp-apps-compatibility) for the user-facing guidance.
|
|
76
76
|
|
|
77
77
|
## Tools {#tools}
|
|
78
78
|
|