appilot-mcp 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "app-configurator",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Set up, configure, audit, repair, back up, restore, and verify an Appilot app: provision the app, its domains and widget key, scaffold the host integration, and keep the content model correct. Uses the Appilot MCP server and the app-configurator skill.",
5
5
  "author": {
6
6
  "name": "Appilot",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "app-configurator",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Set up, configure, audit, repair, back up, restore, and verify an Appilot app: provision the app, its domains and widget key, scaffold the host integration, and keep the content model correct. Uses the Appilot MCP server and the app-configurator skill.",
5
5
  "author": {
6
6
  "name": "Appilot",
package/README.md CHANGED
@@ -1,11 +1,21 @@
1
1
  # appilot-mcp
2
2
 
3
- MCP server that lets an AI agent **read, validate, fix, and soak** an Appilot
4
- app's content-model configuration (Views, Controls, Forms, Action Plans,
5
- Knowledge, Zones, Tools) against the **config health contract**.
3
+ Two MCP servers ship from this package, and they do opposite jobs.
6
4
 
7
- It is the tool surface behind the `app-configurator` skill. The skill is the
8
- instructions; this server is what actually touches your instance.
5
+ **Appilot Studio** lets an AI agent **read, validate, fix, and soak** an Appilot
6
+ app's content-model configuration (Views, Controls, Forms, Action Plans,
7
+ Knowledge, Zones, Tools) against the **config health contract**. It is the tool
8
+ surface behind the `app-configurator` skill: the skill is the instructions, and
9
+ this server is what actually touches your instance. It is what a bare
10
+ `appilot-mcp` starts.
11
+
12
+ **Appilot**, the runtime connector, lets the person who USES a configured app
13
+ operate it from the assistant they already pay for. It reads the page they are
14
+ sharing, answers from the app's curated knowledge, and runs the app's own guided
15
+ procedures in their browser under their own session. It writes no configuration.
16
+ Start it with `appilot-mcp --runtime`, or connect to `/mcp/runtime` on the
17
+ deployed service. See
18
+ [the connector spec](../../../docs/architecture/appilot-runtime-connector.md).
9
19
 
10
20
  ## Why
11
21
 
@@ -21,10 +31,10 @@ Endpoint-agnostic by design. The same binary talks to a cloud tenant or an
21
31
  on-premise / sovereign instance purely by pointing `APPILOT_BASE_URL` at it. The
22
32
  static gate runs locally from `appilot-shared`, so it works with no network.
23
33
 
24
- ## Two transports, one tool surface
34
+ ## Two transports
25
35
 
26
- The same tools serve two shapes, and which one you need is decided by the client,
27
- not by preference.
36
+ Each server serves two shapes, and which one you need is decided by the client,
37
+ not by preference. A tool is registered once per server and reachable over both.
28
38
 
29
39
  | Transport | Who launches it | Credential | Clients |
30
40
  |-----------|-----------------|------------|---------|
@@ -44,6 +54,8 @@ OAuth. That is what HTTP mode is for. See
44
54
  | `APPILOT_PAT` | for writes / server echo | A scoped service token (`appilot_pat_…`), minted in the Backoffice (Service tokens). `config:read` to read/validate, `config:write` to apply. |
45
55
  | `APPILOT_APP_ID` | optional | Default app id for tools that omit one |
46
56
  | `APPILOT_SOAK_STORAGE_STATE` | optional | Path to a Playwright `storageState` JSON for an authenticated site session (soak) |
57
+ | `APPILOT_SESSION_TOKEN` | for `--runtime` | An Appilot user session. The connector authenticates as the person, so this is the only credential it reads. |
58
+ | `APPILOT_MCP_SERVER` | optional | `runtime` starts the Appilot connector instead of Studio. Same as `--runtime`. |
47
59
 
48
60
  HTTP mode reads a different profile. It holds no Appilot credential of its own,
49
61
  because each caller brings theirs.
