@elixium.ai/mcp-server 0.2.0 → 0.2.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/dist/index.js +78 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -283,7 +283,7 @@ const normalizeLane = async (lane) => {
|
|
|
283
283
|
const map = style === "upper" ? LANE_UPPER : LANE_TITLE;
|
|
284
284
|
return map[key] || (style === "upper" ? lane.trim().toUpperCase() : lane.trim());
|
|
285
285
|
};
|
|
286
|
-
const buildIterationContext = (stories, user = null) => {
|
|
286
|
+
const buildIterationContext = (stories, user = null, infraProfile) => {
|
|
287
287
|
const currentIteration = stories.filter((story) => normalizeLaneForComparison(story?.lane) === "current");
|
|
288
288
|
const backlog = stories.filter((story) => normalizeLaneForComparison(story?.lane) === "backlog");
|
|
289
289
|
// Cost summary across current iteration
|
|
@@ -294,7 +294,13 @@ const buildIterationContext = (stories, user = null) => {
|
|
|
294
294
|
estimatedCount: withEstimates.length,
|
|
295
295
|
unestimatedCount: iterationStories.length - withEstimates.length,
|
|
296
296
|
};
|
|
297
|
-
return {
|
|
297
|
+
return {
|
|
298
|
+
currentIteration,
|
|
299
|
+
backlog,
|
|
300
|
+
user,
|
|
301
|
+
costSummary,
|
|
302
|
+
...(infraProfile ? { infrastructureProfile: infraProfile } : {}),
|
|
303
|
+
};
|
|
298
304
|
};
|
|
299
305
|
const createServer = () => {
|
|
300
306
|
const server = new Server({
|
|
@@ -520,7 +526,15 @@ const createServer = () => {
|
|
|
520
526
|
description: "Optional constraints (e.g., budget limit, region, instance types)",
|
|
521
527
|
},
|
|
522
528
|
},
|
|
523
|
-
required: ["storyId"
|
|
529
|
+
required: ["storyId"],
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
name: "get_infrastructure_profile",
|
|
534
|
+
description: "Get the workspace infrastructure profile. Returns cloud provider, regions, compliance frameworks, existing services, and constraints. Use this to understand the team's environment before making infrastructure recommendations.",
|
|
535
|
+
inputSchema: {
|
|
536
|
+
type: "object",
|
|
537
|
+
properties: {},
|
|
524
538
|
},
|
|
525
539
|
},
|
|
526
540
|
{
|
|
@@ -727,6 +741,13 @@ ${config.branchingDefaults ? `- Trunk-Based: ${config.branchingDefaults.trunkBas
|
|
|
727
741
|
- Auto-Merge: ${config.branchingDefaults.autoMerge ? "Yes" : "No"}
|
|
728
742
|
- Source: ${config.branchingDefaults.source}` : "Not configured (branch-based default)"}
|
|
729
743
|
|
|
744
|
+
## Infrastructure Profile
|
|
745
|
+
${config.infrastructureProfile?.provider ? `- Provider: ${config.infrastructureProfile.provider.toUpperCase()}
|
|
746
|
+
- Regions: ${config.infrastructureProfile.regions?.join(", ") || "Not set"}
|
|
747
|
+
- Compliance: ${config.infrastructureProfile.complianceFrameworks?.join(", ").toUpperCase() || "None"}
|
|
748
|
+
- Existing Services: ${config.infrastructureProfile.existingServices?.length || 0}
|
|
749
|
+
> Use \`get_infrastructure_profile\` for full details.` : "Not configured. Set up in Settings → Infrastructure."}
|
|
750
|
+
|
|
730
751
|
> **Tip:** Features can be configured at workspace or board level. Board settings override workspace defaults.
|
|
731
752
|
`;
|
|
732
753
|
return {
|
|
@@ -782,9 +803,10 @@ ${config.branchingDefaults ? `- Trunk-Based: ${config.branchingDefaults.trunkBas
|
|
|
782
803
|
const hasContextData = Array.isArray(currentIteration) &&
|
|
783
804
|
Array.isArray(backlog) &&
|
|
784
805
|
(currentIteration.length > 0 || backlog.length > 0);
|
|
806
|
+
const iterConfig = await fetchFeatureConfig();
|
|
785
807
|
const context = hasContextData
|
|
786
|
-
? contextData
|
|
787
|
-
: buildIterationContext(await fetchStories(), contextData?.user ?? null);
|
|
808
|
+
? { ...contextData, ...(iterConfig.infrastructureProfile ? { infrastructureProfile: iterConfig.infrastructureProfile } : {}) }
|
|
809
|
+
: buildIterationContext(await fetchStories(), contextData?.user ?? null, iterConfig.infrastructureProfile);
|
|
788
810
|
return {
|
|
789
811
|
content: [
|
|
790
812
|
{ type: "text", text: JSON.stringify(context, null, 2) },
|
|
@@ -1105,11 +1127,22 @@ ${result.next_step}
|
|
|
1105
1127
|
}
|
|
1106
1128
|
case "estimate_cost": {
|
|
1107
1129
|
const args = request.params.arguments;
|
|
1108
|
-
const { storyId,
|
|
1130
|
+
const { storyId, constraints } = args;
|
|
1131
|
+
let { provider } = args;
|
|
1109
1132
|
if (!storyId)
|
|
1110
1133
|
throw new Error("storyId is required");
|
|
1134
|
+
// Default provider from infrastructure profile if not explicitly provided
|
|
1135
|
+
if (!provider) {
|
|
1136
|
+
const costConfig = await fetchFeatureConfig();
|
|
1137
|
+
const profileProvider = costConfig.infrastructureProfile?.provider;
|
|
1138
|
+
if (profileProvider) {
|
|
1139
|
+
// Map gov variants to commercial for cost estimation API
|
|
1140
|
+
const govMap = { "aws-gov": "aws", "azure-gov": "azure" };
|
|
1141
|
+
provider = govMap[profileProvider] || profileProvider;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1111
1144
|
if (!provider)
|
|
1112
|
-
throw new Error("provider is required");
|
|
1145
|
+
throw new Error("provider is required (set it explicitly or configure an infrastructure profile)");
|
|
1113
1146
|
if (!["gcp", "aws", "azure", "self-hosted"].includes(provider)) {
|
|
1114
1147
|
throw new Error("provider must be one of: gcp, aws, azure, self-hosted");
|
|
1115
1148
|
}
|
|
@@ -1119,12 +1152,14 @@ ${result.next_step}
|
|
|
1119
1152
|
if (!storyData.description) {
|
|
1120
1153
|
throw new Error("Story needs a description before cost estimation");
|
|
1121
1154
|
}
|
|
1122
|
-
// Call the AI estimate-cost endpoint
|
|
1155
|
+
// Call the AI estimate-cost endpoint (with epicId/boardId for infra context)
|
|
1123
1156
|
const estimateRes = await client.post("/ai/estimate-cost", {
|
|
1124
1157
|
storyTitle: storyData.title,
|
|
1125
1158
|
description: storyData.description,
|
|
1126
1159
|
provider,
|
|
1127
1160
|
...(constraints ? { constraints } : {}),
|
|
1161
|
+
...(storyData.epicId ? { epicId: storyData.epicId } : {}),
|
|
1162
|
+
...(storyData.boardId ? { boardId: storyData.boardId } : {}),
|
|
1128
1163
|
});
|
|
1129
1164
|
const estimate = estimateRes.data;
|
|
1130
1165
|
// Save the estimate to the story
|
|
@@ -1223,6 +1258,41 @@ ${unestimated.length === 0
|
|
|
1223
1258
|
content: [{ type: "text", text: formattedResult.trim() }],
|
|
1224
1259
|
};
|
|
1225
1260
|
}
|
|
1261
|
+
case "get_infrastructure_profile": {
|
|
1262
|
+
const profileConfig = await fetchFeatureConfig();
|
|
1263
|
+
const profile = profileConfig.infrastructureProfile;
|
|
1264
|
+
if (!profile || !profile.provider) {
|
|
1265
|
+
return {
|
|
1266
|
+
content: [{
|
|
1267
|
+
type: "text",
|
|
1268
|
+
text: "# Infrastructure Profile\n\nNo infrastructure profile configured. Ask the workspace admin to set one up in **Settings → Infrastructure**.\n\nThis profile tells the AI about your cloud environment — provider, regions, compliance frameworks, and existing services — so cost estimates and recommendations are accurate.",
|
|
1269
|
+
}],
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
const sections = ["# Workspace Infrastructure Profile\n"];
|
|
1273
|
+
sections.push(`**Cloud Provider:** ${profile.provider.toUpperCase()}`);
|
|
1274
|
+
if (profile.regions?.length) {
|
|
1275
|
+
sections.push(`**Regions:** ${profile.regions.join(", ")}`);
|
|
1276
|
+
}
|
|
1277
|
+
if (profile.complianceFrameworks?.length) {
|
|
1278
|
+
sections.push(`\n## Compliance Frameworks\n${profile.complianceFrameworks.map((f) => `- ${f.toUpperCase()}`).join("\n")}`);
|
|
1279
|
+
}
|
|
1280
|
+
if (profile.existingServices?.length) {
|
|
1281
|
+
sections.push(`\n## Existing Services\n| Service | Category | Specs |\n|---------|----------|-------|\n${profile.existingServices.map((s) => `| ${s.name} | ${s.category} | ${s.specs || "-"} |`).join("\n")}`);
|
|
1282
|
+
}
|
|
1283
|
+
if (profile.networkTopology) {
|
|
1284
|
+
sections.push(`\n## Network Topology\n${profile.networkTopology}`);
|
|
1285
|
+
}
|
|
1286
|
+
if (profile.additionalConstraints) {
|
|
1287
|
+
sections.push(`\n## Additional Constraints\n${profile.additionalConstraints}`);
|
|
1288
|
+
}
|
|
1289
|
+
if (profile.updatedAt) {
|
|
1290
|
+
sections.push(`\n---\n*Last updated: ${new Date(profile.updatedAt).toLocaleDateString()}*`);
|
|
1291
|
+
}
|
|
1292
|
+
return {
|
|
1293
|
+
content: [{ type: "text", text: sections.join("\n") }],
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1226
1296
|
default:
|
|
1227
1297
|
throw new Error("Unknown tool");
|
|
1228
1298
|
}
|