@caelo-cms/mcp-server 0.10.26 → 0.10.28
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 +28 -2
- package/dist/admin-server.d.ts.map +1 -1
- package/dist/admin-server.js +7 -2
- package/dist/admin-server.js.map +1 -1
- package/dist/chat-bridge.d.ts +14 -0
- package/dist/chat-bridge.d.ts.map +1 -1
- package/dist/chat-bridge.js +1 -11
- package/dist/chat-bridge.js.map +1 -1
- package/dist/http.d.ts +0 -9
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +14 -1
- package/dist/http.js.map +1 -1
- package/dist/image-upload.d.ts +80 -0
- package/dist/image-upload.d.ts.map +1 -0
- package/dist/image-upload.js +159 -0
- package/dist/image-upload.js.map +1 -0
- package/dist/ingress-auth.d.ts +27 -0
- package/dist/ingress-auth.d.ts.map +1 -0
- package/dist/ingress-auth.js +126 -0
- package/dist/ingress-auth.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +20 -2
- package/dist/server.js.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
MCP servers for your Caelo CMS install. Two surfaces, selected by the
|
|
4
4
|
token's scope:
|
|
5
5
|
|
|
6
|
-
- **`caelo_chat`** (default mode, scope `chat`) —
|
|
6
|
+
- **`caelo_chat`** (default mode, scope `chat`) — talks
|
|
7
7
|
to Caelo's own AI agent. You describe an outcome; Caelo's chat-runner
|
|
8
8
|
does the work.
|
|
9
9
|
- **Power-MCP** (`caelo-admin-mcp` binary / `caelo-mcp-server admin`,
|
|
@@ -42,6 +42,19 @@ with these env vars set:
|
|
|
42
42
|
|---|---|---|
|
|
43
43
|
| `CAELO_ADMIN_URL` | yes | `https://admin.example.com` — point at your install. |
|
|
44
44
|
| `CAELO_MCP_TOKEN` | yes | Bearer minted at `/security/mcp`. |
|
|
45
|
+
| `CAELO_IAP_SERVICE_ACCOUNT` | on GCP installs | The admin's MCP service account. `/security/mcp` includes it in the `claude mcp add` command when the admin is behind Google IAP. |
|
|
46
|
+
|
|
47
|
+
### Installs behind Google IAP (GCP)
|
|
48
|
+
|
|
49
|
+
On `gcp` and `gcp-firebase` installs the admin sits behind Identity-Aware Proxy, which rejects every request before Caelo sees it unless it carries a Google credential. With `CAELO_IAP_SERVICE_ACCOUNT` set, the server signs a short-lived JWT as that service account (IAM Credentials `signJwt`, using your Application Default Credentials) and sends it in `Authorization` next to `x-caelo-mcp-token`: IAP checks the first, Caelo the second.
|
|
50
|
+
|
|
51
|
+
One-time setup on your machine:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
gcloud auth application-default login
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The provisioner creates the service account (`caelo-mcp@<project>`), allowlists it on IAP and lets everyone on the IAP allowlist sign as it — on new installs via Pulumi, on existing ones during `cms-provision upgrade`. No service-account keys are involved.
|
|
45
58
|
|
|
46
59
|
## The `caelo_chat` tool
|
|
47
60
|
|
|
@@ -49,6 +62,7 @@ with these env vars set:
|
|
|
49
62
|
|---|---|---|
|
|
50
63
|
| `message` | string, required | What you want to say to the Caelo agent. |
|
|
51
64
|
| `chatSessionId` | uuid, optional | Continue an existing chat session. |
|
|
65
|
+
| `attachments` | array, optional | Up to four image references returned by `caelo_upload_images`. |
|
|
52
66
|
| `pageId` | uuid, optional | Bind a NEW chat to one page so the agent's page-context block populates. |
|
|
53
67
|
|
|
54
68
|
Output: assistant reply text + a JSON block with `chatSessionId` (for
|
|
@@ -58,7 +72,7 @@ tool-call summaries the agent dispatched, the per-turn cost in
|
|
|
58
72
|
microcents, and a `pendingProposals` count so the agent can surface
|
|
59
73
|
"you have N things waiting for Owner approval".
|
|
60
74
|
|
|
61
|
-
## Why
|
|
75
|
+
## Why route editing through chat?
|
|
62
76
|
|
|
63
77
|
Browse / publish / propose actions happen *through* the chat — "which
|
|
64
78
|
pages exist?" → the Caelo agent calls `pages.list` internally → answers
|
|
@@ -69,3 +83,15 @@ human-equivalent agent, not to a programmatic API.
|
|
|
69
83
|
## License
|
|
70
84
|
|
|
71
85
|
MPL-2.0.
|
|
86
|
+
|
|
87
|
+
## Image uploads
|
|
88
|
+
|
|
89
|
+
Both modes expose `caelo_upload_images`. For example, call it with:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{"images":[{"filePath":"/home/me/Pictures/character.png","alt":"Main character reference"}]}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Paths are local to the MCP process. Alternatively use `base64` plus an optional `filename`; supply exactly one of `filePath` and `base64`. Uploads support PNG/JPEG/WebP/GIF, up to 5 MiB each, with at most four files per call. The result contains per-file successes/errors and an `attachments` array. Pass that array to `caelo_chat` alongside `message` to send actual image content to Caelo's AI. In admin mode, the returned asset IDs can be used with regular media/page tools.
|
|
96
|
+
|
|
97
|
+
The token owner's current `content.write` permission is required for either scope. Images are stored in the shared CMS media library; admin previews require authentication. Uploading alone does not publish a page. A partial batch keeps successful uploads — retry only the failed entries. See the [upload workflow](https://caelo-cms.com/mcp#upload-and-attach-images) for HTTP examples and server limits.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-server.d.ts","sourceRoot":"","sources":["../src/admin-server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"admin-server.d.ts","sourceRoot":"","sources":["../src/admin-server.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAyED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAwI7E"}
|
package/dist/admin-server.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MPL-2.0
|
|
2
2
|
/**
|
|
3
3
|
* Issue #376 — the Power-MCP server (`caelo-admin-mcp` / `caelo-mcp-server
|
|
4
|
-
* admin`). Where the chat server
|
|
4
|
+
* admin`). Where the chat server routes editing through a tool that talks to Caelo's own
|
|
5
5
|
* AI, this server exposes the whole chat-runner tool catalogue so the
|
|
6
6
|
* CALLING agent (Claude Code et al.) drives the tool loop itself — no
|
|
7
7
|
* Caelo-side reasoning cost.
|
|
8
8
|
*
|
|
9
9
|
* The catalogue is fetched live from `/api/mcp/tools` at startup (an
|
|
10
10
|
* admin-scoped token is required; 'chat' tokens get a 401 with the fix).
|
|
11
|
-
*
|
|
11
|
+
* Local companion tools:
|
|
12
12
|
*
|
|
13
|
+
* - `caelo_upload_images` — uploads local or base64 image references to the media library.
|
|
13
14
|
* - `caelo_open_session` — opens (or resumes) the work session whose
|
|
14
15
|
* preview branch every subsequent tool call writes to. The session id
|
|
15
16
|
* is held here in process state so the agent doesn't thread it through
|
|
@@ -25,6 +26,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
25
26
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
26
27
|
import { z } from "zod";
|
|
27
28
|
import { postAdmin, resolveTimeoutMs } from "./http.js";
|
|
29
|
+
import { UPLOAD_IMAGES_TOOL, uploadImages } from "./image-upload.js";
|
|
28
30
|
const openSessionInput = z
|
|
29
31
|
.object({
|
|
30
32
|
title: z.string().min(1).max(200).optional(),
|
|
@@ -72,6 +74,7 @@ export async function startAdminMcpServer(opts) {
|
|
|
72
74
|
const server = new Server({ name: "caelo-admin-mcp", version: "0.1.0" }, { capabilities: { tools: {} } });
|
|
73
75
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
74
76
|
tools: [
|
|
77
|
+
UPLOAD_IMAGES_TOOL,
|
|
75
78
|
OPEN_SESSION_TOOL,
|
|
76
79
|
GET_CONTEXT_TOOL,
|
|
77
80
|
...catalogue.tools.map((t) => ({
|
|
@@ -84,6 +87,8 @@ export async function startAdminMcpServer(opts) {
|
|
|
84
87
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
85
88
|
const name = req.params.name;
|
|
86
89
|
try {
|
|
90
|
+
if (name === UPLOAD_IMAGES_TOOL.name)
|
|
91
|
+
return await uploadImages(opts, req.params.arguments);
|
|
87
92
|
if (name === OPEN_SESSION_TOOL.name) {
|
|
88
93
|
const parsed = openSessionInput.safeParse(req.params.arguments ?? {});
|
|
89
94
|
if (!parsed.success) {
|
package/dist/admin-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-server.js","sourceRoot":"","sources":["../src/admin-server.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAEnC
|
|
1
|
+
{"version":3,"file":"admin-server.js","sourceRoot":"","sources":["../src/admin-server.ts"],"names":[],"mappings":"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"}
|
package/dist/chat-bridge.d.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP bridge — translates a `caelo_chat` MCP call into a single POST
|
|
3
|
+
* against the admin install's `/api/mcp/chat` endpoint. The endpoint
|
|
4
|
+
* dispatches `mcp.send_chat` (system-only op) which resolves the
|
|
5
|
+
* bearer to a Caelo actor and drives `runChatTurn`.
|
|
6
|
+
*
|
|
7
|
+
* 30-second default client-side timeout (override with
|
|
8
|
+
* `CAELO_MCP_TIMEOUT_MS`) — chat-runner turns longer than that are
|
|
9
|
+
* likely stuck (the runner has its own provider-call timeouts). MCP
|
|
10
|
+
* clients see a clean error instead of a hung connection.
|
|
11
|
+
*/
|
|
12
|
+
import type { z } from "zod";
|
|
13
|
+
import type { uploadedImageSchema } from "./image-upload.js";
|
|
1
14
|
export interface SendChatOpts {
|
|
2
15
|
readonly adminUrl: string;
|
|
3
16
|
readonly token: string;
|
|
4
17
|
readonly message: string;
|
|
18
|
+
readonly attachments?: z.infer<typeof uploadedImageSchema>[];
|
|
5
19
|
readonly chatSessionId?: string;
|
|
6
20
|
readonly pageId?: string;
|
|
7
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-bridge.d.ts","sourceRoot":"","sources":["../src/chat-bridge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"chat-bridge.d.ts","sourceRoot":"","sources":["../src/chat-bridge.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,EAAE,CAAC;IAC7D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzF,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAa1E"}
|
package/dist/chat-bridge.js
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
-
/**
|
|
3
|
-
* HTTP bridge — translates a `caelo_chat` MCP call into a single POST
|
|
4
|
-
* against the admin install's `/api/mcp/chat` endpoint. The endpoint
|
|
5
|
-
* dispatches `mcp.send_chat` (system-only op) which resolves the
|
|
6
|
-
* bearer to a Caelo actor and drives `runChatTurn`.
|
|
7
|
-
*
|
|
8
|
-
* 30-second default client-side timeout (override with
|
|
9
|
-
* `CAELO_MCP_TIMEOUT_MS`) — chat-runner turns longer than that are
|
|
10
|
-
* likely stuck (the runner has its own provider-call timeouts). MCP
|
|
11
|
-
* clients see a clean error instead of a hung connection.
|
|
12
|
-
*/
|
|
13
2
|
import { postAdmin, resolveTimeoutMs } from "./http.js";
|
|
14
3
|
export async function sendChat(opts) {
|
|
15
4
|
return postAdmin({
|
|
@@ -18,6 +7,7 @@ export async function sendChat(opts) {
|
|
|
18
7
|
path: "/api/mcp/chat",
|
|
19
8
|
body: {
|
|
20
9
|
message: opts.message,
|
|
10
|
+
attachments: opts.attachments,
|
|
21
11
|
chatSessionId: opts.chatSessionId,
|
|
22
12
|
pageId: opts.pageId,
|
|
23
13
|
},
|
package/dist/chat-bridge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-bridge.js","sourceRoot":"","sources":["../src/chat-bridge.ts"],"names":[],"mappings":"AAAA,mCAAmC;
|
|
1
|
+
{"version":3,"file":"chat-bridge.js","sourceRoot":"","sources":["../src/chat-bridge.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAenC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAqBxD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAkB;IAC/C,OAAO,SAAS,CAAiB;QAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE;YACJ,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB;QACD,SAAS,EAAE,gBAAgB,CAAC,MAAM,CAAC;KACpC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/http.d.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared HTTP plumbing for both MCP surfaces (chat + admin). One POST
|
|
3
|
-
* per call against the admin install's /api/mcp/* endpoints, bearer in
|
|
4
|
-
* the `x-caelo-mcp-token` header, with an abortable client-side timeout.
|
|
5
|
-
*
|
|
6
|
-
* Timeouts default per call site (chat 30s, tool execution 120s — bulk
|
|
7
|
-
* ops and media imports legitimately run long) and can be overridden
|
|
8
|
-
* globally via `CAELO_MCP_TIMEOUT_MS`.
|
|
9
|
-
*/
|
|
10
1
|
export interface AdminPostOpts {
|
|
11
2
|
readonly adminUrl: string;
|
|
12
3
|
readonly token: string;
|
package/dist/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAK1D;AAED,wBAAsB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,CAgClE"}
|
package/dist/http.js
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Shared HTTP plumbing for both MCP surfaces (chat + admin). One POST
|
|
4
|
+
* per call against the admin install's /api/mcp/* endpoints, bearer in
|
|
5
|
+
* the `x-caelo-mcp-token` header, with an abortable client-side timeout.
|
|
6
|
+
* On IAP-protected installs the IAP credential rides along in
|
|
7
|
+
* `authorization` (see ingress-auth.ts).
|
|
8
|
+
*
|
|
9
|
+
* Timeouts default per call site (chat 30s, tool execution 120s — bulk
|
|
10
|
+
* ops and media imports legitimately run long) and can be overridden
|
|
11
|
+
* globally via `CAELO_MCP_TIMEOUT_MS`.
|
|
12
|
+
*/
|
|
13
|
+
import { describeIapRejection, ingressHeaders } from "./ingress-auth.js";
|
|
2
14
|
/** The per-call default unless the operator set `CAELO_MCP_TIMEOUT_MS`. */
|
|
3
15
|
export function resolveTimeoutMs(defaultMs) {
|
|
4
16
|
const raw = process.env.CAELO_MCP_TIMEOUT_MS;
|
|
@@ -15,6 +27,7 @@ export async function postAdmin(opts) {
|
|
|
15
27
|
const res = await fetch(url, {
|
|
16
28
|
method: "POST",
|
|
17
29
|
headers: {
|
|
30
|
+
...(await ingressHeaders()),
|
|
18
31
|
"content-type": "application/json",
|
|
19
32
|
"x-caelo-mcp-token": opts.token,
|
|
20
33
|
},
|
|
@@ -23,7 +36,7 @@ export async function postAdmin(opts) {
|
|
|
23
36
|
});
|
|
24
37
|
if (!res.ok) {
|
|
25
38
|
const body = await safeText(res);
|
|
26
|
-
throw new Error(`HTTP ${res.status}: ${body || res.statusText}`);
|
|
39
|
+
throw new Error(describeIapRejection(res, body) ?? `HTTP ${res.status}: ${body || res.statusText}`);
|
|
27
40
|
}
|
|
28
41
|
return (await res.json());
|
|
29
42
|
}
|
package/dist/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,mCAAmC;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAEnC;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAWzE,2EAA2E;AAC3E,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAC7C,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAI,IAAmB;IACpD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACnE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,GAAG,CAAC,MAAM,cAAc,EAAE,CAAC;gBAC3B,cAAc,EAAE,kBAAkB;gBAClC,mBAAmB,EAAE,IAAI,CAAC,KAAK;aAChC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;YAC/B,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,QAAQ,GAAG,CAAC,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,EAAE,CACnF,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;IACjC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CACb,iBAAiB,IAAI,CAAC,SAAS,GAAG,IAAI,wCAAwC,CAC/E,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,CAAC;IACV,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,GAAa;IACnC,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Uploaded media references accepted by caelo_chat; never accept object-store keys. */
|
|
3
|
+
export declare const uploadedImageSchema: z.ZodObject<{
|
|
4
|
+
assetId: z.ZodString;
|
|
5
|
+
mime: z.ZodEnum<{
|
|
6
|
+
"image/png": "image/png";
|
|
7
|
+
"image/jpeg": "image/jpeg";
|
|
8
|
+
"image/webp": "image/webp";
|
|
9
|
+
"image/gif": "image/gif";
|
|
10
|
+
}>;
|
|
11
|
+
alt: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}, z.core.$strict>;
|
|
13
|
+
/** A bounded batch; each file has its own success/error result for safe retries. */
|
|
14
|
+
export declare const uploadImagesInput: z.ZodObject<{
|
|
15
|
+
images: z.ZodArray<z.ZodObject<{
|
|
16
|
+
filePath: z.ZodOptional<z.ZodString>;
|
|
17
|
+
base64: z.ZodOptional<z.ZodString>;
|
|
18
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
19
|
+
alt: z.ZodOptional<z.ZodString>;
|
|
20
|
+
reference: z.ZodOptional<z.ZodBoolean>;
|
|
21
|
+
}, z.core.$strict>>;
|
|
22
|
+
}, z.core.$strict>;
|
|
23
|
+
/** Exposed in both MCP catalogues, including chat-scoped connections. */
|
|
24
|
+
export declare const UPLOAD_IMAGES_TOOL: {
|
|
25
|
+
name: string;
|
|
26
|
+
description: string;
|
|
27
|
+
inputSchema: {
|
|
28
|
+
type: "object";
|
|
29
|
+
required: string[];
|
|
30
|
+
additionalProperties: boolean;
|
|
31
|
+
properties: {
|
|
32
|
+
images: {
|
|
33
|
+
type: string;
|
|
34
|
+
minItems: number;
|
|
35
|
+
maxItems: number;
|
|
36
|
+
items: {
|
|
37
|
+
type: string;
|
|
38
|
+
additionalProperties: boolean;
|
|
39
|
+
properties: {
|
|
40
|
+
filePath: {
|
|
41
|
+
type: string;
|
|
42
|
+
description: string;
|
|
43
|
+
};
|
|
44
|
+
base64: {
|
|
45
|
+
type: string;
|
|
46
|
+
description: string;
|
|
47
|
+
};
|
|
48
|
+
filename: {
|
|
49
|
+
type: string;
|
|
50
|
+
description: string;
|
|
51
|
+
};
|
|
52
|
+
alt: {
|
|
53
|
+
type: string;
|
|
54
|
+
description: string;
|
|
55
|
+
};
|
|
56
|
+
reference: {
|
|
57
|
+
type: string;
|
|
58
|
+
description: string;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
oneOf: {
|
|
62
|
+
required: string[];
|
|
63
|
+
}[];
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
/** Upload caller-selected files, returning failures individually without dropping successes. */
|
|
70
|
+
export declare function uploadImages(opts: {
|
|
71
|
+
adminUrl: string;
|
|
72
|
+
token: string;
|
|
73
|
+
}, input: unknown): Promise<{
|
|
74
|
+
content: {
|
|
75
|
+
type: "text";
|
|
76
|
+
text: string;
|
|
77
|
+
}[];
|
|
78
|
+
isError?: boolean | undefined;
|
|
79
|
+
}>;
|
|
80
|
+
//# sourceMappingURL=image-upload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-upload.d.ts","sourceRoot":"","sources":["../src/image-upload.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,wFAAwF;AACxF,eAAO,MAAM,mBAAmB;;;;;;;;;kBAMrB,CAAC;AAoBZ,oFAAoF;AACpF,eAAO,MAAM,iBAAiB;;;;;;;;kBAAmE,CAAC;AAElG,yEAAyE;AACzE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4C9B,CAAC;AAEF,gGAAgG;AAChG,wBAAsB,YAAY,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,OAAO;;;;;;GA4E3F"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
/** Image upload transport shared by chat and admin MCP servers. */
|
|
3
|
+
import { constants } from "node:fs";
|
|
4
|
+
import { open } from "node:fs/promises";
|
|
5
|
+
import { basename } from "node:path";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { resolveTimeoutMs } from "./http.js";
|
|
8
|
+
import { describeIapRejection, ingressHeaders } from "./ingress-auth.js";
|
|
9
|
+
const MAX_BYTES = 5 * 1024 * 1024;
|
|
10
|
+
/** Uploaded media references accepted by caelo_chat; never accept object-store keys. */
|
|
11
|
+
export const uploadedImageSchema = z
|
|
12
|
+
.object({
|
|
13
|
+
assetId: z.string().uuid(),
|
|
14
|
+
mime: z.enum(["image/png", "image/jpeg", "image/webp", "image/gif"]),
|
|
15
|
+
alt: z.string().max(2048).optional(),
|
|
16
|
+
})
|
|
17
|
+
.strict();
|
|
18
|
+
const imageInput = z
|
|
19
|
+
.object({
|
|
20
|
+
filePath: z.string().min(1).max(4096).optional(),
|
|
21
|
+
base64: z
|
|
22
|
+
.string()
|
|
23
|
+
.min(4)
|
|
24
|
+
.max(Math.ceil(MAX_BYTES / 3) * 4)
|
|
25
|
+
.regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/)
|
|
26
|
+
.optional(),
|
|
27
|
+
filename: z.string().min(1).max(512).optional(),
|
|
28
|
+
alt: z.string().max(2048).optional(),
|
|
29
|
+
reference: z.boolean().optional(),
|
|
30
|
+
})
|
|
31
|
+
.strict()
|
|
32
|
+
.refine((i) => (i.filePath === undefined) !== (i.base64 === undefined), "Supply exactly one of filePath or base64");
|
|
33
|
+
/** A bounded batch; each file has its own success/error result for safe retries. */
|
|
34
|
+
export const uploadImagesInput = z.object({ images: z.array(imageInput).min(1).max(4) }).strict();
|
|
35
|
+
/** Exposed in both MCP catalogues, including chat-scoped connections. */
|
|
36
|
+
export const UPLOAD_IMAGES_TOOL = {
|
|
37
|
+
name: "caelo_upload_images",
|
|
38
|
+
description: "Upload 1–4 PNG, JPEG, WebP or GIF images (5 MiB each) to the Caelo media library. " +
|
|
39
|
+
"Prefer filePath for files on the machine running this MCP server; otherwise supply raw base64 (no data URL). " +
|
|
40
|
+
"Files become shared CMS media assets. Set reference: true for images that only guide image generation or editing " +
|
|
41
|
+
"(character sheets, style samples): they stay out of the page-image library and are never published. " +
|
|
42
|
+
"Returns attachments for caelo_chat " +
|
|
43
|
+
"or asset IDs for page tools. Uploading does not send a chat message or publish a page. " +
|
|
44
|
+
"Results are per file: retry only failures. Requires the token owner's current content.write permission.",
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: "object",
|
|
47
|
+
required: ["images"],
|
|
48
|
+
additionalProperties: false,
|
|
49
|
+
properties: {
|
|
50
|
+
images: {
|
|
51
|
+
type: "array",
|
|
52
|
+
minItems: 1,
|
|
53
|
+
maxItems: 4,
|
|
54
|
+
items: {
|
|
55
|
+
type: "object",
|
|
56
|
+
additionalProperties: false,
|
|
57
|
+
properties: {
|
|
58
|
+
filePath: {
|
|
59
|
+
type: "string",
|
|
60
|
+
description: "Path on the MCP server machine. Mutually exclusive with base64.",
|
|
61
|
+
},
|
|
62
|
+
base64: {
|
|
63
|
+
type: "string",
|
|
64
|
+
description: "Raw image bytes as base64. Mutually exclusive with filePath.",
|
|
65
|
+
},
|
|
66
|
+
filename: { type: "string", description: "Optional media filename." },
|
|
67
|
+
alt: { type: "string", description: "Optional description of the image." },
|
|
68
|
+
reference: {
|
|
69
|
+
type: "boolean",
|
|
70
|
+
description: "True for an image that only guides generation/editing; it is never placed on a page.",
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
oneOf: [{ required: ["filePath"] }, { required: ["base64"] }],
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
/** Upload caller-selected files, returning failures individually without dropping successes. */
|
|
80
|
+
export async function uploadImages(opts, input) {
|
|
81
|
+
const parsed = uploadImagesInput.parse(input);
|
|
82
|
+
const results = [];
|
|
83
|
+
for (const [index, image] of parsed.images.entries()) {
|
|
84
|
+
try {
|
|
85
|
+
let bytes;
|
|
86
|
+
if (image.filePath) {
|
|
87
|
+
const file = await open(image.filePath, constants.O_RDONLY | constants.O_NONBLOCK);
|
|
88
|
+
try {
|
|
89
|
+
const stat = await file.stat();
|
|
90
|
+
if (!stat.isFile() || stat.size === 0 || stat.size > MAX_BYTES)
|
|
91
|
+
throw new Error("Expected an image file of 1 byte to 5 MiB");
|
|
92
|
+
// Read at most cap+1 even if the file grows after stat().
|
|
93
|
+
const buffer = Buffer.alloc(MAX_BYTES + 1);
|
|
94
|
+
let total = 0;
|
|
95
|
+
while (total < buffer.length) {
|
|
96
|
+
const { bytesRead } = await file.read(buffer, total, buffer.length - total, null);
|
|
97
|
+
if (!bytesRead)
|
|
98
|
+
break;
|
|
99
|
+
total += bytesRead;
|
|
100
|
+
}
|
|
101
|
+
bytes = buffer.subarray(0, total);
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
await file.close();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
if (image.base64 === undefined)
|
|
109
|
+
throw new Error("Missing image bytes");
|
|
110
|
+
bytes = Buffer.from(image.base64, "base64");
|
|
111
|
+
}
|
|
112
|
+
if (!bytes.length || bytes.length > MAX_BYTES)
|
|
113
|
+
throw new Error("Image must be at most 5 MiB and non-empty");
|
|
114
|
+
const filename = image.filename ?? (image.filePath ? basename(image.filePath) : "image");
|
|
115
|
+
const query = new URLSearchParams({ filename });
|
|
116
|
+
if (image.alt)
|
|
117
|
+
query.set("alt", image.alt);
|
|
118
|
+
if (image.reference)
|
|
119
|
+
query.set("visibility", "reference");
|
|
120
|
+
const response = await fetch(`${opts.adminUrl.replace(/\/+$/, "")}/api/mcp/images?${query}`, {
|
|
121
|
+
method: "POST",
|
|
122
|
+
headers: {
|
|
123
|
+
...(await ingressHeaders()),
|
|
124
|
+
"x-caelo-mcp-token": opts.token,
|
|
125
|
+
"content-type": "application/octet-stream",
|
|
126
|
+
},
|
|
127
|
+
body: new Uint8Array(bytes),
|
|
128
|
+
signal: AbortSignal.timeout(resolveTimeoutMs(120_000)),
|
|
129
|
+
});
|
|
130
|
+
if (!response.ok) {
|
|
131
|
+
const text = await response.text();
|
|
132
|
+
throw new Error(describeIapRejection(response, text) ?? `HTTP ${response.status}: ${text.slice(0, 500)}`);
|
|
133
|
+
}
|
|
134
|
+
const value = (await response.json());
|
|
135
|
+
const attachment = uploadedImageSchema.parse({
|
|
136
|
+
assetId: value.assetId,
|
|
137
|
+
mime: value.mime,
|
|
138
|
+
alt: image.alt ?? filename,
|
|
139
|
+
});
|
|
140
|
+
results.push({ index, attachment });
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
results.push({ index, error: e instanceof Error ? e.message : String(e) });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
...(results.every((r) => "error" in r) ? { isError: true } : {}),
|
|
148
|
+
content: [
|
|
149
|
+
{
|
|
150
|
+
type: "text",
|
|
151
|
+
text: JSON.stringify({
|
|
152
|
+
results,
|
|
153
|
+
attachments: results.flatMap((r) => ("attachment" in r ? [r.attachment] : [])),
|
|
154
|
+
}),
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=image-upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-upload.js","sourceRoot":"","sources":["../src/image-upload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface IngressAuth {
|
|
2
|
+
/** Extra request headers that get the request through IAP. */
|
|
3
|
+
headers(): Promise<Record<string, string>>;
|
|
4
|
+
readonly serviceAccount: string;
|
|
5
|
+
}
|
|
6
|
+
export interface IngressAuthDeps {
|
|
7
|
+
/** OAuth access token of the operator's Application Default Credentials. */
|
|
8
|
+
getAccessToken?: () => Promise<string>;
|
|
9
|
+
fetch?: typeof fetch;
|
|
10
|
+
/** Seconds since epoch. */
|
|
11
|
+
now?: () => number;
|
|
12
|
+
}
|
|
13
|
+
/** `https://admin.example.com/anything` → `https://admin.example.com/*` (the JWT `aud`). */
|
|
14
|
+
export declare function iapAudience(adminUrl: string): string;
|
|
15
|
+
export declare function createIngressAuth(env: {
|
|
16
|
+
readonly CAELO_IAP_SERVICE_ACCOUNT?: string;
|
|
17
|
+
readonly CAELO_ADMIN_URL?: string;
|
|
18
|
+
}, deps?: IngressAuthDeps): IngressAuth | null;
|
|
19
|
+
/** Ingress headers for this process, configured from `process.env` on first use. */
|
|
20
|
+
export declare function ingressHeaders(): Promise<Record<string, string>>;
|
|
21
|
+
/**
|
|
22
|
+
* Turns IAP's own rejection (`x-goog-iap-generated-response: true`) into an
|
|
23
|
+
* actionable message — otherwise the operator only sees "Invalid IAP
|
|
24
|
+
* credentials: empty token" and has no idea which knob to turn.
|
|
25
|
+
*/
|
|
26
|
+
export declare function describeIapRejection(res: Response, body: string): string | null;
|
|
27
|
+
//# sourceMappingURL=ingress-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingress-auth.d.ts","sourceRoot":"","sources":["../src/ingress-auth.ts"],"names":[],"mappings":"AAgCA,MAAM,WAAW,WAAW;IAC1B,8DAA8D;IAC9D,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,2BAA2B;IAC3B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AASD,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE;IAAE,QAAQ,CAAC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,EACvF,IAAI,GAAE,eAAoB,GACzB,WAAW,GAAG,IAAI,CAqEpB;AAID,oFAAoF;AACpF,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAOtE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM/E"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
/**
|
|
3
|
+
* IAP ingress for GCP installs (issue #37).
|
|
4
|
+
*
|
|
5
|
+
* On `gcp` / `gcp-firebase` installs the admin app sits behind Google
|
|
6
|
+
* Identity-Aware Proxy. IAP rejects every request that doesn't carry a
|
|
7
|
+
* Google-signed credential BEFORE Caelo's own `x-caelo-mcp-token` check
|
|
8
|
+
* runs, so the shim has to satisfy both gates: IAP first, Caelo second
|
|
9
|
+
* (CLAUDE.md §11.B — IAP stays the first line of defense).
|
|
10
|
+
*
|
|
11
|
+
* Cloud Run native IAP uses a Google-managed OAuth client, which does not
|
|
12
|
+
* allow programmatic access with user tokens. What it does accept is a
|
|
13
|
+
* JWT signed by an allowlisted service account (Google's documented
|
|
14
|
+
* "service account JWT" path): `iss`/`sub` = the SA, `aud` = the admin
|
|
15
|
+
* origin with a path wildcard, signed via the IAM Credentials `signJwt`
|
|
16
|
+
* API. The provisioner creates that SA (`caelo-mcp@<project>`), allowlists
|
|
17
|
+
* it on IAP and lets every IAP-allowlisted operator impersonate it, so the
|
|
18
|
+
* operator's own `gcloud auth application-default login` is all the shim
|
|
19
|
+
* needs — no service-account keys on laptops (CLAUDE.md §11.C).
|
|
20
|
+
*
|
|
21
|
+
* Active only when `CAELO_IAP_SERVICE_ACCOUNT` is set (the admin's
|
|
22
|
+
* /security/mcp page puts it into the `claude mcp add` command on IAP
|
|
23
|
+
* installs); otherwise requests go out exactly as before.
|
|
24
|
+
*/
|
|
25
|
+
import { GoogleAuth } from "google-auth-library";
|
|
26
|
+
/** Signed JWTs live at most 1 hour; refresh a minute before expiry. */
|
|
27
|
+
const TOKEN_LIFETIME_S = 3600;
|
|
28
|
+
const REFRESH_MARGIN_S = 60;
|
|
29
|
+
/** `https://admin.example.com/anything` → `https://admin.example.com/*` (the JWT `aud`). */
|
|
30
|
+
export function iapAudience(adminUrl) {
|
|
31
|
+
return `${new URL(adminUrl).origin}/*`;
|
|
32
|
+
}
|
|
33
|
+
async function adcAccessToken() {
|
|
34
|
+
const auth = new GoogleAuth({ scopes: ["https://www.googleapis.com/auth/cloud-platform"] });
|
|
35
|
+
const token = await auth.getAccessToken();
|
|
36
|
+
if (!token)
|
|
37
|
+
throw new Error("Application Default Credentials returned no access token");
|
|
38
|
+
return token;
|
|
39
|
+
}
|
|
40
|
+
export function createIngressAuth(env, deps = {}) {
|
|
41
|
+
const configured = env.CAELO_IAP_SERVICE_ACCOUNT?.trim();
|
|
42
|
+
if (!configured)
|
|
43
|
+
return null;
|
|
44
|
+
const serviceAccount = configured;
|
|
45
|
+
if (!env.CAELO_ADMIN_URL)
|
|
46
|
+
throw new Error("CAELO_IAP_SERVICE_ACCOUNT is set but CAELO_ADMIN_URL is not");
|
|
47
|
+
const audience = iapAudience(env.CAELO_ADMIN_URL);
|
|
48
|
+
const getAccessToken = deps.getAccessToken ?? adcAccessToken;
|
|
49
|
+
const doFetch = deps.fetch ?? fetch;
|
|
50
|
+
const now = deps.now ?? (() => Math.floor(Date.now() / 1000));
|
|
51
|
+
let cached = null;
|
|
52
|
+
let inflight = null;
|
|
53
|
+
async function mint() {
|
|
54
|
+
const iat = now();
|
|
55
|
+
const exp = iat + TOKEN_LIFETIME_S;
|
|
56
|
+
let accessToken;
|
|
57
|
+
try {
|
|
58
|
+
accessToken = await getAccessToken();
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
throw new Error(`IAP: no Google credentials for signing the access token (${e instanceof Error ? e.message : String(e)}). ` +
|
|
62
|
+
"Run `gcloud auth application-default login` with an account that is allowed on this Caelo install.");
|
|
63
|
+
}
|
|
64
|
+
const res = await doFetch(`https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${encodeURIComponent(serviceAccount)}:signJwt`, {
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers: { authorization: `Bearer ${accessToken}`, "content-type": "application/json" },
|
|
67
|
+
body: JSON.stringify({
|
|
68
|
+
payload: JSON.stringify({
|
|
69
|
+
iss: serviceAccount,
|
|
70
|
+
sub: serviceAccount,
|
|
71
|
+
aud: audience,
|
|
72
|
+
iat,
|
|
73
|
+
exp,
|
|
74
|
+
}),
|
|
75
|
+
}),
|
|
76
|
+
});
|
|
77
|
+
if (!res.ok) {
|
|
78
|
+
const detail = await res.text().catch(() => "");
|
|
79
|
+
throw new Error(`IAP: could not sign an access token as ${serviceAccount} (HTTP ${res.status}). ` +
|
|
80
|
+
"Your Google account needs roles/iam.serviceAccountTokenCreator on that service account — " +
|
|
81
|
+
"`cms-provision upgrade` grants it to every IAP-allowlisted user. " +
|
|
82
|
+
detail.slice(0, 300));
|
|
83
|
+
}
|
|
84
|
+
const { signedJwt } = (await res.json());
|
|
85
|
+
if (!signedJwt)
|
|
86
|
+
throw new Error("IAP: signJwt response carried no signedJwt");
|
|
87
|
+
cached = { jwt: signedJwt, exp };
|
|
88
|
+
return signedJwt;
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
serviceAccount,
|
|
92
|
+
async headers() {
|
|
93
|
+
if (!cached || cached.exp - REFRESH_MARGIN_S <= now()) {
|
|
94
|
+
inflight ??= mint().finally(() => {
|
|
95
|
+
inflight = null;
|
|
96
|
+
});
|
|
97
|
+
await inflight;
|
|
98
|
+
}
|
|
99
|
+
return { authorization: `Bearer ${cached.jwt}` };
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
let processIngress;
|
|
104
|
+
/** Ingress headers for this process, configured from `process.env` on first use. */
|
|
105
|
+
export async function ingressHeaders() {
|
|
106
|
+
if (processIngress === undefined)
|
|
107
|
+
processIngress = createIngressAuth({
|
|
108
|
+
CAELO_IAP_SERVICE_ACCOUNT: process.env.CAELO_IAP_SERVICE_ACCOUNT,
|
|
109
|
+
CAELO_ADMIN_URL: process.env.CAELO_ADMIN_URL,
|
|
110
|
+
});
|
|
111
|
+
return processIngress ? processIngress.headers() : {};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Turns IAP's own rejection (`x-goog-iap-generated-response: true`) into an
|
|
115
|
+
* actionable message — otherwise the operator only sees "Invalid IAP
|
|
116
|
+
* credentials: empty token" and has no idea which knob to turn.
|
|
117
|
+
*/
|
|
118
|
+
export function describeIapRejection(res, body) {
|
|
119
|
+
if (res.headers.get("x-goog-iap-generated-response") !== "true")
|
|
120
|
+
return null;
|
|
121
|
+
const configured = Boolean(process.env.CAELO_IAP_SERVICE_ACCOUNT?.trim());
|
|
122
|
+
return configured
|
|
123
|
+
? `HTTP ${res.status} from Google IAP: ${body.trim()} — the service account in CAELO_IAP_SERVICE_ACCOUNT is not allowed on this install's IAP. Run \`cms-provision upgrade\` (it allowlists the MCP service account) or check the value against /security/mcp.`
|
|
124
|
+
: `HTTP ${res.status} from Google IAP: ${body.trim()} — this admin is protected by Google IAP. Copy the \`claude mcp add\` command from /security/mcp again (it includes CAELO_IAP_SERVICE_ACCOUNT on IAP installs) and run \`gcloud auth application-default login\`.`;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=ingress-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingress-auth.js","sourceRoot":"","sources":["../src/ingress-auth.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAWD,wBAAsB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA+GnE"}
|
package/dist/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MPL-2.0
|
|
2
2
|
/**
|
|
3
|
-
* MCP server construction. Registers
|
|
4
|
-
* and binds it to a stdio transport.
|
|
3
|
+
* MCP server construction. Registers `caelo_chat` and the image upload companion
|
|
4
|
+
* and binds it to a stdio transport. Routing edits through one conversational tool is
|
|
5
5
|
* deliberate: the remote agent talks to Caelo's chat-runner the same
|
|
6
6
|
* way a human in the browser does. Browse / publish / propose actions
|
|
7
7
|
* happen through the chat ("which pages exist?" → agent calls
|
|
@@ -13,8 +13,10 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
13
13
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
import { sendChat } from "./chat-bridge.js";
|
|
16
|
+
import { UPLOAD_IMAGES_TOOL, uploadedImageSchema, uploadImages } from "./image-upload.js";
|
|
16
17
|
const caeloChatInputSchema = z
|
|
17
18
|
.object({
|
|
19
|
+
attachments: z.array(uploadedImageSchema).max(4).optional(),
|
|
18
20
|
message: z.string().min(1).max(50_000),
|
|
19
21
|
chatSessionId: z.string().uuid().optional(),
|
|
20
22
|
pageId: z.string().uuid().optional(),
|
|
@@ -29,6 +31,7 @@ export async function startMcpServer(opts) {
|
|
|
29
31
|
});
|
|
30
32
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
31
33
|
tools: [
|
|
34
|
+
UPLOAD_IMAGES_TOOL,
|
|
32
35
|
{
|
|
33
36
|
name: "caelo_chat",
|
|
34
37
|
description: "Talk to your Caelo CMS install's AI agent. Same agent that powers the live-edit chat overlay — it can read pages, propose edits, queue Owner-approval proposals, summarise plugin data. Continues an existing chat session (when chatSessionId is supplied) or starts a fresh one. Returns the agent's reply text plus structured tool-call summaries.",
|
|
@@ -36,6 +39,12 @@ export async function startMcpServer(opts) {
|
|
|
36
39
|
type: "object",
|
|
37
40
|
required: ["message"],
|
|
38
41
|
properties: {
|
|
42
|
+
attachments: {
|
|
43
|
+
type: "array",
|
|
44
|
+
maxItems: 4,
|
|
45
|
+
description: "Attachments returned by caelo_upload_images.",
|
|
46
|
+
items: z.toJSONSchema(uploadedImageSchema),
|
|
47
|
+
},
|
|
39
48
|
message: {
|
|
40
49
|
type: "string",
|
|
41
50
|
description: "What you want to say to the Caelo agent.",
|
|
@@ -54,6 +63,14 @@ export async function startMcpServer(opts) {
|
|
|
54
63
|
],
|
|
55
64
|
}));
|
|
56
65
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
66
|
+
if (req.params.name === UPLOAD_IMAGES_TOOL.name) {
|
|
67
|
+
try {
|
|
68
|
+
return await uploadImages(opts, req.params.arguments);
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
return { isError: true, content: [{ type: "text", text: String(e) }] };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
57
74
|
if (req.params.name !== "caelo_chat") {
|
|
58
75
|
return {
|
|
59
76
|
isError: true,
|
|
@@ -72,6 +89,7 @@ export async function startMcpServer(opts) {
|
|
|
72
89
|
adminUrl: opts.adminUrl,
|
|
73
90
|
token: opts.token,
|
|
74
91
|
message: parsed.data.message,
|
|
92
|
+
...(parsed.data.attachments ? { attachments: parsed.data.attachments } : {}),
|
|
75
93
|
...(parsed.data.chatSessionId ? { chatSessionId: parsed.data.chatSessionId } : {}),
|
|
76
94
|
...(parsed.data.pageId ? { pageId: parsed.data.pageId } : {}),
|
|
77
95
|
});
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAEnC;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AACnG,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caelo-cms/mcp-server",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.28",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"description": "MCP servers for Caelo CMS: `caelo_chat` (talk to Caelo's own AI) and the admin-scoped Power-MCP (the full chat-runner tool catalogue, driven by your own agent). Lets Claude Code (or any MCP-aware client) drive a Caelo install from outside the browser.",
|
|
@@ -36,8 +36,9 @@
|
|
|
36
36
|
"prepublishOnly": "tsc -b --force"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@modelcontextprotocol/sdk": "1.
|
|
40
|
-
"
|
|
39
|
+
"@modelcontextprotocol/sdk": "1.31.0",
|
|
40
|
+
"google-auth-library": "11.1.0",
|
|
41
|
+
"zod": "4.6.5"
|
|
41
42
|
},
|
|
42
43
|
"publishConfig": {
|
|
43
44
|
"access": "public"
|