toolcraft 0.0.119 → 0.0.121
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/composition.json +17 -2
- package/dist/composition.json +17 -2
- package/dist/http.compile-check.d.ts +1 -0
- package/dist/http.compile-check.js +31 -0
- package/dist/http.d.ts +19 -0
- package/dist/http.js +62 -0
- package/dist/mcp.js +26 -11
- package/node_modules/jose/LICENSE.md +21 -0
- package/node_modules/jose/README.md +153 -0
- package/node_modules/jose/dist/types/index.d.ts +55 -0
- package/node_modules/jose/dist/types/jwe/compact/decrypt.d.ts +31 -0
- package/node_modules/jose/dist/types/jwe/compact/encrypt.d.ts +65 -0
- package/node_modules/jose/dist/types/jwe/flattened/decrypt.d.ts +31 -0
- package/node_modules/jose/dist/types/jwe/flattened/encrypt.d.ts +83 -0
- package/node_modules/jose/dist/types/jwe/general/decrypt.d.ts +38 -0
- package/node_modules/jose/dist/types/jwe/general/encrypt.d.ts +74 -0
- package/node_modules/jose/dist/types/jwk/embedded.d.ts +17 -0
- package/node_modules/jose/dist/types/jwk/thumbprint.d.ts +32 -0
- package/node_modules/jose/dist/types/jwks/local.d.ts +29 -0
- package/node_modules/jose/dist/types/jwks/remote.d.ts +237 -0
- package/node_modules/jose/dist/types/jws/compact/sign.d.ts +36 -0
- package/node_modules/jose/dist/types/jws/compact/verify.d.ts +33 -0
- package/node_modules/jose/dist/types/jws/flattened/sign.d.ts +42 -0
- package/node_modules/jose/dist/types/jws/flattened/verify.d.ts +33 -0
- package/node_modules/jose/dist/types/jws/general/sign.d.ts +53 -0
- package/node_modules/jose/dist/types/jws/general/verify.d.ts +41 -0
- package/node_modules/jose/dist/types/jwt/decrypt.d.ts +35 -0
- package/node_modules/jose/dist/types/jwt/encrypt.d.ts +91 -0
- package/node_modules/jose/dist/types/jwt/sign.d.ts +43 -0
- package/node_modules/jose/dist/types/jwt/unsecured.d.ts +43 -0
- package/node_modules/jose/dist/types/jwt/verify.d.ts +37 -0
- package/node_modules/jose/dist/types/key/export.d.ts +33 -0
- package/node_modules/jose/dist/types/key/generate_key_pair.d.ts +47 -0
- package/node_modules/jose/dist/types/key/generate_secret.d.ts +35 -0
- package/node_modules/jose/dist/types/key/import.d.ts +83 -0
- package/node_modules/jose/dist/types/types.d.ts +852 -0
- package/node_modules/jose/dist/types/util/base64url.d.ts +9 -0
- package/node_modules/jose/dist/types/util/decode_jwt.d.ts +18 -0
- package/node_modules/jose/dist/types/util/decode_protected_header.d.ts +17 -0
- package/node_modules/jose/dist/types/util/errors.d.ts +213 -0
- package/node_modules/jose/dist/webapi/index.js +32 -0
- package/node_modules/jose/dist/webapi/jwe/compact/decrypt.js +27 -0
- package/node_modules/jose/dist/webapi/jwe/compact/encrypt.js +27 -0
- package/node_modules/jose/dist/webapi/jwe/flattened/decrypt.js +159 -0
- package/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +167 -0
- package/node_modules/jose/dist/webapi/jwe/general/decrypt.js +31 -0
- package/node_modules/jose/dist/webapi/jwe/general/encrypt.js +182 -0
- package/node_modules/jose/dist/webapi/jwk/embedded.js +17 -0
- package/node_modules/jose/dist/webapi/jwk/thumbprint.js +68 -0
- package/node_modules/jose/dist/webapi/jwks/local.js +119 -0
- package/node_modules/jose/dist/webapi/jwks/remote.js +179 -0
- package/node_modules/jose/dist/webapi/jws/compact/sign.js +18 -0
- package/node_modules/jose/dist/webapi/jws/compact/verify.js +21 -0
- package/node_modules/jose/dist/webapi/jws/flattened/sign.js +89 -0
- package/node_modules/jose/dist/webapi/jws/flattened/verify.js +110 -0
- package/node_modules/jose/dist/webapi/jws/general/sign.js +70 -0
- package/node_modules/jose/dist/webapi/jws/general/verify.js +24 -0
- package/node_modules/jose/dist/webapi/jwt/decrypt.js +23 -0
- package/node_modules/jose/dist/webapi/jwt/encrypt.js +101 -0
- package/node_modules/jose/dist/webapi/jwt/sign.js +52 -0
- package/node_modules/jose/dist/webapi/jwt/unsecured.js +63 -0
- package/node_modules/jose/dist/webapi/jwt/verify.js +15 -0
- package/node_modules/jose/dist/webapi/key/export.js +11 -0
- package/node_modules/jose/dist/webapi/key/generate_key_pair.js +97 -0
- package/node_modules/jose/dist/webapi/key/generate_secret.js +40 -0
- package/node_modules/jose/dist/webapi/key/import.js +57 -0
- package/node_modules/jose/dist/webapi/lib/aesgcmkw.js +15 -0
- package/node_modules/jose/dist/webapi/lib/aeskw.js +25 -0
- package/node_modules/jose/dist/webapi/lib/asn1.js +243 -0
- package/node_modules/jose/dist/webapi/lib/base64.js +22 -0
- package/node_modules/jose/dist/webapi/lib/buffer_utils.js +43 -0
- package/node_modules/jose/dist/webapi/lib/check_key_type.js +122 -0
- package/node_modules/jose/dist/webapi/lib/content_encryption.js +217 -0
- package/node_modules/jose/dist/webapi/lib/crypto_key.js +136 -0
- package/node_modules/jose/dist/webapi/lib/deflate.js +44 -0
- package/node_modules/jose/dist/webapi/lib/ecdhes.js +52 -0
- package/node_modules/jose/dist/webapi/lib/helpers.js +19 -0
- package/node_modules/jose/dist/webapi/lib/invalid_key_input.js +27 -0
- package/node_modules/jose/dist/webapi/lib/is_key_like.js +17 -0
- package/node_modules/jose/dist/webapi/lib/jwk_to_key.js +107 -0
- package/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +238 -0
- package/node_modules/jose/dist/webapi/lib/key_management.js +186 -0
- package/node_modules/jose/dist/webapi/lib/key_to_jwk.js +31 -0
- package/node_modules/jose/dist/webapi/lib/normalize_key.js +166 -0
- package/node_modules/jose/dist/webapi/lib/pbes2kw.js +42 -0
- package/node_modules/jose/dist/webapi/lib/rsaes.js +24 -0
- package/node_modules/jose/dist/webapi/lib/signing.js +68 -0
- package/node_modules/jose/dist/webapi/lib/type_checks.js +40 -0
- package/node_modules/jose/dist/webapi/lib/validate_algorithms.js +10 -0
- package/node_modules/jose/dist/webapi/lib/validate_crit.js +33 -0
- package/node_modules/jose/dist/webapi/util/base64url.js +30 -0
- package/node_modules/jose/dist/webapi/util/decode_jwt.js +32 -0
- package/node_modules/jose/dist/webapi/util/decode_protected_header.js +34 -0
- package/node_modules/jose/dist/webapi/util/errors.js +99 -0
- package/node_modules/jose/package.json +200 -0
- package/node_modules/tiny-http-mcp-server/LICENSE +21 -0
- package/node_modules/tiny-http-mcp-server/README.md +778 -0
- package/node_modules/tiny-http-mcp-server/dist/auth.d.ts +69 -0
- package/node_modules/tiny-http-mcp-server/dist/auth.js +261 -0
- package/node_modules/tiny-http-mcp-server/dist/cli.d.ts +20 -0
- package/node_modules/tiny-http-mcp-server/dist/cli.js +465 -0
- package/node_modules/tiny-http-mcp-server/dist/composition.json +30 -0
- package/node_modules/tiny-http-mcp-server/dist/express-middleware.d.ts +18 -0
- package/node_modules/tiny-http-mcp-server/dist/express-middleware.js +90 -0
- package/node_modules/tiny-http-mcp-server/dist/http-server.d.ts +49 -0
- package/node_modules/tiny-http-mcp-server/dist/http-server.js +264 -0
- package/node_modules/tiny-http-mcp-server/dist/http-transport.d.ts +164 -0
- package/node_modules/tiny-http-mcp-server/dist/http-transport.js +897 -0
- package/node_modules/tiny-http-mcp-server/dist/index.d.ts +13 -0
- package/node_modules/tiny-http-mcp-server/dist/index.js +6 -0
- package/node_modules/tiny-http-mcp-server/dist/load-oauth-verifier.d.ts +6 -0
- package/node_modules/tiny-http-mcp-server/dist/load-oauth-verifier.js +43 -0
- package/node_modules/tiny-http-mcp-server/dist/parse-body.d.ts +22 -0
- package/node_modules/tiny-http-mcp-server/dist/parse-body.js +150 -0
- package/node_modules/tiny-http-mcp-server/dist/server.d.ts +9 -0
- package/node_modules/tiny-http-mcp-server/dist/server.js +4 -0
- package/node_modules/tiny-http-mcp-server/dist/session.d.ts +18 -0
- package/node_modules/tiny-http-mcp-server/dist/session.js +37 -0
- package/node_modules/tiny-http-mcp-server/dist/sse.d.ts +11 -0
- package/node_modules/tiny-http-mcp-server/dist/sse.js +22 -0
- package/node_modules/tiny-http-mcp-server/dist/test-support.d.ts +10 -0
- package/node_modules/tiny-http-mcp-server/dist/test-support.js +398 -0
- package/node_modules/tiny-http-mcp-server/dist/testing.d.ts +59 -0
- package/node_modules/tiny-http-mcp-server/dist/testing.js +191 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/LICENSE +21 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/README.md +70 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/auth-store-session-store.d.ts +14 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/auth-store-session-store.js +169 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/authorization-state.d.ts +8 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/authorization-state.js +47 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.d.ts +3 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +627 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/loopback-authorization.d.ts +20 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/loopback-authorization.js +207 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/pkce.d.ts +2 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/pkce.js +7 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.d.ts +40 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.js +164 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/types.d.ts +113 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/types.js +1 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/index.d.ts +10 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/index.js +7 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/resource-indicator.d.ts +1 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/resource-indicator.js +11 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/server/jwks-token-verifier.d.ts +32 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/server/jwks-token-verifier.js +388 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/types.compile-check.d.ts +1 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/types.compile-check.js +22 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/package.json +28 -0
- package/node_modules/tiny-http-mcp-server/package.json +59 -0
- package/node_modules/tiny-stdio-mcp-server/dist/composition.json +1 -1
- package/node_modules/toolcraft-schema/package.json +1 -1
- package/package.json +11 -4
package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/server/jwks-token-verifier.js
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import { decodeProtectedHeader, errors, importJWK, jwtVerify } from "jose";
|
|
2
|
+
import { canonicalizeResourceIndicator } from "../resource-indicator.js";
|
|
3
|
+
const DEFAULT_ALLOWED_ALGORITHMS = [
|
|
4
|
+
"ES256",
|
|
5
|
+
"ES384",
|
|
6
|
+
"ES512",
|
|
7
|
+
"RS256",
|
|
8
|
+
"RS384",
|
|
9
|
+
"RS512",
|
|
10
|
+
"PS256",
|
|
11
|
+
"PS384",
|
|
12
|
+
"PS512",
|
|
13
|
+
"EdDSA"
|
|
14
|
+
];
|
|
15
|
+
function isTokenVerificationErrorShape(error) {
|
|
16
|
+
if (!(error instanceof Error)) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const challengeError = error;
|
|
20
|
+
return (challengeError.error === "invalid_token" ||
|
|
21
|
+
challengeError.error === "insufficient_scope" ||
|
|
22
|
+
challengeError.error === "temporarily_unavailable");
|
|
23
|
+
}
|
|
24
|
+
function isObjectRecord(value) {
|
|
25
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26
|
+
}
|
|
27
|
+
function isStringArray(value) {
|
|
28
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
29
|
+
}
|
|
30
|
+
function getOwnEntry(record, key) {
|
|
31
|
+
return Object.prototype.hasOwnProperty.call(record, key)
|
|
32
|
+
? record[key]
|
|
33
|
+
: undefined;
|
|
34
|
+
}
|
|
35
|
+
function getOwnString(record, key) {
|
|
36
|
+
const value = getOwnEntry(record, key);
|
|
37
|
+
return typeof value === "string" ? value : undefined;
|
|
38
|
+
}
|
|
39
|
+
function toUrl(value, label) {
|
|
40
|
+
try {
|
|
41
|
+
return new URL(String(value));
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new Error(`${label} must be an absolute URL`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function normalizeAudience(value) {
|
|
48
|
+
if (typeof value === "string") {
|
|
49
|
+
return [value];
|
|
50
|
+
}
|
|
51
|
+
return isStringArray(value) ? [...value] : [];
|
|
52
|
+
}
|
|
53
|
+
function normalizeVerifiedAudience(value, expectedResource) {
|
|
54
|
+
const audiences = normalizeAudience(value);
|
|
55
|
+
for (const audience of audiences) {
|
|
56
|
+
try {
|
|
57
|
+
const normalizedAudience = canonicalizeResourceIndicator(audience);
|
|
58
|
+
if (normalizedAudience === expectedResource) {
|
|
59
|
+
return [normalizedAudience];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
throw createInvalidTokenError("audience mismatch");
|
|
67
|
+
}
|
|
68
|
+
function parseScopes(payload) {
|
|
69
|
+
const scope = getOwnString(payload, "scope");
|
|
70
|
+
const scopes = getOwnEntry(payload, "scopes");
|
|
71
|
+
const raw = scope !== undefined ? scope : typeof scopes === "string" ? scopes : null;
|
|
72
|
+
if (raw !== null) {
|
|
73
|
+
return raw
|
|
74
|
+
.split(" ")
|
|
75
|
+
.map((scope) => scope.trim())
|
|
76
|
+
.filter((scope) => scope.length > 0);
|
|
77
|
+
}
|
|
78
|
+
return isStringArray(scopes) ? [...scopes] : [];
|
|
79
|
+
}
|
|
80
|
+
function toVerifiedAccessToken(token, payload, audience = normalizeAudience(getOwnEntry(payload, "aud"))) {
|
|
81
|
+
const issuer = getOwnString(payload, "iss");
|
|
82
|
+
const expiresAt = getOwnEntry(payload, "exp");
|
|
83
|
+
const subject = getOwnString(payload, "sub");
|
|
84
|
+
const clientId = getOwnString(payload, "client_id");
|
|
85
|
+
return {
|
|
86
|
+
token,
|
|
87
|
+
issuer: issuer ?? "",
|
|
88
|
+
audience,
|
|
89
|
+
scopes: parseScopes(payload),
|
|
90
|
+
expiresAt: expiresAt,
|
|
91
|
+
claims: { ...payload },
|
|
92
|
+
...(subject !== undefined
|
|
93
|
+
? {
|
|
94
|
+
subject
|
|
95
|
+
}
|
|
96
|
+
: {}),
|
|
97
|
+
...(clientId !== undefined
|
|
98
|
+
? {
|
|
99
|
+
clientId
|
|
100
|
+
}
|
|
101
|
+
: {})
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function createTokenVerificationError(input) {
|
|
105
|
+
return Object.assign(new Error(input.errorDescription ?? input.error), input);
|
|
106
|
+
}
|
|
107
|
+
function createTemporarilyUnavailableError() {
|
|
108
|
+
return createTokenVerificationError({
|
|
109
|
+
error: "temporarily_unavailable",
|
|
110
|
+
errorDescription: "token verification temporarily unavailable"
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function createInvalidTokenError(errorDescription) {
|
|
114
|
+
return createTokenVerificationError({
|
|
115
|
+
error: "invalid_token",
|
|
116
|
+
errorDescription
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
function normalizeVerificationError(error) {
|
|
120
|
+
if (isTokenVerificationErrorShape(error)) {
|
|
121
|
+
return error;
|
|
122
|
+
}
|
|
123
|
+
if (error instanceof errors.JWTExpired) {
|
|
124
|
+
return createInvalidTokenError("token expired");
|
|
125
|
+
}
|
|
126
|
+
if (error instanceof errors.JWTClaimValidationFailed) {
|
|
127
|
+
if (error.claim === "aud") {
|
|
128
|
+
return createInvalidTokenError("audience mismatch");
|
|
129
|
+
}
|
|
130
|
+
if (error.claim === "iss") {
|
|
131
|
+
return createInvalidTokenError("issuer mismatch");
|
|
132
|
+
}
|
|
133
|
+
if (error.claim === "nbf") {
|
|
134
|
+
return createInvalidTokenError("token not active yet");
|
|
135
|
+
}
|
|
136
|
+
if (error.claim === "exp") {
|
|
137
|
+
if (error.reason === "missing") {
|
|
138
|
+
return createInvalidTokenError("token missing expiry");
|
|
139
|
+
}
|
|
140
|
+
return createInvalidTokenError("token expired");
|
|
141
|
+
}
|
|
142
|
+
if (error.claim === "typ") {
|
|
143
|
+
return createInvalidTokenError("invalid access token type");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (error instanceof errors.JOSEAlgNotAllowed || error instanceof errors.JOSENotSupported) {
|
|
147
|
+
return createInvalidTokenError("unsupported token algorithm");
|
|
148
|
+
}
|
|
149
|
+
if (error instanceof errors.JWKSNoMatchingKey ||
|
|
150
|
+
error instanceof errors.JWKSMultipleMatchingKeys ||
|
|
151
|
+
error instanceof errors.JWSSignatureVerificationFailed) {
|
|
152
|
+
return createInvalidTokenError("token signature invalid");
|
|
153
|
+
}
|
|
154
|
+
if (error instanceof errors.JWKSInvalid || error instanceof errors.JWKSTimeout) {
|
|
155
|
+
return createTemporarilyUnavailableError();
|
|
156
|
+
}
|
|
157
|
+
return createInvalidTokenError("token verification failed");
|
|
158
|
+
}
|
|
159
|
+
async function loadJwks(jwksUrl, fetchImplementation, timeoutMs) {
|
|
160
|
+
try {
|
|
161
|
+
const response = await fetchImplementation(jwksUrl, {
|
|
162
|
+
headers: {
|
|
163
|
+
Accept: "application/json"
|
|
164
|
+
},
|
|
165
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
166
|
+
});
|
|
167
|
+
if (!response.ok) {
|
|
168
|
+
throw createTemporarilyUnavailableError();
|
|
169
|
+
}
|
|
170
|
+
const payload = (await response.json());
|
|
171
|
+
const keys = isObjectRecord(payload) ? getOwnEntry(payload, "keys") : undefined;
|
|
172
|
+
if (!isObjectRecord(payload) || !Array.isArray(keys) || !keys.every(isObjectRecord)) {
|
|
173
|
+
throw createTemporarilyUnavailableError();
|
|
174
|
+
}
|
|
175
|
+
return { keys };
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (isTokenVerificationErrorShape(error)) {
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
throw createTemporarilyUnavailableError();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function resolveAlgorithm(token, allowedAlgorithms) {
|
|
185
|
+
const header = decodeProtectedHeader(token);
|
|
186
|
+
const alg = getOwnString(header, "alg");
|
|
187
|
+
if (hasCriticalHeaderClaims(header)) {
|
|
188
|
+
throw createInvalidTokenError("unsupported critical token claims");
|
|
189
|
+
}
|
|
190
|
+
if (typeof alg !== "string" ||
|
|
191
|
+
alg === "none" ||
|
|
192
|
+
alg.startsWith("HS") ||
|
|
193
|
+
!allowedAlgorithms.includes(alg)) {
|
|
194
|
+
throw createInvalidTokenError("unsupported token algorithm");
|
|
195
|
+
}
|
|
196
|
+
return alg;
|
|
197
|
+
}
|
|
198
|
+
function hasCriticalHeaderClaims(header) {
|
|
199
|
+
const criticalClaims = getOwnEntry(header, "crit");
|
|
200
|
+
return Array.isArray(criticalClaims) && criticalClaims.length > 0;
|
|
201
|
+
}
|
|
202
|
+
function isVerificationCandidate(key, alg, kid) {
|
|
203
|
+
const keyId = getOwnString(key, "kid");
|
|
204
|
+
const keyAlgorithm = getOwnString(key, "alg");
|
|
205
|
+
const keyUse = getOwnString(key, "use");
|
|
206
|
+
const keyOps = getOwnEntry(key, "key_ops");
|
|
207
|
+
if (kid !== undefined && keyId !== kid) {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
if (keyAlgorithm !== undefined && keyAlgorithm !== alg) {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
if (keyUse !== undefined && keyUse !== "sig") {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
if (Array.isArray(keyOps) && !keyOps.includes("verify")) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
function shouldContinueWithNextKey(error) {
|
|
222
|
+
return error instanceof errors.JWSSignatureVerificationFailed;
|
|
223
|
+
}
|
|
224
|
+
async function verifyJwtAgainstJwks(input) {
|
|
225
|
+
const protectedHeader = decodeProtectedHeader(input.token);
|
|
226
|
+
const kid = getOwnString(protectedHeader, "kid");
|
|
227
|
+
const candidateKeys = input.jwks.keys.filter((key) => isVerificationCandidate(key, input.alg, kid));
|
|
228
|
+
if (candidateKeys.length === 0) {
|
|
229
|
+
throw new NoMatchingKeyError();
|
|
230
|
+
}
|
|
231
|
+
let lastSignatureError;
|
|
232
|
+
let hasMalformedKey = false;
|
|
233
|
+
for (const candidate of candidateKeys) {
|
|
234
|
+
let key;
|
|
235
|
+
try {
|
|
236
|
+
key = await importJWK(candidate, input.alg);
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
hasMalformedKey = true;
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
return await jwtVerify(input.token, key, {
|
|
244
|
+
algorithms: [input.alg],
|
|
245
|
+
issuer: [...input.authorizationServers],
|
|
246
|
+
clockTolerance: input.clockSkewSeconds,
|
|
247
|
+
requiredClaims: ["exp"],
|
|
248
|
+
...(input.requireAccessTokenType ? { typ: "at+jwt" } : {})
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
if (shouldContinueWithNextKey(error)) {
|
|
253
|
+
lastSignatureError = error;
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (hasMalformedKey) {
|
|
260
|
+
throw createTemporarilyUnavailableError();
|
|
261
|
+
}
|
|
262
|
+
throw lastSignatureError ?? createInvalidTokenError("token signature invalid");
|
|
263
|
+
}
|
|
264
|
+
class NoMatchingKeyError extends Error {
|
|
265
|
+
}
|
|
266
|
+
function isLoopbackHostname(hostname) {
|
|
267
|
+
if (hostname === "localhost" || hostname.endsWith(".localhost")) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
if (hostname === "[::1]" || hostname === "::1") {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
const parts = hostname.split(".");
|
|
274
|
+
return (parts.length === 4 &&
|
|
275
|
+
parts[0] === "127" &&
|
|
276
|
+
parts.slice(1).every((part) => {
|
|
277
|
+
const value = Number(part);
|
|
278
|
+
return Number.isInteger(value) && value >= 0 && value <= 255;
|
|
279
|
+
}));
|
|
280
|
+
}
|
|
281
|
+
export function createJwksTokenVerifier(options) {
|
|
282
|
+
const jwksUrl = toUrl(options.jwksUrl, "jwksUrl");
|
|
283
|
+
const clockSkewSeconds = options.clockSkewSeconds ?? 30;
|
|
284
|
+
const allowedAlgorithms = options.allowedAlgorithms ?? DEFAULT_ALLOWED_ALGORITHMS;
|
|
285
|
+
const jwksCacheTtlMs = options.jwksCacheTtlMs ?? 300_000;
|
|
286
|
+
const jwksFetchTimeoutMs = options.jwksFetchTimeoutMs ?? 5_000;
|
|
287
|
+
const jwksRefreshCooldownMs = options.jwksRefreshCooldownMs ?? 30_000;
|
|
288
|
+
const requireAccessTokenType = options.requireAccessTokenType ?? false;
|
|
289
|
+
const fetchImplementation = options.fetch ?? globalThis.fetch;
|
|
290
|
+
let cachedJwks;
|
|
291
|
+
let pendingJwks;
|
|
292
|
+
let pendingForcedRefresh;
|
|
293
|
+
let lastForcedRefreshAt = Number.NEGATIVE_INFINITY;
|
|
294
|
+
if (jwksUrl.protocol !== "https:" &&
|
|
295
|
+
!isLoopbackHostname(jwksUrl.hostname) &&
|
|
296
|
+
options.allowInsecureJwks !== true) {
|
|
297
|
+
throw new Error("jwksUrl must use HTTPS for non-loopback hosts");
|
|
298
|
+
}
|
|
299
|
+
if (typeof fetchImplementation !== "function") {
|
|
300
|
+
throw new Error("fetch is not available; pass options.fetch explicitly");
|
|
301
|
+
}
|
|
302
|
+
async function getJwks(forceRefresh = false) {
|
|
303
|
+
const now = Date.now();
|
|
304
|
+
if (!forceRefresh && cachedJwks !== undefined && cachedJwks.expiresAt > now) {
|
|
305
|
+
return cachedJwks.value;
|
|
306
|
+
}
|
|
307
|
+
if (pendingJwks !== undefined) {
|
|
308
|
+
return pendingJwks;
|
|
309
|
+
}
|
|
310
|
+
pendingJwks = loadJwks(jwksUrl, fetchImplementation, jwksFetchTimeoutMs)
|
|
311
|
+
.then((jwks) => {
|
|
312
|
+
cachedJwks = {
|
|
313
|
+
value: jwks,
|
|
314
|
+
expiresAt: Date.now() + jwksCacheTtlMs
|
|
315
|
+
};
|
|
316
|
+
return jwks;
|
|
317
|
+
})
|
|
318
|
+
.finally(() => {
|
|
319
|
+
pendingJwks = undefined;
|
|
320
|
+
});
|
|
321
|
+
return pendingJwks;
|
|
322
|
+
}
|
|
323
|
+
function refreshJwksAfterUnknownKey() {
|
|
324
|
+
if (pendingForcedRefresh !== undefined) {
|
|
325
|
+
return pendingForcedRefresh;
|
|
326
|
+
}
|
|
327
|
+
const now = Date.now();
|
|
328
|
+
if (now - lastForcedRefreshAt < jwksRefreshCooldownMs) {
|
|
329
|
+
throw new NoMatchingKeyError();
|
|
330
|
+
}
|
|
331
|
+
lastForcedRefreshAt = now;
|
|
332
|
+
pendingForcedRefresh = getJwks(true).finally(() => {
|
|
333
|
+
pendingForcedRefresh = undefined;
|
|
334
|
+
});
|
|
335
|
+
return pendingForcedRefresh;
|
|
336
|
+
}
|
|
337
|
+
return {
|
|
338
|
+
async verify(input) {
|
|
339
|
+
try {
|
|
340
|
+
const expectedResource = canonicalizeResourceIndicator(input.resource);
|
|
341
|
+
const algorithm = resolveAlgorithm(input.token, allowedAlgorithms);
|
|
342
|
+
let jwks = await getJwks();
|
|
343
|
+
let verified;
|
|
344
|
+
try {
|
|
345
|
+
verified = await verifyJwtAgainstJwks({
|
|
346
|
+
token: input.token,
|
|
347
|
+
jwks,
|
|
348
|
+
alg: algorithm,
|
|
349
|
+
authorizationServers: input.authorizationServers,
|
|
350
|
+
clockSkewSeconds,
|
|
351
|
+
requireAccessTokenType
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
if (!(error instanceof NoMatchingKeyError)) {
|
|
356
|
+
throw error;
|
|
357
|
+
}
|
|
358
|
+
jwks = await refreshJwksAfterUnknownKey();
|
|
359
|
+
verified = await verifyJwtAgainstJwks({
|
|
360
|
+
token: input.token,
|
|
361
|
+
jwks,
|
|
362
|
+
alg: algorithm,
|
|
363
|
+
authorizationServers: input.authorizationServers,
|
|
364
|
+
clockSkewSeconds,
|
|
365
|
+
requireAccessTokenType
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
const audience = normalizeVerifiedAudience(getOwnEntry(verified.payload, "aud"), expectedResource);
|
|
369
|
+
const accessToken = toVerifiedAccessToken(input.token, verified.payload, audience);
|
|
370
|
+
if (input.requiredScopes.length > 0 &&
|
|
371
|
+
!input.requiredScopes.every((scope) => accessToken.scopes.includes(scope))) {
|
|
372
|
+
throw createTokenVerificationError({
|
|
373
|
+
error: "insufficient_scope",
|
|
374
|
+
errorDescription: "insufficient scope",
|
|
375
|
+
scope: [...input.requiredScopes]
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
return accessToken;
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
if (error instanceof NoMatchingKeyError) {
|
|
382
|
+
throw createInvalidTokenError("token signature invalid");
|
|
383
|
+
}
|
|
384
|
+
throw normalizeVerificationError(error);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/types.compile-check.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const ignoredImplicitGrantOptions = {
|
|
2
|
+
client: {
|
|
3
|
+
mode: "static",
|
|
4
|
+
clientId: "client-id",
|
|
5
|
+
// @ts-expect-error implicit response types are not configurable via the public API
|
|
6
|
+
responseType: "token",
|
|
7
|
+
},
|
|
8
|
+
browser: {
|
|
9
|
+
openBrowser: async () => { },
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
const ignoredPasswordGrantOptions = {
|
|
13
|
+
client: {
|
|
14
|
+
mode: "dynamic",
|
|
15
|
+
// @ts-expect-error password grants are not configurable via the public API
|
|
16
|
+
grantType: "password",
|
|
17
|
+
},
|
|
18
|
+
browser: {
|
|
19
|
+
openBrowser: async () => { },
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"license": "MIT",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"tiny-oauth-test-server": "*"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/poe-platform/poe-code.git",
|
|
26
|
+
"directory": "packages/mcp-oauth"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tiny-http-mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Minimal MCP server over HTTP built on tiny-stdio-mcp-server",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"tiny-http-mcp-server": "dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./server": {
|
|
17
|
+
"types": "./dist/server.d.ts",
|
|
18
|
+
"import": "./dist/server.js"
|
|
19
|
+
},
|
|
20
|
+
"./testing": {
|
|
21
|
+
"types": "./dist/testing.d.ts",
|
|
22
|
+
"import": "./dist/testing.js"
|
|
23
|
+
},
|
|
24
|
+
"./test-support": {
|
|
25
|
+
"types": "./dist/test-support.d.ts",
|
|
26
|
+
"import": "./dist/test-support.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "node ../../scripts/guard-package-dist.mjs && tsc",
|
|
31
|
+
"prepack": "node ../../scripts/set-bin-executable.mjs && node ../../scripts/manage-bundled-workspace-deps.mjs prepare . mcp-oauth auth-store tiny-mcp-client jose",
|
|
32
|
+
"postpack": "node ../../scripts/manage-bundled-workspace-deps.mjs cleanup . mcp-oauth auth-store tiny-mcp-client jose",
|
|
33
|
+
"prepublishOnly": "tsc"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"LICENSE",
|
|
37
|
+
"dist"
|
|
38
|
+
],
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=20"
|
|
41
|
+
},
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/poe-platform/poe-code.git",
|
|
45
|
+
"directory": "packages/tiny-http-mcp-server"
|
|
46
|
+
},
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"bundleDependencies": [
|
|
49
|
+
"mcp-oauth"
|
|
50
|
+
],
|
|
51
|
+
"optionalDependencies": {
|
|
52
|
+
"mcp-oauth": "*"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
56
|
+
"@types/express": "^5.0.6",
|
|
57
|
+
"express": "^5.1.0"
|
|
58
|
+
}
|
|
59
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "toolcraft",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.121",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -70,6 +70,10 @@
|
|
|
70
70
|
"types": "./dist/human-in-loop/index.d.ts",
|
|
71
71
|
"import": "./dist/human-in-loop/index.js"
|
|
72
72
|
},
|
|
73
|
+
"./http": {
|
|
74
|
+
"types": "./dist/http.d.ts",
|
|
75
|
+
"import": "./dist/http.js"
|
|
76
|
+
},
|
|
73
77
|
"./frontmatter": {
|
|
74
78
|
"types": "./dist/frontmatter.d.ts",
|
|
75
79
|
"import": "./dist/frontmatter.js"
|
|
@@ -104,8 +108,8 @@
|
|
|
104
108
|
"test": "cd ../.. && vitest run packages/toolcraft/src",
|
|
105
109
|
"test:unit": "cd ../.. && vitest run packages/toolcraft/src",
|
|
106
110
|
"lint": "cd ../.. && eslint packages/toolcraft/src --ext ts && tsc -p packages/toolcraft/tsconfig.json --noEmit",
|
|
107
|
-
"prepack": "node ../../scripts/manage-bundled-workspace-deps.mjs prepare . toolcraft-schema toolcraft-design @poe-code/frontmatter @poe-code/agent-mcp-config @poe-code/agent-human-in-loop @poe-code/task-list @poe-code/agent-defs @poe-code/config-mutations @poe-code/process-runner tiny-mcp-client tiny-stdio-mcp-server auth-store fast-string-width fast-wrap-ansi ignore jsonc-parser sisteransi smol-toml yaml",
|
|
108
|
-
"postpack": "node ../../scripts/manage-bundled-workspace-deps.mjs cleanup . toolcraft-schema toolcraft-design @poe-code/frontmatter @poe-code/agent-mcp-config @poe-code/agent-human-in-loop @poe-code/task-list @poe-code/agent-defs @poe-code/config-mutations @poe-code/process-runner tiny-mcp-client tiny-stdio-mcp-server auth-store fast-string-width fast-wrap-ansi ignore jsonc-parser sisteransi smol-toml yaml"
|
|
111
|
+
"prepack": "node ../../scripts/manage-bundled-workspace-deps.mjs prepare . toolcraft-schema toolcraft-design @poe-code/frontmatter @poe-code/agent-mcp-config @poe-code/agent-human-in-loop @poe-code/task-list @poe-code/agent-defs @poe-code/config-mutations @poe-code/process-runner tiny-http-mcp-server tiny-mcp-client tiny-stdio-mcp-server auth-store jose fast-string-width fast-wrap-ansi ignore jsonc-parser sisteransi smol-toml yaml",
|
|
112
|
+
"postpack": "node ../../scripts/manage-bundled-workspace-deps.mjs cleanup . toolcraft-schema toolcraft-design @poe-code/frontmatter @poe-code/agent-mcp-config @poe-code/agent-human-in-loop @poe-code/task-list @poe-code/agent-defs @poe-code/config-mutations @poe-code/process-runner tiny-http-mcp-server tiny-mcp-client tiny-stdio-mcp-server auth-store jose fast-string-width fast-wrap-ansi ignore jsonc-parser sisteransi smol-toml yaml"
|
|
109
113
|
},
|
|
110
114
|
"dependencies": {
|
|
111
115
|
"commander": "^13.1.0",
|
|
@@ -142,9 +146,11 @@
|
|
|
142
146
|
"@poe-code/agent-defs",
|
|
143
147
|
"@poe-code/config-mutations",
|
|
144
148
|
"@poe-code/process-runner",
|
|
149
|
+
"tiny-http-mcp-server",
|
|
145
150
|
"tiny-mcp-client",
|
|
146
151
|
"tiny-stdio-mcp-server",
|
|
147
152
|
"auth-store",
|
|
153
|
+
"jose",
|
|
148
154
|
"fast-string-width",
|
|
149
155
|
"fast-wrap-ansi",
|
|
150
156
|
"ignore",
|
|
@@ -154,7 +160,7 @@
|
|
|
154
160
|
"yaml"
|
|
155
161
|
],
|
|
156
162
|
"optionalDependencies": {
|
|
157
|
-
"toolcraft-schema": "0.0.
|
|
163
|
+
"toolcraft-schema": "0.0.121",
|
|
158
164
|
"toolcraft-design": "*",
|
|
159
165
|
"@poe-code/frontmatter": "*",
|
|
160
166
|
"@poe-code/agent-mcp-config": "*",
|
|
@@ -163,6 +169,7 @@
|
|
|
163
169
|
"@poe-code/agent-defs": "*",
|
|
164
170
|
"@poe-code/config-mutations": "*",
|
|
165
171
|
"@poe-code/process-runner": "*",
|
|
172
|
+
"tiny-http-mcp-server": "*",
|
|
166
173
|
"tiny-mcp-client": "*",
|
|
167
174
|
"tiny-stdio-mcp-server": "*",
|
|
168
175
|
"auth-store": "*"
|