@growthbook/mcp 0.1.0 → 0.1.2
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 +12 -12
- package/build/docs.js +508 -0
- package/build/index.js +37 -3
- package/build/tools/defaults.js +169 -0
- package/build/tools/environments.js +0 -1
- package/build/tools/experiments.js +148 -40
- package/build/tools/features.js +51 -85
- package/build/tools/projects.js +1 -2
- package/build/tools/sdk-connections.js +4 -17
- package/build/tools/search.js +1 -2
- package/build/utils.js +38 -29
- package/package.json +5 -4
package/build/tools/features.js
CHANGED
|
@@ -1,65 +1,37 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { getDocsMetadata,
|
|
2
|
+
import { getDocsMetadata, handleResNotOk, generateLinkToGrowthBook, SUPPORTED_FILE_EXTENSIONS, } from "../utils.js";
|
|
3
|
+
import { exec } from "child_process";
|
|
3
4
|
export function registerFeatureTools({ server, baseApiUrl, apiKey, appOrigin, user, }) {
|
|
4
5
|
/**
|
|
5
6
|
* Tool: create_feature_flag
|
|
6
|
-
* Description: Creates, adds, or wraps an element with a feature flag in GrowthBook. Allows specifying key, type, default value, and other metadata.
|
|
7
7
|
*/
|
|
8
|
-
server.tool("create_feature_flag", "
|
|
8
|
+
server.tool("create_feature_flag", "Creates a new feature flag in GrowthBook and modifies the codebase when relevant.", {
|
|
9
9
|
id: z
|
|
10
10
|
.string()
|
|
11
11
|
.regex(/^[a-zA-Z0-9_-]+$/, "Feature key can only include letters, numbers, hyphens, and underscores.")
|
|
12
12
|
.describe("A unique key name for the feature"),
|
|
13
|
-
archived: z
|
|
14
|
-
.boolean()
|
|
15
|
-
.optional()
|
|
16
|
-
.default(false)
|
|
17
|
-
.describe("Whether the feature flag is archived"),
|
|
18
13
|
description: z
|
|
19
14
|
.string()
|
|
20
15
|
.optional()
|
|
21
16
|
.default("")
|
|
22
|
-
.describe("A
|
|
23
|
-
project: z
|
|
24
|
-
.string()
|
|
25
|
-
.optional()
|
|
26
|
-
.default("")
|
|
27
|
-
.describe("The project the feature flag belongs to"),
|
|
17
|
+
.describe("A briefdescription of the feature flag"),
|
|
28
18
|
valueType: z
|
|
29
19
|
.enum(["string", "number", "boolean", "json"])
|
|
30
20
|
.describe("The value type the feature flag will return"),
|
|
31
21
|
defaultValue: z
|
|
32
22
|
.string()
|
|
33
23
|
.describe("The default value of the feature flag"),
|
|
34
|
-
tags: z
|
|
35
|
-
.array(z.string())
|
|
36
|
-
.optional()
|
|
37
|
-
.describe("Tags for the feature flag"),
|
|
38
24
|
fileExtension: z
|
|
39
|
-
.enum(
|
|
40
|
-
".tsx",
|
|
41
|
-
".jsx",
|
|
42
|
-
".ts",
|
|
43
|
-
".js",
|
|
44
|
-
".vue",
|
|
45
|
-
".py",
|
|
46
|
-
".go",
|
|
47
|
-
".php",
|
|
48
|
-
".rb",
|
|
49
|
-
".java",
|
|
50
|
-
".cs",
|
|
51
|
-
])
|
|
25
|
+
.enum(SUPPORTED_FILE_EXTENSIONS)
|
|
52
26
|
.describe("The extension of the current file. If it's unclear, ask the user."),
|
|
53
|
-
}, async ({ id,
|
|
27
|
+
}, async ({ id, description, valueType, defaultValue, fileExtension }) => {
|
|
54
28
|
const payload = {
|
|
55
29
|
id,
|
|
56
|
-
archived,
|
|
57
30
|
description,
|
|
58
31
|
owner: user,
|
|
59
|
-
project,
|
|
60
32
|
valueType,
|
|
61
33
|
defaultValue,
|
|
62
|
-
tags,
|
|
34
|
+
tags: ["mcp"],
|
|
63
35
|
};
|
|
64
36
|
try {
|
|
65
37
|
const res = await fetch(`${baseApiUrl}/api/v1/features`, {
|
|
@@ -70,23 +42,9 @@ export function registerFeatureTools({ server, baseApiUrl, apiKey, appOrigin, us
|
|
|
70
42
|
},
|
|
71
43
|
body: JSON.stringify(payload),
|
|
72
44
|
});
|
|
73
|
-
|
|
74
|
-
let errorMessage = `HTTP ${res.status} ${res.statusText}`;
|
|
75
|
-
try {
|
|
76
|
-
const errorBody = await res.json();
|
|
77
|
-
errorMessage += `: ${JSON.stringify(errorBody)}`;
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
// fallback to text if not JSON
|
|
81
|
-
const errorText = await res.text();
|
|
82
|
-
if (errorText)
|
|
83
|
-
errorMessage += `: ${errorText}`;
|
|
84
|
-
}
|
|
85
|
-
throw new Error(errorMessage);
|
|
86
|
-
}
|
|
45
|
+
await handleResNotOk(res);
|
|
87
46
|
const data = await res.json();
|
|
88
|
-
const
|
|
89
|
-
const { docs, language } = getDocsMetadata(fileExtension);
|
|
47
|
+
const { docs, language, stub } = getDocsMetadata(fileExtension);
|
|
90
48
|
const linkToGrowthBook = generateLinkToGrowthBook(appOrigin, "features", id);
|
|
91
49
|
const text = `This is the API response: ${JSON.stringify(data, null, 2)}
|
|
92
50
|
|
|
@@ -98,7 +56,7 @@ export function registerFeatureTools({ server, baseApiUrl, apiKey, appOrigin, us
|
|
|
98
56
|
**How to use it in your code:**
|
|
99
57
|
(To the LLM agent. Use the text below to properly add the feature flag to the codebase. Also, surface the relevant docs/implemenation to the user)
|
|
100
58
|
|
|
101
|
-
${
|
|
59
|
+
${stub}
|
|
102
60
|
|
|
103
61
|
**Want to learn more?**
|
|
104
62
|
See the [GrowthBook ${language} docs](${docs})
|
|
@@ -108,26 +66,21 @@ export function registerFeatureTools({ server, baseApiUrl, apiKey, appOrigin, us
|
|
|
108
66
|
};
|
|
109
67
|
}
|
|
110
68
|
catch (error) {
|
|
111
|
-
|
|
112
|
-
throw error;
|
|
69
|
+
throw new Error(`Error creating feature flag: ${error}`);
|
|
113
70
|
}
|
|
114
71
|
});
|
|
115
72
|
/**
|
|
116
73
|
* Tool: get_feature_flags
|
|
117
|
-
* Description: Fetches all feature flags from the GrowthBook API, with optional limit, offset, and project filtering.
|
|
118
74
|
*/
|
|
119
|
-
server.tool("get_feature_flags", "Fetches all feature flags from the GrowthBook API
|
|
75
|
+
server.tool("get_feature_flags", "Fetches all feature flags from the GrowthBook API, with optional limit, offset, and project filtering.", {
|
|
120
76
|
limit: z.number().optional().default(100),
|
|
121
77
|
offset: z.number().optional().default(0),
|
|
122
|
-
|
|
123
|
-
}, async ({ limit, offset, project }) => {
|
|
78
|
+
}, async ({ limit, offset }) => {
|
|
124
79
|
try {
|
|
125
80
|
const queryParams = new URLSearchParams({
|
|
126
81
|
limit: limit?.toString(),
|
|
127
82
|
offset: offset?.toString(),
|
|
128
83
|
});
|
|
129
|
-
if (project)
|
|
130
|
-
queryParams.append("project", project);
|
|
131
84
|
const res = await fetch(`${baseApiUrl}/api/v1/features?${queryParams.toString()}`, {
|
|
132
85
|
headers: {
|
|
133
86
|
Authorization: `Bearer ${apiKey}`,
|
|
@@ -141,13 +94,11 @@ export function registerFeatureTools({ server, baseApiUrl, apiKey, appOrigin, us
|
|
|
141
94
|
};
|
|
142
95
|
}
|
|
143
96
|
catch (error) {
|
|
144
|
-
|
|
145
|
-
throw error;
|
|
97
|
+
throw new Error(`Error fetching flags: ${error}`);
|
|
146
98
|
}
|
|
147
99
|
});
|
|
148
100
|
/**
|
|
149
101
|
* Tool: get_single_feature_flag
|
|
150
|
-
* Description: Fetches a specific feature flag from the GrowthBook API by its ID, with optional project filtering.
|
|
151
102
|
*/
|
|
152
103
|
server.tool("get_single_feature_flag", "Fetches a specific feature flag from the GrowthBook API", {
|
|
153
104
|
id: z.string().describe("The ID of the feature flag"),
|
|
@@ -180,26 +131,21 @@ export function registerFeatureTools({ server, baseApiUrl, apiKey, appOrigin, us
|
|
|
180
131
|
};
|
|
181
132
|
}
|
|
182
133
|
catch (error) {
|
|
183
|
-
|
|
184
|
-
throw error;
|
|
134
|
+
throw new Error(`Error fetching flags: ${error}`);
|
|
185
135
|
}
|
|
186
136
|
});
|
|
187
137
|
/**
|
|
188
138
|
* Tool: get_stale_safe_rollouts
|
|
189
|
-
* Description: Fetches all complete safe rollouts (rolled-back or released) from the GrowthBook API, with optional limit, offset, and project filtering.
|
|
190
139
|
*/
|
|
191
140
|
server.tool("get_stale_safe_rollouts", "Fetches all complete safe rollouts (rolled-back or released) from the GrowthBook API", {
|
|
192
141
|
limit: z.number().optional().default(100),
|
|
193
142
|
offset: z.number().optional().default(0),
|
|
194
|
-
|
|
195
|
-
}, async ({ limit, offset, project }) => {
|
|
143
|
+
}, async ({ limit, offset }) => {
|
|
196
144
|
try {
|
|
197
145
|
const queryParams = new URLSearchParams({
|
|
198
146
|
limit: limit?.toString(),
|
|
199
147
|
offset: offset?.toString(),
|
|
200
148
|
});
|
|
201
|
-
if (project)
|
|
202
|
-
queryParams.append("project", project);
|
|
203
149
|
const res = await fetch(`${baseApiUrl}/api/v1/features?${queryParams.toString()}`, {
|
|
204
150
|
headers: {
|
|
205
151
|
Authorization: `Bearer ${apiKey}`,
|
|
@@ -236,25 +182,45 @@ export function registerFeatureTools({ server, baseApiUrl, apiKey, appOrigin, us
|
|
|
236
182
|
};
|
|
237
183
|
}
|
|
238
184
|
catch (error) {
|
|
239
|
-
|
|
240
|
-
throw error;
|
|
185
|
+
throw new Error(`Error fetching stale safe rollouts: ${error}`);
|
|
241
186
|
}
|
|
242
187
|
});
|
|
243
188
|
/**
|
|
244
189
|
* Tool: generate_flag_types
|
|
245
|
-
* Description: Generates types for feature flags using the GrowthBook CLI.
|
|
246
190
|
*/
|
|
247
|
-
server.tool("generate_flag_types", "Generate types for feature flags", {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
191
|
+
server.tool("generate_flag_types", "Generate types for feature flags", {
|
|
192
|
+
currentWorkingDirectory: z
|
|
193
|
+
.string()
|
|
194
|
+
.describe("The current working directory of the user's project"),
|
|
195
|
+
}, async ({ currentWorkingDirectory }) => {
|
|
196
|
+
function runCommand(command, cwd) {
|
|
197
|
+
return new Promise((resolve, reject) => {
|
|
198
|
+
exec(command, { cwd }, (error, stdout, stderr) => {
|
|
199
|
+
if (error) {
|
|
200
|
+
reject(stderr || error.message);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
resolve(stdout);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
try {
|
|
209
|
+
// Login command
|
|
210
|
+
await runCommand(`npx -y growthbook@latest auth login -k ${apiKey} -u ${baseApiUrl} -p default`, currentWorkingDirectory);
|
|
211
|
+
// Generate types command
|
|
212
|
+
const output = await runCommand(`npx -y growthbook@latest features generate-types -u ${baseApiUrl}`, currentWorkingDirectory);
|
|
213
|
+
return {
|
|
214
|
+
content: [
|
|
215
|
+
{
|
|
216
|
+
type: "text",
|
|
217
|
+
text: `✅ Types generated successfully:\n${output}`,
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
throw new Error(`Error generating types: ${error}`);
|
|
224
|
+
}
|
|
259
225
|
});
|
|
260
226
|
}
|
package/build/tools/projects.js
CHANGED
|
@@ -2,11 +2,10 @@ import { z } from "zod";
|
|
|
2
2
|
import { handleResNotOk } from "../utils.js";
|
|
3
3
|
/**
|
|
4
4
|
* Tool: get_projects
|
|
5
|
-
* Description: Fetches all projects from the GrowthBook API, with optional limit and offset for pagination.
|
|
6
5
|
*/
|
|
7
6
|
export function registerProjectTools({ server, baseApiUrl, apiKey, }) {
|
|
8
7
|
server.tool("get_projects", "Fetches all projects from the GrowthBook API", {
|
|
9
|
-
limit: z.number().optional().default(
|
|
8
|
+
limit: z.number().optional().default(100),
|
|
10
9
|
offset: z.number().optional().default(0),
|
|
11
10
|
}, async ({ limit, offset }) => {
|
|
12
11
|
const queryParams = new URLSearchParams({
|
|
@@ -3,23 +3,16 @@ import { handleResNotOk } from "../utils.js";
|
|
|
3
3
|
export function registerSdkConnectionTools({ server, baseApiUrl, apiKey, }) {
|
|
4
4
|
/**
|
|
5
5
|
* Tool: get_sdk_connections
|
|
6
|
-
* Description: Retrieves all SDK connections, which are how GrowthBook connects to an app.
|
|
7
|
-
* Users need the key, which is a public key that allows the app to fetch features and experiments from the API.
|
|
8
6
|
*/
|
|
9
|
-
server.tool("get_sdk_connections",
|
|
10
|
-
which are how GrowthBook connects to an app.
|
|
11
|
-
Importantly, users need the key, which is a public client key that allows the app to fetch features and experiments the API `, {
|
|
7
|
+
server.tool("get_sdk_connections", "Get all SDK connections. SDK connections are how GrowthBook connects to an app. Users need the client key to fetch features and experiments from the API.", {
|
|
12
8
|
limit: z.number().optional().default(100),
|
|
13
9
|
offset: z.number().optional().default(0),
|
|
14
|
-
|
|
15
|
-
}, async ({ limit, offset, project }) => {
|
|
10
|
+
}, async ({ limit, offset }) => {
|
|
16
11
|
try {
|
|
17
12
|
const queryParams = new URLSearchParams({
|
|
18
13
|
limit: limit?.toString(),
|
|
19
14
|
offset: offset?.toString(),
|
|
20
15
|
});
|
|
21
|
-
if (project)
|
|
22
|
-
queryParams.append("project", project);
|
|
23
16
|
const res = await fetch(`${baseApiUrl}/api/v1/sdk-connections?${queryParams.toString()}`, {
|
|
24
17
|
headers: {
|
|
25
18
|
Authorization: `Bearer ${apiKey}`,
|
|
@@ -33,15 +26,11 @@ export function registerSdkConnectionTools({ server, baseApiUrl, apiKey, }) {
|
|
|
33
26
|
};
|
|
34
27
|
}
|
|
35
28
|
catch (error) {
|
|
36
|
-
|
|
37
|
-
content: [{ type: "text", text: `Error: ${error}` }],
|
|
38
|
-
};
|
|
29
|
+
throw new Error(`Error fetching sdk connections: ${error}`);
|
|
39
30
|
}
|
|
40
31
|
});
|
|
41
32
|
/**
|
|
42
33
|
* Tool: create_sdk_connection
|
|
43
|
-
* Description: Creates an SDK connection for a user. Returns an SDK clientKey that can be used to fetch features and experiments.
|
|
44
|
-
* Requires a name, language, and optionally an environment.
|
|
45
34
|
*/
|
|
46
35
|
server.tool("create_sdk_connection", `Create an SDK connection for a user. Returns an SDK clientKey that can be used to fetch features and experiments.`, {
|
|
47
36
|
name: z
|
|
@@ -123,9 +112,7 @@ export function registerSdkConnectionTools({ server, baseApiUrl, apiKey, }) {
|
|
|
123
112
|
};
|
|
124
113
|
}
|
|
125
114
|
catch (error) {
|
|
126
|
-
|
|
127
|
-
content: [{ type: "text", text: `Error: ${error}` }],
|
|
128
|
-
};
|
|
115
|
+
throw new Error(`Error creating sdk connection: ${error}`);
|
|
129
116
|
}
|
|
130
117
|
});
|
|
131
118
|
}
|
package/build/tools/search.js
CHANGED
|
@@ -2,9 +2,8 @@ import { z } from "zod";
|
|
|
2
2
|
import { searchGrowthBookDocs } from "../utils.js";
|
|
3
3
|
/**
|
|
4
4
|
* Tool: search_growthbook_docs
|
|
5
|
-
* Description: Searches the GrowthBook documentation for information on how to use a feature, based on a user-provided query.
|
|
6
5
|
*/
|
|
7
|
-
export function
|
|
6
|
+
export function registerSearchTools({ server }) {
|
|
8
7
|
server.tool("search_growthbook_docs", "Search the GrowthBook docs on how to use a feature", {
|
|
9
8
|
query: z
|
|
10
9
|
.string()
|
package/build/utils.js
CHANGED
|
@@ -1,13 +1,34 @@
|
|
|
1
|
+
import { getFeatureFlagDocs } from "./docs.js";
|
|
2
|
+
// Shared file extension enum for all MCP tools
|
|
3
|
+
export const SUPPORTED_FILE_EXTENSIONS = [
|
|
4
|
+
".tsx",
|
|
5
|
+
".jsx",
|
|
6
|
+
".ts",
|
|
7
|
+
".js",
|
|
8
|
+
".vue",
|
|
9
|
+
".py",
|
|
10
|
+
".go",
|
|
11
|
+
".php",
|
|
12
|
+
".rb",
|
|
13
|
+
".java",
|
|
14
|
+
".cs",
|
|
15
|
+
".swift",
|
|
16
|
+
".ex",
|
|
17
|
+
".exs",
|
|
18
|
+
".kt",
|
|
19
|
+
".kts",
|
|
20
|
+
".ktm",
|
|
21
|
+
".dart",
|
|
22
|
+
];
|
|
1
23
|
export async function handleResNotOk(res) {
|
|
2
24
|
if (!res.ok) {
|
|
25
|
+
const errorText = await res.text();
|
|
3
26
|
let errorMessage = `HTTP ${res.status} ${res.statusText}`;
|
|
4
27
|
try {
|
|
5
|
-
const errorBody =
|
|
28
|
+
const errorBody = JSON.parse(errorText);
|
|
6
29
|
errorMessage += `: ${JSON.stringify(errorBody)}`;
|
|
7
30
|
}
|
|
8
31
|
catch {
|
|
9
|
-
// fallback to text if not JSON
|
|
10
|
-
const errorText = await res.text();
|
|
11
32
|
if (errorText)
|
|
12
33
|
errorMessage += `: ${errorText}`;
|
|
13
34
|
}
|
|
@@ -44,69 +65,69 @@ export function getDocsMetadata(extension) {
|
|
|
44
65
|
case ".jsx":
|
|
45
66
|
return {
|
|
46
67
|
language: "react",
|
|
47
|
-
|
|
68
|
+
stub: getFeatureFlagDocs("react"),
|
|
48
69
|
docs: "https://docs.growthbook.io/lib/react",
|
|
49
70
|
};
|
|
50
71
|
case ".ts":
|
|
51
72
|
case ".js":
|
|
52
73
|
return {
|
|
53
74
|
language: "javascript",
|
|
54
|
-
|
|
75
|
+
stub: getFeatureFlagDocs("javascript"),
|
|
55
76
|
docs: "https://docs.growthbook.io/lib/js",
|
|
56
77
|
};
|
|
57
78
|
case ".vue":
|
|
58
79
|
return {
|
|
59
80
|
language: "vue",
|
|
60
|
-
|
|
81
|
+
stub: getFeatureFlagDocs("vue"),
|
|
61
82
|
docs: "https://docs.growthbook.io/lib/vue",
|
|
62
83
|
};
|
|
63
84
|
case ".py":
|
|
64
85
|
return {
|
|
65
86
|
language: "python",
|
|
66
|
-
|
|
87
|
+
stub: getFeatureFlagDocs("python"),
|
|
67
88
|
docs: "https://docs.growthbook.io/lib/python",
|
|
68
89
|
};
|
|
69
90
|
case ".go":
|
|
70
91
|
return {
|
|
71
92
|
language: "go",
|
|
72
|
-
|
|
93
|
+
stub: getFeatureFlagDocs("go"),
|
|
73
94
|
docs: "https://docs.growthbook.io/lib/go",
|
|
74
95
|
};
|
|
75
96
|
case ".php":
|
|
76
97
|
return {
|
|
77
98
|
language: "php",
|
|
78
|
-
|
|
99
|
+
stub: getFeatureFlagDocs("php"),
|
|
79
100
|
docs: "https://docs.growthbook.io/lib/php",
|
|
80
101
|
};
|
|
81
102
|
case ".rb":
|
|
82
103
|
return {
|
|
83
104
|
language: "ruby",
|
|
84
|
-
|
|
105
|
+
stub: getFeatureFlagDocs("ruby"),
|
|
85
106
|
docs: "https://docs.growthbook.io/lib/ruby",
|
|
86
107
|
};
|
|
87
108
|
case ".java":
|
|
88
109
|
return {
|
|
89
110
|
language: "java",
|
|
90
|
-
|
|
111
|
+
stub: getFeatureFlagDocs("java"),
|
|
91
112
|
docs: "https://docs.growthbook.io/lib/java",
|
|
92
113
|
};
|
|
93
114
|
case ".cs":
|
|
94
115
|
return {
|
|
95
116
|
language: "csharp",
|
|
96
|
-
|
|
117
|
+
stub: getFeatureFlagDocs("csharp"),
|
|
97
118
|
docs: "https://docs.growthbook.io/lib/csharp",
|
|
98
119
|
};
|
|
99
120
|
case ".swift":
|
|
100
121
|
return {
|
|
101
122
|
language: "swift",
|
|
102
|
-
|
|
123
|
+
stub: getFeatureFlagDocs("swift"),
|
|
103
124
|
docs: "https://docs.growthbook.io/lib/swift",
|
|
104
125
|
};
|
|
105
126
|
case ".ex":
|
|
106
127
|
case ".exs":
|
|
107
128
|
return {
|
|
108
129
|
language: "elixir",
|
|
109
|
-
|
|
130
|
+
stub: getFeatureFlagDocs("elixir"),
|
|
110
131
|
docs: "https://docs.growthbook.io/lib/elixir",
|
|
111
132
|
};
|
|
112
133
|
case ".kt":
|
|
@@ -114,19 +135,19 @@ export function getDocsMetadata(extension) {
|
|
|
114
135
|
case ".ktm":
|
|
115
136
|
return {
|
|
116
137
|
language: "kotlin",
|
|
117
|
-
|
|
138
|
+
stub: getFeatureFlagDocs("kotlin"),
|
|
118
139
|
docs: "https://docs.growthbook.io/lib/kotlin",
|
|
119
140
|
};
|
|
120
141
|
case ".dart":
|
|
121
142
|
return {
|
|
122
143
|
language: "flutter",
|
|
123
|
-
|
|
144
|
+
stub: getFeatureFlagDocs("flutter"),
|
|
124
145
|
docs: "https://docs.growthbook.io/lib/flutter",
|
|
125
146
|
};
|
|
126
147
|
default:
|
|
127
148
|
return {
|
|
128
149
|
language: "unknown",
|
|
129
|
-
|
|
150
|
+
stub: getFeatureFlagDocs("unknown"),
|
|
130
151
|
docs: "https://docs.growthbook.io/lib/",
|
|
131
152
|
};
|
|
132
153
|
}
|
|
@@ -155,18 +176,6 @@ export async function searchGrowthBookDocs(query) {
|
|
|
155
176
|
return [];
|
|
156
177
|
}
|
|
157
178
|
}
|
|
158
|
-
export async function findImplementationDocs(extension) {
|
|
159
|
-
const { md } = getDocsMetadata(extension);
|
|
160
|
-
try {
|
|
161
|
-
const response = await fetch(md);
|
|
162
|
-
await handleResNotOk(response);
|
|
163
|
-
const markdown = await response.text();
|
|
164
|
-
return markdown;
|
|
165
|
-
}
|
|
166
|
-
catch (error) {
|
|
167
|
-
return "Docs not found";
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
179
|
export function generateLinkToGrowthBook(appOrigin, resource, id) {
|
|
171
180
|
return `${appOrigin}/${resource}/${id}`;
|
|
172
181
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@growthbook/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"access": "public",
|
|
6
6
|
"homepage": "https://github.com/growthbook/growthbook-mcp",
|
|
@@ -22,11 +22,12 @@
|
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"packageManager": "pnpm@10.6.1",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
26
|
-
"
|
|
25
|
+
"@modelcontextprotocol/sdk": "^1.13.1",
|
|
26
|
+
"env-paths": "^3.0.0",
|
|
27
|
+
"zod": "^3.25.67"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"@types/node": "^
|
|
30
|
+
"@types/node": "^24.0.4",
|
|
30
31
|
"typescript": "^5.8.3"
|
|
31
32
|
},
|
|
32
33
|
"type": "module"
|