@cyanheads/hn-mcp-server 0.5.11 → 0.5.13
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/CLAUDE.md +59 -12
- package/Dockerfile +11 -7
- package/LICENSE +1 -1
- package/README.md +7 -5
- package/dist/config/server-config.d.ts.map +1 -1
- package/dist/config/server-config.js +1 -0
- package/dist/config/server-config.js.map +1 -1
- package/dist/mcp-server/tools/definitions/get-stories.tool.d.ts +35 -5
- package/dist/mcp-server/tools/definitions/get-stories.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/get-stories.tool.js +39 -0
- package/dist/mcp-server/tools/definitions/get-stories.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/get-thread.tool.d.ts +29 -0
- package/dist/mcp-server/tools/definitions/get-thread.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/get-thread.tool.js +48 -3
- package/dist/mcp-server/tools/definitions/get-thread.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/get-user.tool.d.ts +31 -0
- package/dist/mcp-server/tools/definitions/get-user.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/get-user.tool.js +72 -16
- package/dist/mcp-server/tools/definitions/get-user.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/search-content.tool.d.ts +39 -5
- package/dist/mcp-server/tools/definitions/search-content.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/search-content.tool.js +69 -14
- package/dist/mcp-server/tools/definitions/search-content.tool.js.map +1 -1
- package/dist/services/hn/hn-service.d.ts +12 -1
- package/dist/services/hn/hn-service.d.ts.map +1 -1
- package/dist/services/hn/hn-service.js +101 -32
- package/dist/services/hn/hn-service.js.map +1 -1
- package/package.json +11 -10
- package/server.json +5 -5
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @fileoverview HN API service — Firebase and Algolia HTTP clients with HTML stripping utilities.
|
|
3
3
|
* @module services/hn/hn-service
|
|
4
4
|
*/
|
|
5
|
-
import { serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
|
|
5
|
+
import { JsonRpcErrorCode, McpError, serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
|
|
6
6
|
import { fetchWithTimeout, withRetry } from '@cyanheads/mcp-ts-core/utils';
|
|
7
7
|
import { getServerConfig } from '../../config/server-config.js';
|
|
8
8
|
const HN_API = 'https://hacker-news.firebaseio.com/v0';
|
|
@@ -111,8 +111,10 @@ function isHtmlErrorBody(text) {
|
|
|
111
111
|
return /^\s*<(!DOCTYPE\s+html|html[\s>])/i.test(text);
|
|
112
112
|
}
|
|
113
113
|
/**
|
|
114
|
-
* Parse an HN/Algolia JSON body
|
|
115
|
-
*
|
|
114
|
+
* Parse an HN/Algolia JSON body. Both ways a 200 response can still be unusable
|
|
115
|
+
* — an HTML error page (common during upstream rate limiting) and a body that
|
|
116
|
+
* is not JSON at all — throw a classified error rather than a raw `SyntaxError`,
|
|
117
|
+
* whose message quotes the offending body back at the client.
|
|
116
118
|
*/
|
|
117
119
|
function parseJsonBody(text, upstream) {
|
|
118
120
|
if (isHtmlErrorBody(text)) {
|
|
@@ -124,7 +126,79 @@ function parseJsonBody(text, upstream) {
|
|
|
124
126
|
},
|
|
125
127
|
});
|
|
126
128
|
}
|
|
127
|
-
|
|
129
|
+
try {
|
|
130
|
+
return JSON.parse(text);
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
throw serviceUnavailable(`${upstream} returned a body that is not JSON.`, {
|
|
134
|
+
upstream,
|
|
135
|
+
reason: 'upstream_malformed',
|
|
136
|
+
recovery: {
|
|
137
|
+
hint: `${upstream} answered 200 with a body that is not its API response. Retry after a brief delay; no input change helps while the upstream is serving something else.`,
|
|
138
|
+
},
|
|
139
|
+
}, { cause: err });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Map an upstream HTTP status onto a contract reason, its JSON-RPC code, and
|
|
144
|
+
* the agent's next move. Three buckets: 429 is a pacing problem, 5xx is an
|
|
145
|
+
* upstream outage, and every other 4xx means the request itself was rejected
|
|
146
|
+
* and will be rejected again unchanged.
|
|
147
|
+
*
|
|
148
|
+
* The code travels with the reason rather than being taken from the framework's
|
|
149
|
+
* finer-grained status ladder, so each reason surfaces exactly the code its
|
|
150
|
+
* tools declare in `errors[]`. That ladder would otherwise split one reason
|
|
151
|
+
* across several codes — HN answers an unknown path with 401, and a 500 or 504
|
|
152
|
+
* would arrive as `InternalError` or `Timeout`, blurring the two codes that
|
|
153
|
+
* mean "this server broke" and "this server's own fetch timed out". The exact
|
|
154
|
+
* status stays on `data.status`.
|
|
155
|
+
*/
|
|
156
|
+
function upstreamFailureFor(upstream, status) {
|
|
157
|
+
if (status === 429) {
|
|
158
|
+
return {
|
|
159
|
+
code: JsonRpcErrorCode.RateLimited,
|
|
160
|
+
reason: 'upstream_rate_limited',
|
|
161
|
+
hint: `${upstream} is rate-limiting this server. Wait several seconds before retrying the same call, and reduce how often it is called.`,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (status >= 500) {
|
|
165
|
+
return {
|
|
166
|
+
code: JsonRpcErrorCode.ServiceUnavailable,
|
|
167
|
+
reason: 'upstream_unavailable',
|
|
168
|
+
hint: `${upstream} is failing or in maintenance. Retry after a short delay — no input change helps while the upstream is down.`,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
code: JsonRpcErrorCode.InvalidParams,
|
|
173
|
+
reason: 'upstream_rejected',
|
|
174
|
+
hint: `${upstream} rejected the request as malformed. Check the tool input values against the schema; retrying the same input fails identically.`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Translate `fetchWithTimeout`'s raw non-2xx throw into a classified error
|
|
179
|
+
* carrying `reason` and `recovery.hint`, matching the shape `parseJsonBody`
|
|
180
|
+
* already produces for HTML error bodies.
|
|
181
|
+
*
|
|
182
|
+
* Wraps *outside* `withRetry` so the framework's own classification is left
|
|
183
|
+
* untouched: retry eligibility, `Retry-After` honoring, timeouts, and caller
|
|
184
|
+
* aborts all resolve against the original error, and only HTTP-status failures
|
|
185
|
+
* (`errorSource: 'FetchHttpError'`) are rewritten. The message drops the
|
|
186
|
+
* upstream URL and the verbatim response body, which stay on the `cause` chain
|
|
187
|
+
* for server-side logs.
|
|
188
|
+
*/
|
|
189
|
+
async function withUpstreamHttpErrors(upstream, fn) {
|
|
190
|
+
try {
|
|
191
|
+
return await fn();
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
if (!(err instanceof McpError) || err.data?.errorSource !== 'FetchHttpError')
|
|
195
|
+
throw err;
|
|
196
|
+
const status = err.data.status;
|
|
197
|
+
if (typeof status !== 'number')
|
|
198
|
+
throw err;
|
|
199
|
+
const { code, reason, hint } = upstreamFailureFor(upstream, status);
|
|
200
|
+
throw new McpError(code, `${upstream} returned HTTP ${status}.`, { upstream, status, reason, recovery: { hint } }, { cause: err });
|
|
201
|
+
}
|
|
128
202
|
}
|
|
129
203
|
// ---------------------------------------------------------------------------
|
|
130
204
|
// Service
|
|
@@ -134,34 +208,35 @@ export class HnService {
|
|
|
134
208
|
constructor(concurrencyLimit) {
|
|
135
209
|
this.concurrencyLimit = concurrencyLimit;
|
|
136
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* GET a JSON document from an upstream, with retries around the full
|
|
213
|
+
* fetch-and-parse pipeline and both failure shapes — non-2xx status and
|
|
214
|
+
* HTML-instead-of-JSON — classified onto a contract reason.
|
|
215
|
+
*/
|
|
216
|
+
getJson(upstream, operation, url, ctx) {
|
|
217
|
+
const rc = toRequestContext(ctx);
|
|
218
|
+
return withUpstreamHttpErrors(upstream, () => withRetry(async () => {
|
|
219
|
+
const res = await fetchWithTimeout(url, REQUEST_TIMEOUT_MS, rc, { signal: ctx.signal });
|
|
220
|
+
return parseJsonBody(await res.text(), upstream);
|
|
221
|
+
}, { operation, context: rc, signal: ctx.signal }));
|
|
222
|
+
}
|
|
137
223
|
/** Fetch a single item by ID. Returns null when HN reports the item is missing. */
|
|
138
224
|
fetchItem(id, ctx) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
/** Fetch a user profile by username. Returns null when the user does not exist. */
|
|
225
|
+
return this.getJson('HN API', 'hn.fetchItem', `${HN_API}/item/${id}.json`, ctx);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Fetch a user profile by username. Returns null when the user does not exist.
|
|
229
|
+
* The username is percent-encoded as a single path segment — an unencoded
|
|
230
|
+
* value containing `/` or dot-segments would otherwise escape the `/user/`
|
|
231
|
+
* route and resolve to a different Firebase resource.
|
|
232
|
+
*/
|
|
148
233
|
fetchUser(username, ctx) {
|
|
149
|
-
|
|
150
|
-
return withRetry(async () => {
|
|
151
|
-
const res = await fetchWithTimeout(`${HN_API}/user/${username}.json`, REQUEST_TIMEOUT_MS, rc, { signal: ctx.signal });
|
|
152
|
-
return parseJsonBody(await res.text(), 'HN API');
|
|
153
|
-
}, { operation: 'hn.fetchUser', context: rc, signal: ctx.signal });
|
|
234
|
+
return this.getJson('HN API', 'hn.fetchUser', `${HN_API}/user/${encodeURIComponent(username)}.json`, ctx);
|
|
154
235
|
}
|
|
155
236
|
/** Fetch a feed's ID array. Throws on upstream failure after retries. */
|
|
156
237
|
fetchFeed(type, ctx) {
|
|
157
238
|
const endpoint = type === 'jobs' ? 'jobstories' : `${type}stories`;
|
|
158
|
-
|
|
159
|
-
return withRetry(async () => {
|
|
160
|
-
const res = await fetchWithTimeout(`${HN_API}/${endpoint}.json`, REQUEST_TIMEOUT_MS, rc, {
|
|
161
|
-
signal: ctx.signal,
|
|
162
|
-
});
|
|
163
|
-
return parseJsonBody(await res.text(), 'HN API');
|
|
164
|
-
}, { operation: 'hn.fetchFeed', context: rc, signal: ctx.signal });
|
|
239
|
+
return this.getJson('HN API', 'hn.fetchFeed', `${HN_API}/${endpoint}.json`, ctx);
|
|
165
240
|
}
|
|
166
241
|
/**
|
|
167
242
|
* Batch-fetch items with concurrency limiting. Preserves input order.
|
|
@@ -219,13 +294,7 @@ export class HnService {
|
|
|
219
294
|
}
|
|
220
295
|
if (numericFilters.length)
|
|
221
296
|
url.searchParams.set('numericFilters', numericFilters.join(','));
|
|
222
|
-
|
|
223
|
-
return withRetry(async () => {
|
|
224
|
-
const res = await fetchWithTimeout(url, REQUEST_TIMEOUT_MS, rc, {
|
|
225
|
-
signal: ctx.signal,
|
|
226
|
-
});
|
|
227
|
-
return parseJsonBody(await res.text(), 'Algolia');
|
|
228
|
-
}, { operation: 'hn.search', context: rc, signal: ctx.signal });
|
|
297
|
+
return this.getJson('Algolia', 'hn.search', url, ctx);
|
|
229
298
|
}
|
|
230
299
|
}
|
|
231
300
|
// ---------------------------------------------------------------------------
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hn-service.js","sourceRoot":"","sources":["../../../src/services/hn/hn-service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"hn-service.js","sourceRoot":"","sources":["../../../src/services/hn/hn-service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/hn-mcp-server",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.13",
|
|
4
4
|
"description": "Browse Hacker News feeds, threads, and user profiles with full-text search via MCP. STDIO or Streamable HTTP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"bugs": {
|
|
53
53
|
"url": "https://github.com/cyanheads/hn-mcp-server/issues"
|
|
54
54
|
},
|
|
55
|
-
"author": "
|
|
55
|
+
"author": "Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)",
|
|
56
56
|
"license": "Apache-2.0",
|
|
57
57
|
"funding": [
|
|
58
58
|
{
|
|
@@ -68,23 +68,24 @@
|
|
|
68
68
|
"node": ">=24.0.0",
|
|
69
69
|
"bun": ">=1.3.0"
|
|
70
70
|
},
|
|
71
|
-
"packageManager": "bun@1.3.
|
|
71
|
+
"packageManager": "bun@1.3.14",
|
|
72
72
|
"publishConfig": {
|
|
73
73
|
"access": "public"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@cyanheads/mcp-ts-core": "^0.
|
|
76
|
+
"@cyanheads/mcp-ts-core": "^0.11.0",
|
|
77
77
|
"zod": "^4.4.3"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
|
-
"@biomejs/biome": "^2.5.
|
|
80
|
+
"@biomejs/biome": "^2.5.5",
|
|
81
81
|
"@hono/otel": "^1.1.2",
|
|
82
|
-
"@
|
|
82
|
+
"@socketsecurity/bun-security-scanner": "^1.1.2",
|
|
83
|
+
"@types/node": "^26.1.1",
|
|
83
84
|
"depcheck": "^1.4.7",
|
|
84
|
-
"ignore": "^7.0.
|
|
85
|
+
"ignore": "^7.0.6",
|
|
85
86
|
"pino-pretty": "^13.1.3",
|
|
86
|
-
"tsc-alias": "^1.
|
|
87
|
-
"typescript": "^
|
|
88
|
-
"vitest": "^4.1.
|
|
87
|
+
"tsc-alias": "^1.9.1",
|
|
88
|
+
"typescript": "^7.0.2",
|
|
89
|
+
"vitest": "^4.1.10"
|
|
89
90
|
}
|
|
90
91
|
}
|
package/server.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"url": "https://github.com/cyanheads/hn-mcp-server",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.5.
|
|
9
|
+
"version": "0.5.13",
|
|
10
10
|
"remotes": [
|
|
11
11
|
{
|
|
12
12
|
"type": "streamable-http",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
20
20
|
"identifier": "@cyanheads/hn-mcp-server",
|
|
21
21
|
"runtimeHint": "bun",
|
|
22
|
-
"version": "0.5.
|
|
22
|
+
"version": "0.5.13",
|
|
23
23
|
"packageArguments": [
|
|
24
24
|
{
|
|
25
25
|
"type": "positional",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"environmentVariables": [
|
|
34
34
|
{
|
|
35
35
|
"name": "HN_CONCURRENCY_LIMIT",
|
|
36
|
-
"description": "Max concurrent HTTP requests for batch item fetches (1–50).",
|
|
36
|
+
"description": "Max concurrent HTTP requests for batch item fetches (integer, 1–50).",
|
|
37
37
|
"format": "string",
|
|
38
38
|
"isRequired": false,
|
|
39
39
|
"default": "10"
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
56
56
|
"identifier": "@cyanheads/hn-mcp-server",
|
|
57
57
|
"runtimeHint": "bun",
|
|
58
|
-
"version": "0.5.
|
|
58
|
+
"version": "0.5.13",
|
|
59
59
|
"packageArguments": [
|
|
60
60
|
{
|
|
61
61
|
"type": "positional",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"environmentVariables": [
|
|
70
70
|
{
|
|
71
71
|
"name": "HN_CONCURRENCY_LIMIT",
|
|
72
|
-
"description": "Max concurrent HTTP requests for batch item fetches (1–50).",
|
|
72
|
+
"description": "Max concurrent HTTP requests for batch item fetches (integer, 1–50).",
|
|
73
73
|
"format": "string",
|
|
74
74
|
"isRequired": false,
|
|
75
75
|
"default": "10"
|