@stackable-labs/mcp-app-extension 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, writeFile, readFile } from 'fs/promises';
3
+ import { join } from 'path';
4
+ import { homedir } from 'os';
5
+
6
+ // ../../lib/contracts/src/permissions.ts
7
+ var SUPER_ROLE = {
8
+ ADMIN: "org:super_admin"
9
+ };
10
+ var ORG_ROLE = {
11
+ ADMIN: "org:admin",
12
+ OWNER: "org:owner"};
13
+ var EDITOR_ROLES = [
14
+ SUPER_ROLE.ADMIN,
15
+ ORG_ROLE.ADMIN,
16
+ ORG_ROLE.OWNER
17
+ ];
18
+ [
19
+ ...Object.values(SUPER_ROLE),
20
+ ...Object.values(EDITOR_ROLES)
21
+ ];
22
+
23
+ // ../../lib/utils-auth/src/constants.ts
24
+ var STANDALONE_CLIENT = {
25
+ CLI: "@stackable-labs/cli-app-extension",
26
+ MCP: "@stackable-labs/mcp-app-extension"
27
+ };
28
+ Object.values(STANDALONE_CLIENT);
29
+
30
+ // ../../lib/utils-auth/src/index.ts
31
+ var AUTH_DIR = join(homedir(), ".stackable");
32
+ join(AUTH_DIR, "auth.json");
33
+ join(AUTH_DIR, "mcp-auth.json");
34
+ var resolveAuthFile = (filename) => join(AUTH_DIR, filename ?? "auth.json");
35
+ var readAuthState = async (filename) => {
36
+ try {
37
+ const content = await readFile(resolveAuthFile(filename), "utf8");
38
+ return JSON.parse(content);
39
+ } catch {
40
+ return null;
41
+ }
42
+ };
43
+ var writeAuthState = async (state, filename) => {
44
+ await mkdir(AUTH_DIR, { recursive: true, mode: 448 });
45
+ await writeFile(resolveAuthFile(filename), JSON.stringify(state, null, 2), { mode: 384 });
46
+ };
47
+ var decodeJwtPayload = (token) => {
48
+ try {
49
+ const [, payload] = token.split(".");
50
+ if (!payload) {
51
+ return null;
52
+ }
53
+ const json = Buffer.from(payload, "base64url").toString("utf8");
54
+ return JSON.parse(json);
55
+ } catch {
56
+ return null;
57
+ }
58
+ };
59
+ var getToken = async (filename) => {
60
+ const state = await readAuthState(filename);
61
+ if (!state) {
62
+ throw new Error("Not authenticated. Run `stackable-app-extension auth login` first.");
63
+ }
64
+ const payload = decodeJwtPayload(state.token);
65
+ if (payload?.exp && typeof payload.exp === "number") {
66
+ if (Date.now() >= payload.exp * 1e3) {
67
+ throw new Error("Session expired. Run `stackable-app-extension auth login` to re-authenticate.");
68
+ }
69
+ }
70
+ return state.token;
71
+ };
72
+
73
+ export { STANDALONE_CLIENT, getToken, writeAuthState };
@@ -0,0 +1,72 @@
1
+ import { mkdir, writeFile, readFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { homedir } from 'os';
4
+
5
+ // ../../lib/utils-auth/src/constants.ts
6
+ var STANDALONE_CLIENT = {
7
+ CLI: "@stackable-labs/cli-app-extension",
8
+ MCP: "@stackable-labs/mcp-app-extension"
9
+ };
10
+ Object.values(STANDALONE_CLIENT);
11
+
12
+ // ../../lib/contracts/src/permissions.ts
13
+ var SUPER_ROLE = {
14
+ ADMIN: "org:super_admin"
15
+ };
16
+ var ORG_ROLE = {
17
+ ADMIN: "org:admin",
18
+ OWNER: "org:owner"};
19
+ var EDITOR_ROLES = [
20
+ SUPER_ROLE.ADMIN,
21
+ ORG_ROLE.ADMIN,
22
+ ORG_ROLE.OWNER
23
+ ];
24
+ [
25
+ ...Object.values(SUPER_ROLE),
26
+ ...Object.values(EDITOR_ROLES)
27
+ ];
28
+
29
+ // ../../lib/utils-auth/src/index.ts
30
+ var AUTH_DIR = join(homedir(), ".stackable");
31
+ join(AUTH_DIR, "auth.json");
32
+ join(AUTH_DIR, "mcp-auth.json");
33
+ var resolveAuthFile = (filename) => join(AUTH_DIR, filename ?? "auth.json");
34
+ var readAuthState = async (filename) => {
35
+ try {
36
+ const content = await readFile(resolveAuthFile(filename), "utf8");
37
+ return JSON.parse(content);
38
+ } catch {
39
+ return null;
40
+ }
41
+ };
42
+ var writeAuthState = async (state, filename) => {
43
+ await mkdir(AUTH_DIR, { recursive: true, mode: 448 });
44
+ await writeFile(resolveAuthFile(filename), JSON.stringify(state, null, 2), { mode: 384 });
45
+ };
46
+ var decodeJwtPayload = (token) => {
47
+ try {
48
+ const [, payload] = token.split(".");
49
+ if (!payload) {
50
+ return null;
51
+ }
52
+ const json = Buffer.from(payload, "base64url").toString("utf8");
53
+ return JSON.parse(json);
54
+ } catch {
55
+ return null;
56
+ }
57
+ };
58
+ var getToken = async (filename) => {
59
+ const state = await readAuthState(filename);
60
+ if (!state) {
61
+ throw new Error("Not authenticated. Run `stackable-app-extension auth login` first.");
62
+ }
63
+ const payload = decodeJwtPayload(state.token);
64
+ if (payload?.exp && typeof payload.exp === "number") {
65
+ if (Date.now() >= payload.exp * 1e3) {
66
+ throw new Error("Session expired. Run `stackable-app-extension auth login` to re-authenticate.");
67
+ }
68
+ }
69
+ return state.token;
70
+ };
71
+
72
+ export { STANDALONE_CLIENT, getToken, writeAuthState };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { STANDALONE_CLIENT, getToken } from './chunk-4XCX3LVH.js';
2
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
4
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
5
  import { IDENTITY_EVENTS, ACTIVITY_EVENTS, SURFACE_TARGETS, PERMISSIONS, CAPABILITY_PERMISSION_MAP, ALLOWED_ICONS, UI_TAGS, UI_TAG_ATTRIBUTES, tagToComponentName } from '@stackable-labs/sdk-extension-contracts';
@@ -3751,28 +3752,6 @@ pair(EXAMPLE_SNIPPETS, EXAMPLE_SNIPPETS2);
3751
3752
  pair(CAPABILITY_SNIPPETS, CAPABILITY_SNIPPETS2);
3752
3753
  pair(EVENT_SNIPPETS, EVENT_SNIPPETS2);
3753
3754
 
3754
- // ../../lib/contracts/src/permissions.ts
3755
- var SUPER_ROLE = {
3756
- ADMIN: "org:super_admin"
3757
- };
3758
- var ORG_ROLE = {
3759
- ADMIN: "org:admin",
3760
- OWNER: "org:owner"};
3761
- var EDITOR_ROLES = [
3762
- SUPER_ROLE.ADMIN,
3763
- ORG_ROLE.ADMIN,
3764
- ORG_ROLE.OWNER
3765
- ];
3766
- [
3767
- ...Object.values(SUPER_ROLE),
3768
- ...Object.values(EDITOR_ROLES)
3769
- ];
3770
-
3771
- // ../../lib/utils-services/src/auth/index.ts
3772
- var STANDALONE_CLIENT = {
3773
- MCP: "@stackable-labs/mcp-app-extension"
3774
- };
3775
-
3776
3755
  // package.json
3777
3756
  var package_default = {
3778
3757
  version: "0.0.0"};
@@ -3780,6 +3759,7 @@ var package_default = {
3780
3759
  // src/server.ts
3781
3760
  var MCP_CLIENT_NAME = STANDALONE_CLIENT.MCP;
3782
3761
  var DEFAULT_ADMIN_API_URL = "https://api-use1.stackablelabs.io/admin";
3762
+ var DEFAULT_MCP_DISCOVERY_URL = "https://api-use1.stackablelabs.io/mcp/.well-known/oauth-authorization-server";
3783
3763
  var textContent = (text) => ({ content: [{ type: "text", text }] });
3784
3764
  var errorContent = (text) => ({ content: [{ type: "text", text }], isError: true });
3785
3765
  var createMcpServer = (options = {}) => {
@@ -3791,31 +3771,13 @@ var createMcpServer = (options = {}) => {
3791
3771
  if (options.authContext?.token) {
3792
3772
  return options.authContext.token;
3793
3773
  }
3794
- const { readFile } = await import('fs/promises');
3795
- const { join } = await import('path');
3796
- const { homedir } = await import('os');
3797
- const authFile = join(homedir(), ".stackable", "auth.json");
3798
- let state;
3799
3774
  try {
3800
- const content = await readFile(authFile, "utf8");
3801
- state = JSON.parse(content);
3775
+ return await getToken("mcp-auth.json");
3802
3776
  } catch {
3803
- throw new Error("Not authenticated. Run 'stackable-app-extension auth login' first.");
3804
- }
3805
- const [, payload] = state.token.split(".");
3806
- if (payload) {
3807
- try {
3808
- const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
3809
- if (decoded.exp && Date.now() >= decoded.exp * 1e3) {
3810
- throw new Error("Session expired. Run 'stackable-app-extension auth login' to re-authenticate.");
3811
- }
3812
- } catch (err) {
3813
- if (err instanceof Error && err.message.includes("expired")) {
3814
- throw err;
3815
- }
3816
- }
3817
3777
  }
3818
- return state.token;
3778
+ const { performOAuthFlow } = await import('./auth-AJDGAQSE.js');
3779
+ const discoveryUrl = process.env.MCP_DISCOVERY_URL ?? DEFAULT_MCP_DISCOVERY_URL;
3780
+ return performOAuthFlow(discoveryUrl);
3819
3781
  };
3820
3782
  const authHeaders = (token) => ({
3821
3783
  authorization: `Bearer ${token}`,
package/dist/server.js CHANGED
@@ -1,9 +1,8 @@
1
+ import { STANDALONE_CLIENT, getToken } from './chunk-6EMXRSXY.js';
1
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
3
  import { IDENTITY_EVENTS, ACTIVITY_EVENTS, SURFACE_TARGETS, PERMISSIONS, CAPABILITY_PERMISSION_MAP, ALLOWED_ICONS, UI_TAGS, UI_TAG_ATTRIBUTES, tagToComponentName } from '@stackable-labs/sdk-extension-contracts';
3
4
  import { z } from 'zod';
4
5
 
5
- // src/server.ts
6
-
7
6
  // ../../sdk/extension/ai-docs/src/generated/template-content.ts
8
7
  var PATTERN_SECTIONS = [
9
8
  {
@@ -3751,28 +3750,6 @@ pair(EXAMPLE_SNIPPETS, EXAMPLE_SNIPPETS2);
3751
3750
  pair(CAPABILITY_SNIPPETS, CAPABILITY_SNIPPETS2);
3752
3751
  pair(EVENT_SNIPPETS, EVENT_SNIPPETS2);
3753
3752
 
3754
- // ../../lib/contracts/src/permissions.ts
3755
- var SUPER_ROLE = {
3756
- ADMIN: "org:super_admin"
3757
- };
3758
- var ORG_ROLE = {
3759
- ADMIN: "org:admin",
3760
- OWNER: "org:owner"};
3761
- var EDITOR_ROLES = [
3762
- SUPER_ROLE.ADMIN,
3763
- ORG_ROLE.ADMIN,
3764
- ORG_ROLE.OWNER
3765
- ];
3766
- [
3767
- ...Object.values(SUPER_ROLE),
3768
- ...Object.values(EDITOR_ROLES)
3769
- ];
3770
-
3771
- // ../../lib/utils-services/src/auth/index.ts
3772
- var STANDALONE_CLIENT = {
3773
- MCP: "@stackable-labs/mcp-app-extension"
3774
- };
3775
-
3776
3753
  // package.json
3777
3754
  var package_default = {
3778
3755
  version: "0.0.0"};
@@ -3780,6 +3757,7 @@ var package_default = {
3780
3757
  // src/server.ts
3781
3758
  var MCP_CLIENT_NAME = STANDALONE_CLIENT.MCP;
3782
3759
  var DEFAULT_ADMIN_API_URL = "https://api-use1.stackablelabs.io/admin";
3760
+ var DEFAULT_MCP_DISCOVERY_URL = "https://api-use1.stackablelabs.io/mcp/.well-known/oauth-authorization-server";
3783
3761
  var textContent = (text) => ({ content: [{ type: "text", text }] });
3784
3762
  var errorContent = (text) => ({ content: [{ type: "text", text }], isError: true });
3785
3763
  var createMcpServer = (options = {}) => {
@@ -3791,31 +3769,13 @@ var createMcpServer = (options = {}) => {
3791
3769
  if (options.authContext?.token) {
3792
3770
  return options.authContext.token;
3793
3771
  }
3794
- const { readFile } = await import('fs/promises');
3795
- const { join } = await import('path');
3796
- const { homedir } = await import('os');
3797
- const authFile = join(homedir(), ".stackable", "auth.json");
3798
- let state;
3799
3772
  try {
3800
- const content = await readFile(authFile, "utf8");
3801
- state = JSON.parse(content);
3773
+ return await getToken("mcp-auth.json");
3802
3774
  } catch {
3803
- throw new Error("Not authenticated. Run 'stackable-app-extension auth login' first.");
3804
- }
3805
- const [, payload] = state.token.split(".");
3806
- if (payload) {
3807
- try {
3808
- const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
3809
- if (decoded.exp && Date.now() >= decoded.exp * 1e3) {
3810
- throw new Error("Session expired. Run 'stackable-app-extension auth login' to re-authenticate.");
3811
- }
3812
- } catch (err) {
3813
- if (err instanceof Error && err.message.includes("expired")) {
3814
- throw err;
3815
- }
3816
- }
3817
3775
  }
3818
- return state.token;
3776
+ const { performOAuthFlow } = await import('./auth-JRYNP3PL.js');
3777
+ const discoveryUrl = process.env.MCP_DISCOVERY_URL ?? DEFAULT_MCP_DISCOVERY_URL;
3778
+ return performOAuthFlow(discoveryUrl);
3819
3779
  };
3820
3780
  const authHeaders = (token) => ({
3821
3781
  authorization: `Bearer ${token}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackable-labs/mcp-app-extension",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mcp-app-extension": "./dist/index.js"
@@ -23,6 +23,8 @@
23
23
  "dependencies": {
24
24
  "@modelcontextprotocol/sdk": "1.x",
25
25
  "@stackable-labs/sdk-extension-contracts": "latest",
26
+ "oauth4webapi": "3.x",
27
+ "open": "10.x",
26
28
  "zod": "3.x"
27
29
  },
28
30
  "description": "MCP server for AI-assisted Stackable extension development.",