@stackable-labs/mcp-app-extension 0.24.0 → 1.0.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.
- package/dist/index.js +753 -28
- package/dist/server.js +82 -21
- package/package.json +1 -1
- package/dist/auth-DWIWIJNN.js +0 -629
- package/dist/auth-WHLYYSCQ.js +0 -630
- package/dist/chunk-DCPV7HMV.js +0 -108
- package/dist/chunk-HOOVB46Z.js +0 -107
package/dist/server.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { STANDALONE_CLIENT, MCP_AUTH_FILE, getToken, STANDALONE_CLIENT_AUTH_FILE } from './chunk-HOOVB46Z.js';
|
|
2
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
-
import { IDENTITY_EVENT, ACTIVITY_EVENT, SURFACE_TARGET, PERMISSIONS, CAPABILITY_PERMISSION_MAP, ALLOWED_ICONS, UI_TAGS, UI_TAG_ATTRIBUTES, tagToComponentName } from '@stackable-labs/sdk-extension-contracts';
|
|
2
|
+
import { IDENTITY_EVENT, ACTIVITY_EVENT, SURFACE_TARGET, TEMPLATE_FLAVORS, PERMISSIONS, CAPABILITY_PERMISSION_MAP, EVENT_HOOK_PERMISSION_MAP, ALLOWED_ICONS, UI_TAGS, UI_TAG_ATTRIBUTES, tagToComponentName } from '@stackable-labs/sdk-extension-contracts';
|
|
3
|
+
import { readFile } from 'fs/promises';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { homedir } from 'os';
|
|
4
6
|
import { z } from 'zod';
|
|
5
7
|
|
|
8
|
+
// src/server.ts
|
|
9
|
+
|
|
6
10
|
// ../../sdk/extension/ai-docs/src/generated/template-content.ts
|
|
7
11
|
var PATTERN_SECTIONS = [
|
|
8
12
|
{
|
|
@@ -1736,8 +1740,6 @@ export const Header = () => {
|
|
|
1736
1740
|
- **Use ScrollArea** \u2014 wrap content surfaces in \`<ui.ScrollArea>\` for overflow handling
|
|
1737
1741
|
`;
|
|
1738
1742
|
};
|
|
1739
|
-
|
|
1740
|
-
// ../../sdk/extension/ai-docs/src/cli-commands.ts
|
|
1741
1743
|
var DLX = "pnpm --config.dlx-cache-max-age=0 dlx";
|
|
1742
1744
|
var CLI = {
|
|
1743
1745
|
/** Scaffold a new extension project */
|
|
@@ -1766,11 +1768,14 @@ var CLI = {
|
|
|
1766
1768
|
mcp: `${DLX} @stackable-labs/cli-app-extension@latest ai mcp`
|
|
1767
1769
|
}
|
|
1768
1770
|
};
|
|
1769
|
-
var
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1771
|
+
var TEMPLATE_FLAVOR_META = {
|
|
1772
|
+
minimal: { label: "Minimal", description: "Bare minimum \u2014 single surface, hello-world component" },
|
|
1773
|
+
starter: { label: "Starter", description: "Common patterns \u2014 store, api helpers, menu (default)" },
|
|
1774
|
+
"kitchen-sink": { label: "Kitchen Sink", description: "Everything \u2014 every component, capability, surface, and hook" }
|
|
1775
|
+
};
|
|
1776
|
+
var TEMPLATE_FLAVOR_DETAILS = TEMPLATE_FLAVORS.map(
|
|
1777
|
+
(name) => ({ name, ...TEMPLATE_FLAVOR_META[name] })
|
|
1778
|
+
);
|
|
1774
1779
|
|
|
1775
1780
|
// ../../sdk/extension/ai-docs/src/generators/quick-start.ts
|
|
1776
1781
|
var generateQuickStart = () => {
|
|
@@ -1962,7 +1967,7 @@ var generateCliReference = () => {
|
|
|
1962
1967
|
description: "CLI commands for creating, developing, and deploying Stackable extensions",
|
|
1963
1968
|
globs: ["packages/extension/src/**/*.tsx", "packages/extension/src/**/*.ts"]
|
|
1964
1969
|
});
|
|
1965
|
-
const templateRows =
|
|
1970
|
+
const templateRows = TEMPLATE_FLAVOR_DETAILS.map((t) => `| \`${t.name}\` | ${t.description} |`).join("\n");
|
|
1966
1971
|
return `${fm}
|
|
1967
1972
|
|
|
1968
1973
|
# CLI Reference
|
|
@@ -3380,6 +3385,7 @@ var generateValidateExtensionCommand = () => {
|
|
|
3380
3385
|
description: "Validate this extension for common errors before deploying (manifest, permissions, surfaces, imports)",
|
|
3381
3386
|
targets: ["*"]
|
|
3382
3387
|
});
|
|
3388
|
+
const eventHookBullets = Object.keys(EVENT_HOOK_PERMISSION_MAP).map((hook) => `- \`${hook}\` \u2192 needs \`${EVENT_HOOK_PERMISSION_MAP[hook]}\` permission (also check manifest \`events\` array has matching entries)`).join("\n");
|
|
3383
3389
|
return `${fm}
|
|
3384
3390
|
|
|
3385
3391
|
# Validate Extension
|
|
@@ -3415,9 +3421,7 @@ Scan all \`.tsx\` files in \`packages/extension/src/\` for capability usage:
|
|
|
3415
3421
|
- \`capabilities.actions.toast\` \u2192 needs \`actions:toast\` permission
|
|
3416
3422
|
- \`capabilities.actions.invoke\` \u2192 needs \`actions:invoke\` permission
|
|
3417
3423
|
- \`useExtendIdentity\` \u2192 needs \`extend:identity\` permission
|
|
3418
|
-
|
|
3419
|
-
- \`useMessagingEvent\` \u2192 needs \`events:messaging\` permission (also check manifest \`events\` array has matching entries)
|
|
3420
|
-
- \`useActivityEvent\` \u2192 needs \`events:activity\` permission (also check manifest \`events\` array has matching entries)
|
|
3424
|
+
${eventHookBullets}
|
|
3421
3425
|
|
|
3422
3426
|
Report:
|
|
3423
3427
|
- **Missing permissions:** capabilities used in code but not declared in manifest
|
|
@@ -4431,6 +4435,64 @@ pair(EXAMPLE_SNIPPETS, EXAMPLE_SNIPPETS2);
|
|
|
4431
4435
|
pair(CAPABILITY_SNIPPETS, CAPABILITY_SNIPPETS2);
|
|
4432
4436
|
pair(EVENT_SNIPPETS, EVENT_SNIPPETS2);
|
|
4433
4437
|
|
|
4438
|
+
// ../../lib/contracts/src/custom.ts
|
|
4439
|
+
var CUSTOM_ROLE = {
|
|
4440
|
+
SUPER_ADMIN: "super_admin"
|
|
4441
|
+
};
|
|
4442
|
+
new Set(Object.values(CUSTOM_ROLE));
|
|
4443
|
+
|
|
4444
|
+
// ../../lib/utils-auth/src/constants.ts
|
|
4445
|
+
var STANDALONE_CLIENT_DATA = {
|
|
4446
|
+
CLI: { name: "@stackable-labs/cli-app-extension", authFile: "cli-auth.json" },
|
|
4447
|
+
MCP: { name: "@stackable-labs/mcp-app-extension", authFile: "mcp-auth.json" }
|
|
4448
|
+
};
|
|
4449
|
+
var STANDALONE_CLIENT = Object.fromEntries(
|
|
4450
|
+
Object.entries(STANDALONE_CLIENT_DATA).map(([k, v]) => [k, v.name])
|
|
4451
|
+
);
|
|
4452
|
+
var STANDALONE_CLIENT_AUTH_FILE = Object.fromEntries(
|
|
4453
|
+
Object.entries(STANDALONE_CLIENT_DATA).map(([k, v]) => [k, v.authFile])
|
|
4454
|
+
);
|
|
4455
|
+
Object.values(STANDALONE_CLIENT);
|
|
4456
|
+
|
|
4457
|
+
// ../../lib/utils-auth/src/index.ts
|
|
4458
|
+
var AUTH_DIR = join(homedir(), ".stackable");
|
|
4459
|
+
join(AUTH_DIR, STANDALONE_CLIENT_AUTH_FILE.CLI);
|
|
4460
|
+
var MCP_AUTH_FILE = join(AUTH_DIR, STANDALONE_CLIENT_AUTH_FILE.MCP);
|
|
4461
|
+
var resolveAuthFile = (filename) => join(AUTH_DIR, filename ?? STANDALONE_CLIENT_AUTH_FILE.CLI);
|
|
4462
|
+
var readAuthState = async (filename) => {
|
|
4463
|
+
try {
|
|
4464
|
+
const content = await readFile(resolveAuthFile(filename), "utf8");
|
|
4465
|
+
return JSON.parse(content);
|
|
4466
|
+
} catch {
|
|
4467
|
+
return null;
|
|
4468
|
+
}
|
|
4469
|
+
};
|
|
4470
|
+
var decodeJwtPayload = (token) => {
|
|
4471
|
+
try {
|
|
4472
|
+
const [, payload] = token.split(".");
|
|
4473
|
+
if (!payload) {
|
|
4474
|
+
return null;
|
|
4475
|
+
}
|
|
4476
|
+
const json = Buffer.from(payload, "base64url").toString("utf8");
|
|
4477
|
+
return JSON.parse(json);
|
|
4478
|
+
} catch {
|
|
4479
|
+
return null;
|
|
4480
|
+
}
|
|
4481
|
+
};
|
|
4482
|
+
var getToken = async (filename) => {
|
|
4483
|
+
const state = await readAuthState(filename);
|
|
4484
|
+
if (!state) {
|
|
4485
|
+
throw new Error("Not authenticated. Run `stackable-app-extension auth login` first.");
|
|
4486
|
+
}
|
|
4487
|
+
const payload = decodeJwtPayload(state.token);
|
|
4488
|
+
if (payload?.exp && typeof payload.exp === "number") {
|
|
4489
|
+
if (Date.now() >= payload.exp * 1e3) {
|
|
4490
|
+
throw new Error("Session expired. Run `stackable-app-extension auth login` to re-authenticate.");
|
|
4491
|
+
}
|
|
4492
|
+
}
|
|
4493
|
+
return state.token;
|
|
4494
|
+
};
|
|
4495
|
+
|
|
4434
4496
|
// package.json
|
|
4435
4497
|
var package_default = {
|
|
4436
4498
|
version: "0.0.0"};
|
|
@@ -4454,9 +4516,13 @@ var createMcpServer = (options = {}) => {
|
|
|
4454
4516
|
return await getToken(STANDALONE_CLIENT_AUTH_FILE.MCP);
|
|
4455
4517
|
} catch {
|
|
4456
4518
|
}
|
|
4457
|
-
|
|
4519
|
+
if (!options.performOAuthFlow) {
|
|
4520
|
+
throw new Error(
|
|
4521
|
+
"No auth token available. Provide authContext (server) or performOAuthFlow (CLI)."
|
|
4522
|
+
);
|
|
4523
|
+
}
|
|
4458
4524
|
const MCP_API_BASE_URL = process.env.MCP_API_BASE_URL ?? DEFAULT_MCP_API_BASE_URL;
|
|
4459
|
-
return performOAuthFlow(`${MCP_API_BASE_URL}/.well-known/oauth-authorization-server`);
|
|
4525
|
+
return options.performOAuthFlow(`${MCP_API_BASE_URL}/.well-known/oauth-authorization-server`);
|
|
4460
4526
|
};
|
|
4461
4527
|
const authHeaders = (token) => ({
|
|
4462
4528
|
authorization: `Bearer ${token}`,
|
|
@@ -4593,12 +4659,7 @@ ${errors.map((e) => `- ${e}`).join("\n")}`);
|
|
|
4593
4659
|
usedPermissions.add(permission);
|
|
4594
4660
|
}
|
|
4595
4661
|
}
|
|
4596
|
-
const
|
|
4597
|
-
useIdentityEvent: "events:identity",
|
|
4598
|
-
useMessagingEvent: "events:messaging",
|
|
4599
|
-
useActivityEvent: "events:activity"
|
|
4600
|
-
};
|
|
4601
|
-
for (const [hook, permission] of Object.entries(eventHookMap)) {
|
|
4662
|
+
for (const [hook, permission] of Object.entries(EVENT_HOOK_PERMISSION_MAP)) {
|
|
4602
4663
|
if (allSource.includes(hook)) {
|
|
4603
4664
|
usedPermissions.add(permission);
|
|
4604
4665
|
}
|