@@ -59,7 +71,7 @@ because each caller brings theirs.
59
71
  | `APPILOT_MCP_BACKOFFICE_URL` | no | The Backoffice origin consent screens link to, and the only origin account approval is accepted from. Must be HTTPS (localhost excepted). Defaults to `https://backoffice.appilot.space` when the instance is the Appilot cloud. |
60
72
  | `APPILOT_MCP_HANDOFF_SECRET` | no | Enables account approval instead of pasting a service token. At least 32 characters, and it must match the backend's. Separate from the OAuth secret, and it requires `APPILOT_MCP_BACKOFFICE_URL`. |
61
73
 
62
- ## Tools
74
+ ## Studio tools
63
75
 
64
76
  Twenty-five, in the order the server registers them. `test/toolSurface.test.ts`
65
77
  holds this table, `mcpb/manifest.json` and the registered tools to one list.
@@ -87,6 +99,40 @@ holds this table, `mcpb/manifest.json` and the registered tools to one list.
87
99
  | `scaffold_agent_first` | The artifacts one capability needs to be operable by the agent |
88
100
  | `report_feedback` / `list_feedback` | Report a gap or a defect in Appilot, and see what this organization has already raised |
89
101
 
102
+ ## Appilot connector tools
103
+
104
+ Eight, and deliberately no more: a model reads the whole list on every call.
105
+ They are named in the vocabulary of the person using the app rather than in
106
+ ours. `test/toolSurface.test.ts` holds this table to the registered surface.
107
+
108
+ | Tool | Purpose |
109
+ |------|---------|
110
+ | `where_am_i` | Which app and view, whether the app is configured, whether a tab is shared, which plans apply here |
111
+ | `read_page` | The shared page as an outline, as the visible text of a region, or as form state with its validation errors |
112
+ | `find_on_page` | Elements by role and accessible name, with refs `highlight` can point at |
113
+ | `highlight` | Point at one control, zone or element on the person's screen |
114
+ | `search_knowledge` | The app's curated knowledge, with citations |
115
+ | `list_plans` | The curated procedures that apply to this view, with the `plan_id` and fields `run_plan` takes |
116
+ | `run_plan` | Run one curated plan in the page at a pace (`teach`, `walk`, `do`) |
117
+ | `plan_status` | How a running plan is going, with a waiting mode that holds for the page to move |
118
+
119
+ Every result says whether its work was visible in the page and what the answer
120
+ is grounded in, and the tool descriptions oblige the assistant to act on both:
121
+ confirm a plan in one sentence rather than re-listing steps the person is
122
+ watching, and state the mode without inflating it.
123
+
124
+ `read_page` and `find_on_page` answer with one `page_content` string: the DOM
125
+ result serialized inside the backend's untrusted-content delimiters. The
126
+ connector passes it through untouched, because the delimiters are the
127
+ prompt-injection defence and they only work while they are still around the
128
+ content. What the connector does decide is how much a read asks for, and over a
129
+ hosted connection that is capped.
130
+
131
+ The connector needs a live Appilot session, and over stdio that is
132
+ `APPILOT_SESSION_TOKEN`. It never reads `APPILOT_PAT`: a service token names an
133
+ organization, a session names a person, and the runtime routes exist so the
134
+ connector can do no more than that person can.
135
+
90
136
  ## The command line
91
137
 
92
138
  The package is an MCP server first, and a small CLI for the things a pipeline
@@ -259,8 +305,10 @@ What it serves:
259
305
 
260
306
  | Path | Purpose |
261
307
  |------|---------|
262
- | `POST /mcp` | The MCP endpoint, Streamable HTTP, bearer required |
263
- | `/.well-known/oauth-protected-resource/mcp` | Points a client at the authorization server |
308
+ | `POST /mcp` | Appilot Studio over Streamable HTTP, bearer required, a configuration scope required |
309
+ | `POST /mcp/runtime` | The Appilot connector, same transport, `runtime:use` required |
310
+ | `/.well-known/oauth-protected-resource/mcp` | Points a Studio client at the authorization server |
311
+ | `/.well-known/oauth-protected-resource/mcp/runtime` | The same for the connector |
264
312
  | `/.well-known/oauth-authorization-server` | Metadata, PKCE with S256, dynamic registration |
