cloud-cost-mcp 1.1.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/LICENSE +190 -0
- package/NOTICE +15 -0
- package/README.md +232 -0
- package/dist/data/bundled/aws-pricing.json +379 -0
- package/dist/data/bundled/azure-pricing.json +367 -0
- package/dist/data/bundled/gcp-pricing.json +383 -0
- package/dist/data/bundled/oci-pricing.json +290 -0
- package/dist/data/cache.d.ts +53 -0
- package/dist/data/cache.d.ts.map +1 -0
- package/dist/data/cache.js +95 -0
- package/dist/data/cache.js.map +1 -0
- package/dist/data/fetchers/aws.d.ts +65 -0
- package/dist/data/fetchers/aws.d.ts.map +1 -0
- package/dist/data/fetchers/aws.js +298 -0
- package/dist/data/fetchers/aws.js.map +1 -0
- package/dist/data/fetchers/azure.d.ts +83 -0
- package/dist/data/fetchers/azure.d.ts.map +1 -0
- package/dist/data/fetchers/azure.js +369 -0
- package/dist/data/fetchers/azure.js.map +1 -0
- package/dist/data/fetchers/gcp.d.ts +44 -0
- package/dist/data/fetchers/gcp.d.ts.map +1 -0
- package/dist/data/fetchers/gcp.js +182 -0
- package/dist/data/fetchers/gcp.js.map +1 -0
- package/dist/data/fetchers/oci.d.ts +65 -0
- package/dist/data/fetchers/oci.d.ts.map +1 -0
- package/dist/data/fetchers/oci.js +130 -0
- package/dist/data/fetchers/oci.js.map +1 -0
- package/dist/data/loader.d.ts +56 -0
- package/dist/data/loader.d.ts.map +1 -0
- package/dist/data/loader.js +149 -0
- package/dist/data/loader.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +715 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/calculator.d.ts +36 -0
- package/dist/tools/calculator.d.ts.map +1 -0
- package/dist/tools/calculator.js +271 -0
- package/dist/tools/calculator.js.map +1 -0
- package/dist/tools/compare.d.ts +64 -0
- package/dist/tools/compare.d.ts.map +1 -0
- package/dist/tools/compare.js +243 -0
- package/dist/tools/compare.js.map +1 -0
- package/dist/types.d.ts +171 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud Cost MCP - In-memory cache for pricing data
|
|
3
|
+
*/
|
|
4
|
+
export declare class PricingCache {
|
|
5
|
+
private cache;
|
|
6
|
+
private defaultTTL;
|
|
7
|
+
constructor(defaultTTLMinutes?: number);
|
|
8
|
+
/**
|
|
9
|
+
* Get an item from the cache
|
|
10
|
+
*/
|
|
11
|
+
get<T>(key: string): T | null;
|
|
12
|
+
/**
|
|
13
|
+
* Set an item in the cache
|
|
14
|
+
*/
|
|
15
|
+
set<T>(key: string, data: T, ttlMinutes?: number): void;
|
|
16
|
+
/**
|
|
17
|
+
* Check if a key exists and is not expired
|
|
18
|
+
*/
|
|
19
|
+
has(key: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Delete an item from the cache
|
|
22
|
+
*/
|
|
23
|
+
delete(key: string): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Clear all items from the cache
|
|
26
|
+
*/
|
|
27
|
+
clear(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Get cache statistics
|
|
30
|
+
*/
|
|
31
|
+
getStats(): {
|
|
32
|
+
size: number;
|
|
33
|
+
keys: string[];
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Clean expired entries
|
|
37
|
+
*/
|
|
38
|
+
private cleanExpired;
|
|
39
|
+
}
|
|
40
|
+
export declare const pricingCache: PricingCache;
|
|
41
|
+
export declare const CACHE_KEYS: {
|
|
42
|
+
readonly AWS_PRICING: "aws_pricing_data";
|
|
43
|
+
readonly AZURE_PRICING: "azure_pricing_data";
|
|
44
|
+
readonly GCP_PRICING: "gcp_pricing_data";
|
|
45
|
+
readonly OCI_PRICING: "oci_pricing_data";
|
|
46
|
+
readonly ALL_COMPUTE: "all_compute_instances";
|
|
47
|
+
readonly ALL_STORAGE: "all_storage_options";
|
|
48
|
+
readonly ALL_EGRESS: "all_egress_pricing";
|
|
49
|
+
readonly ALL_KUBERNETES: "all_kubernetes_options";
|
|
50
|
+
readonly AZURE_REALTIME: "azure_realtime";
|
|
51
|
+
readonly OCI_REALTIME: "oci_realtime";
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/data/cache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,UAAU,CAAS;gBAEf,iBAAiB,GAAE,MAAW;IAI1C;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAgB7B;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAWvD;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,QAAQ,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE;IAQ5C;;OAEG;IACH,OAAO,CAAC,YAAY;CAQrB;AAGD,eAAO,MAAM,YAAY,cAAuB,CAAC;AAGjD,eAAO,MAAM,UAAU;;;;;;;;;;;CAgBb,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud Cost MCP - In-memory cache for pricing data
|
|
3
|
+
*/
|
|
4
|
+
export class PricingCache {
|
|
5
|
+
cache = new Map();
|
|
6
|
+
defaultTTL; // milliseconds
|
|
7
|
+
constructor(defaultTTLMinutes = 60) {
|
|
8
|
+
this.defaultTTL = defaultTTLMinutes * 60 * 1000;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get an item from the cache
|
|
12
|
+
*/
|
|
13
|
+
get(key) {
|
|
14
|
+
const entry = this.cache.get(key);
|
|
15
|
+
if (!entry) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
// Check if expired
|
|
19
|
+
if (Date.now() > entry.expiresAt) {
|
|
20
|
+
this.cache.delete(key);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
return entry.data;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Set an item in the cache
|
|
27
|
+
*/
|
|
28
|
+
set(key, data, ttlMinutes) {
|
|
29
|
+
const ttl = ttlMinutes ? ttlMinutes * 60 * 1000 : this.defaultTTL;
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
this.cache.set(key, {
|
|
32
|
+
data,
|
|
33
|
+
timestamp: now,
|
|
34
|
+
expiresAt: now + ttl,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Check if a key exists and is not expired
|
|
39
|
+
*/
|
|
40
|
+
has(key) {
|
|
41
|
+
return this.get(key) !== null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Delete an item from the cache
|
|
45
|
+
*/
|
|
46
|
+
delete(key) {
|
|
47
|
+
return this.cache.delete(key);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Clear all items from the cache
|
|
51
|
+
*/
|
|
52
|
+
clear() {
|
|
53
|
+
this.cache.clear();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get cache statistics
|
|
57
|
+
*/
|
|
58
|
+
getStats() {
|
|
59
|
+
this.cleanExpired();
|
|
60
|
+
return {
|
|
61
|
+
size: this.cache.size,
|
|
62
|
+
keys: Array.from(this.cache.keys()),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Clean expired entries
|
|
67
|
+
*/
|
|
68
|
+
cleanExpired() {
|
|
69
|
+
const now = Date.now();
|
|
70
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
71
|
+
if (now > entry.expiresAt) {
|
|
72
|
+
this.cache.delete(key);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Singleton instance for the pricing data cache
|
|
78
|
+
export const pricingCache = new PricingCache(60); // 1 hour default TTL
|
|
79
|
+
// Cache keys for all providers
|
|
80
|
+
export const CACHE_KEYS = {
|
|
81
|
+
// Provider-specific data
|
|
82
|
+
AWS_PRICING: 'aws_pricing_data',
|
|
83
|
+
AZURE_PRICING: 'azure_pricing_data',
|
|
84
|
+
GCP_PRICING: 'gcp_pricing_data',
|
|
85
|
+
OCI_PRICING: 'oci_pricing_data',
|
|
86
|
+
// Combined/computed data
|
|
87
|
+
ALL_COMPUTE: 'all_compute_instances',
|
|
88
|
+
ALL_STORAGE: 'all_storage_options',
|
|
89
|
+
ALL_EGRESS: 'all_egress_pricing',
|
|
90
|
+
ALL_KUBERNETES: 'all_kubernetes_options',
|
|
91
|
+
// Real-time API caches
|
|
92
|
+
AZURE_REALTIME: 'azure_realtime',
|
|
93
|
+
OCI_REALTIME: 'oci_realtime',
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/data/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud Cost MCP - AWS Real-Time Pricing Fetcher
|
|
3
|
+
* Uses instances.vantage.sh API (no auth required)
|
|
4
|
+
* Data source: https://instances.vantage.sh/instances.json
|
|
5
|
+
*
|
|
6
|
+
* Coverage: 1,147 EC2 instance types, 353 RDS instance types
|
|
7
|
+
*/
|
|
8
|
+
import type { ComputeInstance, DatabasePricing } from '../../types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Fetch all EC2 instance pricing from instances.vantage.sh
|
|
11
|
+
*/
|
|
12
|
+
export declare function fetchAWSEC2Pricing(options?: {
|
|
13
|
+
region?: string;
|
|
14
|
+
family?: string;
|
|
15
|
+
architecture?: 'x86' | 'arm';
|
|
16
|
+
maxResults?: number;
|
|
17
|
+
includeSpot?: boolean;
|
|
18
|
+
includeReserved?: boolean;
|
|
19
|
+
}): Promise<{
|
|
20
|
+
instances: ComputeInstance[];
|
|
21
|
+
totalCount: number;
|
|
22
|
+
timestamp: string;
|
|
23
|
+
source: string;
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* Fetch AWS RDS database pricing
|
|
27
|
+
*/
|
|
28
|
+
export declare function fetchAWSRDSPricing(options?: {
|
|
29
|
+
region?: string;
|
|
30
|
+
engine?: string;
|
|
31
|
+
maxResults?: number;
|
|
32
|
+
}): Promise<{
|
|
33
|
+
instances: DatabasePricing[];
|
|
34
|
+
totalCount: number;
|
|
35
|
+
timestamp: string;
|
|
36
|
+
source: string;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Get AWS Lightsail bundle pricing
|
|
40
|
+
*/
|
|
41
|
+
export declare function getAWSLightsailPricing(options?: {
|
|
42
|
+
region?: string;
|
|
43
|
+
}): {
|
|
44
|
+
bundles: ComputeInstance[];
|
|
45
|
+
notes: string[];
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Get available AWS regions from the data
|
|
49
|
+
*/
|
|
50
|
+
export declare function getAWSRegions(): Promise<string[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Check if AWS data source is accessible
|
|
53
|
+
*/
|
|
54
|
+
export declare function checkAWSAPIStatus(): Promise<{
|
|
55
|
+
available: boolean;
|
|
56
|
+
message: string;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Get instance families/categories available
|
|
60
|
+
*/
|
|
61
|
+
export declare function getAWSInstanceFamilies(): Promise<{
|
|
62
|
+
family: string;
|
|
63
|
+
count: number;
|
|
64
|
+
}[]>;
|
|
65
|
+
//# sourceMappingURL=aws.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws.d.ts","sourceRoot":"","sources":["../../../src/data/fetchers/aws.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAmB,MAAM,gBAAgB,CAAC;AAuExF;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,CAAC,EAAE;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,GAAG,OAAO,CAAC;IACV,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAoED;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,CAAC,EAAE;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC;IACV,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAsED;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG;IACF,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CA0BA;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAcvD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAgB1F;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAmB3F"}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud Cost MCP - AWS Real-Time Pricing Fetcher
|
|
3
|
+
* Uses instances.vantage.sh API (no auth required)
|
|
4
|
+
* Data source: https://instances.vantage.sh/instances.json
|
|
5
|
+
*
|
|
6
|
+
* Coverage: 1,147 EC2 instance types, 353 RDS instance types
|
|
7
|
+
*/
|
|
8
|
+
import { pricingCache } from '../cache.js';
|
|
9
|
+
// Data source endpoints (public, no auth required)
|
|
10
|
+
const EC2_INSTANCES_URL = 'https://instances.vantage.sh/instances.json';
|
|
11
|
+
const RDS_INSTANCES_URL = 'https://instances.vantage.sh/rds/instances.json';
|
|
12
|
+
// AWS Lightsail pricing (manually curated - AWS doesn't expose this via API)
|
|
13
|
+
const LIGHTSAIL_BUNDLES = [
|
|
14
|
+
{ name: 'nano', vcpus: 1, memoryGB: 0.5, storageGB: 20, transferTB: 1, hourlyPrice: 0.0047, monthlyPrice: 3.50 },
|
|
15
|
+
{ name: 'micro', vcpus: 1, memoryGB: 1, storageGB: 40, transferTB: 2, hourlyPrice: 0.0067, monthlyPrice: 5.00 },
|
|
16
|
+
{ name: 'small', vcpus: 1, memoryGB: 2, storageGB: 60, transferTB: 3, hourlyPrice: 0.0134, monthlyPrice: 10.00 },
|
|
17
|
+
{ name: 'medium', vcpus: 2, memoryGB: 4, storageGB: 80, transferTB: 4, hourlyPrice: 0.0268, monthlyPrice: 20.00 },
|
|
18
|
+
{ name: 'large', vcpus: 2, memoryGB: 8, storageGB: 160, transferTB: 5, hourlyPrice: 0.0536, monthlyPrice: 40.00 },
|
|
19
|
+
{ name: 'xlarge', vcpus: 4, memoryGB: 16, storageGB: 320, transferTB: 6, hourlyPrice: 0.1072, monthlyPrice: 80.00 },
|
|
20
|
+
{ name: '2xlarge', vcpus: 8, memoryGB: 32, storageGB: 640, transferTB: 7, hourlyPrice: 0.2144, monthlyPrice: 160.00 },
|
|
21
|
+
];
|
|
22
|
+
// Cache keys
|
|
23
|
+
const CACHE_KEY_EC2 = 'AWS_EC2_REALTIME';
|
|
24
|
+
const CACHE_KEY_RDS = 'AWS_RDS_REALTIME';
|
|
25
|
+
const CACHE_TTL_MINUTES = 60; // Cache for 1 hour
|
|
26
|
+
/**
|
|
27
|
+
* Fetch all EC2 instance pricing from instances.vantage.sh
|
|
28
|
+
*/
|
|
29
|
+
export async function fetchAWSEC2Pricing(options) {
|
|
30
|
+
const region = options?.region || 'us-east-1';
|
|
31
|
+
const maxResults = options?.maxResults || 500;
|
|
32
|
+
// Check cache first
|
|
33
|
+
const cacheKey = `${CACHE_KEY_EC2}_${region}`;
|
|
34
|
+
const cached = pricingCache.get(cacheKey);
|
|
35
|
+
if (cached) {
|
|
36
|
+
return {
|
|
37
|
+
instances: filterAndLimit(cached, options, maxResults),
|
|
38
|
+
totalCount: cached.length,
|
|
39
|
+
timestamp: new Date().toISOString(),
|
|
40
|
+
source: 'cache',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const response = await fetch(EC2_INSTANCES_URL);
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
throw new Error(`Failed to fetch EC2 data: ${response.status}`);
|
|
47
|
+
}
|
|
48
|
+
const data = await response.json();
|
|
49
|
+
const instances = [];
|
|
50
|
+
for (const item of data) {
|
|
51
|
+
const regionPricing = item.pricing[region];
|
|
52
|
+
if (!regionPricing?.linux?.ondemand)
|
|
53
|
+
continue;
|
|
54
|
+
const hourlyPrice = parseFloat(regionPricing.linux.ondemand);
|
|
55
|
+
if (isNaN(hourlyPrice))
|
|
56
|
+
continue;
|
|
57
|
+
const category = mapFamilyToCategory(item.family);
|
|
58
|
+
const architecture = item.arch?.includes('arm64') ? 'arm' : 'x86';
|
|
59
|
+
const instance = {
|
|
60
|
+
provider: 'aws',
|
|
61
|
+
name: item.instance_type,
|
|
62
|
+
displayName: `${item.instance_type} (${item.family})`,
|
|
63
|
+
vcpus: item.vCPU,
|
|
64
|
+
memoryGB: item.memory,
|
|
65
|
+
hourlyPrice,
|
|
66
|
+
monthlyPrice: Math.round(hourlyPrice * 730 * 100) / 100,
|
|
67
|
+
region,
|
|
68
|
+
category,
|
|
69
|
+
architecture,
|
|
70
|
+
gpuCount: item.GPU || undefined,
|
|
71
|
+
notes: buildNotes(item, regionPricing, options),
|
|
72
|
+
};
|
|
73
|
+
instances.push(instance);
|
|
74
|
+
}
|
|
75
|
+
// Sort by monthly price
|
|
76
|
+
instances.sort((a, b) => a.monthlyPrice - b.monthlyPrice);
|
|
77
|
+
// Cache the full result
|
|
78
|
+
pricingCache.set(cacheKey, instances, CACHE_TTL_MINUTES);
|
|
79
|
+
return {
|
|
80
|
+
instances: filterAndLimit(instances, options, maxResults),
|
|
81
|
+
totalCount: instances.length,
|
|
82
|
+
timestamp: new Date().toISOString(),
|
|
83
|
+
source: EC2_INSTANCES_URL,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
throw new Error(`Failed to fetch AWS EC2 pricing: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Fetch AWS RDS database pricing
|
|
92
|
+
*/
|
|
93
|
+
export async function fetchAWSRDSPricing(options) {
|
|
94
|
+
const region = options?.region || 'us-east-1';
|
|
95
|
+
const engine = options?.engine || 'PostgreSQL';
|
|
96
|
+
const maxResults = options?.maxResults || 100;
|
|
97
|
+
// Check cache first
|
|
98
|
+
const cacheKey = `${CACHE_KEY_RDS}_${region}_${engine}`;
|
|
99
|
+
const cached = pricingCache.get(cacheKey);
|
|
100
|
+
if (cached) {
|
|
101
|
+
return {
|
|
102
|
+
instances: cached.slice(0, maxResults),
|
|
103
|
+
totalCount: cached.length,
|
|
104
|
+
timestamp: new Date().toISOString(),
|
|
105
|
+
source: 'cache',
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const response = await fetch(RDS_INSTANCES_URL);
|
|
110
|
+
if (!response.ok) {
|
|
111
|
+
throw new Error(`Failed to fetch RDS data: ${response.status}`);
|
|
112
|
+
}
|
|
113
|
+
const data = await response.json();
|
|
114
|
+
const instances = [];
|
|
115
|
+
for (const item of data) {
|
|
116
|
+
const regionPricing = item.pricing[region];
|
|
117
|
+
if (!regionPricing)
|
|
118
|
+
continue;
|
|
119
|
+
// Try to find pricing for the requested engine
|
|
120
|
+
const engineKey = Object.keys(regionPricing).find(k => k.toLowerCase().includes(engine.toLowerCase()));
|
|
121
|
+
if (!engineKey)
|
|
122
|
+
continue;
|
|
123
|
+
const enginePricing = regionPricing[engineKey];
|
|
124
|
+
if (!enginePricing?.ondemand)
|
|
125
|
+
continue;
|
|
126
|
+
const hourlyPrice = parseFloat(enginePricing.ondemand);
|
|
127
|
+
if (isNaN(hourlyPrice))
|
|
128
|
+
continue;
|
|
129
|
+
instances.push({
|
|
130
|
+
provider: 'aws',
|
|
131
|
+
name: `RDS ${item.instance_type}`,
|
|
132
|
+
type: 'relational',
|
|
133
|
+
engine,
|
|
134
|
+
vcpus: item.vCPU,
|
|
135
|
+
memoryGB: item.memory,
|
|
136
|
+
hourlyPrice,
|
|
137
|
+
monthlyPrice: Math.round(hourlyPrice * 730 * 100) / 100,
|
|
138
|
+
notes: `Single-AZ, ${engine}`,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
// Sort by monthly price
|
|
142
|
+
instances.sort((a, b) => a.monthlyPrice - b.monthlyPrice);
|
|
143
|
+
// Cache the result
|
|
144
|
+
pricingCache.set(cacheKey, instances, CACHE_TTL_MINUTES);
|
|
145
|
+
return {
|
|
146
|
+
instances: instances.slice(0, maxResults),
|
|
147
|
+
totalCount: instances.length,
|
|
148
|
+
timestamp: new Date().toISOString(),
|
|
149
|
+
source: RDS_INSTANCES_URL,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
throw new Error(`Failed to fetch AWS RDS pricing: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get AWS Lightsail bundle pricing
|
|
158
|
+
*/
|
|
159
|
+
export function getAWSLightsailPricing(options) {
|
|
160
|
+
const region = options?.region || 'us-east-1';
|
|
161
|
+
const bundles = LIGHTSAIL_BUNDLES.map(bundle => ({
|
|
162
|
+
provider: 'aws',
|
|
163
|
+
name: `Lightsail ${bundle.name}`,
|
|
164
|
+
displayName: `Lightsail ${bundle.name.charAt(0).toUpperCase() + bundle.name.slice(1)} (${bundle.memoryGB}GB RAM)`,
|
|
165
|
+
vcpus: bundle.vcpus,
|
|
166
|
+
memoryGB: bundle.memoryGB,
|
|
167
|
+
hourlyPrice: bundle.hourlyPrice,
|
|
168
|
+
monthlyPrice: bundle.monthlyPrice,
|
|
169
|
+
region,
|
|
170
|
+
category: 'general',
|
|
171
|
+
architecture: 'x86',
|
|
172
|
+
notes: `Includes ${bundle.storageGB}GB SSD, ${bundle.transferTB}TB transfer`,
|
|
173
|
+
}));
|
|
174
|
+
return {
|
|
175
|
+
bundles,
|
|
176
|
+
notes: [
|
|
177
|
+
'Lightsail is a simplified VPS service with fixed monthly pricing',
|
|
178
|
+
'Includes SSD storage, data transfer, and static IP',
|
|
179
|
+
'Prices are consistent across most regions',
|
|
180
|
+
'Windows instances cost approximately 60% more',
|
|
181
|
+
],
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get available AWS regions from the data
|
|
186
|
+
*/
|
|
187
|
+
export async function getAWSRegions() {
|
|
188
|
+
try {
|
|
189
|
+
const response = await fetch(EC2_INSTANCES_URL);
|
|
190
|
+
if (!response.ok)
|
|
191
|
+
return [];
|
|
192
|
+
const data = await response.json();
|
|
193
|
+
if (data.length === 0)
|
|
194
|
+
return [];
|
|
195
|
+
// Get regions from first instance
|
|
196
|
+
const regions = Object.keys(data[0].pricing || {});
|
|
197
|
+
return regions.sort();
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Check if AWS data source is accessible
|
|
205
|
+
*/
|
|
206
|
+
export async function checkAWSAPIStatus() {
|
|
207
|
+
try {
|
|
208
|
+
const response = await fetch(EC2_INSTANCES_URL, { method: 'HEAD' });
|
|
209
|
+
if (response.ok) {
|
|
210
|
+
return {
|
|
211
|
+
available: true,
|
|
212
|
+
message: `instances.vantage.sh API is accessible (1,147+ EC2 instances available)`
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
return { available: false, message: `API returned status ${response.status}` };
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
return {
|
|
219
|
+
available: false,
|
|
220
|
+
message: `API check failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Get instance families/categories available
|
|
226
|
+
*/
|
|
227
|
+
export async function getAWSInstanceFamilies() {
|
|
228
|
+
try {
|
|
229
|
+
const response = await fetch(EC2_INSTANCES_URL);
|
|
230
|
+
if (!response.ok)
|
|
231
|
+
return [];
|
|
232
|
+
const data = await response.json();
|
|
233
|
+
const familyCounts = new Map();
|
|
234
|
+
for (const item of data) {
|
|
235
|
+
const count = familyCounts.get(item.family) || 0;
|
|
236
|
+
familyCounts.set(item.family, count + 1);
|
|
237
|
+
}
|
|
238
|
+
return Array.from(familyCounts.entries())
|
|
239
|
+
.map(([family, count]) => ({ family, count }))
|
|
240
|
+
.sort((a, b) => b.count - a.count);
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
return [];
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Helper functions
|
|
247
|
+
function mapFamilyToCategory(family) {
|
|
248
|
+
const familyLower = family.toLowerCase();
|
|
249
|
+
if (familyLower.includes('compute'))
|
|
250
|
+
return 'compute';
|
|
251
|
+
if (familyLower.includes('memory'))
|
|
252
|
+
return 'memory';
|
|
253
|
+
if (familyLower.includes('storage'))
|
|
254
|
+
return 'storage';
|
|
255
|
+
if (familyLower.includes('accelerated') || familyLower.includes('gpu'))
|
|
256
|
+
return 'gpu';
|
|
257
|
+
return 'general';
|
|
258
|
+
}
|
|
259
|
+
function filterAndLimit(instances, options, maxResults) {
|
|
260
|
+
let filtered = instances;
|
|
261
|
+
if (options?.family) {
|
|
262
|
+
filtered = filtered.filter(i => i.displayName?.toLowerCase().includes(options.family.toLowerCase()));
|
|
263
|
+
}
|
|
264
|
+
if (options?.architecture) {
|
|
265
|
+
filtered = filtered.filter(i => i.architecture === options.architecture);
|
|
266
|
+
}
|
|
267
|
+
return filtered.slice(0, maxResults);
|
|
268
|
+
}
|
|
269
|
+
function buildNotes(item, regionPricing, options) {
|
|
270
|
+
const notes = [];
|
|
271
|
+
if (item.physical_processor) {
|
|
272
|
+
notes.push(item.physical_processor);
|
|
273
|
+
}
|
|
274
|
+
if (item.generation === 'previous') {
|
|
275
|
+
notes.push('Previous generation');
|
|
276
|
+
}
|
|
277
|
+
if (options?.includeSpot && regionPricing.linux?.spot_avg) {
|
|
278
|
+
const spotPrice = parseFloat(regionPricing.linux.spot_avg);
|
|
279
|
+
const ondemandPrice = parseFloat(regionPricing.linux.ondemand || '0');
|
|
280
|
+
if (!isNaN(spotPrice) && !isNaN(ondemandPrice) && ondemandPrice > 0) {
|
|
281
|
+
const savings = Math.round((1 - spotPrice / ondemandPrice) * 100);
|
|
282
|
+
notes.push(`Spot: $${spotPrice.toFixed(4)}/hr (${savings}% savings)`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (options?.includeReserved && regionPricing.linux?.reserved) {
|
|
286
|
+
const reserved1yr = regionPricing.linux.reserved['yrTerm1Standard.noUpfront'];
|
|
287
|
+
if (reserved1yr) {
|
|
288
|
+
const reservedPrice = parseFloat(reserved1yr);
|
|
289
|
+
const ondemandPrice = parseFloat(regionPricing.linux.ondemand || '0');
|
|
290
|
+
if (!isNaN(reservedPrice) && !isNaN(ondemandPrice) && ondemandPrice > 0) {
|
|
291
|
+
const savings = Math.round((1 - reservedPrice / ondemandPrice) * 100);
|
|
292
|
+
notes.push(`1yr Reserved: $${reservedPrice.toFixed(4)}/hr (${savings}% savings)`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return notes.join('. ') || 'Linux on-demand pricing';
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=aws.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws.js","sourceRoot":"","sources":["../../../src/data/fetchers/aws.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud Cost MCP - Azure Real-Time Pricing Fetcher
|
|
3
|
+
* Uses Azure Retail Prices API (public, no auth required)
|
|
4
|
+
* https://learn.microsoft.com/en-us/rest/api/cost-management/retail-prices/azure-retail-prices
|
|
5
|
+
*/
|
|
6
|
+
import type { ComputeInstance, StoragePricing } from '../../types.js';
|
|
7
|
+
export interface AzureRetailPrice {
|
|
8
|
+
currencyCode: string;
|
|
9
|
+
tierMinimumUnits: number;
|
|
10
|
+
retailPrice: number;
|
|
11
|
+
unitPrice: number;
|
|
12
|
+
armRegionName: string;
|
|
13
|
+
location: string;
|
|
14
|
+
effectiveStartDate: string;
|
|
15
|
+
meterId: string;
|
|
16
|
+
meterName: string;
|
|
17
|
+
productId: string;
|
|
18
|
+
skuId: string;
|
|
19
|
+
productName: string;
|
|
20
|
+
skuName: string;
|
|
21
|
+
serviceName: string;
|
|
22
|
+
serviceId: string;
|
|
23
|
+
serviceFamily: string;
|
|
24
|
+
unitOfMeasure: string;
|
|
25
|
+
type: string;
|
|
26
|
+
isPrimaryMeterRegion: boolean;
|
|
27
|
+
armSkuName: string;
|
|
28
|
+
}
|
|
29
|
+
export interface AzureRetailResponse {
|
|
30
|
+
BillingCurrency: string;
|
|
31
|
+
CustomerEntityId: string;
|
|
32
|
+
CustomerEntityType: string;
|
|
33
|
+
Items: AzureRetailPrice[];
|
|
34
|
+
NextPageLink: string | null;
|
|
35
|
+
Count: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Fetch Azure VM pricing from the Retail Prices API
|
|
39
|
+
*/
|
|
40
|
+
export declare function fetchAzureComputePricing(options?: {
|
|
41
|
+
region?: string;
|
|
42
|
+
vmSeries?: string;
|
|
43
|
+
maxResults?: number;
|
|
44
|
+
}): Promise<ComputeInstance[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Fetch Azure Storage pricing
|
|
47
|
+
*/
|
|
48
|
+
export declare function fetchAzureStoragePricing(options?: {
|
|
49
|
+
region?: string;
|
|
50
|
+
}): Promise<StoragePricing[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Check if Azure API is accessible
|
|
53
|
+
*/
|
|
54
|
+
export declare function checkAzureAPIStatus(): Promise<{
|
|
55
|
+
available: boolean;
|
|
56
|
+
message: string;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Fetch comprehensive Azure VM pricing from vantage.sh (1,199 instance types)
|
|
60
|
+
*/
|
|
61
|
+
export declare function fetchAzureVantagePricing(options?: {
|
|
62
|
+
region?: string;
|
|
63
|
+
category?: string;
|
|
64
|
+
includeSpot?: boolean;
|
|
65
|
+
maxResults?: number;
|
|
66
|
+
}): Promise<{
|
|
67
|
+
instances: ComputeInstance[];
|
|
68
|
+
totalCount: number;
|
|
69
|
+
timestamp: string;
|
|
70
|
+
source: string;
|
|
71
|
+
}>;
|
|
72
|
+
/**
|
|
73
|
+
* Get available Azure regions from vantage.sh data
|
|
74
|
+
*/
|
|
75
|
+
export declare function getAzureVantageRegions(): Promise<string[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Get Azure instance categories from vantage.sh
|
|
78
|
+
*/
|
|
79
|
+
export declare function getAzureCategories(): Promise<{
|
|
80
|
+
category: string;
|
|
81
|
+
count: number;
|
|
82
|
+
}[]>;
|
|
83
|
+
//# sourceMappingURL=azure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure.d.ts","sourceRoot":"","sources":["../../../src/data/fetchers/azure.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAItE,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,EAAE,OAAO,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,CAAC,EAAE;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAqE7B;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,CAAC,EAAE;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAoD5B;AAoGD;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAa5F;AAqCD;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,CAAC,EAAE;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC;IACV,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CA4ED;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAahE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAmBzF"}
|