tides-mcp 1.0.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/README.md +43 -0
- package/dist/api.d.ts +5 -0
- package/dist/api.js +10 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +12 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +33 -0
- package/package.json +42 -0
- package/server.json +20 -0
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# tides-mcp
|
|
2
|
+
|
|
3
|
+
A small MCP server for coastal planning with NOAA CO-OPS tide data. It is useful for fishing, kayaking, tidepool trips, photography, flood awareness, and checking whether a tide window is worth investigating.
|
|
4
|
+
|
|
5
|
+
## Tools
|
|
6
|
+
|
|
7
|
+
- `get_tide_predictions`: high and low predictions or hourly predictions for a station and date range.
|
|
8
|
+
- `get_water_levels`: observed water levels for a station and date range.
|
|
9
|
+
|
|
10
|
+
The server uses the public NOAA CO-OPS API and needs no key. Dates use `YYYY-MM-DD`; station ids are NOAA station identifiers such as `9414290`. Requests time out after 20 seconds.
|
|
11
|
+
|
|
12
|
+
## Run
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install
|
|
16
|
+
npm run build
|
|
17
|
+
node dist/index.js
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The server uses stdio MCP transport and does not write files or contact any service other than NOAA.
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install
|
|
26
|
+
npm run build
|
|
27
|
+
node dist/index.js
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The server uses stdio, so it can be connected to Claude Desktop, Cursor, VS Code, MCP Inspector, or another compatible MCP client.
|
|
31
|
+
|
|
32
|
+
## Tools at a glance
|
|
33
|
+
|
|
34
|
+
- `get_tide_predictions`: Get NOAA high low or hourly tide predictions for a station and date range.
|
|
35
|
+
- `get_water_levels`: Get observed NOAA water levels for a station and short date range.
|
|
36
|
+
|
|
37
|
+
## Limits and privacy
|
|
38
|
+
|
|
39
|
+
This project is intentionally narrow. It should be treated as a practical helper, not a complete certification or security audit. Check the implementation and the returned data before using it with sensitive material. No credentials are required unless the project explicitly says otherwise.
|
|
40
|
+
|
|
41
|
+
## Try it
|
|
42
|
+
|
|
43
|
+
After building, connect the server through your MCP client. The repository root also contains `smoke-test.mjs` for projects covered by the shared harness. A typical tool call starts with `get_tide_predictions`.
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare class TidesError extends Error {
|
|
2
|
+
}
|
|
3
|
+
export declare function predictions(station: string, begin: string, end: string, interval?: "hilo" | "h", units?: string): Promise<any>;
|
|
4
|
+
export declare function waterLevels(station: string, begin: string, end: string, interval?: string, units?: string): Promise<any>;
|
|
5
|
+
export declare function format(data: any): string;
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const BASE = "https://api.tidesandcurrents.noaa.gov/api/prod/datagetter";
|
|
2
|
+
const HEADERS = { "User-Agent": "mrfentmen-tides-mcp/1.0" };
|
|
3
|
+
export class TidesError extends Error {
|
|
4
|
+
}
|
|
5
|
+
async function get(params) { const url = new URL(BASE); Object.entries({ ...params, format: "json", units: params.units ?? "english", time_zone: params.time_zone ?? "gmt" }).forEach(([k, v]) => url.searchParams.set(k, v)); const res = await fetch(url, { headers: HEADERS, signal: AbortSignal.timeout(20000) }); if (!res.ok)
|
|
6
|
+
throw new TidesError(`NOAA tides error ${res.status}`); const data = await res.json(); if (data.error)
|
|
7
|
+
throw new TidesError(data.error.message ?? "NOAA returned an error"); return data; }
|
|
8
|
+
export function predictions(station, begin, end, interval = "hilo", units = "english") { return get({ station, product: "predictions", datum: "MLLW", begin_date: begin.replaceAll("-", ""), end_date: end.replaceAll("-", ""), interval, units }); }
|
|
9
|
+
export function waterLevels(station, begin, end, interval = "6", units = "english") { return get({ station, product: "water_level", datum: "MLLW", begin_date: begin.replaceAll("-", ""), end_date: end.replaceAll("-", ""), interval, units }); }
|
|
10
|
+
export function format(data) { return JSON.stringify(data, null, 2).slice(0, 12000); }
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
|
+
import { createServer } from "./server.js";
|
|
3
|
+
async function main() {
|
|
4
|
+
const server = createServer();
|
|
5
|
+
const transport = new StdioServerTransport();
|
|
6
|
+
await server.connect(transport);
|
|
7
|
+
console.error("MCP server running on stdio");
|
|
8
|
+
}
|
|
9
|
+
main().catch((err) => {
|
|
10
|
+
console.error("Fatal error:", err);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
});
|
package/dist/server.d.ts
ADDED
package/dist/server.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { format, predictions, TidesError, waterLevels } from "./api.js";
|
|
4
|
+
const text = (s) => ({ content: [{ type: "text", text: s }] });
|
|
5
|
+
const textError = (t) => ({ content: [{ type: "text", text: t }], isError: true });
|
|
6
|
+
const READ_ONLY = { readOnlyHint: true, openWorldHint: true };
|
|
7
|
+
export function createServer() {
|
|
8
|
+
const server = new McpServer({ name: "tides-mcp", version: "1.0.0" });
|
|
9
|
+
server.registerTool("get_tide_predictions", {
|
|
10
|
+
title: "Get tide predictions",
|
|
11
|
+
description: "Get NOAA high low or hourly tide predictions for a station and date range.",
|
|
12
|
+
inputSchema: z.object({ station: z.string().min(3), begin: z.string().describe("YYYY-MM-DD"), end: z.string().describe("YYYY-MM-DD"), interval: z.enum(["hilo", "h"]).default("hilo"), units: z.enum(["english", "metric"]).default("english") }),
|
|
13
|
+
annotations: READ_ONLY,
|
|
14
|
+
}, async ({ station, begin, end, interval, units }) => { try {
|
|
15
|
+
return text(format(await predictions(station, begin, end, interval, units)));
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
return textError(`Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
19
|
+
} });
|
|
20
|
+
server.registerTool("get_water_levels", {
|
|
21
|
+
title: "Get water levels",
|
|
22
|
+
description: "Get observed NOAA water levels for a station and short date range.",
|
|
23
|
+
inputSchema: z.object({ station: z.string().min(3), begin: z.string(), end: z.string(), interval: z.enum(["6", "h"]).default("6"), units: z.enum(["english", "metric"]).default("english") }),
|
|
24
|
+
annotations: READ_ONLY,
|
|
25
|
+
}, async ({ station, begin, end, interval, units }) => { try {
|
|
26
|
+
return text(format(await waterLevels(station, begin, end, interval, units)));
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
return textError(`Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
30
|
+
} });
|
|
31
|
+
return server;
|
|
32
|
+
}
|
|
33
|
+
export { TidesError };
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tides-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Use this MCP server to NOAA tides and currents predictions and water levels. Tools include get tide predictions, get water levels",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"mcpName": "io.github.mrfentmen/tides-mcp",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/mrfentmen/tides-mcp.git"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"tides-mcp": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"server.json",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc -p tsconfig.json",
|
|
22
|
+
"start": "node dist/index.js",
|
|
23
|
+
"dev": "npm run build && node dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"mcp",
|
|
27
|
+
"public-data",
|
|
28
|
+
"tides"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
33
|
+
"zod": "^3.23.8"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^22.0.0",
|
|
37
|
+
"typescript": "^5.6.0"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=20"
|
|
41
|
+
}
|
|
42
|
+
}
|
package/server.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.mrfentmen/tides-mcp",
|
|
4
|
+
"description": "Use this MCP server to NOAA tides and currents predictions and water levels. Tools include get...",
|
|
5
|
+
"repository": {
|
|
6
|
+
"url": "https://github.com/mrfentmen/tides-mcp",
|
|
7
|
+
"source": "github"
|
|
8
|
+
},
|
|
9
|
+
"version": "1.0.0",
|
|
10
|
+
"packages": [
|
|
11
|
+
{
|
|
12
|
+
"registryType": "npm",
|
|
13
|
+
"identifier": "tides-mcp",
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"transport": {
|
|
16
|
+
"type": "stdio"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|