@layers/amba-mcp 4.0.10 → 4.0.11

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.
@@ -34,11 +34,19 @@ export interface ApiClientOptions {
34
34
  * tokens transparently. Sync values should be wrapped in `() => Promise.resolve(token)`.
35
35
  */
36
36
  getToken?: () => Promise<string>;
37
+ /**
38
+ * Signup token forwarded on `/auth/developer/signup` as
39
+ * `X-Amba-Signup-Token`. The hosted MCP server copies it from the inbound
40
+ * request header of the same name so Amba's CI can sign up through MCP
41
+ * while public signup is closed. Unset for every other caller.
42
+ */
43
+ signupToken?: string;
37
44
  }
38
45
  export declare class ApiClient {
39
46
  private baseUrl;
40
47
  private apiRoot;
41
48
  private tokenProvider?;
49
+ private signupToken?;
42
50
  constructor(options?: ApiClientOptions);
43
51
  /**
44
52
  * Return a sibling `ApiClient` bound to a different Bearer token.
@@ -54,6 +62,8 @@ export declare class ApiClient {
54
62
  * routing stays identical — only the token provider differs.
55
63
  */
56
64
  withToken(token: string): ApiClient;
65
+ /** The signup token to forward on `/auth/developer/signup`, if any. */
66
+ getSignupToken(): string | undefined;
57
67
  /**
58
68
  * Returns the configured admin-prefixed base URL (e.g.
59
69
  * `https://api.amba.dev/admin`). Auth tools (`amba_developer_signup`,
package/dist/index.d.ts CHANGED
@@ -38,6 +38,7 @@ export declare function registerAllTools(server: McpServer, apiClient: ApiClient
38
38
  export declare function createApiClient(options: {
39
39
  baseUrl?: string;
40
40
  token?: string;
41
+ signupToken?: string;
41
42
  }): ApiClient;
42
43
  export { ApiClient } from './api-client.js';
43
44
  export type { ApiClientOptions } from './api-client.js';
package/dist/index.js CHANGED
@@ -60,12 +60,15 @@ var ApiClient = class ApiClient {
60
60
  baseUrl;
61
61
  apiRoot;
62
62
  tokenProvider;
63
+ signupToken;
63
64
  constructor(options) {
64
65
  const raw = (options?.baseUrl ?? BASE_URL).replace(/\/+$/, "");
65
66
  if (!/\/admin$/.test(raw)) throw new Error(`ApiClient baseUrl must end in /admin (got ${JSON.stringify(raw)}). Set AMBA_API_URL=https://api.amba.dev/v1/admin (or your equivalent versioned host).`);
66
67
  this.baseUrl = raw;
67
68
  this.apiRoot = raw.replace(/\/admin$/, "");
68
69
  this.tokenProvider = options?.getToken;
70
+ const signupToken = options?.signupToken?.trim();
71
+ if (signupToken) this.signupToken = signupToken;
69
72
  }
70
73
  /**
71
74
  * Return a sibling `ApiClient` bound to a different Bearer token.
@@ -81,10 +84,16 @@ var ApiClient = class ApiClient {
81
84
  * routing stays identical — only the token provider differs.
82
85
  */
83
86
  withToken(token) {
84
- return new ApiClient({
87
+ const opts = {
85
88
  baseUrl: this.baseUrl,
86
89
  getToken: async () => token
87
- });
90
+ };
91
+ if (this.signupToken !== void 0) opts.signupToken = this.signupToken;
92
+ return new ApiClient(opts);
93
+ }
94
+ /** The signup token to forward on `/auth/developer/signup`, if any. */
95
+ getSignupToken() {
96
+ return this.signupToken;
88
97
  }
89
98
  /**
90
99
  * Returns the configured admin-prefixed base URL (e.g.
@@ -4562,6 +4571,7 @@ async function authFetch(apiClient, options) {
4562
4571
  const headers = { Accept: "application/json" };
4563
4572
  if (options.body !== void 0) headers["Content-Type"] = "application/json";
4564
4573
  if (options.bearer) headers["Authorization"] = `Bearer ${options.bearer}`;
4574
+ if (options.signupToken) headers["X-Amba-Signup-Token"] = options.signupToken;
4565
4575
  const res = await fetch(url, {
4566
4576
  method: options.method,
4567
4577
  headers,
@@ -4705,10 +4715,12 @@ function registerTools$20(server, apiClient) {
4705
4715
  };
4706
4716
  if (name !== void 0) body.name = name;
4707
4717
  if (referral_code !== void 0) body.referral_code = referral_code;
4718
+ const signupToken = apiClient.getSignupToken();
4708
4719
  return enrichedAuthResult(await authFetch(apiClient, {
4709
4720
  method: "POST",
4710
4721
  path: "/auth/developer/signup",
4711
- body
4722
+ body,
4723
+ ...signupToken ? { signupToken } : {}
4712
4724
  }), SIGNUP_AGENT_INSTRUCTIONS);
4713
4725
  });
4714
4726
  registerPublicTool(server, "amba_affiliate_signup", [
@@ -4730,10 +4742,12 @@ function registerTools$20(server, apiClient) {
4730
4742
  password
4731
4743
  };
4732
4744
  if (name !== void 0) body.name = name;
4745
+ const signupToken = apiClient.getSignupToken();
4733
4746
  return enrichedAuthResult(await authFetch(apiClient, {
4734
4747
  method: "POST",
4735
4748
  path: "/auth/developer/signup",
4736
- body
4749
+ body,
4750
+ ...signupToken ? { signupToken } : {}
4737
4751
  }), SIGNUP_AGENT_INSTRUCTIONS);
4738
4752
  });
4739
4753
  registerPublicTool(server, "amba_developer_login", [
@@ -5946,6 +5960,7 @@ function registerTools$17(server, apiClient) {
5946
5960
  "Deploy a static site to an Amba project. Creates the site if it does not yet exist, then uploads the supplied files as a new deployment.",
5947
5961
  "The deployment is immutable — its files live forever under the site's storage prefix — and the site flips to serve the new deployment atomically. Older deployments are kept for rollback via `amba_sites_list`.",
5948
5962
  "Site name must match /^[a-z][a-z0-9_-]{0,49}$/. Per-file cap: 25 MiB. The site's public URL is `https://{slug}.app.amba.host` where `slug` is `{first 8 chars of project_id}-{name}`.",
5963
+ "Routing follows common static-host conventions, so directory-style exports work as-is: `/a/` serves `a/index.html`; `/a` serves the exact file, then `a.html`, then 308-redirects to `/a/` when only `a/index.html` exists. Include a top-level `404.html` to answer unknown paths with status 404; without one, extensionless paths fall back to `index.html` (single-page-app mode).",
5949
5964
  "Returns the deployment record + public URL + file/byte counts."
5950
5965
  ].join(" "), {
5951
5966
  project_id: z.string().describe("The Amba project ID."),
@@ -6197,11 +6212,12 @@ function registerTools$14(server, apiClient) {
6197
6212
  "Writes a new version to the backing secret store and enqueues the sync. Subsequent function invocations see the new value once sync_status flips to \"synced\" (typically <30s).",
6198
6213
  "Secret name must match /^[A-Z][A-Z0-9_]{0,62}$/. Function name (when given) must match /^[a-z][a-z0-9_-]{0,57}$/.",
6199
6214
  "The complete AMBA_ and EDGE_ namespaces, plus the exact names STORAGE and EDGE_DB_PROXY, are platform-managed. MCP rejects them before an API/provider call; the API also returns 400 RESERVED_BINDING.",
6215
+ "Every function already receives AMBA_API_URL, AMBA_PROJECT_ID, AMBA_INTERNAL_TOKEN (project-scoped admin token), and AMBA_AI_GATEWAY_URL in `env`, so never set those. For your own values, use an app prefix: store the project client key as APP_CLIENT_KEY, for example.",
6200
6216
  "Secrets may be set BEFORE deploying the function — the sync drains once a deployment lands, so you can set every secret first and deploy once.",
6201
6217
  "Value cap: 64 KiB. Plaintext is never returned afterwards."
6202
6218
  ].join(" "), {
6203
6219
  project_id: z.string().describe("The Amba project ID."),
6204
- name: SET_SECRET_NAME.describe("Secret name. UPPER_SNAKE_CASE. The AMBA_ and EDGE_ prefixes and exact names STORAGE and EDGE_DB_PROXY are reserved."),
6220
+ name: SET_SECRET_NAME.describe("Secret name. UPPER_SNAKE_CASE. The AMBA_ and EDGE_ prefixes and exact names STORAGE and EDGE_DB_PROXY are reserved; use an app prefix such as APP_ (APP_CLIENT_KEY)."),
6205
6221
  value: z.string().describe("Secret value. Stored encrypted at rest; never returned in plaintext afterwards."),
6206
6222
  function: z.string().optional().describe("Function this secret binds to. OMIT for a project-wide secret (applied to every function in the project).")
6207
6223
  }, async ({ project_id, name, value, function: functionName }, { pat }) => {
@@ -11320,6 +11336,7 @@ function registerAllTools(server, apiClient) {
11320
11336
  function createApiClient(options) {
11321
11337
  const opts = {};
11322
11338
  if (options.baseUrl !== void 0) opts.baseUrl = options.baseUrl;
11339
+ if (options.signupToken !== void 0) opts.signupToken = options.signupToken;
11323
11340
  if (options.token !== void 0) {
11324
11341
  const token = options.token;
11325
11342
  opts.getToken = async () => token;
@@ -17,6 +17,8 @@
17
17
  * The complete AMBA_ and EDGE_ namespaces, plus the exact names STORAGE
18
18
  * and EDGE_DB_PROXY, are platform-reserved. MCP rejects these before an
19
19
  * API/provider call; the API independently enforces the same shared rule.
20
+ * The shared helper's message names the rule, lists the bindings every
21
+ * function already receives, and suggests an `APP_`-prefixed name.
20
22
  *
21
23
  * Plaintext values are NEVER returned. `amba_secrets_list` returns
22
24
  * name + version + sync_status (pending/syncing/synced/failed) only.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@layers/amba-mcp",
3
- "version": "4.0.10",
3
+ "version": "4.0.11",
4
4
  "license": "Apache-2.0",
5
5
  "engines": {
6
6
  "node": ">=22"
@@ -26,7 +26,7 @@
26
26
  "dependencies": {
27
27
  "@modelcontextprotocol/sdk": "^1.12.1",
28
28
  "zod": "^3.25.0",
29
- "@layers/amba-shared": "4.0.5"
29
+ "@layers/amba-shared": "4.0.6"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.10.2",