265
313
  | `/authorize`, `/token`, `/register` | The OAuth 2.1 flow |
266
314
  | `/consent` | Manual token verification and review |
Binary file
package/dist/cli.d.ts CHANGED
@@ -14,7 +14,7 @@
14
14
  * that was documented only as a marketplace command pointing at a repository
15
15
  * that does not exist.
16
16
  */
17
- export declare const HELP = "appilot-mcp 0.3.0\n\nThe Appilot MCP server: read, validate, fix and provision an Appilot app.\n\nUSAGE\n appilot-mcp Start the MCP server on stdio (what a client launches)\n appilot-mcp --http Start the remote HTTP service instead\n appilot-mcp plan <file> Preview an appilot.app-manifest. Writes nothing\n appilot-mcp apply <file> Plan, then apply the same manifest\n appilot-mcp install-skill Copy the app-configurator skill to an agent client\n appilot-mcp --help | --version\n\nOPTIONS\n apply --mode merge|replace How the config half is imported. Default merge\n --allow-unhealthy Import a bundle the health gate would refuse\n install-skill --claude | --codex | --cursor | --gemini | --dir <path>\n\nENVIRONMENT\n APPILOT_BASE_URL Your instance, e.g. https://api.appilot.space or http://localhost:6001\n APPILOT_PAT A scoped service token from the Backoffice, under Service tokens\n APPILOT_APP_ID Optional default app id\n\nDocs: https://docs.appilot.space/docs/developers/configure-with-ai/overview";
17
+ export declare const HELP = "appilot-mcp 0.4.0\n\nThe Appilot MCP server: read, validate, fix and provision an Appilot app.\n\nUSAGE\n appilot-mcp Start Appilot Studio on stdio (what a client launches)\n appilot-mcp --runtime Start the Appilot connector instead: operate a configured app\n appilot-mcp --http Start the remote HTTP service, which serves both\n appilot-mcp plan <file> Preview an appilot.app-manifest. Writes nothing\n appilot-mcp apply <file> Plan, then apply the same manifest\n appilot-mcp install-skill Copy the app-configurator skill to an agent client\n appilot-mcp --help | --version\n\nOPTIONS\n apply --mode merge|replace How the config half is imported. Default merge\n --allow-unhealthy Import a bundle the health gate would refuse\n install-skill --claude | --codex | --cursor | --gemini | --dir <path>\n\nENVIRONMENT\n APPILOT_BASE_URL Your instance, e.g. https://api.appilot.space or http://localhost:6001\n APPILOT_PAT A scoped service token from the Backoffice, under Service tokens\n APPILOT_APP_ID Optional default app id\n APPILOT_SESSION_TOKEN An Appilot user session, which is what --runtime authenticates with\n\nDocs: https://docs.appilot.space/docs/developers/configure-with-ai/overview";
18
18
  /** Where each client looks for a skill. One directory per client, all under $HOME. */
19
19
  export declare const SKILL_TARGETS: Record<string, string>;
20
20
  /**
package/dist/cli.js CHANGED
@@ -27,8 +27,9 @@ export const HELP = `appilot-mcp ${SERVER_VERSION}
27
27
  The Appilot MCP server: read, validate, fix and provision an Appilot app.
28
28
 
29
29
  USAGE
30
- appilot-mcp Start the MCP server on stdio (what a client launches)
31
- appilot-mcp --http Start the remote HTTP service instead
30
+ appilot-mcp Start Appilot Studio on stdio (what a client launches)
31
+ appilot-mcp --runtime Start the Appilot connector instead: operate a configured app
32
+ appilot-mcp --http Start the remote HTTP service, which serves both
32
33
  appilot-mcp plan <file> Preview an appilot.app-manifest. Writes nothing
33
34
  appilot-mcp apply <file> Plan, then apply the same manifest
34
35
  appilot-mcp install-skill Copy the app-configurator skill to an agent client
@@ -43,6 +44,7 @@ ENVIRONMENT
43
44
  APPILOT_BASE_URL Your instance, e.g. https://api.appilot.space or http://localhost:6001
44
45
  APPILOT_PAT A scoped service token from the Backoffice, under Service tokens
45
46
  APPILOT_APP_ID Optional default app id
47
+ APPILOT_SESSION_TOKEN An Appilot user session, which is what --runtime authenticates with
46
48
 
47
49
  Docs: https://docs.appilot.space/docs/developers/configure-with-ai/overview`;
48
50
  /** Where each client looks for a skill. One directory per client, all under $HOME. */
