OSP Marketing Tools MCP Server
- src
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import dotenv from "dotenv";
// environment variables
dotenv.config();
const BASE_URL = "https://developer.nps.gov/api/v1";
const API_KEY = process.env.API_KEY || "Key Not Supplied";
const headers = {
'Content-Type': 'application/json',
'X-Api-Key': API_KEY
}
interface ParamsType {
start: Number
limit: Number
parkCode?: String
stateCode?: String
}
/**********************************************************************************************************************
* This function will perform the fetch given an endpoint and params; the NPS endpoints are all GET methods
*********************************************************************************************************************/
export const fetchData = async (endpoint: string, params: any | {}) => {
const url = new URL(`${BASE_URL}/${endpoint}`);
url.search = new URLSearchParams(params).toString();
const options = {
method: 'GET',
headers
};
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error("Error fetching data:", error);
}
}
/**********************************************************************************************************************
* This function will fetch all of the national parks and return the code, states array, and full name
* These codes can then be used to fetch detailed information for specific parks and/or states
*********************************************************************************************************************/
export const fetchAllParkCodes = async () => {
let codes = [];
let start = 0;
const limit = 50;
let data;
let paginating = true;
while (paginating) {
const body = await fetchData('parks', { start, limit });
data = body.data;
// @ts-ignore
codes.push(...data.map(item => ({ parkCode: item.parkCode, fullName: item.fullName, states: item.states.split(',') })));
start += limit;
if (body.total < start) {
paginating = false;
}
}
return codes;
}
/**********************************************************************************************************************
* This function will fetch details for a national park given a park code
*********************************************************************************************************************/
export const fetchParkDetails = async (parkCode: String) => {
let start = 0;
const limit = 50;
let data = []
let paginating = true;
let params: ParamsType = { start, limit, parkCode };
while (paginating) {
const body = await fetchData('parks', params);
data.push(...body.data);
start += limit;
if (body.total < start) {
paginating = false;
}
}
return data;
}
/**********************************************************************************************************************
* This function will return a list of parks for a given state
*********************************************************************************************************************/
export const fetchParksList = async (stateCode: String) => {
let start = 0;
const limit = 50;
let data = []
let paginating = true;
let params: ParamsType = { start, limit, stateCode };
while (paginating) {
const body = await fetchData('parks', params);
data.push(...body.data);
start += limit;
if (body.total < start) {
paginating = false;
}
}
return data.map(item => ({ fullName: item.fullName, description: item.description, parkCode: item.parkCode }));
}
/**********************************************************************************************************************
* MCP Server for National Park Services data
* - retrieve list of parks given a state
* - get details about a park given a park code
*********************************************************************************************************************/
const server = new McpServer(
{
name: "nps",
version: "1.0.0",
}
);
// tool for fetching park details
server.tool(
"park-details",
"Get details for a specific national park",
{
parkCode: z.string().describe("National Park lookup code"),
},
async ({ parkCode }) => {
const data = await fetchParkDetails(parkCode);
return { content: [{ type: "text", text: JSON.stringify(data) }] }
}
);
server.tool(
"park-list",
"Get list of parks for a given state",
{
stateCode: z.string().describe("Two-letter state code")
},
async ({ stateCode }) => {
const data = await fetchParksList(stateCode);
return { content: [{ type: "text", text: JSON.stringify(data) }] }
}
);
server.prompt(
"parks-by-state",
{ stateCode: z.string() },
({ stateCode }) => ({
messages: [{
role: "user",
content: {
type: "text",
text: `What National Parks are in the state of ${stateCode}`
}
}]
})
);
server.prompt(
"details-for-park",
{ park: z.string() },
({ park }) => ({
messages: [{
role: "user",
content: {
type: "text",
text: `Give me details about ${park}`
}
}]
})
);
// connect and start receiving messages
const transport = new StdioServerTransport();
await server.connect(transport);