Skip to content

Commit 0e673b1

Browse files
1.0.11
1 parent f819e26 commit 0e673b1

28 files changed

+175
-139
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@programcomputer/nasa-mcp-server",
3-
"version": "1.0.10",
3+
"version": "1.0.11",
44
"description": "Model Context Protocol (MCP) server for NASA APIs",
55
"main": "dist/index.js",
66
"files": [

src/handlers/jpl/cad.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import axios from 'axios';
2-
import { addResource } from '../../index.js';
2+
import { addResource } from '../../resources';
33

44
/**
55
* Handler for JPL SB Close Approach (CAD) API
@@ -76,4 +76,4 @@ export async function cadHandler(args: Record<string, any>) {
7676
}
7777

7878
// Export default for dynamic imports
79-
export default cadHandler;
79+
export default cadHandler;

src/handlers/jpl/fireball.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,4 @@ export async function jplFireballHandler(params: FireballParams) {
6060
}]
6161
};
6262
}
63-
}
63+
}

src/handlers/jpl/horizons.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import axios from 'axios';
2-
import { addResource } from '../../index.js';
2+
import { addResource } from '../../resources';
33

44
/**
55
* Handler for JPL Horizons API
@@ -80,4 +80,4 @@ export async function horizonsHandler(args: Record<string, any>) {
8080
}
8181

8282
// Export default for dynamic imports
83-
export default horizonsHandler;
83+
export default horizonsHandler;

src/handlers/jpl/horizons_file.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import axios from 'axios';
22
import FormData from 'form-data'; // Need form-data for multipart POST
3-
import { addResource } from '../../index';
3+
import { addResource } from '../../resources';
44

55
/**
66
* Handler for JPL Horizons File API (POST request)
@@ -100,4 +100,4 @@ export async function horizonsFileHandler(args: Record<string, any>) {
100100
}
101101

102102
// Export default for dynamic imports in index.ts
103-
export default horizonsFileHandler;
103+
export default horizonsFileHandler;

src/handlers/jpl/jd_cal.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import axios from 'axios';
2-
import { addResource } from '../../index.js';
2+
import { addResource } from '../../resources';
33

44
/**
55
* Handler for JPL Julian Date Calendar Conversion API
@@ -56,4 +56,4 @@ export async function jdCalHandler(args: Record<string, any>) {
5656
}
5757

5858
// Export default for dynamic imports
59-
export default jdCalHandler;
59+
export default jdCalHandler;

src/handlers/jpl/nhats.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import axios from 'axios';
2-
import { addResource } from '../../index.js';
2+
import { addResource } from '../../resources';
33

44
/**
55
* Handler for JPL NHATS API (Human-accessible NEOs data)
@@ -68,4 +68,4 @@ export async function nhatsHandler(args: Record<string, any>) {
6868
}
6969

7070
// Export default for dynamic imports
71-
export default nhatsHandler;
71+
export default nhatsHandler;

src/handlers/jpl/periodic_orbits.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import axios from 'axios';
2-
import { addResource } from '../../index.js';
2+
import { addResource } from '../../resources';
33

44
// Define expected parameters based on documentation
55
// Required: sys, family
@@ -85,4 +85,4 @@ export async function periodicOrbitsHandler(args: PeriodicOrbitParams) {
8585
}
8686

8787
// Export default for dynamic imports in index.ts
88-
export default periodicOrbitsHandler;
88+
export default periodicOrbitsHandler;

src/handlers/jpl/sbdb.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,4 @@ export async function jplSbdbHandler(params: SbdbParams) {
8686
}]
8787
};
8888
}
89-
}
89+
}

src/handlers/jpl/scout.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { z } from 'zod';
22
import { jplApiRequest } from '../../utils/api-client';
33
import { ScoutParams } from '../setup';
4-
import { addResource } from '../../index'; // Import addResource
4+
import { addResource } from '../../resources'; // Import addResource
55

66
/**
77
* Process the Scout API result and format it for display.
@@ -118,4 +118,4 @@ export async function jplScoutHandler(params: ScoutParams) {
118118
}]
119119
};
120120
}
121-
}
121+
}

src/handlers/jpl/sentry.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import axios from 'axios';
2-
import { addResource } from '../../index.js';
2+
import { addResource } from '../../resources';
33

44
/**
55
* Handler for JPL Sentry API
@@ -105,4 +105,4 @@ export async function sentryHandler(args: Record<string, any>) {
105105
}
106106

107107
// Export default for dynamic imports
108-
export default sentryHandler;
108+
export default sentryHandler;

src/handlers/nasa/apod.ts

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { z } from 'zod';
22
import { nasaApiRequest } from '../../utils/api-client';
3-
import { addResource } from '../../index.js';
3+
import { addResource } from '../../resources';
4+
import axios from 'axios';
45

56
// Schema for validating APOD request parameters
67
export const apodParamsSchema = z.object({
@@ -24,18 +25,22 @@ export async function nasaApodHandler(params: ApodParams) {
2425
const result = await nasaApiRequest('/planetary/apod', params);
2526

2627
// Store results as resources
27-
const processedResult = processApodResult(result);
28+
const processedResult = await processApodResultWithBase64(result);
2829

2930
return {
3031
content: [
3132
{
3233
type: "text",
3334
text: processedResult.summary
3435
},
35-
// Instead of trying to include images directly, include them as text with URLs
3636
...processedResult.images.map(img => ({
3737
type: "text",
38-
text: `![${img.title}](${img.data})`
38+
text: `![${img.title}](${img.url})`
39+
})),
40+
...processedResult.images.map(img => ({
41+
type: "image",
42+
data: img.base64,
43+
mimeType: img.mimeType || "image/jpeg"
3944
}))
4045
],
4146
isError: false
@@ -55,46 +60,48 @@ export async function nasaApodHandler(params: ApodParams) {
5560
}
5661
}
5762

58-
/**
59-
* Process APOD API result
60-
* Convert to resource and return formatted data
61-
*/
62-
function processApodResult(result: any) {
63-
// Handle both single result and array of results
63+
// New async version that fetches and encodes images as base64
64+
async function processApodResultWithBase64(result: any) {
6465
const results = Array.isArray(result) ? result : [result];
65-
6666
let summary = '';
6767
const images: any[] = [];
68-
69-
results.forEach((apod) => {
70-
// Create a unique ID for this APOD entry
68+
for (const apod of results) {
7169
const apodId = `nasa://apod/image?date=${apod.date}`;
72-
73-
// Store as a resource
70+
let mimeType = 'image/jpeg';
71+
if (apod.url) {
72+
if (apod.url.endsWith('.png')) mimeType = 'image/png';
73+
else if (apod.url.endsWith('.gif')) mimeType = 'image/gif';
74+
else if (apod.url.endsWith('.jpg') || apod.url.endsWith('.jpeg')) mimeType = 'image/jpeg';
75+
}
7476
addResource(apodId, {
7577
name: `Astronomy Picture of the Day - ${apod.title}`,
7678
mimeType: 'application/json',
7779
text: JSON.stringify(apod, null, 2)
7880
});
79-
80-
// Add to summary text
8181
summary += `## ${apod.title} (${apod.date})\n\n${apod.explanation}\n\n`;
82-
83-
// Add image info if available
84-
if (apod.url) {
82+
if (apod.url && (!apod.media_type || apod.media_type === 'image')) {
8583
summary += `Image URL: ${apod.url}\n\n`;
84+
let base64 = null;
85+
try {
86+
const imageResponse = await axios.get(apod.url, { responseType: 'arraybuffer', timeout: 30000 });
87+
base64 = Buffer.from(imageResponse.data).toString('base64');
88+
} catch (err) {
89+
console.error('Failed to fetch APOD image for base64:', apod.url, err);
90+
}
8691
images.push({
87-
data: apod.url,
88-
title: apod.title
92+
url: apod.url,
93+
title: apod.title,
94+
resourceUri: apodId,
95+
mimeType,
96+
base64
8997
});
9098
}
91-
});
92-
99+
}
93100
return {
94101
summary,
95102
images
96103
};
97104
}
98105

99106
// Export the handler function directly as default
100-
export default nasaApodHandler;
107+
export default nasaApodHandler;

src/handlers/nasa/cmr.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { z } from 'zod';
22
import axios from 'axios';
3-
import { addResource } from '../../index';
3+
import { addResource } from '../../resources';
44

55
const CMR_API_BASE_URL = 'https://cmr.earthdata.nasa.gov/search';
66

@@ -221,4 +221,4 @@ export async function nasaCmrHandler(params: CmrParams) {
221221
}
222222

223223
// Export the handler function directly as default
224-
export default nasaCmrHandler;
224+
export default nasaCmrHandler;

src/handlers/nasa/donki.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { z } from 'zod';
22
import { nasaApiRequest } from '../../utils/api-client';
33
import { DonkiParams } from '../setup';
4-
import { addResource } from '../../index';
4+
import { addResource } from '../../resources';
55

66
/**
77
* Handle requests for NASA's Space Weather Database Of Notifications, Knowledge, Information (DONKI) API
@@ -88,4 +88,4 @@ export async function nasaDonkiHandler(params: DonkiParams) {
8888
}
8989

9090
// Export the handler function directly as default
91-
export default nasaDonkiHandler;
91+
export default nasaDonkiHandler;

src/handlers/nasa/earth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { z } from 'zod';
22
import { nasaApiRequest } from '../../utils/api-client';
3-
import { addResource } from '../../index.js';
3+
import { addResource } from '../../resources';
44

55
// Schema for validating Earth API request parameters
66
export const earthParamsSchema = z.object({
@@ -113,4 +113,4 @@ function processEarthResult(result: any, params: EarthParams) {
113113
}
114114

115115
// Export the handler function directly as default
116-
export default nasaEarthHandler;
116+
export default nasaEarthHandler;

src/handlers/nasa/eonet.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { z } from 'zod';
22
import axios from 'axios';
33
import { nasaApiRequest } from '../../utils/api-client';
44
import { EonetParams } from '../setup';
5-
import { addResource } from '../../index';
5+
import { addResource } from '../../resources';
66

77
// Define the EONET API base URL
88
const EONET_API_BASE_URL = 'https://eonet.gsfc.nasa.gov/api';
@@ -110,4 +110,4 @@ export async function nasaEonetHandler(params: EonetParams) {
110110
}
111111

112112
// Export the handler function directly as default
113-
export default nasaEonetHandler;
113+
export default nasaEonetHandler;

src/handlers/nasa/epic.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { z } from 'zod';
22
import axios from 'axios';
33
import { nasaApiRequest } from '../../utils/api-client';
4-
import { addResource } from '../../index';
4+
import { addResource } from '../../resources';
55

66
// Define the EPIC API base URL
77
const EPIC_API_BASE_URL = 'https://epic.gsfc.nasa.gov/api';
@@ -38,8 +38,8 @@ async function processEpicResults(epicData: any[], collection: string) {
3838
const dateStr = firstImage.date.split(' ')[0];
3939
const [year, month, day] = dateStr.split('-');
4040

41-
// Format each image and register it as a resource
42-
const images = [];
41+
// Collect image data including base64 for direct display
42+
const images: Array<{ identifier: string; caption: string; imageUrl: string; resourceUri: string; base64?: string; mimeType?: string; error?: string }> = [];
4343

4444
for (const img of epicData) {
4545
// Construct the image URL according to NASA's format
@@ -56,6 +56,9 @@ async function processEpicResults(epicData: any[], collection: string) {
5656
timeout: 30000
5757
});
5858

59+
// Convert image data to Base64 for direct response
60+
const imageBase64 = Buffer.from(imageResponse.data).toString('base64');
61+
5962
// Register this image as a resource with binary data
6063
addResource(resourceUri, {
6164
name: `NASA EPIC Earth Image - ${img.identifier}`,
@@ -76,11 +79,14 @@ async function processEpicResults(epicData: any[], collection: string) {
7679
blob: Buffer.from(imageResponse.data)
7780
});
7881

82+
// Keep data for direct response
7983
images.push({
8084
identifier: img.identifier,
8185
caption: img.caption || "Earth view from DSCOVR satellite",
8286
imageUrl: imageUrl,
83-
resourceUri: resourceUri
87+
resourceUri: resourceUri,
88+
base64: imageBase64,
89+
mimeType: "image/png"
8490
});
8591
} catch (error) {
8692
console.error(`Error fetching EPIC image ${img.identifier}:`, error);
@@ -146,14 +152,15 @@ export async function nasaEpicHandler(params: EpicParams) {
146152

147153
return {
148154
content: [
149-
{
150-
type: "text",
151-
text: results.summary
152-
},
153-
...results.images.map(img => ({
154-
type: "text",
155-
text: `![${img.caption}](${img.resourceUri})`
156-
}))
155+
{ type: "text", text: results.summary },
156+
// Existing resource URI entries
157+
...results.images.map(img => ({ type: "text", text: `![${img.caption}](${img.resourceUri})` })),
158+
// Direct image URL markdown entries
159+
...results.images.map(img => ({ type: "text", text: `![${img.caption}](${img.imageUrl})` })),
160+
// Embedded binary images
161+
...results.images
162+
.filter(img => img.base64)
163+
.map(img => ({ type: "image", data: img.base64!, mimeType: img.mimeType! })),
157164
],
158165
isError: false
159166
};
@@ -192,4 +199,4 @@ export async function nasaEpicHandler(params: EpicParams) {
192199
}
193200

194201
// Export the handler function directly as default
195-
export default nasaEpicHandler;
202+
export default nasaEpicHandler;

0 commit comments

Comments
 (0)