@layers/amba-mcp 1.0.0 → 4.0.2

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/README.md CHANGED
@@ -1,29 +1,24 @@
1
1
  # @layers/amba-mcp
2
2
 
3
- Reusable Model Context Protocol (MCP) tool registry for [Amba](https://amba.dev) — the agent-native backend-as-a-service for mobile apps.
3
+ Amba is the agent-native backend-as-a-service for mobile and web apps. This package is the Model Context Protocol (MCP) tool registry that lets an AI agent drive the Amba admin API directly.
4
4
 
5
- This package exposes ~178 MCP tools across ~17 groups (projects, push, segments, config, content, users, achievements, challenges, economy, leaderboards, platform, social, xp, events, auth, and more) that an AI agent can call against the Amba admin API.
6
-
7
- It is the same registry consumed by the hosted MCP server at `mcp.amba.dev`.
5
+ It exposes ~178 tools across ~17 groups (projects, push, segments, config, content, users, achievements, challenges, economy, leaderboards, platform, social, xp, events, auth, …) and is the same registry that powers the hosted MCP server at `mcp.amba.dev`.
8
6
 
9
7
  ## Install
10
8
 
11
9
  ```bash
12
- npm install @layers/amba-mcp
10
+ npm install @layers/amba-mcp@1.0.1
13
11
  ```
14
12
 
15
- ## Usage
13
+ ## Configure + first call
16
14
 
17
- `@layers/amba-mcp` is a tool registry. It registers tools against an injected `McpServer` and `ApiClient`. It does NOT bootstrap a transport — your code does.
15
+ This package is a tool registry, not a transport. You mount it into your own MCP server:
18
16
 
19
17
  ```ts
20
18
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
21
19
  import { registerAllTools, createApiClient } from '@layers/amba-mcp';
22
20
 
23
- const server = new McpServer({
24
- name: 'amba-mcp',
25
- version: '0.1.0',
26
- });
21
+ const server = new McpServer({ name: 'amba-mcp', version: '1.0.0' });
27
22
 
28
23
  const apiClient = createApiClient({
29
24
  baseUrl: 'https://api.amba.dev/v1/admin',
@@ -31,19 +26,22 @@ const apiClient = createApiClient({
31
26
  });
32
27
 
33
28
  registerAllTools(server, apiClient);
34
-
35
- // Mount `server` behind any MCP transport (stdio, Streamable HTTP, SSE, ...).
29
+ // Then mount `server` behind any MCP transport (stdio, Streamable HTTP, SSE).
36
30
  ```
37
31
 
38
- ### Authenticating
39
-
40
- Every tool except the public auth tools (`amba_developer_signup`, `_login`, `_refresh`) requires a developer Bearer token. Pass it explicitly via `createApiClient({ token })`, or omit `token` to fall back to the CLI credential file at `~/.amba/credentials.json`.
32
+ ### Bootstrap with no browser
41
33
 
42
- For agent flows the recommended bootstrap is:
34
+ Every tool except the public auth tools (`amba_developer_signup`, `amba_developer_login`, `amba_developer_refresh`) requires a developer Bearer token.
43
35
 
44
- 1. Call `amba_developer_signup` with no Authorization header to create an account. The response includes a long-lived Personal Access Token (`pat`) and a freshly provisioned project.
36
+ 1. Call `amba_developer_signup` with no Authorization header — the response includes a long-lived Personal Access Token (`pat`) and a freshly provisioned project.
45
37
  2. Pass the `pat` as the inbound Bearer on every subsequent MCP call.
46
- 3. Poll `amba_get_provisioning_status` until the project flips to `status='active'` (~10s) before issuing client-plane traffic.
38
+ 3. Poll `amba_get_provisioning_status` until the project flips to `status: "active"` before issuing client traffic.
39
+
40
+ Omit `token` on `createApiClient` to fall back to the CLI credential file at `~/.amba/credentials.json`.
41
+
42
+ ## Docs
43
+
44
+ Tool reference: <https://docs.amba.dev/mcp>.
47
45
 
48
46
  ## License
49
47
 
@@ -1,3 +1,27 @@
1
+ /**
2
+ * Structured error thrown by `ApiClient.request` (and by the dev-tooling
3
+ * `callWithPat` rawFetch path) on any non-2xx response. Preserves the
4
+ * upstream `error.code` + HTTP `status` so callers can do code-based
5
+ * branching (e.g. `if (err.code === 'ALREADY_EXISTS')`) instead of
6
+ * regex-matching the prose of the thrown message.
7
+ *
8
+ * Backward-compat: the `message` string still follows the same
9
+ * `API error ${status}: ${message}` shape that the prior plain-Error
10
+ * throw used, so any caller that grepped the message keeps working.
11
+ *
12
+ * Lives in api-client.ts (not tools/_pat.ts) so both the bound-ApiClient
13
+ * delegate path AND the rawFetch path throw the same instanceof-able
14
+ * type — without this, BugBot 2026-05-16 caught that my catch blocks
15
+ * (`err instanceof AmbaApiError`) on `amba_sites_deploy`,
16
+ * `amba_sites_remove_domain`, and `amba_functions_delete` were silently
17
+ * skipped on the no-pat (hosted-MCP-primary) path because that path
18
+ * threw plain Error.
19
+ */
20
+ export declare class AmbaApiError extends Error {
21
+ readonly status: number;
22
+ readonly code: string | undefined;
23
+ constructor(status: number, code: string | undefined, message: string);
24
+ }
1
25
  export interface ApiClientOptions {
2
26
  baseUrl?: string;
3
27
  /**
@@ -16,6 +40,20 @@ export declare class ApiClient {
16
40
  private apiRoot;
17
41
  private tokenProvider?;
18
42
  constructor(options?: ApiClientOptions);
43
+ /**
44
+ * Return a sibling `ApiClient` bound to a different Bearer token.
45
+ *
46
+ * Used by the `pat`-as-tool-argument pattern (`packages/mcp/src/lib/with-pat.ts`):
47
+ * an agent that just minted a PAT via `amba_developer_signup` cannot
48
+ * mutate the static HTTP `Authorization` header its MCP client sends
49
+ * with each request, so every tool accepts a `pat` argument and the
50
+ * `registerTool` helper calls `withToken(pat)` to override the inbound
51
+ * Bearer for that one tool invocation.
52
+ *
53
+ * The new client shares the same `baseUrl` / `apiRoot` so downstream
54
+ * routing stays identical — only the token provider differs.
55
+ */
56
+ withToken(token: string): ApiClient;
19
57
  /**
20
58
  * Returns the configured admin-prefixed base URL (e.g.
21
59
  * `https://api.amba.dev/admin`). Auth tools (`amba_developer_signup`,
@@ -43,10 +81,10 @@ export declare class ApiClient {
43
81
  private getToken;
44
82
  private request;
45
83
  get<T>(path: string, query?: Record<string, string>): Promise<T>;
46
- post<T>(path: string, body?: unknown): Promise<T>;
47
- put<T>(path: string, body?: unknown): Promise<T>;
48
- patch<T>(path: string, body?: unknown): Promise<T>;
49
- delete<T>(path: string): Promise<T>;
84
+ post<T>(path: string, body?: unknown, query?: Record<string, string>): Promise<T>;
85
+ put<T>(path: string, body?: unknown, query?: Record<string, string>): Promise<T>;
86
+ patch<T>(path: string, body?: unknown, query?: Record<string, string>): Promise<T>;
87
+ delete<T>(path: string, query?: Record<string, string>): Promise<T>;
50
88
  /**
51
89
  * GET that returns the raw response body as a string and only reads up to
52
90
  * `maxBytes` bytes. Used by export tools that hit CSV/NDJSON streaming
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Canonical 7-category taxonomy for Amba MCP tools.
3
+ *
4
+ * Mirrors the marketing-site taxonomy
5
+ * (`apps/marketing-site/app/components/feature-grid.tsx`) and the docs IA
6
+ * (`apps/docs/content/docs/meta.json`). Keep them in lock-step; the
7
+ * council audit at `.council-reports/skill-06-positioning.md` is the
8
+ * canonical reference and documents why the count is 7, not 9 or 19.
9
+ *
10
+ * The MCP protocol itself has no native "category" field — `ToolAnnotations`
11
+ * is a closed set (title, readOnlyHint, destructiveHint, idempotentHint,
12
+ * openWorldHint). So this module exposes the category metadata as a
13
+ * separate, type-safe API for surfaces that consume the registry
14
+ * (mcp-server resource pages, console tool browsers, MCP-tools docs).
15
+ *
16
+ * Lookup is by tool name. Both the canonical name and any legacy alias
17
+ * registered in `tools/__test-fixtures__/rename-map.ts` resolve to the
18
+ * same category so callers don't need to canonicalize first.
19
+ */
20
+ /** The 7 canonical Amba categories. */
21
+ export type AmbaCategory = 'identity' | 'engagement' | 'gamification' | 'economy' | 'social' | 'analytics' | 'infrastructure';
22
+ /** Display-friendly metadata for each category. */
23
+ export declare const CATEGORY_META: Record<AmbaCategory, {
24
+ readonly title: string;
25
+ readonly blurb: string;
26
+ readonly order: number;
27
+ }>;
28
+ /** Display order for callers that need it. */
29
+ export declare const CATEGORY_ORDER: ReadonlyArray<AmbaCategory>;
30
+ /**
31
+ * Exhaustive tool-name → category map. Includes BOTH the canonical
32
+ * `amba_<resource>_<verb>` names AND the legacy aliases listed in
33
+ * `tools/__test-fixtures__/rename-map.ts`. Lookup via `getToolCategory`
34
+ * is therefore alias-agnostic.
35
+ *
36
+ * Edits land here when a new MCP tool is registered. The
37
+ * `categories.test.ts` companion asserts every registered tool name has
38
+ * a mapping — drift surfaces at test time, not in production.
39
+ */
40
+ export declare const TOOL_CATEGORY: Readonly<Record<string, AmbaCategory>>;
41
+ /**
42
+ * Look up the canonical category for an MCP tool name. Accepts both
43
+ * canonical names and legacy aliases. Returns `null` for unknown names —
44
+ * the test suite asserts every registered tool has a mapping, so a
45
+ * `null` at runtime indicates a registration that drifted ahead of
46
+ * the taxonomy.
47
+ */
48
+ export declare function getToolCategory(toolName: string): AmbaCategory | null;