@stackable-labs/mcp-app-extension 0.3.1 → 0.4.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/README.md +93 -0
- package/dist/auth-AJDGAQSE.js +669 -0
- package/dist/auth-JRYNP3PL.js +668 -0
- package/dist/chunk-4XCX3LVH.js +73 -0
- package/dist/chunk-6EMXRSXY.js +72 -0
- package/dist/index.js +25 -48
- package/dist/server.js +25 -50
- package/package.json +3 -1
|
@@ -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_API_BASE_URL = "https://api-use1.stackablelabs.io/mcp";
|
|
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
|
-
|
|
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
|
-
|
|
3778
|
+
const { performOAuthFlow } = await import('./auth-AJDGAQSE.js');
|
|
3779
|
+
const MCP_API_BASE_URL = process.env.MCP_API_BASE_URL ?? DEFAULT_MCP_API_BASE_URL;
|
|
3780
|
+
return performOAuthFlow(`${MCP_API_BASE_URL}/.well-known/oauth-authorization-server`);
|
|
3819
3781
|
};
|
|
3820
3782
|
const authHeaders = (token) => ({
|
|
3821
3783
|
authorization: `Bearer ${token}`,
|
|
@@ -3824,10 +3786,18 @@ var createMcpServer = (options = {}) => {
|
|
|
3824
3786
|
});
|
|
3825
3787
|
const callApi = async (path) => {
|
|
3826
3788
|
const token = await getAuthToken();
|
|
3827
|
-
const
|
|
3828
|
-
const
|
|
3789
|
+
const ADMIN_API_BASE_URL = process.env.ADMIN_API_BASE_URL ?? DEFAULT_ADMIN_API_URL;
|
|
3790
|
+
const url = `${ADMIN_API_BASE_URL}${path}`;
|
|
3791
|
+
let res;
|
|
3792
|
+
try {
|
|
3793
|
+
res = await fetch(url, { headers: authHeaders(token) });
|
|
3794
|
+
} catch (err) {
|
|
3795
|
+
return errorContent(
|
|
3796
|
+
`Network error calling ${url}: ${err.message}. Check ADMIN_API_BASE_URL env var (currently "${ADMIN_API_BASE_URL}").`
|
|
3797
|
+
);
|
|
3798
|
+
}
|
|
3829
3799
|
if (!res.ok) {
|
|
3830
|
-
return errorContent(`API error: ${res.status} ${res.statusText}`);
|
|
3800
|
+
return errorContent(`API error: ${res.status} ${res.statusText} (${url})`);
|
|
3831
3801
|
}
|
|
3832
3802
|
const data = await res.json();
|
|
3833
3803
|
return textContent(JSON.stringify(data, null, 2));
|
|
@@ -3836,7 +3806,14 @@ var createMcpServer = (options = {}) => {
|
|
|
3836
3806
|
try {
|
|
3837
3807
|
return await fn();
|
|
3838
3808
|
} catch (err) {
|
|
3839
|
-
|
|
3809
|
+
const e = err;
|
|
3810
|
+
if (e.message.includes("fetch")) {
|
|
3811
|
+
const MCP_API_BASE_URL = process.env.MCP_API_BASE_URL ?? DEFAULT_MCP_API_BASE_URL;
|
|
3812
|
+
return errorContent(
|
|
3813
|
+
`MCP auth flow failed: ${e.message}. Check MCP_API_BASE_URL env var (currently "${MCP_API_BASE_URL}"). To re-auth from scratch: rm ~/.stackable/mcp-auth.json`
|
|
3814
|
+
);
|
|
3815
|
+
}
|
|
3816
|
+
return errorContent(e.message);
|
|
3840
3817
|
}
|
|
3841
3818
|
};
|
|
3842
3819
|
const registrySkills = listSkills("registry");
|
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_API_BASE_URL = "https://api-use1.stackablelabs.io/mcp";
|
|
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
|
-
|
|
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
3775
|
}
|
|
3805
|
-
const
|
|
3806
|
-
|
|
3807
|
-
|
|
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
|
-
}
|
|
3818
|
-
return state.token;
|
|
3776
|
+
const { performOAuthFlow } = await import('./auth-JRYNP3PL.js');
|
|
3777
|
+
const MCP_API_BASE_URL = process.env.MCP_API_BASE_URL ?? DEFAULT_MCP_API_BASE_URL;
|
|
3778
|
+
return performOAuthFlow(`${MCP_API_BASE_URL}/.well-known/oauth-authorization-server`);
|
|
3819
3779
|
};
|
|
3820
3780
|
const authHeaders = (token) => ({
|
|
3821
3781
|
authorization: `Bearer ${token}`,
|
|
@@ -3824,10 +3784,18 @@ var createMcpServer = (options = {}) => {
|
|
|
3824
3784
|
});
|
|
3825
3785
|
const callApi = async (path) => {
|
|
3826
3786
|
const token = await getAuthToken();
|
|
3827
|
-
const
|
|
3828
|
-
const
|
|
3787
|
+
const ADMIN_API_BASE_URL = process.env.ADMIN_API_BASE_URL ?? DEFAULT_ADMIN_API_URL;
|
|
3788
|
+
const url = `${ADMIN_API_BASE_URL}${path}`;
|
|
3789
|
+
let res;
|
|
3790
|
+
try {
|
|
3791
|
+
res = await fetch(url, { headers: authHeaders(token) });
|
|
3792
|
+
} catch (err) {
|
|
3793
|
+
return errorContent(
|
|
3794
|
+
`Network error calling ${url}: ${err.message}. Check ADMIN_API_BASE_URL env var (currently "${ADMIN_API_BASE_URL}").`
|
|
3795
|
+
);
|
|
3796
|
+
}
|
|
3829
3797
|
if (!res.ok) {
|
|
3830
|
-
return errorContent(`API error: ${res.status} ${res.statusText}`);
|
|
3798
|
+
return errorContent(`API error: ${res.status} ${res.statusText} (${url})`);
|
|
3831
3799
|
}
|
|
3832
3800
|
const data = await res.json();
|
|
3833
3801
|
return textContent(JSON.stringify(data, null, 2));
|
|
@@ -3836,7 +3804,14 @@ var createMcpServer = (options = {}) => {
|
|
|
3836
3804
|
try {
|
|
3837
3805
|
return await fn();
|
|
3838
3806
|
} catch (err) {
|
|
3839
|
-
|
|
3807
|
+
const e = err;
|
|
3808
|
+
if (e.message.includes("fetch")) {
|
|
3809
|
+
const MCP_API_BASE_URL = process.env.MCP_API_BASE_URL ?? DEFAULT_MCP_API_BASE_URL;
|
|
3810
|
+
return errorContent(
|
|
3811
|
+
`MCP auth flow failed: ${e.message}. Check MCP_API_BASE_URL env var (currently "${MCP_API_BASE_URL}"). To re-auth from scratch: rm ~/.stackable/mcp-auth.json`
|
|
3812
|
+
);
|
|
3813
|
+
}
|
|
3814
|
+
return errorContent(e.message);
|
|
3840
3815
|
}
|
|
3841
3816
|
};
|
|
3842
3817
|
const registrySkills = listSkills("registry");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackable-labs/mcp-app-extension",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
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.",
|