@ttoss/http-server-mcp 0.28.1 → 0.28.2
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 +13 -0
- package/dist/index.cjs +27 -2
- package/dist/index.mjs +27 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -127,6 +127,17 @@ const data = await apiCall('GET', 'https://partner.api.com/data', {
|
|
|
127
127
|
|
|
128
128
|
`apiCall` throws with a clear message when called with a relative path and no `apiBaseUrl` is configured in the context.
|
|
129
129
|
|
|
130
|
+
### Errors
|
|
131
|
+
|
|
132
|
+
A non-2xx response throws, with the message read off the error body — `{ error: 'text' }` and `{ error: { code, message } }` both work, the latter as `code: message`. A body naming neither falls back to `HTTP <status>`.
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// { "error": { "code": "plan_limit_reached", "message": "Upgrade to add more." } }
|
|
136
|
+
// → Error: plan_limit_reached: Upgrade to add more.
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Inside a tool handler the thrown message is what the MCP SDK returns to the client, so it is the whole answer the calling model acts on.
|
|
140
|
+
|
|
130
141
|
## Authentication
|
|
131
142
|
|
|
132
143
|
`createMcpRouter` supports OAuth 2.0 Bearer token authentication via the `auth` option. Incoming MCP requests must include a valid `Authorization: Bearer <token>` header — invalid or missing tokens receive a `401 Unauthorized` response. The MCP lifecycle methods `initialize` and `tools/list` are exempt by default so clients can discover the server before authenticating (see [Public methods and discovery](#public-methods-and-discovery)).
|
|
@@ -593,6 +604,8 @@ Generic HTTP helper for use inside MCP tool handlers.
|
|
|
593
604
|
|
|
594
605
|
**Returns:** `Promise<unknown>` — Parsed JSON response body
|
|
595
606
|
|
|
607
|
+
**Throws:** `Error` on a non-2xx response, carrying the error body's message (see [Errors](#errors))
|
|
608
|
+
|
|
596
609
|
### `getIdentity<T>()`
|
|
597
610
|
|
|
598
611
|
Returns the verified JWT payload for the current MCP request. Only available inside a tool handler when `auth` is configured. Returns `undefined` when called outside an authenticated context.
|
package/dist/index.cjs
CHANGED
|
@@ -588,6 +588,31 @@ var buildVerifyToken = auth => {
|
|
|
588
588
|
return payload;
|
|
589
589
|
};
|
|
590
590
|
};
|
|
591
|
+
var isRecord = value => {
|
|
592
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
593
|
+
};
|
|
594
|
+
var readText = value => {
|
|
595
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
596
|
+
};
|
|
597
|
+
/**
|
|
598
|
+
* The message an error body carries, across the two shapes REST APIs answer
|
|
599
|
+
* with: `{ error: 'text' }` and `{ error: { code?, message? } }`.
|
|
600
|
+
*
|
|
601
|
+
* The structured one is why this is read rather than taken: an object handed
|
|
602
|
+
* to `new Error()` renders as `[object Object]`, and inside a tool handler
|
|
603
|
+
* that string is the whole answer the calling model acts on.
|
|
604
|
+
*/
|
|
605
|
+
var errorBodyMessage = body => {
|
|
606
|
+
if (!isRecord(body)) return;
|
|
607
|
+
const {
|
|
608
|
+
error
|
|
609
|
+
} = body;
|
|
610
|
+
if (!isRecord(error)) return readText(error);
|
|
611
|
+
const code = readText(error.code);
|
|
612
|
+
const message = readText(error.message);
|
|
613
|
+
if (message === void 0) return code;
|
|
614
|
+
return code === void 0 ? message : `${code}: ${message}`;
|
|
615
|
+
};
|
|
591
616
|
/**
|
|
592
617
|
* Generic HTTP helper for use inside MCP tool handlers.
|
|
593
618
|
*
|
|
@@ -663,12 +688,12 @@ var apiCall = async (method, url, options) => {
|
|
|
663
688
|
body: hasBody ? JSON.stringify(options.body) : void 0
|
|
664
689
|
});
|
|
665
690
|
if (!response.ok) {
|
|
666
|
-
const
|
|
691
|
+
const errorBody = await response.json().catch(() => {
|
|
667
692
|
return {
|
|
668
693
|
error: response.statusText
|
|
669
694
|
};
|
|
670
695
|
});
|
|
671
|
-
throw new Error(
|
|
696
|
+
throw new Error(errorBodyMessage(errorBody) ?? `HTTP ${response.status}`);
|
|
672
697
|
}
|
|
673
698
|
if (response.status === 204 || response.status === 205) return;
|
|
674
699
|
if (response.headers.get("content-type")?.includes("application/json")) return response.json();
|
package/dist/index.mjs
CHANGED
|
@@ -585,6 +585,31 @@ var buildVerifyToken = auth => {
|
|
|
585
585
|
return payload;
|
|
586
586
|
};
|
|
587
587
|
};
|
|
588
|
+
var isRecord = value => {
|
|
589
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
590
|
+
};
|
|
591
|
+
var readText = value => {
|
|
592
|
+
return typeof value === "string" && value !== "" ? value : void 0;
|
|
593
|
+
};
|
|
594
|
+
/**
|
|
595
|
+
* The message an error body carries, across the two shapes REST APIs answer
|
|
596
|
+
* with: `{ error: 'text' }` and `{ error: { code?, message? } }`.
|
|
597
|
+
*
|
|
598
|
+
* The structured one is why this is read rather than taken: an object handed
|
|
599
|
+
* to `new Error()` renders as `[object Object]`, and inside a tool handler
|
|
600
|
+
* that string is the whole answer the calling model acts on.
|
|
601
|
+
*/
|
|
602
|
+
var errorBodyMessage = body => {
|
|
603
|
+
if (!isRecord(body)) return;
|
|
604
|
+
const {
|
|
605
|
+
error
|
|
606
|
+
} = body;
|
|
607
|
+
if (!isRecord(error)) return readText(error);
|
|
608
|
+
const code = readText(error.code);
|
|
609
|
+
const message = readText(error.message);
|
|
610
|
+
if (message === void 0) return code;
|
|
611
|
+
return code === void 0 ? message : `${code}: ${message}`;
|
|
612
|
+
};
|
|
588
613
|
/**
|
|
589
614
|
* Generic HTTP helper for use inside MCP tool handlers.
|
|
590
615
|
*
|
|
@@ -660,12 +685,12 @@ var apiCall = async (method, url, options) => {
|
|
|
660
685
|
body: hasBody ? JSON.stringify(options.body) : void 0
|
|
661
686
|
});
|
|
662
687
|
if (!response.ok) {
|
|
663
|
-
const
|
|
688
|
+
const errorBody = await response.json().catch(() => {
|
|
664
689
|
return {
|
|
665
690
|
error: response.statusText
|
|
666
691
|
};
|
|
667
692
|
});
|
|
668
|
-
throw new Error(
|
|
693
|
+
throw new Error(errorBodyMessage(errorBody) ?? `HTTP ${response.status}`);
|
|
669
694
|
}
|
|
670
695
|
if (response.status === 204 || response.status === 205) return;
|
|
671
696
|
if (response.headers.get("content-type")?.includes("application/json")) return response.json();
|