@layers/amba-mcp 4.0.8 → 4.0.9
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.
|
@@ -51,6 +51,8 @@ export interface CollectionPolicy {
|
|
|
51
51
|
export interface AppMcpClientAuth {
|
|
52
52
|
apiKey: string;
|
|
53
53
|
sessionToken?: string;
|
|
54
|
+
/** Verified by the client API on every request; never trusted locally. */
|
|
55
|
+
groupContext?: string;
|
|
54
56
|
baseUrl: string;
|
|
55
57
|
}
|
|
56
58
|
export interface RegisterCollectionToolsOptions {
|
|
@@ -26,12 +26,14 @@
|
|
|
26
26
|
* named `recipes`.
|
|
27
27
|
*/
|
|
28
28
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
29
|
+
import type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
|
|
29
30
|
import { type AppMcpClientAuth } from './collection-tools.js';
|
|
30
31
|
/** One exposed function from the app-MCP manifest. */
|
|
31
32
|
export interface AppMcpManifestFunction {
|
|
32
33
|
name: string;
|
|
33
34
|
description?: string | null;
|
|
34
35
|
input_schema?: Record<string, unknown> | null;
|
|
36
|
+
annotations?: ToolAnnotations | null;
|
|
35
37
|
public?: boolean;
|
|
36
38
|
invoke_url: string;
|
|
37
39
|
}
|
package/dist/index.js
CHANGED
|
@@ -641,9 +641,9 @@ function registerTool(server, apiClient, name, description, schema, handler, ali
|
|
|
641
641
|
* `amba_developer_login`, `amba_developer_refresh`) — anything else
|
|
642
642
|
* should go through `registerTool`.
|
|
643
643
|
*/
|
|
644
|
-
function registerPublicTool(server, name, description, schema, handler, aliases = []) {
|
|
645
|
-
server.tool(name, description, schema, deriveToolAnnotations(name), handler);
|
|
646
|
-
for (const alias of aliases) server.tool(alias, description, schema, deriveToolAnnotations(alias), (async (args) => {
|
|
644
|
+
function registerPublicTool(server, name, description, schema, handler, aliases = [], annotations) {
|
|
645
|
+
server.tool(name, description, schema, annotations ?? deriveToolAnnotations(name), handler);
|
|
646
|
+
for (const alias of aliases) server.tool(alias, description, schema, annotations ?? deriveToolAnnotations(alias), (async (args) => {
|
|
647
647
|
warnDeprecatedAlias(alias, name);
|
|
648
648
|
return handler(args);
|
|
649
649
|
}));
|
|
@@ -1489,6 +1489,13 @@ function jsonResult$1(payload) {
|
|
|
1489
1489
|
text: JSON.stringify(payload, null, 2)
|
|
1490
1490
|
}] };
|
|
1491
1491
|
}
|
|
1492
|
+
/** Preserve an HTTP response wrapper while mapping failures to MCP isError. */
|
|
1493
|
+
function httpResult(result) {
|
|
1494
|
+
return {
|
|
1495
|
+
...jsonResult$1(result),
|
|
1496
|
+
...result.status >= 400 ? { isError: true } : {}
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1492
1499
|
/**
|
|
1493
1500
|
* Flatten an upstream HTTP response into the agent-facing tool payload.
|
|
1494
1501
|
* Body fields are spread FIRST so a future top-level `status` key in
|
|
@@ -1496,10 +1503,13 @@ function jsonResult$1(payload) {
|
|
|
1496
1503
|
* `parsed.status` to distinguish 2xx from 4xx/5xx.
|
|
1497
1504
|
*/
|
|
1498
1505
|
function passthroughResult(result) {
|
|
1499
|
-
return
|
|
1500
|
-
...
|
|
1501
|
-
|
|
1502
|
-
|
|
1506
|
+
return {
|
|
1507
|
+
...jsonResult$1({
|
|
1508
|
+
...result.body !== null && typeof result.body === "object" ? result.body : {},
|
|
1509
|
+
status: result.status
|
|
1510
|
+
}),
|
|
1511
|
+
...result.status >= 400 ? { isError: true } : {}
|
|
1512
|
+
};
|
|
1503
1513
|
}
|
|
1504
1514
|
//#endregion
|
|
1505
1515
|
//#region src/tools/users.ts
|
|
@@ -5755,14 +5765,17 @@ function registerTools$18(server, apiClient) {
|
|
|
5755
5765
|
"Function name must match /^[a-z][a-z0-9_-]*$/ and be ≤58 chars. Bundle size cap: 10 MiB (enforced client-side too — oversize uploads are rejected before the round-trip).",
|
|
5756
5766
|
"Optional `rate_limit` declares a per-function rate-limit config (validated server-side). Pass null/omit for no rate limit.",
|
|
5757
5767
|
"Optional `public` (default false) deploys the function WITHOUT the X-Api-Key gate, so third-party webhook senders (RevenueCat, Stripe, GitHub, Slack) that cannot attach a custom header can reach it. SECURITY: when public, YOU must verify the webhook signature (HMAC) inside the function body — the runtime no longer requires a caller credential. `public: true` only skips the key requirement; rate-limiting and the per-request signed identity context still apply. Leave it false for functions only your own app calls.",
|
|
5768
|
+
"Optional `forward_authorization` (default false) forwards a verified client Bearer to customer code. X-Api-Key and platform internal-trigger credentials are always stripped. Enable only when the function must validate or proxy the end-user session.",
|
|
5758
5769
|
"Returns the function deployment row + the public URL (`fn_url`: `https://{project_slug}.fn.amba.host/{name}`)."
|
|
5759
5770
|
].join(" "), {
|
|
5760
5771
|
project_id: z.string().describe("The Amba project ID."),
|
|
5761
5772
|
name: z.string().describe("Function name. Lowercase, /^[a-z][a-z0-9_-]*$/, ≤58 chars."),
|
|
5762
5773
|
code: z.string().describe("Bundled JavaScript module source (one entry file)."),
|
|
5763
5774
|
rate_limit: z.unknown().optional().describe("Optional rate-limit config object. Shape: see @layers/amba-shared:RateLimitConfig."),
|
|
5764
|
-
public: z.boolean().optional().describe("Deploy the function as PUBLIC (no X-Api-Key required) so external webhook senders can reach it. Default false. When true, you MUST verify the webhook HMAC signature inside the function body — public skips the credential gate only; rate-limiting and signed identity context still apply.")
|
|
5765
|
-
|
|
5775
|
+
public: z.boolean().optional().describe("Deploy the function as PUBLIC (no X-Api-Key required) so external webhook senders can reach it. Default false. When true, you MUST verify the webhook HMAC signature inside the function body — public skips the credential gate only; rate-limiting and signed identity context still apply."),
|
|
5776
|
+
forward_authorization: z.boolean().optional().describe("Forward a verified client Authorization Bearer to customer code. Default false. X-Api-Key and platform internal credentials are never forwarded."),
|
|
5777
|
+
mcp: z.unknown().optional().describe("Optional app-MCP tool config: {description?, input_schema?, annotations?}. Safety annotations support readOnlyHint, destructiveHint, idempotentHint, and openWorldHint booleans.")
|
|
5778
|
+
}, async ({ project_id, name, code, rate_limit, public: isPublic, forward_authorization: forwardAuthorization, mcp }, { pat }) => {
|
|
5766
5779
|
const byteLen = Buffer.byteLength(code, "utf8");
|
|
5767
5780
|
if (byteLen > MAX_BUNDLE_BYTES) throw new Error(`Bundle size ${byteLen} bytes exceeds ${MAX_BUNDLE_BYTES}-byte cap (10 MiB).`);
|
|
5768
5781
|
const form = new FormData();
|
|
@@ -5770,6 +5783,8 @@ function registerTools$18(server, apiClient) {
|
|
|
5770
5783
|
const metadata = { name };
|
|
5771
5784
|
if (rate_limit !== void 0 && rate_limit !== null) metadata.rate_limit = rate_limit;
|
|
5772
5785
|
if (isPublic === true) metadata.public = true;
|
|
5786
|
+
if (forwardAuthorization === true) metadata.forward_authorization = true;
|
|
5787
|
+
if (mcp !== void 0) metadata.mcp = mcp;
|
|
5773
5788
|
form.append("metadata", new Blob([JSON.stringify(metadata)], { type: "application/json" }), "metadata.json");
|
|
5774
5789
|
return jsonResult(await callWithPat(apiClient, pat, "POST", `/projects/${encodeURIComponent(project_id)}/functions/deploy`, { formData: form }));
|
|
5775
5790
|
}, ["amba_deploy_function"]);
|
|
@@ -5859,6 +5874,9 @@ function registerTools$18(server, apiClient) {
|
|
|
5859
5874
|
deleted: true
|
|
5860
5875
|
});
|
|
5861
5876
|
});
|
|
5877
|
+
registerTool(server, apiClient, "amba_functions_list_schedules", "List function schedules with their cron expression, timezone, pause state, next fire time, and most recent fire time. Rows degrade with enriched=false if one provider describe call fails.", { project_id: z.string().describe("The Amba project ID.") }, async ({ project_id }, { pat }) => {
|
|
5878
|
+
return jsonResult(await callWithPat(apiClient, pat, "GET", `/projects/${encodeURIComponent(project_id)}/functions/schedules`));
|
|
5879
|
+
});
|
|
5862
5880
|
registerTool(server, apiClient, "amba_functions_schedule", [
|
|
5863
5881
|
"Register a cron Schedule for a function. The schedule is keyed deterministically per (project, function) — re-calling with a different cron/timezone replaces the prior schedule rather than creating a duplicate.",
|
|
5864
5882
|
"Cron must be a standard 5- or 6-field whitespace-separated expression. `timezone` defaults to \"UTC\" if omitted. Timezones are IANA strings (e.g. \"America/Los_Angeles\").",
|
|
@@ -10148,6 +10166,7 @@ const TOOL_CATEGORY = {
|
|
|
10148
10166
|
amba_functions_get_logs: "infrastructure",
|
|
10149
10167
|
amba_get_function_logs: "infrastructure",
|
|
10150
10168
|
amba_functions_schedule: "infrastructure",
|
|
10169
|
+
amba_functions_list_schedules: "infrastructure",
|
|
10151
10170
|
amba_schedule_function: "infrastructure",
|
|
10152
10171
|
amba_functions_pause_schedule: "infrastructure",
|
|
10153
10172
|
amba_pause_function_schedule: "infrastructure",
|
|
@@ -10706,6 +10725,7 @@ async function adminFetch(apiClient, bearer, call) {
|
|
|
10706
10725
|
async function clientFetch(clientAuth, call) {
|
|
10707
10726
|
const headers = { "X-Api-Key": clientAuth.apiKey };
|
|
10708
10727
|
if (clientAuth.sessionToken) headers["Authorization"] = `Bearer ${clientAuth.sessionToken}`;
|
|
10728
|
+
if (clientAuth.groupContext) headers["X-Group-Context"] = clientAuth.groupContext;
|
|
10709
10729
|
return proxyFetch(clientAuth.baseUrl, headers, call);
|
|
10710
10730
|
}
|
|
10711
10731
|
/**
|
|
@@ -11067,23 +11087,23 @@ function registerFunctionToolsFor(server, options) {
|
|
|
11067
11087
|
});
|
|
11068
11088
|
if (declaredShape) {
|
|
11069
11089
|
registerPublicTool(server, toolName, description, declaredShape, async (args) => {
|
|
11070
|
-
return
|
|
11090
|
+
return httpResult(await invokeFunction({
|
|
11071
11091
|
invokeUrl: fn.invoke_url,
|
|
11072
11092
|
clientAuth,
|
|
11073
11093
|
body: args
|
|
11074
11094
|
}));
|
|
11075
|
-
});
|
|
11095
|
+
}, [], fn.annotations ?? void 0);
|
|
11076
11096
|
return;
|
|
11077
11097
|
}
|
|
11078
11098
|
registerPublicTool(server, toolName, description, GENERIC_FUNCTION_SHAPE, async (args) => {
|
|
11079
11099
|
const { body, query } = args;
|
|
11080
|
-
return
|
|
11100
|
+
return httpResult(await invokeFunction({
|
|
11081
11101
|
invokeUrl: fn.invoke_url,
|
|
11082
11102
|
clientAuth,
|
|
11083
11103
|
body,
|
|
11084
11104
|
...query ? { query } : {}
|
|
11085
11105
|
}));
|
|
11086
|
-
});
|
|
11106
|
+
}, [], fn.annotations ?? void 0);
|
|
11087
11107
|
}
|
|
11088
11108
|
//#endregion
|
|
11089
11109
|
//#region src/auto/index.ts
|
|
@@ -11222,7 +11242,8 @@ async function registerAutoMcpTools(server, apiClient, options) {
|
|
|
11222
11242
|
fn,
|
|
11223
11243
|
clientAuth: {
|
|
11224
11244
|
apiKey: clientAuth.apiKey,
|
|
11225
|
-
...clientAuth.sessionToken ? { sessionToken: clientAuth.sessionToken } : {}
|
|
11245
|
+
...clientAuth.sessionToken ? { sessionToken: clientAuth.sessionToken } : {},
|
|
11246
|
+
...clientAuth.groupContext ? { groupContext: clientAuth.groupContext } : {}
|
|
11226
11247
|
}
|
|
11227
11248
|
});
|
|
11228
11249
|
return {
|
|
@@ -34,6 +34,17 @@ export declare function jsonResult(payload: unknown): {
|
|
|
34
34
|
text: string;
|
|
35
35
|
}[];
|
|
36
36
|
};
|
|
37
|
+
/** Preserve an HTTP response wrapper while mapping failures to MCP isError. */
|
|
38
|
+
export declare function httpResult(result: {
|
|
39
|
+
status: number;
|
|
40
|
+
body: unknown;
|
|
41
|
+
}): {
|
|
42
|
+
isError?: boolean | undefined;
|
|
43
|
+
content: {
|
|
44
|
+
type: "text";
|
|
45
|
+
text: string;
|
|
46
|
+
}[];
|
|
47
|
+
};
|
|
37
48
|
/**
|
|
38
49
|
* Flatten an upstream HTTP response into the agent-facing tool payload.
|
|
39
50
|
* Body fields are spread FIRST so a future top-level `status` key in
|
|
@@ -44,6 +55,7 @@ export declare function passthroughResult(result: {
|
|
|
44
55
|
status: number;
|
|
45
56
|
body: unknown;
|
|
46
57
|
}): {
|
|
58
|
+
isError?: boolean | undefined;
|
|
47
59
|
content: {
|
|
48
60
|
type: "text";
|
|
49
61
|
text: string;
|
package/dist/lib/with-pat.d.ts
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
* the same call shape without the pat machinery.
|
|
42
42
|
*/
|
|
43
43
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
44
|
+
import type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
|
|
44
45
|
import { z, type ZodRawShape } from 'zod';
|
|
45
46
|
import type { ApiClient } from '../api-client.js';
|
|
46
47
|
/** Wire-shape returned by an MCP tool handler. */
|
|
@@ -49,6 +50,8 @@ export interface ToolResult {
|
|
|
49
50
|
type: 'text';
|
|
50
51
|
text: string;
|
|
51
52
|
}>;
|
|
53
|
+
/** MCP-native failure signal. Tool transports still return HTTP 200. */
|
|
54
|
+
isError?: boolean;
|
|
52
55
|
}
|
|
53
56
|
/** Context passed to handlers registered via `registerTool`. */
|
|
54
57
|
export interface WithPatHandlerContext {
|
|
@@ -122,4 +125,6 @@ export declare function registerPublicTool<S extends ZodRawShape>(server: McpSer
|
|
|
122
125
|
* warning per alias per process. No active auth-tool rename uses this
|
|
123
126
|
* yet, but the parameter exists so future renames stay consistent.
|
|
124
127
|
*/
|
|
125
|
-
aliases?: readonly string[]
|
|
128
|
+
aliases?: readonly string[],
|
|
129
|
+
/** Explicit app-declared safety hints; absent keeps conservative derivation. */
|
|
130
|
+
annotations?: ToolAnnotations): void;
|