@decocms/runtime 0.0.1-testing-beta.1
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/config-schema.json +553 -0
- package/dist/admin.d.ts +5 -0
- package/dist/admin.js +21 -0
- package/dist/admin.js.map +1 -0
- package/dist/bindings/deconfig/index.d.ts +9 -0
- package/dist/bindings/deconfig/index.js +9 -0
- package/dist/bindings/deconfig/index.js.map +1 -0
- package/dist/bindings/index.d.ts +1053 -0
- package/dist/bindings/index.js +132 -0
- package/dist/bindings/index.js.map +1 -0
- package/dist/chunk-4XSQKJLU.js +105 -0
- package/dist/chunk-4XSQKJLU.js.map +1 -0
- package/dist/chunk-AOFOWQXY.js +27 -0
- package/dist/chunk-AOFOWQXY.js.map +1 -0
- package/dist/chunk-F6XZPFWM.js +127 -0
- package/dist/chunk-F6XZPFWM.js.map +1 -0
- package/dist/chunk-IB3KGSMB.js +150 -0
- package/dist/chunk-IB3KGSMB.js.map +1 -0
- package/dist/chunk-NKUMVYKI.js +128 -0
- package/dist/chunk-NKUMVYKI.js.map +1 -0
- package/dist/chunk-NMXOC7PT.js +763 -0
- package/dist/chunk-NMXOC7PT.js.map +1 -0
- package/dist/chunk-OSSKGDAG.js +395 -0
- package/dist/chunk-OSSKGDAG.js.map +1 -0
- package/dist/chunk-UHR3BLMF.js +92 -0
- package/dist/chunk-UHR3BLMF.js.map +1 -0
- package/dist/client.d.ts +28 -0
- package/dist/client.js +4 -0
- package/dist/client.js.map +1 -0
- package/dist/connection-DDtQYrea.d.ts +30 -0
- package/dist/drizzle.d.ts +47 -0
- package/dist/drizzle.js +121 -0
- package/dist/drizzle.js.map +1 -0
- package/dist/index-AKVjfH4b.d.ts +336 -0
- package/dist/index-kMsI0ELb.d.ts +530 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +507 -0
- package/dist/index.js.map +1 -0
- package/dist/mastra.d.ts +8 -0
- package/dist/mastra.js +5 -0
- package/dist/mastra.js.map +1 -0
- package/dist/mcp-Bv7IAgWX.d.ts +109 -0
- package/dist/mcp-client.d.ts +236 -0
- package/dist/mcp-client.js +3 -0
- package/dist/mcp-client.js.map +1 -0
- package/dist/proxy.d.ts +10 -0
- package/dist/proxy.js +4 -0
- package/dist/proxy.js.map +1 -0
- package/dist/resources.d.ts +362 -0
- package/dist/resources.js +3 -0
- package/dist/resources.js.map +1 -0
- package/dist/views.d.ts +72 -0
- package/dist/views.js +3 -0
- package/dist/views.js.map +1 -0
- package/package.json +98 -0
- package/src/admin.ts +16 -0
- package/src/auth.ts +233 -0
- package/src/bindings/README.md +132 -0
- package/src/bindings/binder.ts +143 -0
- package/src/bindings/channels.ts +54 -0
- package/src/bindings/deconfig/helpers.ts +107 -0
- package/src/bindings/deconfig/index.ts +1 -0
- package/src/bindings/deconfig/resources.ts +659 -0
- package/src/bindings/deconfig/types.ts +106 -0
- package/src/bindings/index.ts +61 -0
- package/src/bindings/resources/bindings.ts +99 -0
- package/src/bindings/resources/helpers.ts +95 -0
- package/src/bindings/resources/schemas.ts +265 -0
- package/src/bindings/utils.ts +22 -0
- package/src/bindings/views.ts +14 -0
- package/src/bindings.ts +179 -0
- package/src/client.ts +201 -0
- package/src/connection.ts +53 -0
- package/src/drizzle.ts +201 -0
- package/src/http-client-transport.ts +66 -0
- package/src/index.ts +394 -0
- package/src/mastra.ts +666 -0
- package/src/mcp-client.ts +119 -0
- package/src/mcp.ts +171 -0
- package/src/proxy.ts +204 -0
- package/src/resources.ts +168 -0
- package/src/state.ts +44 -0
- package/src/views.ts +26 -0
- package/src/well-known.ts +20 -0
- package/src/wrangler.ts +146 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
import { DeconfigResource, MCPClient } from './chunk-NMXOC7PT.js';
|
|
2
|
+
export { createMCPFetchStub } from './chunk-NMXOC7PT.js';
|
|
3
|
+
import './chunk-IB3KGSMB.js';
|
|
4
|
+
import './chunk-F6XZPFWM.js';
|
|
5
|
+
import { DECO_MCP_CLIENT_HEADER } from './chunk-4XSQKJLU.js';
|
|
6
|
+
import './chunk-UHR3BLMF.js';
|
|
7
|
+
import { createMCPServer, State } from './chunk-OSSKGDAG.js';
|
|
8
|
+
import './chunk-NKUMVYKI.js';
|
|
9
|
+
import './chunk-AOFOWQXY.js';
|
|
10
|
+
import { decodeJwt, jwtVerify } from 'jose';
|
|
11
|
+
|
|
12
|
+
var DECO_APP_AUTH_COOKIE_NAME = "deco_page_auth";
|
|
13
|
+
var MAX_COOKIE_SIZE = 4e3;
|
|
14
|
+
var StateParser = {
|
|
15
|
+
parse: (state) => {
|
|
16
|
+
return JSON.parse(decodeURIComponent(atob(state)));
|
|
17
|
+
},
|
|
18
|
+
stringify: (state) => {
|
|
19
|
+
return btoa(encodeURIComponent(JSON.stringify(state)));
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var chunkValue = (value) => {
|
|
23
|
+
if (value.length <= MAX_COOKIE_SIZE) {
|
|
24
|
+
return [value];
|
|
25
|
+
}
|
|
26
|
+
const chunks = [];
|
|
27
|
+
for (let i = 0; i < value.length; i += MAX_COOKIE_SIZE) {
|
|
28
|
+
chunks.push(value.slice(i, i + MAX_COOKIE_SIZE));
|
|
29
|
+
}
|
|
30
|
+
return chunks;
|
|
31
|
+
};
|
|
32
|
+
var reassembleChunkedCookies = (cookies, baseName) => {
|
|
33
|
+
if (cookies[baseName]) {
|
|
34
|
+
return cookies[baseName];
|
|
35
|
+
}
|
|
36
|
+
const chunks = [];
|
|
37
|
+
let index = 0;
|
|
38
|
+
while (true) {
|
|
39
|
+
const chunkName = `${baseName}_${index}`;
|
|
40
|
+
if (!cookies[chunkName]) {
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
chunks.push(cookies[chunkName]);
|
|
44
|
+
index++;
|
|
45
|
+
}
|
|
46
|
+
return chunks.length > 0 ? chunks.join("") : void 0;
|
|
47
|
+
};
|
|
48
|
+
var parseCookies = (cookieHeader) => {
|
|
49
|
+
const cookies = {};
|
|
50
|
+
if (!cookieHeader) return cookies;
|
|
51
|
+
cookieHeader.split(";").forEach((cookie) => {
|
|
52
|
+
const [name, ...rest] = cookie.trim().split("=");
|
|
53
|
+
if (name && rest.length > 0) {
|
|
54
|
+
cookies[name] = decodeURIComponent(rest.join("="));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return cookies;
|
|
58
|
+
};
|
|
59
|
+
var parseJWK = (jwk) => JSON.parse(atob(jwk));
|
|
60
|
+
var getReqToken = async (req, env) => {
|
|
61
|
+
const token = () => {
|
|
62
|
+
const authHeader = req.headers.get("Authorization");
|
|
63
|
+
if (authHeader) {
|
|
64
|
+
return authHeader.split(" ")[1];
|
|
65
|
+
}
|
|
66
|
+
const cookieHeader = req.headers.get("Cookie");
|
|
67
|
+
if (cookieHeader) {
|
|
68
|
+
const cookies = parseCookies(cookieHeader);
|
|
69
|
+
return reassembleChunkedCookies(cookies, DECO_APP_AUTH_COOKIE_NAME);
|
|
70
|
+
}
|
|
71
|
+
return void 0;
|
|
72
|
+
};
|
|
73
|
+
const authToken = token();
|
|
74
|
+
if (!authToken) {
|
|
75
|
+
return void 0;
|
|
76
|
+
}
|
|
77
|
+
env.DECO_API_JWT_PUBLIC_KEY && await jwtVerify(authToken, parseJWK(env.DECO_API_JWT_PUBLIC_KEY), {
|
|
78
|
+
issuer: "https://api.decocms.com",
|
|
79
|
+
algorithms: ["RS256"],
|
|
80
|
+
typ: "JWT"
|
|
81
|
+
}).catch((err) => {
|
|
82
|
+
console.error(
|
|
83
|
+
`[auth-token]: error validating: ${err} ${env.DECO_API_JWT_PUBLIC_KEY}`
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
return authToken;
|
|
87
|
+
};
|
|
88
|
+
var handleAuthCallback = async (req, options) => {
|
|
89
|
+
const url = new URL(req.url);
|
|
90
|
+
const code = url.searchParams.get("code");
|
|
91
|
+
const state = url.searchParams.get("state");
|
|
92
|
+
if (!code) {
|
|
93
|
+
return new Response("Missing authorization code", { status: 400 });
|
|
94
|
+
}
|
|
95
|
+
let next = "/";
|
|
96
|
+
if (state) {
|
|
97
|
+
try {
|
|
98
|
+
const parsedState = StateParser.parse(state);
|
|
99
|
+
next = parsedState.next || "/";
|
|
100
|
+
} catch {
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
const apiUrl = options.apiUrl ?? "https://api.decocms.com";
|
|
105
|
+
const exchangeResponse = await fetch(`${apiUrl}/apps/code-exchange`, {
|
|
106
|
+
method: "POST",
|
|
107
|
+
headers: {
|
|
108
|
+
"Content-Type": "application/json"
|
|
109
|
+
},
|
|
110
|
+
body: JSON.stringify({
|
|
111
|
+
code,
|
|
112
|
+
client_id: options.appName
|
|
113
|
+
})
|
|
114
|
+
});
|
|
115
|
+
if (!exchangeResponse.ok) {
|
|
116
|
+
console.error(
|
|
117
|
+
"authentication failed",
|
|
118
|
+
code,
|
|
119
|
+
options.appName,
|
|
120
|
+
await exchangeResponse.text().catch((_) => "")
|
|
121
|
+
);
|
|
122
|
+
return new Response("Authentication failed", { status: 401 });
|
|
123
|
+
}
|
|
124
|
+
const { access_token } = await exchangeResponse.json();
|
|
125
|
+
if (!access_token) {
|
|
126
|
+
return new Response("No access token received", { status: 401 });
|
|
127
|
+
}
|
|
128
|
+
const chunks = chunkValue(access_token);
|
|
129
|
+
const headers = new Headers();
|
|
130
|
+
headers.set("Location", next);
|
|
131
|
+
if (chunks.length === 1) {
|
|
132
|
+
headers.set(
|
|
133
|
+
"Set-Cookie",
|
|
134
|
+
`${DECO_APP_AUTH_COOKIE_NAME}=${access_token}; HttpOnly; SameSite=None; Secure; Path=/`
|
|
135
|
+
);
|
|
136
|
+
} else {
|
|
137
|
+
chunks.forEach((chunk, index) => {
|
|
138
|
+
headers.append(
|
|
139
|
+
"Set-Cookie",
|
|
140
|
+
`${DECO_APP_AUTH_COOKIE_NAME}_${index}=${chunk}; HttpOnly; SameSite=None; Secure; Path=/`
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return new Response(null, {
|
|
145
|
+
status: 302,
|
|
146
|
+
headers
|
|
147
|
+
});
|
|
148
|
+
} catch (err) {
|
|
149
|
+
return new Response(`Authentication failed ${err}`, { status: 500 });
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
var removeAuthCookie = (headers) => {
|
|
153
|
+
headers.append(
|
|
154
|
+
"Set-Cookie",
|
|
155
|
+
`${DECO_APP_AUTH_COOKIE_NAME}=; HttpOnly; SameSite=None; Secure; Path=/; Max-Age=0`
|
|
156
|
+
);
|
|
157
|
+
for (let i = 0; i < 10; i++) {
|
|
158
|
+
headers.append(
|
|
159
|
+
"Set-Cookie",
|
|
160
|
+
`${DECO_APP_AUTH_COOKIE_NAME}_${i}=; HttpOnly; SameSite=None; Secure; Path=/; Max-Age=0`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
var handleLogout = (req) => {
|
|
165
|
+
const url = new URL(req.url);
|
|
166
|
+
const next = url.searchParams.get("next");
|
|
167
|
+
const redirectTo = new URL("/", url);
|
|
168
|
+
const headers = new Headers();
|
|
169
|
+
removeAuthCookie(headers);
|
|
170
|
+
headers.set("Location", next ?? redirectTo.href);
|
|
171
|
+
return new Response(null, {
|
|
172
|
+
status: 302,
|
|
173
|
+
headers
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// src/bindings.ts
|
|
178
|
+
var normalizeWorkspace = (workspace) => {
|
|
179
|
+
if (workspace.startsWith("/users")) {
|
|
180
|
+
return workspace;
|
|
181
|
+
}
|
|
182
|
+
if (workspace.startsWith("/shared")) {
|
|
183
|
+
return workspace;
|
|
184
|
+
}
|
|
185
|
+
if (workspace.includes("/")) {
|
|
186
|
+
return workspace;
|
|
187
|
+
}
|
|
188
|
+
return `/shared/${workspace}`;
|
|
189
|
+
};
|
|
190
|
+
var createAppsUrl = ({
|
|
191
|
+
appName,
|
|
192
|
+
decoChatApiUrl
|
|
193
|
+
}) => new URL(
|
|
194
|
+
`/apps/mcp?appName=${appName}`,
|
|
195
|
+
decoChatApiUrl ?? "https://api.decocms.com"
|
|
196
|
+
).href;
|
|
197
|
+
var createIntegrationsUrl = ({
|
|
198
|
+
integrationId,
|
|
199
|
+
workspace,
|
|
200
|
+
decoCmsApiUrl,
|
|
201
|
+
branch
|
|
202
|
+
}) => {
|
|
203
|
+
const base = `${normalizeWorkspace(workspace)}/${integrationId}/mcp`;
|
|
204
|
+
const url = new URL(base, decoCmsApiUrl ?? "https://api.decocms.com");
|
|
205
|
+
branch && url.searchParams.set("branch", branch);
|
|
206
|
+
return url.href;
|
|
207
|
+
};
|
|
208
|
+
var workspaceClient = (ctx, decocmsApiUrl) => {
|
|
209
|
+
return MCPClient.forWorkspace(ctx.workspace, ctx.token, decocmsApiUrl);
|
|
210
|
+
};
|
|
211
|
+
var mcpClientForAppName = (appName, decoChatApiUrl) => {
|
|
212
|
+
const mcpConnection = {
|
|
213
|
+
type: "HTTP",
|
|
214
|
+
url: createAppsUrl({
|
|
215
|
+
appName,
|
|
216
|
+
decoChatApiUrl
|
|
217
|
+
})
|
|
218
|
+
};
|
|
219
|
+
return MCPClient.forConnection(mcpConnection, decoChatApiUrl);
|
|
220
|
+
};
|
|
221
|
+
var proxyConnectionForId = (integrationId, ctx, decocmsApiUrl, appName) => {
|
|
222
|
+
let headers = appName ? { "x-caller-app": appName } : void 0;
|
|
223
|
+
if (ctx.cookie) {
|
|
224
|
+
headers ??= {};
|
|
225
|
+
headers.cookie = ctx.cookie;
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
type: "HTTP",
|
|
229
|
+
url: createIntegrationsUrl({
|
|
230
|
+
integrationId,
|
|
231
|
+
workspace: ctx.workspace,
|
|
232
|
+
decoCmsApiUrl: decocmsApiUrl,
|
|
233
|
+
branch: ctx.branch
|
|
234
|
+
}),
|
|
235
|
+
token: ctx.token,
|
|
236
|
+
headers
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
var mcpClientForIntegrationId = (integrationId, ctx, decocmsApiUrl, appName) => {
|
|
240
|
+
const mcpConnection = proxyConnectionForId(
|
|
241
|
+
integrationId,
|
|
242
|
+
ctx,
|
|
243
|
+
decocmsApiUrl,
|
|
244
|
+
appName
|
|
245
|
+
);
|
|
246
|
+
return MCPClient.forConnection(mcpConnection, decocmsApiUrl);
|
|
247
|
+
};
|
|
248
|
+
function mcpClientFromState(binding, env) {
|
|
249
|
+
const ctx = env.DECO_REQUEST_CONTEXT;
|
|
250
|
+
const bindingFromState = ctx?.state?.[binding.name];
|
|
251
|
+
const integrationId = bindingFromState && typeof bindingFromState === "object" && "value" in bindingFromState ? bindingFromState.value : void 0;
|
|
252
|
+
if (typeof integrationId !== "string" && "integration_name" in binding) {
|
|
253
|
+
return mcpClientForAppName(binding.integration_name, env.DECO_API_URL);
|
|
254
|
+
}
|
|
255
|
+
return mcpClientForIntegrationId(
|
|
256
|
+
integrationId,
|
|
257
|
+
ctx,
|
|
258
|
+
env.DECO_API_URL,
|
|
259
|
+
env.DECO_APP_NAME
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
var createContractBinding = (binding, env) => {
|
|
263
|
+
return mcpClientFromState(binding, env);
|
|
264
|
+
};
|
|
265
|
+
var createIntegrationBinding = (binding, env) => {
|
|
266
|
+
const integrationId = "integration_id" in binding ? binding.integration_id : void 0;
|
|
267
|
+
if (!integrationId) {
|
|
268
|
+
return mcpClientFromState(binding, env);
|
|
269
|
+
}
|
|
270
|
+
return mcpClientForIntegrationId(
|
|
271
|
+
integrationId,
|
|
272
|
+
{
|
|
273
|
+
workspace: env.DECO_WORKSPACE,
|
|
274
|
+
token: env.DECO_API_TOKEN,
|
|
275
|
+
branch: env.DECO_REQUEST_CONTEXT?.branch
|
|
276
|
+
},
|
|
277
|
+
env.DECO_API_URL,
|
|
278
|
+
env.DECO_APP_NAME
|
|
279
|
+
);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
// src/index.ts
|
|
283
|
+
var WorkersMCPBindings = {
|
|
284
|
+
parse: (bindings) => {
|
|
285
|
+
if (!bindings) return [];
|
|
286
|
+
try {
|
|
287
|
+
return JSON.parse(atob(bindings));
|
|
288
|
+
} catch {
|
|
289
|
+
return [];
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
stringify: (bindings) => {
|
|
293
|
+
return btoa(JSON.stringify(bindings));
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
var creatorByType = {
|
|
297
|
+
mcp: createIntegrationBinding,
|
|
298
|
+
contract: createContractBinding
|
|
299
|
+
};
|
|
300
|
+
var withDefaultBindings = ({
|
|
301
|
+
env,
|
|
302
|
+
server,
|
|
303
|
+
ctx,
|
|
304
|
+
url
|
|
305
|
+
}) => {
|
|
306
|
+
const client = workspaceClient(ctx, env.DECO_API_URL);
|
|
307
|
+
const createWorkspaceDB = (ctx2) => {
|
|
308
|
+
const client2 = workspaceClient(ctx2, env.DECO_API_URL);
|
|
309
|
+
return {
|
|
310
|
+
query: ({ sql, params }) => {
|
|
311
|
+
return client2.DATABASES_RUN_SQL({
|
|
312
|
+
sql,
|
|
313
|
+
params
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
};
|
|
318
|
+
env["SELF"] = new Proxy(
|
|
319
|
+
{},
|
|
320
|
+
{
|
|
321
|
+
get: (_, prop) => {
|
|
322
|
+
if (prop === "toJSON") {
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
return async (args) => {
|
|
326
|
+
return await server.callTool({
|
|
327
|
+
toolCallId: prop,
|
|
328
|
+
toolCallInput: args
|
|
329
|
+
});
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
);
|
|
334
|
+
const workspaceDbBinding = {
|
|
335
|
+
...createWorkspaceDB(ctx),
|
|
336
|
+
forContext: createWorkspaceDB
|
|
337
|
+
};
|
|
338
|
+
env["DECO_API"] = MCPClient;
|
|
339
|
+
env["DECO_WORKSPACE_API"] = client;
|
|
340
|
+
env["DECO_WORKSPACE_DB"] = workspaceDbBinding;
|
|
341
|
+
env["IS_LOCAL"] = (url?.startsWith("http://localhost") || url?.startsWith("http://127.0.0.1")) ?? false;
|
|
342
|
+
};
|
|
343
|
+
var UnauthorizedError = class extends Error {
|
|
344
|
+
constructor(message, redirectTo) {
|
|
345
|
+
super(message);
|
|
346
|
+
this.redirectTo = redirectTo;
|
|
347
|
+
this.name = "UnauthorizedError";
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
var AUTH_CALLBACK_ENDPOINT = "/oauth/callback";
|
|
351
|
+
var AUTH_START_ENDPOINT = "/oauth/start";
|
|
352
|
+
var AUTH_LOGOUT_ENDPOINT = "/oauth/logout";
|
|
353
|
+
var AUTHENTICATED = (user, workspace) => () => {
|
|
354
|
+
return {
|
|
355
|
+
...user ?? {},
|
|
356
|
+
workspace
|
|
357
|
+
};
|
|
358
|
+
};
|
|
359
|
+
var withBindings = ({
|
|
360
|
+
env: _env,
|
|
361
|
+
server,
|
|
362
|
+
tokenOrContext,
|
|
363
|
+
origin,
|
|
364
|
+
url,
|
|
365
|
+
branch
|
|
366
|
+
}) => {
|
|
367
|
+
branch ??= void 0;
|
|
368
|
+
const env = _env;
|
|
369
|
+
const apiUrl = env.DECO_API_URL ?? "https://api.decocms.com";
|
|
370
|
+
let context;
|
|
371
|
+
if (typeof tokenOrContext === "string") {
|
|
372
|
+
const decoded = decodeJwt(tokenOrContext);
|
|
373
|
+
const workspace = decoded.aud;
|
|
374
|
+
context = {
|
|
375
|
+
state: decoded.state,
|
|
376
|
+
token: tokenOrContext,
|
|
377
|
+
integrationId: decoded.integrationId,
|
|
378
|
+
workspace,
|
|
379
|
+
ensureAuthenticated: AUTHENTICATED(decoded.user, workspace),
|
|
380
|
+
branch
|
|
381
|
+
};
|
|
382
|
+
} else if (typeof tokenOrContext === "object") {
|
|
383
|
+
context = tokenOrContext;
|
|
384
|
+
const decoded = decodeJwt(tokenOrContext.token);
|
|
385
|
+
const workspace = decoded.aud;
|
|
386
|
+
const appName = decoded.appName;
|
|
387
|
+
context.callerApp = appName;
|
|
388
|
+
context.integrationId ??= decoded.integrationId;
|
|
389
|
+
context.ensureAuthenticated = AUTHENTICATED(decoded.user, workspace);
|
|
390
|
+
} else {
|
|
391
|
+
context = {
|
|
392
|
+
state: void 0,
|
|
393
|
+
token: env.DECO_API_TOKEN,
|
|
394
|
+
workspace: env.DECO_WORKSPACE,
|
|
395
|
+
branch,
|
|
396
|
+
ensureAuthenticated: (options) => {
|
|
397
|
+
const workspaceHint = options?.workspaceHint ?? env.DECO_WORKSPACE;
|
|
398
|
+
const authUri = new URL("/apps/oauth", apiUrl);
|
|
399
|
+
authUri.searchParams.set("client_id", env.DECO_APP_NAME);
|
|
400
|
+
authUri.searchParams.set(
|
|
401
|
+
"redirect_uri",
|
|
402
|
+
new URL(AUTH_CALLBACK_ENDPOINT, origin ?? env.DECO_APP_ENTRYPOINT).href
|
|
403
|
+
);
|
|
404
|
+
workspaceHint && authUri.searchParams.set("workspace_hint", workspaceHint);
|
|
405
|
+
throw new UnauthorizedError("Unauthorized", authUri);
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
env.DECO_REQUEST_CONTEXT = context;
|
|
410
|
+
const bindings = WorkersMCPBindings.parse(env.DECO_BINDINGS);
|
|
411
|
+
for (const binding of bindings) {
|
|
412
|
+
env[binding.name] = creatorByType[binding.type](binding, env);
|
|
413
|
+
}
|
|
414
|
+
withDefaultBindings({
|
|
415
|
+
env,
|
|
416
|
+
server,
|
|
417
|
+
ctx: env.DECO_REQUEST_CONTEXT,
|
|
418
|
+
url
|
|
419
|
+
});
|
|
420
|
+
return env;
|
|
421
|
+
};
|
|
422
|
+
var withRuntime = (userFns) => {
|
|
423
|
+
const server = createMCPServer(userFns);
|
|
424
|
+
const fetcher = async (req, env, ctx) => {
|
|
425
|
+
const url = new URL(req.url);
|
|
426
|
+
if (url.pathname === AUTH_CALLBACK_ENDPOINT) {
|
|
427
|
+
return handleAuthCallback(req, {
|
|
428
|
+
apiUrl: env.DECO_API_URL,
|
|
429
|
+
appName: env.DECO_APP_NAME
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
if (url.pathname === AUTH_START_ENDPOINT) {
|
|
433
|
+
env.DECO_REQUEST_CONTEXT.ensureAuthenticated();
|
|
434
|
+
const redirectTo = new URL("/", url);
|
|
435
|
+
const next = url.searchParams.get("next");
|
|
436
|
+
return Response.redirect(next ?? redirectTo, 302);
|
|
437
|
+
}
|
|
438
|
+
if (url.pathname === AUTH_LOGOUT_ENDPOINT) {
|
|
439
|
+
return handleLogout(req);
|
|
440
|
+
}
|
|
441
|
+
if (url.pathname === "/mcp") {
|
|
442
|
+
return server.fetch(req, env, ctx);
|
|
443
|
+
}
|
|
444
|
+
if (url.pathname.startsWith("/mcp/call-tool")) {
|
|
445
|
+
const toolCallId = url.pathname.split("/").pop();
|
|
446
|
+
if (!toolCallId) {
|
|
447
|
+
return new Response("Not found", { status: 404 });
|
|
448
|
+
}
|
|
449
|
+
const toolCallInput = await req.json();
|
|
450
|
+
const result = await server.callTool({
|
|
451
|
+
toolCallId,
|
|
452
|
+
toolCallInput
|
|
453
|
+
});
|
|
454
|
+
if (result instanceof Response) {
|
|
455
|
+
return result;
|
|
456
|
+
}
|
|
457
|
+
return new Response(JSON.stringify(result), {
|
|
458
|
+
headers: {
|
|
459
|
+
"Content-Type": "application/json"
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
if (url.pathname.startsWith(DeconfigResource.WatchPathNameBase)) {
|
|
464
|
+
return DeconfigResource.watchAPI(req, env);
|
|
465
|
+
}
|
|
466
|
+
return userFns.fetch?.(req, env, ctx) || new Response("Not found", { status: 404 });
|
|
467
|
+
};
|
|
468
|
+
return {
|
|
469
|
+
fetch: async (req, env, ctx) => {
|
|
470
|
+
const referer = req.headers.get("referer");
|
|
471
|
+
const isFetchRequest = req.headers.has(DECO_MCP_CLIENT_HEADER);
|
|
472
|
+
try {
|
|
473
|
+
const bindings = withBindings({
|
|
474
|
+
env,
|
|
475
|
+
server,
|
|
476
|
+
branch: req.headers.get("x-deco-branch") ?? new URL(req.url).searchParams.get("__b"),
|
|
477
|
+
tokenOrContext: await getReqToken(req, env),
|
|
478
|
+
origin: referer ?? req.headers.get("origin") ?? new URL(req.url).origin,
|
|
479
|
+
url: req.url
|
|
480
|
+
});
|
|
481
|
+
return await State.run(
|
|
482
|
+
{ req, env: bindings, ctx },
|
|
483
|
+
async () => await fetcher(req, bindings, ctx)
|
|
484
|
+
);
|
|
485
|
+
} catch (error) {
|
|
486
|
+
if (error instanceof UnauthorizedError) {
|
|
487
|
+
if (!isFetchRequest) {
|
|
488
|
+
const url = new URL(req.url);
|
|
489
|
+
error.redirectTo.searchParams.set(
|
|
490
|
+
"state",
|
|
491
|
+
StateParser.stringify({
|
|
492
|
+
next: url.searchParams.get("next") ?? referer ?? req.url
|
|
493
|
+
})
|
|
494
|
+
);
|
|
495
|
+
return Response.redirect(error.redirectTo, 302);
|
|
496
|
+
}
|
|
497
|
+
return new Response(null, { status: 401 });
|
|
498
|
+
}
|
|
499
|
+
throw error;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
export { UnauthorizedError, WorkersMCPBindings, proxyConnectionForId, withBindings, withRuntime };
|
|
506
|
+
//# sourceMappingURL=index.js.map
|
|
507
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/auth.ts","../src/bindings.ts","../src/index.ts"],"names":["ctx","client"],"mappings":"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","file":"index.js","sourcesContent":["import { JWK, jwtVerify } from \"jose\";\nimport type { DefaultEnv } from \"./index.ts\";\n\nconst DECO_APP_AUTH_COOKIE_NAME = \"deco_page_auth\";\nconst MAX_COOKIE_SIZE = 4000; // Leave some buffer below the 4096 limit\n\nexport interface State {\n next?: string;\n}\n\nexport const StateParser = {\n parse: (state: string) => {\n return JSON.parse(decodeURIComponent(atob(state))) as State;\n },\n stringify: (state: State) => {\n return btoa(encodeURIComponent(JSON.stringify(state)));\n },\n};\n\n// Helper function to chunk a value into multiple cookies\nconst chunkValue = (value: string): string[] => {\n if (value.length <= MAX_COOKIE_SIZE) {\n return [value];\n }\n\n const chunks: string[] = [];\n for (let i = 0; i < value.length; i += MAX_COOKIE_SIZE) {\n chunks.push(value.slice(i, i + MAX_COOKIE_SIZE));\n }\n return chunks;\n};\n\n// Helper function to reassemble chunked cookies\nconst reassembleChunkedCookies = (\n cookies: Record<string, string>,\n baseName: string,\n): string | undefined => {\n // First try the base cookie (non-chunked)\n if (cookies[baseName]) {\n return cookies[baseName];\n }\n\n // Try to reassemble from chunks\n const chunks: string[] = [];\n let index = 0;\n\n while (true) {\n const chunkName = `${baseName}_${index}`;\n if (!cookies[chunkName]) {\n break;\n }\n chunks.push(cookies[chunkName]);\n index++;\n }\n\n return chunks.length > 0 ? chunks.join(\"\") : undefined;\n};\n\n// Helper function to parse cookies from request\nconst parseCookies = (cookieHeader: string): Record<string, string> => {\n const cookies: Record<string, string> = {};\n if (!cookieHeader) return cookies;\n\n cookieHeader.split(\";\").forEach((cookie) => {\n const [name, ...rest] = cookie.trim().split(\"=\");\n if (name && rest.length > 0) {\n cookies[name] = decodeURIComponent(rest.join(\"=\"));\n }\n });\n\n return cookies;\n};\n\nconst parseJWK = (jwk: string): JWK => JSON.parse(atob(jwk)) as JWK;\n\nexport const getReqToken = async (req: Request, env: DefaultEnv) => {\n const token = () => {\n // First try to get token from Authorization header\n const authHeader = req.headers.get(\"Authorization\");\n if (authHeader) {\n return authHeader.split(\" \")[1];\n }\n\n // If not found, try to get from cookie\n const cookieHeader = req.headers.get(\"Cookie\");\n if (cookieHeader) {\n const cookies = parseCookies(cookieHeader);\n return reassembleChunkedCookies(cookies, DECO_APP_AUTH_COOKIE_NAME);\n }\n\n return undefined;\n };\n\n const authToken = token();\n if (!authToken) {\n return undefined;\n }\n\n env.DECO_API_JWT_PUBLIC_KEY &&\n (await jwtVerify(authToken, parseJWK(env.DECO_API_JWT_PUBLIC_KEY), {\n issuer: \"https://api.decocms.com\",\n algorithms: [\"RS256\"],\n typ: \"JWT\",\n }).catch((err) => {\n console.error(\n `[auth-token]: error validating: ${err} ${env.DECO_API_JWT_PUBLIC_KEY}`,\n );\n }));\n\n return authToken;\n};\n\nexport interface AuthCallbackOptions {\n apiUrl?: string;\n appName: string;\n}\n\nexport const handleAuthCallback = async (\n req: Request,\n options: AuthCallbackOptions,\n): Promise<Response> => {\n const url = new URL(req.url);\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n\n if (!code) {\n return new Response(\"Missing authorization code\", { status: 400 });\n }\n\n // Parse state to get the next URL\n let next = \"/\";\n if (state) {\n try {\n const parsedState = StateParser.parse(state);\n next = parsedState.next || \"/\";\n } catch {\n // ignore parse errors\n }\n }\n\n try {\n // Exchange code for token\n const apiUrl = options.apiUrl ?? \"https://api.decocms.com\";\n const exchangeResponse = await fetch(`${apiUrl}/apps/code-exchange`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n code,\n client_id: options.appName,\n }),\n });\n\n if (!exchangeResponse.ok) {\n console.error(\n \"authentication failed\",\n code,\n options.appName,\n await exchangeResponse.text().catch((_) => \"\"),\n );\n return new Response(\"Authentication failed\", { status: 401 });\n }\n\n const { access_token } = (await exchangeResponse.json()) as {\n access_token: string;\n };\n\n if (!access_token) {\n return new Response(\"No access token received\", { status: 401 });\n }\n\n // Chunk the token if it's too large\n const chunks = chunkValue(access_token);\n const headers = new Headers();\n headers.set(\"Location\", next);\n\n // Set cookies for each chunk\n if (chunks.length === 1) {\n // Single cookie for small tokens\n headers.set(\n \"Set-Cookie\",\n `${DECO_APP_AUTH_COOKIE_NAME}=${access_token}; HttpOnly; SameSite=None; Secure; Path=/`,\n );\n } else {\n // Multiple cookies for large tokens\n chunks.forEach((chunk, index) => {\n headers.append(\n \"Set-Cookie\",\n `${DECO_APP_AUTH_COOKIE_NAME}_${index}=${chunk}; HttpOnly; SameSite=None; Secure; Path=/`,\n );\n });\n }\n\n return new Response(null, {\n status: 302,\n headers,\n });\n } catch (err) {\n return new Response(`Authentication failed ${err}`, { status: 500 });\n }\n};\n\nconst removeAuthCookie = (headers: Headers) => {\n // Clear the base cookie\n headers.append(\n \"Set-Cookie\",\n `${DECO_APP_AUTH_COOKIE_NAME}=; HttpOnly; SameSite=None; Secure; Path=/; Max-Age=0`,\n );\n\n // Clear all potential chunked cookies\n // We'll try to clear up to 10 chunks (which would support tokens up to 40KB)\n // This is a reasonable upper limit\n for (let i = 0; i < 10; i++) {\n headers.append(\n \"Set-Cookie\",\n `${DECO_APP_AUTH_COOKIE_NAME}_${i}=; HttpOnly; SameSite=None; Secure; Path=/; Max-Age=0`,\n );\n }\n};\n\nexport const handleLogout = (req: Request) => {\n const url = new URL(req.url);\n const next = url.searchParams.get(\"next\");\n const redirectTo = new URL(\"/\", url);\n const headers = new Headers();\n removeAuthCookie(headers);\n headers.set(\"Location\", next ?? redirectTo.href);\n return new Response(null, {\n status: 302,\n headers,\n });\n};\n","import type { MCPConnection } from \"./connection.ts\";\nimport type { DefaultEnv, RequestContext } from \"./index.ts\";\nimport { MCPClient } from \"./mcp.ts\";\nimport type {\n BindingBase,\n ContractBinding,\n MCPBinding,\n MCPIntegrationNameBinding,\n} from \"./wrangler.ts\";\n\ninterface IntegrationContext {\n integrationId: string;\n workspace: string;\n branch?: string;\n decoCmsApiUrl?: string;\n}\n\nconst normalizeWorkspace = (workspace: string) => {\n if (workspace.startsWith(\"/users\")) {\n return workspace;\n }\n if (workspace.startsWith(\"/shared\")) {\n return workspace;\n }\n if (workspace.includes(\"/\")) {\n return workspace;\n }\n return `/shared/${workspace}`;\n};\n\n/**\n * Url: /apps/mcp?appName=$appName\n */\nconst createAppsUrl = ({\n appName,\n decoChatApiUrl,\n}: {\n appName: string;\n decoChatApiUrl?: string;\n}) =>\n new URL(\n `/apps/mcp?appName=${appName}`,\n decoChatApiUrl ?? \"https://api.decocms.com\",\n ).href;\n/**\n * Url: /:workspace.root/:workspace.slug/:integrationId/mcp\n */\nconst createIntegrationsUrl = ({\n integrationId,\n workspace,\n decoCmsApiUrl,\n branch,\n}: IntegrationContext) => {\n const base = `${normalizeWorkspace(workspace)}/${integrationId}/mcp`;\n const url = new URL(base, decoCmsApiUrl ?? \"https://api.decocms.com\");\n branch && url.searchParams.set(\"branch\", branch);\n return url.href;\n};\n\ntype WorkspaceClientContext = Omit<\n RequestContext,\n \"ensureAuthenticated\" | \"state\" | \"fetchIntegrationMetadata\"\n>;\nexport const workspaceClient = (\n ctx: WorkspaceClientContext,\n decocmsApiUrl?: string,\n): ReturnType<(typeof MCPClient)[\"forWorkspace\"]> => {\n return MCPClient.forWorkspace(ctx.workspace, ctx.token, decocmsApiUrl);\n};\n\nconst mcpClientForAppName = (appName: string, decoChatApiUrl?: string) => {\n const mcpConnection: MCPConnection = {\n type: \"HTTP\",\n url: createAppsUrl({\n appName,\n decoChatApiUrl,\n }),\n };\n\n return MCPClient.forConnection(mcpConnection, decoChatApiUrl);\n};\n\nexport const proxyConnectionForId = (\n integrationId: string,\n ctx: Omit<WorkspaceClientContext, \"token\"> & {\n token?: string;\n cookie?: string;\n },\n decocmsApiUrl?: string,\n appName?: string,\n): MCPConnection => {\n let headers: Record<string, string> | undefined = appName\n ? { \"x-caller-app\": appName }\n : undefined;\n if (ctx.cookie) {\n headers ??= {};\n headers.cookie = ctx.cookie;\n }\n return {\n type: \"HTTP\",\n url: createIntegrationsUrl({\n integrationId,\n workspace: ctx.workspace,\n decoCmsApiUrl: decocmsApiUrl,\n branch: ctx.branch,\n }),\n token: ctx.token,\n headers,\n };\n};\nconst mcpClientForIntegrationId = (\n integrationId: string,\n ctx: WorkspaceClientContext,\n decocmsApiUrl?: string,\n appName?: string,\n) => {\n const mcpConnection = proxyConnectionForId(\n integrationId,\n ctx,\n decocmsApiUrl,\n appName,\n );\n\n // TODO(@igorbrasileiro): Switch this proxy to be a proxy that call MCP Client.toolCall from @modelcontextprotocol\n return MCPClient.forConnection(mcpConnection, decocmsApiUrl);\n};\n\nfunction mcpClientFromState(\n binding: BindingBase | MCPIntegrationNameBinding,\n env: DefaultEnv,\n) {\n const ctx = env.DECO_REQUEST_CONTEXT;\n const bindingFromState = ctx?.state?.[binding.name];\n const integrationId =\n bindingFromState &&\n typeof bindingFromState === \"object\" &&\n \"value\" in bindingFromState\n ? bindingFromState.value\n : undefined;\n if (typeof integrationId !== \"string\" && \"integration_name\" in binding) {\n // in case of a binding to an app name, we need to use the new apps/mcp endpoint which will proxy the request to the app but without any token\n return mcpClientForAppName(binding.integration_name, env.DECO_API_URL);\n }\n return mcpClientForIntegrationId(\n integrationId,\n ctx,\n env.DECO_API_URL,\n env.DECO_APP_NAME,\n );\n}\n\nexport const createContractBinding = (\n binding: ContractBinding,\n env: DefaultEnv,\n) => {\n return mcpClientFromState(binding, env);\n};\n\nexport const createIntegrationBinding = (\n binding: MCPBinding,\n env: DefaultEnv,\n) => {\n const integrationId =\n \"integration_id\" in binding ? binding.integration_id : undefined;\n if (!integrationId) {\n return mcpClientFromState(binding, env);\n }\n // bindings pointed to an specific integration id are binded using the app deployment workspace\n return mcpClientForIntegrationId(\n integrationId,\n {\n workspace: env.DECO_WORKSPACE,\n token: env.DECO_API_TOKEN,\n branch: env.DECO_REQUEST_CONTEXT?.branch,\n },\n env.DECO_API_URL,\n env.DECO_APP_NAME,\n );\n};\n","/* oxlint-disable no-explicit-any */\nimport type { ExecutionContext } from \"@cloudflare/workers-types\";\nimport { decodeJwt } from \"jose\";\nimport type { z } from \"zod\";\nimport {\n getReqToken,\n handleAuthCallback,\n handleLogout,\n StateParser,\n} from \"./auth.ts\";\nimport {\n createContractBinding,\n createIntegrationBinding,\n workspaceClient,\n} from \"./bindings.ts\";\nimport { DeconfigResource } from \"./bindings/deconfig/index.ts\";\nimport { DECO_MCP_CLIENT_HEADER } from \"./client.ts\";\nimport {\n createMCPServer,\n type CreateMCPServerOptions,\n MCPServer,\n} from \"./mastra.ts\";\nimport { MCPClient, type QueryResult } from \"./mcp.ts\";\nimport { State } from \"./state.ts\";\nimport type { Binding, ContractBinding, MCPBinding } from \"./wrangler.ts\";\nexport { proxyConnectionForId } from \"./bindings.ts\";\nexport {\n createMCPFetchStub,\n type CreateStubAPIOptions,\n type ToolBinder,\n} from \"./mcp.ts\";\nexport interface WorkspaceDB {\n query: (params: {\n sql: string;\n params: string[];\n }) => Promise<{ result: QueryResult[] }>;\n}\n\nexport interface DefaultEnv<TSchema extends z.ZodTypeAny = any> {\n DECO_REQUEST_CONTEXT: RequestContext<TSchema>;\n DECO_APP_NAME: string;\n DECO_APP_SLUG: string;\n DECO_APP_ENTRYPOINT: string;\n DECO_API_URL?: string;\n DECO_WORKSPACE: string;\n DECO_API_JWT_PUBLIC_KEY: string;\n DECO_APP_DEPLOYMENT_ID: string;\n DECO_BINDINGS: string;\n DECO_API_TOKEN: string;\n DECO_WORKSPACE_DB: WorkspaceDB & {\n forContext: (ctx: RequestContext) => WorkspaceDB;\n };\n IS_LOCAL: boolean;\n [key: string]: unknown;\n}\n\nexport interface BindingsObject {\n bindings?: Binding[];\n}\n\nexport const WorkersMCPBindings = {\n parse: (bindings?: string): Binding[] => {\n if (!bindings) return [];\n try {\n return JSON.parse(atob(bindings)) as Binding[];\n } catch {\n return [];\n }\n },\n stringify: (bindings: Binding[]): string => {\n return btoa(JSON.stringify(bindings));\n },\n};\n\nexport interface UserDefaultExport<\n TUserEnv = Record<string, unknown>,\n TSchema extends z.ZodTypeAny = never,\n TEnv = TUserEnv & DefaultEnv<TSchema>,\n> extends CreateMCPServerOptions<TEnv, TSchema> {\n fetch?: (\n req: Request,\n env: TEnv,\n ctx: ExecutionContext,\n ) => Promise<Response> | Response;\n}\n\n// 1. Map binding type to its interface\ninterface BindingTypeMap {\n mcp: MCPBinding;\n contract: ContractBinding;\n}\n\nexport interface User {\n id: string;\n email: string;\n workspace: string;\n user_metadata: {\n avatar_url: string;\n full_name: string;\n picture: string;\n [key: string]: unknown;\n };\n}\n\nexport interface RequestContext<TSchema extends z.ZodTypeAny = any> {\n state: z.infer<TSchema>;\n branch?: string;\n token: string;\n workspace: string;\n ensureAuthenticated: (options?: {\n workspaceHint?: string;\n }) => User | undefined;\n callerApp?: string;\n integrationId?: string;\n}\n\n// 2. Map binding type to its creator function\ntype CreatorByType = {\n [K in keyof BindingTypeMap]: (\n value: BindingTypeMap[K],\n env: DefaultEnv,\n ) => unknown;\n};\n\n// 3. Strongly type creatorByType\nconst creatorByType: CreatorByType = {\n mcp: createIntegrationBinding,\n contract: createContractBinding,\n};\n\nconst withDefaultBindings = ({\n env,\n server,\n ctx,\n url,\n}: {\n env: DefaultEnv;\n server: MCPServer<any, any>;\n ctx: RequestContext;\n url?: string;\n}) => {\n const client = workspaceClient(ctx, env.DECO_API_URL);\n const createWorkspaceDB = (ctx: RequestContext): WorkspaceDB => {\n const client = workspaceClient(ctx, env.DECO_API_URL);\n return {\n query: ({ sql, params }) => {\n return client.DATABASES_RUN_SQL({\n sql,\n params,\n });\n },\n };\n };\n env[\"SELF\"] = new Proxy(\n {},\n {\n get: (_, prop) => {\n if (prop === \"toJSON\") {\n return null;\n }\n\n return async (args: unknown) => {\n return await server.callTool({\n toolCallId: prop as string,\n toolCallInput: args,\n });\n };\n },\n },\n );\n\n const workspaceDbBinding = {\n ...createWorkspaceDB(ctx),\n forContext: createWorkspaceDB,\n };\n\n env[\"DECO_API\"] = MCPClient;\n env[\"DECO_WORKSPACE_API\"] = client;\n env[\"DECO_WORKSPACE_DB\"] = workspaceDbBinding;\n\n env[\"IS_LOCAL\"] =\n (url?.startsWith(\"http://localhost\") ||\n url?.startsWith(\"http://127.0.0.1\")) ??\n false;\n};\n\nexport class UnauthorizedError extends Error {\n constructor(\n message: string,\n public redirectTo: URL,\n ) {\n super(message);\n this.name = \"UnauthorizedError\";\n }\n}\n\nconst AUTH_CALLBACK_ENDPOINT = \"/oauth/callback\";\nconst AUTH_START_ENDPOINT = \"/oauth/start\";\nconst AUTH_LOGOUT_ENDPOINT = \"/oauth/logout\";\nconst AUTHENTICATED = (user?: unknown, workspace?: string) => () => {\n return {\n ...((user as User) ?? {}),\n workspace,\n } as User;\n};\n\nexport const withBindings = <TEnv>({\n env: _env,\n server,\n tokenOrContext,\n origin,\n url,\n branch,\n}: {\n env: TEnv;\n server: MCPServer<TEnv, any>;\n tokenOrContext?: string | RequestContext;\n origin?: string | null;\n url?: string;\n branch?: string | null;\n}): TEnv => {\n branch ??= undefined;\n const env = _env as DefaultEnv<any>;\n\n const apiUrl = env.DECO_API_URL ?? \"https://api.decocms.com\";\n let context;\n if (typeof tokenOrContext === \"string\") {\n const decoded = decodeJwt(tokenOrContext);\n const workspace = decoded.aud as string;\n\n context = {\n state: decoded.state as Record<string, unknown>,\n token: tokenOrContext,\n integrationId: decoded.integrationId as string,\n workspace,\n ensureAuthenticated: AUTHENTICATED(decoded.user, workspace),\n branch,\n } as RequestContext<any>;\n } else if (typeof tokenOrContext === \"object\") {\n context = tokenOrContext;\n const decoded = decodeJwt(tokenOrContext.token);\n const workspace = decoded.aud as string;\n const appName = decoded.appName as string | undefined;\n context.callerApp = appName;\n context.integrationId ??= decoded.integrationId as string;\n context.ensureAuthenticated = AUTHENTICATED(decoded.user, workspace);\n } else {\n context = {\n state: undefined,\n token: env.DECO_API_TOKEN,\n workspace: env.DECO_WORKSPACE,\n branch,\n ensureAuthenticated: (options?: { workspaceHint?: string }) => {\n const workspaceHint = options?.workspaceHint ?? env.DECO_WORKSPACE;\n const authUri = new URL(\"/apps/oauth\", apiUrl);\n authUri.searchParams.set(\"client_id\", env.DECO_APP_NAME);\n authUri.searchParams.set(\n \"redirect_uri\",\n new URL(AUTH_CALLBACK_ENDPOINT, origin ?? env.DECO_APP_ENTRYPOINT)\n .href,\n );\n workspaceHint &&\n authUri.searchParams.set(\"workspace_hint\", workspaceHint);\n throw new UnauthorizedError(\"Unauthorized\", authUri);\n },\n };\n }\n\n env.DECO_REQUEST_CONTEXT = context;\n const bindings = WorkersMCPBindings.parse(env.DECO_BINDINGS);\n\n for (const binding of bindings) {\n env[binding.name] = creatorByType[binding.type](binding as any, env);\n }\n\n withDefaultBindings({\n env,\n server,\n ctx: env.DECO_REQUEST_CONTEXT,\n url,\n });\n\n return env as TEnv;\n};\n\nexport const withRuntime = <TEnv, TSchema extends z.ZodTypeAny = never>(\n userFns: UserDefaultExport<TEnv, TSchema>,\n): ExportedHandler<TEnv & DefaultEnv<TSchema>> => {\n const server = createMCPServer<TEnv, TSchema>(userFns);\n const fetcher = async (\n req: Request,\n env: TEnv & DefaultEnv<TSchema>,\n ctx: ExecutionContext,\n ) => {\n const url = new URL(req.url);\n if (url.pathname === AUTH_CALLBACK_ENDPOINT) {\n return handleAuthCallback(req, {\n apiUrl: env.DECO_API_URL,\n appName: env.DECO_APP_NAME,\n });\n }\n if (url.pathname === AUTH_START_ENDPOINT) {\n env.DECO_REQUEST_CONTEXT.ensureAuthenticated();\n const redirectTo = new URL(\"/\", url);\n const next = url.searchParams.get(\"next\");\n return Response.redirect(next ?? redirectTo, 302);\n }\n if (url.pathname === AUTH_LOGOUT_ENDPOINT) {\n return handleLogout(req);\n }\n if (url.pathname === \"/mcp\") {\n return server.fetch(req, env, ctx);\n }\n\n if (url.pathname.startsWith(\"/mcp/call-tool\")) {\n const toolCallId = url.pathname.split(\"/\").pop();\n if (!toolCallId) {\n return new Response(\"Not found\", { status: 404 });\n }\n const toolCallInput = await req.json();\n const result = await server.callTool({\n toolCallId,\n toolCallInput,\n });\n\n if (result instanceof Response) {\n return result;\n }\n\n return new Response(JSON.stringify(result), {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n }\n\n if (url.pathname.startsWith(DeconfigResource.WatchPathNameBase)) {\n return DeconfigResource.watchAPI(req, env);\n }\n return (\n userFns.fetch?.(req, env, ctx) ||\n new Response(\"Not found\", { status: 404 })\n );\n };\n return {\n fetch: async (\n req: Request,\n env: TEnv & DefaultEnv<TSchema>,\n ctx: ExecutionContext,\n ) => {\n const referer = req.headers.get(\"referer\");\n const isFetchRequest = req.headers.has(DECO_MCP_CLIENT_HEADER);\n\n try {\n const bindings = withBindings({\n env,\n server,\n branch:\n req.headers.get(\"x-deco-branch\") ??\n new URL(req.url).searchParams.get(\"__b\"),\n tokenOrContext: await getReqToken(req, env),\n origin:\n referer ?? req.headers.get(\"origin\") ?? new URL(req.url).origin,\n url: req.url,\n });\n return await State.run(\n { req, env: bindings, ctx },\n async () => await fetcher(req, bindings, ctx),\n );\n } catch (error) {\n if (error instanceof UnauthorizedError) {\n if (!isFetchRequest) {\n const url = new URL(req.url);\n error.redirectTo.searchParams.set(\n \"state\",\n StateParser.stringify({\n next: url.searchParams.get(\"next\") ?? referer ?? req.url,\n }),\n );\n return Response.redirect(error.redirectTo, 302);\n }\n return new Response(null, { status: 401 });\n }\n throw error;\n }\n },\n };\n};\n\nexport {\n type Contract,\n type Migration,\n type WranglerConfig,\n} from \"./wrangler.ts\";\n"]}
|
package/dist/mastra.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import '@mastra/core';
|
|
2
|
+
import '@mastra/core/di';
|
|
3
|
+
import 'zod';
|
|
4
|
+
export { A as AppContext, e as CreateMCPServerOptions, C as CreatedTool, E as ExecWithContext, F as Fetch, I as Integration, M as MCPServer, R as Resources, S as StreamableTool, V as ViewExport, f as createMCPServer, c as createPrivateTool, a as createRuntimeContext, b as createStreamableTool, d as createTool, i as isStreamableTool } from './index-AKVjfH4b.js';
|
|
5
|
+
import './resources.js';
|
|
6
|
+
import '@cloudflare/workers-types';
|
|
7
|
+
import './mcp-Bv7IAgWX.js';
|
|
8
|
+
import './connection-DDtQYrea.js';
|
package/dist/mastra.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createMCPServer, createPrivateTool, createRuntimeContext, createStreamableTool, createTool, isStreamableTool } from './chunk-OSSKGDAG.js';
|
|
2
|
+
import './chunk-NKUMVYKI.js';
|
|
3
|
+
import './chunk-AOFOWQXY.js';
|
|
4
|
+
//# sourceMappingURL=mastra.js.map
|
|
5
|
+
//# sourceMappingURL=mastra.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"mastra.js"}
|