package/dist/config.d.ts CHANGED
@@ -11,6 +11,15 @@ export interface AppilotConnection {
11
11
  baseUrl?: string;
12
12
  /** Scoped service token (appilot_pat_…). Optional for read-only capability probes. */
13
13
  token?: string;
14
+ /**
15
+ * An Appilot USER session, which is what the runtime connector authenticates
16
+ * with (see userClient.ts). It is deliberately a separate field from `token`:
17
+ * a service token names an organization and its scopes, a session names a
18
+ * person, and the runtime routes exist precisely so that a connector can
19
+ * never do more than the person whose session it holds. Sending one where the
20
+ * other belongs would either fail closed or, worse, widen the connector.
21
+ */
22
+ sessionToken?: string;
14
23
  /** Default app id for tools that omit one. */
15
24
  defaultAppId?: number;
16
25
  /** Optional site session for the soak tool (see soak.ts). */
@@ -42,6 +51,18 @@ export declare function loadConnection(env?: NodeJS.ProcessEnv): AppilotConnecti
42
51
  /** Which transport the process serves. Local stdio unless asked otherwise. */
43
52
  export type TransportMode = 'stdio' | 'http';
44
53
  export declare function resolveTransport(argv?: string[], env?: NodeJS.ProcessEnv): TransportMode;
54
+ /**
55
+ * Which of the two servers a stdio process serves.
56
+ *
57
+ * `config` is Appilot Studio, the configuration surface a developer connects to
58
+ * and the default, because it is what every existing client launches. `runtime`
59
+ * is the Appilot connector, which operates an already-configured app on behalf
60
+ * of the person using it. One MCP process serves one server, so the choice is
61
+ * made here rather than inside either factory. The remote transport makes the
62
+ * same choice per request from the path, and never from an environment value.
63
+ */
64
+ export type ServerSurface = 'config' | 'runtime';
65
+ export declare function resolveServerSurface(argv?: string[], env?: NodeJS.ProcessEnv): ServerSurface;
45
66
  /**
46
67
  * Settings for the remote (Streamable HTTP) deployment.
47
68
  *
package/dist/config.js CHANGED
@@ -15,6 +15,7 @@ export function loadConnection(env = process.env) {
15
15
  return {
16
16
  baseUrl: baseUrl ? trimTrailingSlash(baseUrl) : undefined,
17
17
  token: env.APPILOT_PAT?.trim() || undefined,
18
+ sessionToken: env.APPILOT_SESSION_TOKEN?.trim() || undefined,
18
19
  defaultAppId: Number.isFinite(defaultAppId) ? defaultAppId : undefined,
19
20
  soakStorageStatePath: env.APPILOT_SOAK_STORAGE_STATE?.trim() || undefined,
20
21
  };
@@ -24,6 +25,11 @@ export function resolveTransport(argv = process.argv.slice(2), env = process.env
24
25
  return 'http';
25
26
  return env.APPILOT_MCP_TRANSPORT?.trim() === 'http' ? 'http' : 'stdio';
26
27
  }
28
+ export function resolveServerSurface(argv = process.argv.slice(2), env = process.env) {
29
+ if (argv.includes('--runtime'))
30
+ return 'runtime';
31
+ return env.APPILOT_MCP_SERVER?.trim() === 'runtime' ? 'runtime' : 'config';
32
+ }
27
33
  /** Where the docs live when a deployment does not say otherwise. */
28
34
  export const DEFAULT_DOCS_URL = 'https://docs.appilot.space';
29
35
  export class RemoteConfigError extends Error {