@hotscots/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 +94 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +366 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# @hotscots/mcp
|
|
2
|
+
|
|
3
|
+
MCP server for the [Hots&Cots](https://hotscots.app) military quality-of-life API. Gives Claude Desktop, Cursor, and other MCP clients direct access to anonymized barracks and DFAC review data.
|
|
4
|
+
|
|
5
|
+
**Requires an H&CPro API key** (`hc_live_...`) — generate yours at [hotscots.app/subscription/dashboard](https://hotscots.app/subscription/dashboard).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Setup — Claude Desktop
|
|
10
|
+
|
|
11
|
+
Add this to your Claude Desktop config and you're done. No cloning, no building.
|
|
12
|
+
|
|
13
|
+
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
14
|
+
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"mcpServers": {
|
|
19
|
+
"hotscots": {
|
|
20
|
+
"command": "npx",
|
|
21
|
+
"args": ["-y", "@hotscots/mcp"],
|
|
22
|
+
"env": {
|
|
23
|
+
"HOTSCOTS_API_KEY": "hc_live_YOUR_KEY_HERE"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Restart Claude Desktop. The Hots&Cots tools will appear automatically.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Setup — Cursor / Other MCP Clients
|
|
35
|
+
|
|
36
|
+
Same config, different file location. Check your client's MCP documentation for the config path.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## What You Can Ask Claude
|
|
41
|
+
|
|
42
|
+
- *"Check that my Hots&Cots API key is working"*
|
|
43
|
+
- *"List all installations on Hots&Cots — which have the most reviews?"*
|
|
44
|
+
- *"Give me a full snapshot of Fort Hood — barracks and DFAC"*
|
|
45
|
+
- *"Analyze the last 500 barracks reviews — what percentage report mold?"*
|
|
46
|
+
- *"Analyze DFAC reviews — what's the inedible food report rate?"*
|
|
47
|
+
- *"Show medical and CDC facility reviews"*
|
|
48
|
+
- *"How many barracks reviews does Fort Stewart have?"*
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Available Tools
|
|
53
|
+
|
|
54
|
+
| Tool | Description |
|
|
55
|
+
|------|-------------|
|
|
56
|
+
| `hotscots_health` | Verify your API key |
|
|
57
|
+
| `hotscots_get_barracks_reviews` | Paginated barracks (cots) reviews |
|
|
58
|
+
| `hotscots_analyze_barracks` | Statistical analysis — mold rate, HVAC failures, DPW satisfaction, top tags |
|
|
59
|
+
| `hotscots_get_dfac_reviews` | Paginated DFAC (hots) reviews |
|
|
60
|
+
| `hotscots_analyze_dfac` | Statistical analysis — per-meal ratings, food quality flags, inedible rate |
|
|
61
|
+
| `hotscots_get_other_reviews` | Medical, CDC, gym, PX/BX, lodging, moving reviews |
|
|
62
|
+
| `hotscots_list_installations` | All installations with cots/hots/other/total counts |
|
|
63
|
+
| `hotscots_installation_snapshot` | Unified barracks + DFAC snapshot for a named installation |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Architecture
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Claude Desktop / Cursor / AI client
|
|
71
|
+
↓ MCP protocol (stdio)
|
|
72
|
+
@hotscots/mcp ← runs locally on your machine via npx
|
|
73
|
+
↓ HTTPS + Bearer token
|
|
74
|
+
api.hotscots.app/functions/v1/api
|
|
75
|
+
↓ internal
|
|
76
|
+
Supabase (anonymized review data)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The MCP server runs locally — your API key never leaves your machine.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Environment Variables
|
|
84
|
+
|
|
85
|
+
| Variable | Description |
|
|
86
|
+
|----------|-------------|
|
|
87
|
+
| `HOTSCOTS_API_KEY` | Your API key (`hc_live_...`) — required |
|
|
88
|
+
| `HOTSCOTS_API_BASE_URL` | Override the API base URL (optional) |
|
|
89
|
+
| `TRANSPORT` | `stdio` (default) or `http` for remote/multi-user mode |
|
|
90
|
+
| `PORT` | HTTP port when `TRANSPORT=http` (default: `3000`) |
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
**Clean. Safe. Comfort.** — [hotscots.app](https://hotscots.app)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
5
|
+
import express from "express";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
const API_BASE_URL = process.env.HOTSCOTS_API_URL ?? "https://api.hotscots.app/v1";
|
|
8
|
+
const CHARACTER_LIMIT = 25000;
|
|
9
|
+
var ResponseFormat;
|
|
10
|
+
(function (ResponseFormat) {
|
|
11
|
+
ResponseFormat["MARKDOWN"] = "markdown";
|
|
12
|
+
ResponseFormat["JSON"] = "json";
|
|
13
|
+
})(ResponseFormat || (ResponseFormat = {}));
|
|
14
|
+
// --- API client ---
|
|
15
|
+
async function apiRequest(path, params) {
|
|
16
|
+
const apiKey = process.env.HOTSCOTS_API_KEY;
|
|
17
|
+
if (!apiKey)
|
|
18
|
+
throw new Error("HOTSCOTS_API_KEY environment variable is not set");
|
|
19
|
+
const url = new URL(`${API_BASE_URL}${path}`);
|
|
20
|
+
if (params) {
|
|
21
|
+
for (const [k, v] of Object.entries(params)) {
|
|
22
|
+
if (v !== undefined)
|
|
23
|
+
url.searchParams.set(k, String(v));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const res = await fetch(url.toString(), {
|
|
27
|
+
headers: {
|
|
28
|
+
Authorization: `Bearer ${apiKey}`,
|
|
29
|
+
Accept: "application/json",
|
|
30
|
+
},
|
|
31
|
+
signal: AbortSignal.timeout(30_000),
|
|
32
|
+
});
|
|
33
|
+
if (!res.ok) {
|
|
34
|
+
switch (res.status) {
|
|
35
|
+
case 401: throw new Error("Unauthorized — check your HOTSCOTS_API_KEY.");
|
|
36
|
+
case 403: throw new Error("Forbidden — you don't have access to this resource.");
|
|
37
|
+
case 404: throw new Error("Not found — the requested resource does not exist.");
|
|
38
|
+
case 429: throw new Error("Rate limit exceeded — please wait before retrying.");
|
|
39
|
+
default: throw new Error(`API error ${res.status}: ${res.statusText}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return res.json();
|
|
43
|
+
}
|
|
44
|
+
function handleError(err) {
|
|
45
|
+
return `Error: ${err instanceof Error ? err.message : String(err)}`;
|
|
46
|
+
}
|
|
47
|
+
function truncate(text) {
|
|
48
|
+
if (text.length <= CHARACTER_LIMIT)
|
|
49
|
+
return text;
|
|
50
|
+
return text.slice(0, CHARACTER_LIMIT) + "\n\n[Response truncated. Use pagination to see more.]";
|
|
51
|
+
}
|
|
52
|
+
// --- Zod schemas ---
|
|
53
|
+
const PaginationSchema = z.object({
|
|
54
|
+
limit: z.number().int().min(1).max(100).default(20).describe("Max results to return (1–100)"),
|
|
55
|
+
offset: z.number().int().min(0).default(0).describe("Number of results to skip for pagination"),
|
|
56
|
+
});
|
|
57
|
+
const ResponseFormatSchema = z.nativeEnum(ResponseFormat)
|
|
58
|
+
.default(ResponseFormat.MARKDOWN)
|
|
59
|
+
.describe("Output format: 'markdown' for human-readable, 'json' for machine-readable");
|
|
60
|
+
// --- MCP Server ---
|
|
61
|
+
const server = new McpServer({
|
|
62
|
+
name: "hotscots-mcp-server",
|
|
63
|
+
version: "1.0.0",
|
|
64
|
+
});
|
|
65
|
+
// Tool: search installations
|
|
66
|
+
server.registerTool("hotscots_search_installations", {
|
|
67
|
+
title: "Search Military Installations",
|
|
68
|
+
description: `Search for U.S. military installations (bases, posts, camps, forts, stations) in the Hots&Cots database.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
- query (string): Name, abbreviation, or keyword (e.g., "Fort Liberty", "Bragg", "Camp Lejeune")
|
|
72
|
+
- branch (string, optional): Filter by military branch — "Army", "Navy", "Air Force", "Marines", "Coast Guard", "Space Force"
|
|
73
|
+
- state (string, optional): Two-letter US state abbreviation (e.g., "NC", "TX")
|
|
74
|
+
- limit (number): Max results, 1–100 (default: 20)
|
|
75
|
+
- offset (number): Pagination offset (default: 0)
|
|
76
|
+
- response_format: 'markdown' or 'json'
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
List of installations with id, name, branch, state, and city.
|
|
80
|
+
|
|
81
|
+
Examples:
|
|
82
|
+
- "Find Army bases in North Carolina" → query="", branch="Army", state="NC"
|
|
83
|
+
- "Search for Camp Pendleton" → query="Camp Pendleton"`,
|
|
84
|
+
inputSchema: z.object({
|
|
85
|
+
query: z.string().max(200).default("").describe("Search keyword (name, abbreviation, or location)"),
|
|
86
|
+
branch: z.string().optional().describe("Military branch filter"),
|
|
87
|
+
state: z.string().length(2).optional().describe("US state abbreviation (e.g., NC)"),
|
|
88
|
+
...PaginationSchema.shape,
|
|
89
|
+
response_format: ResponseFormatSchema,
|
|
90
|
+
}),
|
|
91
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
92
|
+
}, async (params) => {
|
|
93
|
+
try {
|
|
94
|
+
const result = await apiRequest("/installations", {
|
|
95
|
+
q: params.query || undefined,
|
|
96
|
+
branch: params.branch,
|
|
97
|
+
state: params.state,
|
|
98
|
+
limit: params.limit,
|
|
99
|
+
offset: params.offset,
|
|
100
|
+
});
|
|
101
|
+
if (!result.data.length) {
|
|
102
|
+
return { content: [{ type: "text", text: "No installations found matching your search." }] };
|
|
103
|
+
}
|
|
104
|
+
let text;
|
|
105
|
+
if (params.response_format === ResponseFormat.JSON) {
|
|
106
|
+
text = JSON.stringify(result, null, 2);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
const lines = [
|
|
110
|
+
`# Military Installations (${result.total} total, showing ${result.data.length})`,
|
|
111
|
+
"",
|
|
112
|
+
];
|
|
113
|
+
for (const inst of result.data) {
|
|
114
|
+
lines.push(`## ${inst.name} (\`${inst.id}\`)`);
|
|
115
|
+
lines.push(`- **Branch**: ${inst.branch}`);
|
|
116
|
+
lines.push(`- **Location**: ${[inst.city, inst.state, inst.country].filter(Boolean).join(", ")}`);
|
|
117
|
+
lines.push("");
|
|
118
|
+
}
|
|
119
|
+
if (result.has_more)
|
|
120
|
+
lines.push(`_Use offset=${result.next_offset} to see more._`);
|
|
121
|
+
text = lines.join("\n");
|
|
122
|
+
}
|
|
123
|
+
return { content: [{ type: "text", text: truncate(text) }], structuredContent: result };
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
return { content: [{ type: "text", text: handleError(err) }] };
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
// Tool: get installation
|
|
130
|
+
server.registerTool("hotscots_get_installation", {
|
|
131
|
+
title: "Get Installation Details",
|
|
132
|
+
description: `Get detailed information about a specific military installation by its ID.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
- installation_id (string): The installation ID from hotscots_search_installations
|
|
136
|
+
- response_format: 'markdown' or 'json'
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
Full installation record including name, branch, location, and review summary stats.`,
|
|
140
|
+
inputSchema: z.object({
|
|
141
|
+
installation_id: z.string().min(1).describe("Installation ID (from search results)"),
|
|
142
|
+
response_format: ResponseFormatSchema,
|
|
143
|
+
}),
|
|
144
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
145
|
+
}, async (params) => {
|
|
146
|
+
try {
|
|
147
|
+
const inst = await apiRequest(`/installations/${params.installation_id}`);
|
|
148
|
+
let text;
|
|
149
|
+
if (params.response_format === ResponseFormat.JSON) {
|
|
150
|
+
text = JSON.stringify(inst, null, 2);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
text = [
|
|
154
|
+
`# ${inst.name}`,
|
|
155
|
+
`- **ID**: \`${inst.id}\``,
|
|
156
|
+
`- **Branch**: ${inst.branch}`,
|
|
157
|
+
`- **Location**: ${[inst.city, inst.state, inst.country].filter(Boolean).join(", ")}`,
|
|
158
|
+
].join("\n");
|
|
159
|
+
}
|
|
160
|
+
return { content: [{ type: "text", text }], structuredContent: inst };
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
return { content: [{ type: "text", text: handleError(err) }] };
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
// Tool: get barracks reviews
|
|
167
|
+
server.registerTool("hotscots_get_barracks_reviews", {
|
|
168
|
+
title: "Get Barracks Reviews",
|
|
169
|
+
description: `Fetch barracks (housing) reviews for a military installation.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
- installation_id (string): Installation ID from hotscots_search_installations
|
|
173
|
+
- building (string, optional): Filter by specific building or barracks name/number
|
|
174
|
+
- min_rating (number, optional): Minimum star rating 1–5
|
|
175
|
+
- limit (number): Max results, 1–100 (default: 20)
|
|
176
|
+
- offset (number): Pagination offset (default: 0)
|
|
177
|
+
- response_format: 'markdown' or 'json'
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
Paginated list of barracks reviews with ratings, descriptions, and dates.
|
|
181
|
+
|
|
182
|
+
Examples:
|
|
183
|
+
- "Show me barracks reviews for Fort Liberty" → first get installation ID, then call with that ID
|
|
184
|
+
- "Find highly rated barracks at Bragg" → min_rating=4`,
|
|
185
|
+
inputSchema: z.object({
|
|
186
|
+
installation_id: z.string().min(1).describe("Installation ID"),
|
|
187
|
+
building: z.string().optional().describe("Filter by building name or number"),
|
|
188
|
+
min_rating: z.number().int().min(1).max(5).optional().describe("Minimum star rating (1–5)"),
|
|
189
|
+
...PaginationSchema.shape,
|
|
190
|
+
response_format: ResponseFormatSchema,
|
|
191
|
+
}),
|
|
192
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
193
|
+
}, async (params) => {
|
|
194
|
+
try {
|
|
195
|
+
const result = await apiRequest(`/installations/${params.installation_id}/reviews`, {
|
|
196
|
+
category: "barracks",
|
|
197
|
+
building: params.building,
|
|
198
|
+
min_rating: params.min_rating,
|
|
199
|
+
limit: params.limit,
|
|
200
|
+
offset: params.offset,
|
|
201
|
+
});
|
|
202
|
+
if (!result.data.length) {
|
|
203
|
+
return { content: [{ type: "text", text: "No barracks reviews found for this installation." }] };
|
|
204
|
+
}
|
|
205
|
+
const text = params.response_format === ResponseFormat.JSON
|
|
206
|
+
? JSON.stringify(result, null, 2)
|
|
207
|
+
: formatReviews(result, "Barracks");
|
|
208
|
+
return { content: [{ type: "text", text: truncate(text) }], structuredContent: result };
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
return { content: [{ type: "text", text: handleError(err) }] };
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
// Tool: get DFAC reviews
|
|
215
|
+
server.registerTool("hotscots_get_dfac_reviews", {
|
|
216
|
+
title: "Get DFAC Reviews",
|
|
217
|
+
description: `Fetch DFAC (dining facility) reviews for a military installation.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
- installation_id (string): Installation ID from hotscots_search_installations
|
|
221
|
+
- building (string, optional): Filter by specific DFAC name or building
|
|
222
|
+
- min_rating (number, optional): Minimum star rating 1–5
|
|
223
|
+
- limit (number): Max results, 1–100 (default: 20)
|
|
224
|
+
- offset (number): Pagination offset (default: 0)
|
|
225
|
+
- response_format: 'markdown' or 'json'
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Paginated list of DFAC reviews with ratings, descriptions, and dates.
|
|
229
|
+
|
|
230
|
+
Examples:
|
|
231
|
+
- "What do soldiers think of the chow hall at Camp Lejeune?" → get installation ID, then call this tool
|
|
232
|
+
- "Find DFACs rated above 3 stars at Fort Campbell" → min_rating=4`,
|
|
233
|
+
inputSchema: z.object({
|
|
234
|
+
installation_id: z.string().min(1).describe("Installation ID"),
|
|
235
|
+
building: z.string().optional().describe("Filter by DFAC name or building"),
|
|
236
|
+
min_rating: z.number().int().min(1).max(5).optional().describe("Minimum star rating (1–5)"),
|
|
237
|
+
...PaginationSchema.shape,
|
|
238
|
+
response_format: ResponseFormatSchema,
|
|
239
|
+
}),
|
|
240
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
241
|
+
}, async (params) => {
|
|
242
|
+
try {
|
|
243
|
+
const result = await apiRequest(`/installations/${params.installation_id}/reviews`, {
|
|
244
|
+
category: "dfac",
|
|
245
|
+
building: params.building,
|
|
246
|
+
min_rating: params.min_rating,
|
|
247
|
+
limit: params.limit,
|
|
248
|
+
offset: params.offset,
|
|
249
|
+
});
|
|
250
|
+
if (!result.data.length) {
|
|
251
|
+
return { content: [{ type: "text", text: "No DFAC reviews found for this installation." }] };
|
|
252
|
+
}
|
|
253
|
+
const text = params.response_format === ResponseFormat.JSON
|
|
254
|
+
? JSON.stringify(result, null, 2)
|
|
255
|
+
: formatReviews(result, "DFAC");
|
|
256
|
+
return { content: [{ type: "text", text: truncate(text) }], structuredContent: result };
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
return { content: [{ type: "text", text: handleError(err) }] };
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
// Tool: search reviews across installations
|
|
263
|
+
server.registerTool("hotscots_search_reviews", {
|
|
264
|
+
title: "Search Reviews",
|
|
265
|
+
description: `Full-text search across all Hots&Cots reviews (barracks and DFAC) by keyword.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
- query (string): Keyword or phrase to search in review titles and body text
|
|
269
|
+
- category (string, optional): Filter to 'barracks' or 'dfac' reviews only
|
|
270
|
+
- installation_id (string, optional): Scope search to a specific installation
|
|
271
|
+
- min_rating (number, optional): Minimum star rating 1–5
|
|
272
|
+
- limit (number): Max results, 1–100 (default: 20)
|
|
273
|
+
- offset (number): Pagination offset (default: 0)
|
|
274
|
+
- response_format: 'markdown' or 'json'
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
Paginated list of matching reviews with installation context.
|
|
278
|
+
|
|
279
|
+
Examples:
|
|
280
|
+
- "Find reviews mentioning mold" → query="mold"
|
|
281
|
+
- "Search for DFAC reviews about pizza" → query="pizza", category="dfac"`,
|
|
282
|
+
inputSchema: z.object({
|
|
283
|
+
query: z.string().min(2).max(200).describe("Search keyword or phrase"),
|
|
284
|
+
category: z.enum(["barracks", "dfac"]).optional().describe("Limit to barracks or dfac reviews"),
|
|
285
|
+
installation_id: z.string().optional().describe("Scope to a specific installation"),
|
|
286
|
+
min_rating: z.number().int().min(1).max(5).optional().describe("Minimum star rating (1–5)"),
|
|
287
|
+
...PaginationSchema.shape,
|
|
288
|
+
response_format: ResponseFormatSchema,
|
|
289
|
+
}),
|
|
290
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
291
|
+
}, async (params) => {
|
|
292
|
+
try {
|
|
293
|
+
const result = await apiRequest("/reviews/search", {
|
|
294
|
+
q: params.query,
|
|
295
|
+
category: params.category,
|
|
296
|
+
installation_id: params.installation_id,
|
|
297
|
+
min_rating: params.min_rating,
|
|
298
|
+
limit: params.limit,
|
|
299
|
+
offset: params.offset,
|
|
300
|
+
});
|
|
301
|
+
if (!result.data.length) {
|
|
302
|
+
return { content: [{ type: "text", text: `No reviews found for "${params.query}".` }] };
|
|
303
|
+
}
|
|
304
|
+
const text = params.response_format === ResponseFormat.JSON
|
|
305
|
+
? JSON.stringify(result, null, 2)
|
|
306
|
+
: formatReviews(result, "Search Results");
|
|
307
|
+
return { content: [{ type: "text", text: truncate(text) }], structuredContent: result };
|
|
308
|
+
}
|
|
309
|
+
catch (err) {
|
|
310
|
+
return { content: [{ type: "text", text: handleError(err) }] };
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
// --- Shared formatters ---
|
|
314
|
+
function formatReviews(result, label) {
|
|
315
|
+
const lines = [
|
|
316
|
+
`# ${label} Reviews (${result.total} total, showing ${result.data.length})`,
|
|
317
|
+
"",
|
|
318
|
+
];
|
|
319
|
+
for (const r of result.data) {
|
|
320
|
+
lines.push(`## ${"★".repeat(r.rating)}${"☆".repeat(5 - r.rating)} ${r.title ?? "(no title)"}`);
|
|
321
|
+
if (r.building)
|
|
322
|
+
lines.push(`**Building**: ${r.building}`);
|
|
323
|
+
if (r.author_rank)
|
|
324
|
+
lines.push(`**Reviewer rank**: ${r.author_rank}`);
|
|
325
|
+
lines.push(`**Date**: ${new Date(r.created_at).toLocaleDateString()}`);
|
|
326
|
+
lines.push("");
|
|
327
|
+
lines.push(r.body);
|
|
328
|
+
lines.push("");
|
|
329
|
+
lines.push("---");
|
|
330
|
+
lines.push("");
|
|
331
|
+
}
|
|
332
|
+
if (result.has_more)
|
|
333
|
+
lines.push(`_Use offset=${result.next_offset} to see more._`);
|
|
334
|
+
return lines.join("\n");
|
|
335
|
+
}
|
|
336
|
+
// --- Transport ---
|
|
337
|
+
async function runStdio() {
|
|
338
|
+
const transport = new StdioServerTransport();
|
|
339
|
+
await server.connect(transport);
|
|
340
|
+
console.error("Hots&Cots MCP server running via stdio");
|
|
341
|
+
}
|
|
342
|
+
async function runHTTP() {
|
|
343
|
+
const app = express();
|
|
344
|
+
app.use(express.json());
|
|
345
|
+
app.post("/mcp", async (req, res) => {
|
|
346
|
+
const transport = new StreamableHTTPServerTransport({
|
|
347
|
+
sessionIdGenerator: undefined,
|
|
348
|
+
enableJsonResponse: true,
|
|
349
|
+
});
|
|
350
|
+
res.on("close", () => transport.close());
|
|
351
|
+
await server.connect(transport);
|
|
352
|
+
await transport.handleRequest(req, res, req.body);
|
|
353
|
+
});
|
|
354
|
+
const port = parseInt(process.env.PORT ?? "3000", 10);
|
|
355
|
+
app.listen(port, () => {
|
|
356
|
+
console.error(`Hots&Cots MCP server running on http://localhost:${port}/mcp`);
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
const transportMode = process.env.TRANSPORT ?? "stdio";
|
|
360
|
+
if (transportMode === "http") {
|
|
361
|
+
runHTTP().catch((err) => { console.error(err); process.exit(1); });
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
runStdio().catch((err) => { console.error(err); process.exit(1); });
|
|
365
|
+
}
|
|
366
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hotscots/mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for the Hots&Cots military QoL API — barracks and DFAC reviews for Claude Desktop, Cursor, and other MCP clients",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"hotscots-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/**/*",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"postbuild": "chmod +x dist/index.js",
|
|
17
|
+
"start": "node dist/index.js",
|
|
18
|
+
"dev": "tsc --watch"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"mcp",
|
|
22
|
+
"model-context-protocol",
|
|
23
|
+
"military",
|
|
24
|
+
"barracks",
|
|
25
|
+
"dfac",
|
|
26
|
+
"hotscots",
|
|
27
|
+
"claude",
|
|
28
|
+
"cursor"
|
|
29
|
+
],
|
|
30
|
+
"author": "Hots&Cots <support@hotscots.app>",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"homepage": "https://hotscots.app",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/arbyruns/hotscots-mcp.git"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
45
|
+
"express": "^4.19.2",
|
|
46
|
+
"zod": "^3.23.8"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/express": "^4.17.21",
|
|
50
|
+
"@types/node": "^20.14.0",
|
|
51
|
+
"typescript": "^5.4.5"
|
|
52
|
+
}
|
|
53
|
+
}
|