@koduhai/mcp-kit 0.1.0 โ 0.3.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 +31 -4
- package/dist/auth/introspection-verifier.d.ts +4 -0
- package/dist/auth/introspection-verifier.d.ts.map +1 -1
- package/dist/auth/introspection-verifier.js +2 -2
- package/dist/auth/introspection-verifier.js.map +1 -1
- package/dist/auth/jwt-verifier.d.ts +1 -1
- package/dist/auth/jwt-verifier.d.ts.map +1 -1
- package/dist/auth/jwt-verifier.js +7 -2
- package/dist/auth/jwt-verifier.js.map +1 -1
- package/dist/internal/http.d.ts +16 -0
- package/dist/internal/http.d.ts.map +1 -1
- package/dist/internal/http.js +48 -0
- package/dist/internal/http.js.map +1 -1
- package/dist/server/index.d.ts +23 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +34 -0
- package/dist/server/index.js.map +1 -0
- package/dist/upstream/index.d.ts +17 -0
- package/dist/upstream/index.d.ts.map +1 -1
- package/dist/upstream/index.js +22 -5
- package/dist/upstream/index.js.map +1 -1
- package/package.json +19 -1
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# @koduhai/mcp-kit
|
|
2
2
|
|
|
3
3
|
[](https://github.com/koduhai/mcp-kit/actions/workflows/ci.yml)
|
|
4
|
+
[](https://codecov.io/gh/koduhai/mcp-kit)
|
|
4
5
|
[](https://www.npmjs.com/package/@koduhai/mcp-kit)
|
|
5
6
|
[](https://scorecard.dev/viewer/?uri=github.com/koduhai/mcp-kit)
|
|
6
7
|
[](./LICENSE)
|
|
@@ -20,6 +21,8 @@ Built on top of `@modelcontextprotocol/sdk`. Aligned to the **2025-06-18** autho
|
|
|
20
21
|
npm install @koduhai/mcp-kit
|
|
21
22
|
```
|
|
22
23
|
|
|
24
|
+
๐ [API reference](https://koduhai.github.io/mcp-kit/) ยท ๐ [IdP recipes](./RECIPES.md) (Auth0, Keycloak, Okta, Clerk, โฆ)
|
|
25
|
+
|
|
23
26
|
---
|
|
24
27
|
|
|
25
28
|
## 1. Upstream auth โ `@koduhai/mcp-kit/upstream`
|
|
@@ -119,17 +122,41 @@ const verifier = introspectionVerifier({
|
|
|
119
122
|
|
|
120
123
|
Introspection results are cached for a short TTL (capped by the token's own `exp`) and deduplicated while a call is in flight, so a busy server doesn't introspect the same token on every request. Caching delays revocation visibility by at most the TTL; set `cacheTtlSeconds: 0` if every request must hit the AS.
|
|
121
124
|
|
|
122
|
-
Works with any standards-compliant IdP: Auth0, Logto, Clerk, Keycloak, Okta, Cognito, WorkOS, and friends. mcp-kit verifies tokens; it does not try to be your Authorization Server (the spec says don't, and you shouldn't).
|
|
125
|
+
Works with any standards-compliant IdP: Auth0, Logto, Clerk, Keycloak, Okta, Cognito, WorkOS, and friends โ see [RECIPES.md](./RECIPES.md) for per-provider configs. mcp-kit verifies tokens; it does not try to be your Authorization Server (the spec says don't, and you shouldn't).
|
|
123
126
|
|
|
124
127
|
See [`examples/`](./examples) for a full stdio server and a full remote OAuth server.
|
|
125
128
|
|
|
129
|
+
## 4. Mounting tools โ `@koduhai/mcp-kit/server`
|
|
130
|
+
|
|
131
|
+
`versionTool` (and your own tools) are plain, transport-agnostic [`ToolDescriptor`](./src/versioning/index.ts)s. `serveTools` wires a list of them onto a low-level MCP `Server` in one call: it registers the `tools/list` and `tools/call` handlers, JSON-encodes each result as MCP text content, and rejects unknown tool names. This is the only entry point that needs the MCP SDK at runtime.
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
135
|
+
import { serveTools } from '@koduhai/mcp-kit/server';
|
|
136
|
+
import { apiVersioning, versionTool } from '@koduhai/mcp-kit/versioning';
|
|
137
|
+
|
|
138
|
+
const versioning = apiVersioning({ header: 'Api-Version', version: '2026-01-01' });
|
|
139
|
+
const server = new Server({ name: 'my-mcp', version: '1.0.0' }, { capabilities: { tools: {} } });
|
|
140
|
+
|
|
141
|
+
serveTools(server, [
|
|
142
|
+
versionTool(versioning),
|
|
143
|
+
{
|
|
144
|
+
name: 'get_widget',
|
|
145
|
+
description: 'Fetch a widget.',
|
|
146
|
+
inputSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },
|
|
147
|
+
handler: (a) => api(`/widgets/${a.id}`).then((r) => r.json()),
|
|
148
|
+
},
|
|
149
|
+
]);
|
|
150
|
+
// await server.connect(transport)
|
|
151
|
+
```
|
|
152
|
+
|
|
126
153
|
---
|
|
127
154
|
|
|
128
155
|
## Design
|
|
129
156
|
|
|
130
|
-
- **Layered, optional peers.** `/upstream` and `/versioning` have zero dependencies. `/auth`
|
|
131
|
-
- **Injectable everything.** Every network call and clock is injectable, so the whole thing is tested offline (
|
|
132
|
-
- **Resilient outbound calls.** Every control-plane request the library makes (token, introspection, JWKS, discovery) carries a timeout (default 10s, configurable via `timeoutMs`) so
|
|
157
|
+
- **Layered, optional peers.** `/upstream` and `/versioning` have zero dependencies. `/auth` and `/server` declare `@modelcontextprotocol/sdk` (and `/auth` also `express` and `jose`) as _optional_ peers, so you only install them if you build a remote or SDK-backed server.
|
|
158
|
+
- **Injectable everything.** Every network call and clock is injectable, so the whole thing is tested offline (57 tests, including a real Express + token-verification integration and an in-memory MCP client/server round trip).
|
|
159
|
+
- **Resilient outbound calls.** Every control-plane request the library makes (token, introspection, JWKS, discovery) carries a timeout (default 10s, configurable via `timeoutMs`) and optional bounded retries (`retries`) so a slow or flaky IdP can't hang your server.
|
|
133
160
|
- **ESM, Node โฅ 20, TypeScript-first.**
|
|
134
161
|
|
|
135
162
|
## Compatibility
|
|
@@ -18,6 +18,10 @@ export interface IntrospectionVerifierOptions {
|
|
|
18
18
|
maxCacheEntries?: number;
|
|
19
19
|
/** Timeout (ms) for the introspection request. Default 10000. Pass 0 to disable. */
|
|
20
20
|
timeoutMs?: number;
|
|
21
|
+
/** Retries for transient introspection failures (network, 429, 5xx). Default 0. */
|
|
22
|
+
retries?: number;
|
|
23
|
+
/** Base backoff (ms), doubled each retry. Default 200. */
|
|
24
|
+
retryBaseDelayMs?: number;
|
|
21
25
|
/** Injectable clock (ms). */
|
|
22
26
|
now?: () => number;
|
|
23
27
|
/** Injectable for tests. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"introspection-verifier.d.ts","sourceRoot":"","sources":["../../src/auth/introspection-verifier.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AAI5F,MAAM,WAAW,4BAA4B;IAC3C,6DAA6D;IAC7D,gBAAgB,EAAE,MAAM,CAAC;IACzB,kGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uFAAuF;IACvF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,4BAA4B,GAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"introspection-verifier.d.ts","sourceRoot":"","sources":["../../src/auth/introspection-verifier.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AAI5F,MAAM,WAAW,4BAA4B;IAC3C,6DAA6D;IAC7D,gBAAgB,EAAE,MAAM,CAAC;IACzB,kGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uFAAuF;IACvF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,4BAA4B,GAAG,kBAAkB,CA+F5F"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { InvalidTokenError } from '@modelcontextprotocol/sdk/server/auth/errors.js';
|
|
3
|
-
import { DEFAULT_TIMEOUT_MS,
|
|
3
|
+
import { DEFAULT_TIMEOUT_MS, fetchWithRetry } from '../internal/http.js';
|
|
4
4
|
/**
|
|
5
5
|
* An {@link OAuthTokenVerifier} that validates opaque (or any) access tokens by calling the
|
|
6
6
|
* Authorization Server's introspection endpoint (RFC 7662). Use this when your IdP issues
|
|
@@ -42,7 +42,7 @@ export function introspectionVerifier(opts) {
|
|
|
42
42
|
}
|
|
43
43
|
let res;
|
|
44
44
|
try {
|
|
45
|
-
res = await
|
|
45
|
+
res = await fetchWithRetry(fetchImpl, opts.introspectionUrl, { method: 'POST', headers, body }, timeoutMs, { retries: opts.retries, retryBaseDelayMs: opts.retryBaseDelayMs });
|
|
46
46
|
}
|
|
47
47
|
catch (e) {
|
|
48
48
|
throw new InvalidTokenError(`introspection request failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"introspection-verifier.js","sourceRoot":"","sources":["../../src/auth/introspection-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AAGpF,OAAO,EAAE,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"introspection-verifier.js","sourceRoot":"","sources":["../../src/auth/introspection-verifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,7 @@ export interface JwtVerifierOptions {
|
|
|
22
22
|
scopeClaim?: string;
|
|
23
23
|
/** Provide the key directly (a `KeyLike`/JWKS/resolver) instead of discovering it. Mainly for tests. */
|
|
24
24
|
key?: JwtKeyInput;
|
|
25
|
-
/** Injectable fetch for discovery. */
|
|
25
|
+
/** Injectable fetch for issuer discovery and the JWKS request. */
|
|
26
26
|
fetch?: typeof globalThis.fetch;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt-verifier.d.ts","sourceRoot":"","sources":["../../src/auth/jwt-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,SAAS,
|
|
1
|
+
{"version":3,"file":"jwt-verifier.d.ts","sourceRoot":"","sources":["../../src/auth/jwt-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,SAAS,EAAe,MAAM,MAAM,CAAC;AAElE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AAK5F,gGAAgG;AAChG,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC,kGAAkG;IAClG,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,wFAAwF;IACxF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,kEAAkE;IAClE,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gGAAgG;IAChG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wGAAwG;IACxG,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,kEAAkE;IAClE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAcD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,CA8DxE"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createRemoteJWKSet, jwtVerify } from 'jose';
|
|
1
|
+
import { createRemoteJWKSet, jwtVerify, customFetch } from 'jose';
|
|
2
2
|
import { InvalidTokenError } from '@modelcontextprotocol/sdk/server/auth/errors.js';
|
|
3
3
|
import { DEFAULT_TIMEOUT_MS } from '../internal/http.js';
|
|
4
4
|
import { discoverOAuthMetadata } from './metadata.js';
|
|
@@ -47,7 +47,12 @@ export function jwtVerifier(opts) {
|
|
|
47
47
|
throw new Error('jwtVerifier: issuer metadata has no jwks_uri; pass `jwksUri` or `key`');
|
|
48
48
|
}
|
|
49
49
|
const jwksTimeout = opts.timeoutMs && opts.timeoutMs > 0 ? opts.timeoutMs : DEFAULT_TIMEOUT_MS;
|
|
50
|
-
keyInput = createRemoteJWKSet(new URL(jwksUri), {
|
|
50
|
+
keyInput = createRemoteJWKSet(new URL(jwksUri), {
|
|
51
|
+
timeoutDuration: jwksTimeout,
|
|
52
|
+
// Route the JWKS fetch through the injected fetch too, so the whole
|
|
53
|
+
// discovery -> JWKS -> verify path is exercisable offline in tests.
|
|
54
|
+
...(opts.fetch ? { [customFetch]: opts.fetch } : {}),
|
|
55
|
+
});
|
|
51
56
|
return keyInput;
|
|
52
57
|
})();
|
|
53
58
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwt-verifier.js","sourceRoot":"","sources":["../../src/auth/jwt-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"jwt-verifier.js","sourceRoot":"","sources":["../../src/auth/jwt-verifier.ts"],"names":[],"mappings":"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"}
|
package/dist/internal/http.d.ts
CHANGED
|
@@ -12,5 +12,21 @@ type FetchInput = Parameters<typeof globalThis.fetch>[0];
|
|
|
12
12
|
* or non-finite `timeoutMs` to disable the timeout entirely.
|
|
13
13
|
*/
|
|
14
14
|
export declare function fetchWithTimeout(fetchImpl: typeof globalThis.fetch, input: FetchInput, init?: RequestInit, timeoutMs?: number): Promise<Response>;
|
|
15
|
+
export interface RetryOptions {
|
|
16
|
+
/** Number of retries after the first attempt. Default 0 (no retries). */
|
|
17
|
+
retries?: number;
|
|
18
|
+
/** Base backoff in ms; doubles each attempt (200, 400, 800, ...). Default 200. */
|
|
19
|
+
retryBaseDelayMs?: number;
|
|
20
|
+
/** Injectable delay, for tests. */
|
|
21
|
+
sleep?: (ms: number) => Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* `fetchWithTimeout` plus bounded exponential-backoff retries on transient
|
|
25
|
+
* failures (network errors, 429, and 5xx). A timeout abort counts as a failure
|
|
26
|
+
* and is retried. On a 429/503 carrying a `Retry-After` header, that delay is
|
|
27
|
+
* honored (capped) instead of the backoff. With `retries: 0` (the default) this
|
|
28
|
+
* is exactly one attempt.
|
|
29
|
+
*/
|
|
30
|
+
export declare function fetchWithRetry(fetchImpl: typeof globalThis.fetch, input: FetchInput, init: RequestInit, timeoutMs: number, retry?: RetryOptions): Promise<Response>;
|
|
15
31
|
export {};
|
|
16
32
|
//# sourceMappingURL=http.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/internal/http.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAEzC,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,OAAO,UAAU,CAAC,KAAK,EAClC,KAAK,EAAE,UAAU,EACjB,IAAI,GAAE,WAAgB,EACtB,SAAS,GAAE,MAA2B,GACrC,OAAO,CAAC,QAAQ,CAAC,CAWnB"}
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/internal/http.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAEzC,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,OAAO,UAAU,CAAC,KAAK,EAClC,KAAK,EAAE,UAAU,EACjB,IAAI,GAAE,WAAgB,EACtB,SAAS,GAAE,MAA2B,GACrC,OAAO,CAAC,QAAQ,CAAC,CAWnB;AAoBD,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mCAAmC;IACnC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,OAAO,UAAU,CAAC,KAAK,EAClC,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,YAAiB,GACvB,OAAO,CAAC,QAAQ,CAAC,CAsBnB"}
|
package/dist/internal/http.js
CHANGED
|
@@ -25,4 +25,52 @@ export async function fetchWithTimeout(fetchImpl, input, init = {}, timeoutMs =
|
|
|
25
25
|
throw e;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
+
/** HTTP status codes worth retrying: rate limiting and transient server errors. */
|
|
29
|
+
const RETRYABLE_STATUS = new Set([429, 500, 502, 503, 504]);
|
|
30
|
+
/** Upper bound on any single retry wait, so a hostile `Retry-After` can't stall a request. */
|
|
31
|
+
const MAX_RETRY_DELAY_MS = 30_000;
|
|
32
|
+
/**
|
|
33
|
+
* Parse a `Retry-After` header into milliseconds. Handles the delta-seconds form
|
|
34
|
+
* (e.g. `120`); the HTTP-date form is not special-cased and falls back to backoff.
|
|
35
|
+
* Capped at {@link MAX_RETRY_DELAY_MS}.
|
|
36
|
+
*/
|
|
37
|
+
function parseRetryAfterMs(header) {
|
|
38
|
+
if (!header)
|
|
39
|
+
return undefined;
|
|
40
|
+
const seconds = Number(header);
|
|
41
|
+
if (!Number.isFinite(seconds) || seconds < 0)
|
|
42
|
+
return undefined;
|
|
43
|
+
return Math.min(seconds * 1000, MAX_RETRY_DELAY_MS);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `fetchWithTimeout` plus bounded exponential-backoff retries on transient
|
|
47
|
+
* failures (network errors, 429, and 5xx). A timeout abort counts as a failure
|
|
48
|
+
* and is retried. On a 429/503 carrying a `Retry-After` header, that delay is
|
|
49
|
+
* honored (capped) instead of the backoff. With `retries: 0` (the default) this
|
|
50
|
+
* is exactly one attempt.
|
|
51
|
+
*/
|
|
52
|
+
export async function fetchWithRetry(fetchImpl, input, init, timeoutMs, retry = {}) {
|
|
53
|
+
const retries = retry.retries ?? 0;
|
|
54
|
+
const base = retry.retryBaseDelayMs ?? 200;
|
|
55
|
+
const sleep = retry.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
56
|
+
let attempt = 0;
|
|
57
|
+
for (;;) {
|
|
58
|
+
try {
|
|
59
|
+
const res = await fetchWithTimeout(fetchImpl, input, init, timeoutMs);
|
|
60
|
+
if (RETRYABLE_STATUS.has(res.status) && attempt < retries) {
|
|
61
|
+
const backoff = Math.min(base * 2 ** attempt, MAX_RETRY_DELAY_MS);
|
|
62
|
+
await sleep(parseRetryAfterMs(res.headers.get('retry-after')) ?? backoff);
|
|
63
|
+
attempt++;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
return res;
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
if (attempt >= retries)
|
|
70
|
+
throw e;
|
|
71
|
+
await sleep(Math.min(base * 2 ** attempt, MAX_RETRY_DELAY_MS));
|
|
72
|
+
attempt++;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
28
76
|
//# sourceMappingURL=http.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/internal/http.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,2EAA2E;AAC3E,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAIzC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAkC,EAClC,KAAiB,EACjB,OAAoB,EAAE,EACtB,YAAoB,kBAAkB;IAEtC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC/E,IAAI,CAAC;QACH,OAAO,MAAM,SAAS,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,4EAA4E;QAC5E,IAAI,OAAO,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,SAAS,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7F,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/internal/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server glue for mounting transport-agnostic {@link ToolDescriptor}s onto an MCP
|
|
3
|
+
* `Server` in one call. This is the only entry point that needs the MCP SDK at
|
|
4
|
+
* runtime, so it lives apart from the zero-dependency `/versioning` module.
|
|
5
|
+
*/
|
|
6
|
+
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
7
|
+
import type { ToolDescriptor } from '../versioning/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* Register a list of {@link ToolDescriptor}s on a low-level MCP `Server`: wires the
|
|
10
|
+
* `tools/list` and `tools/call` handlers, JSON-encodes each handler's return value as
|
|
11
|
+
* MCP text content, and answers unknown tool names with a `MethodNotFound` error. This
|
|
12
|
+
* replaces the boilerplate you'd otherwise hand-write per server.
|
|
13
|
+
*
|
|
14
|
+
* The server must advertise the tools capability when constructed, e.g.
|
|
15
|
+
* `new Server(info, { capabilities: { tools: {} } })`.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const server = new Server({ name: 'x', version: '1.0.0' }, { capabilities: { tools: {} } });
|
|
19
|
+
* serveTools(server, [versionTool(versioning), myTool]);
|
|
20
|
+
* await server.connect(transport);
|
|
21
|
+
*/
|
|
22
|
+
export declare function serveTools(server: Server, tools: ToolDescriptor[]): void;
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAOxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,IAAI,CAkBxE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, McpError, ErrorCode, } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Register a list of {@link ToolDescriptor}s on a low-level MCP `Server`: wires the
|
|
4
|
+
* `tools/list` and `tools/call` handlers, JSON-encodes each handler's return value as
|
|
5
|
+
* MCP text content, and answers unknown tool names with a `MethodNotFound` error. This
|
|
6
|
+
* replaces the boilerplate you'd otherwise hand-write per server.
|
|
7
|
+
*
|
|
8
|
+
* The server must advertise the tools capability when constructed, e.g.
|
|
9
|
+
* `new Server(info, { capabilities: { tools: {} } })`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const server = new Server({ name: 'x', version: '1.0.0' }, { capabilities: { tools: {} } });
|
|
13
|
+
* serveTools(server, [versionTool(versioning), myTool]);
|
|
14
|
+
* await server.connect(transport);
|
|
15
|
+
*/
|
|
16
|
+
export function serveTools(server, tools) {
|
|
17
|
+
const byName = new Map(tools.map((t) => [t.name, t]));
|
|
18
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
19
|
+
tools: tools.map((t) => ({
|
|
20
|
+
name: t.name,
|
|
21
|
+
description: t.description,
|
|
22
|
+
inputSchema: t.inputSchema,
|
|
23
|
+
})),
|
|
24
|
+
}));
|
|
25
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
26
|
+
const tool = byName.get(req.params.name);
|
|
27
|
+
if (!tool)
|
|
28
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${req.params.name}`);
|
|
29
|
+
const result = await tool.handler((req.params.arguments ?? {}));
|
|
30
|
+
const text = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
|
|
31
|
+
return { content: [{ type: 'text', text }] };
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,QAAQ,EACR,SAAS,GACV,MAAM,oCAAoC,CAAC;AAG5C;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,KAAuB;IAChE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtD,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,WAAW,EAAE,CAAC,CAAC,WAAiC;SACjD,CAAC,CAAC;KACJ,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,iBAAiB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5F,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAA4B,CAAC,CAAC;QAC3F,MAAM,IAAI,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACnF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/upstream/index.d.ts
CHANGED
|
@@ -3,6 +3,19 @@ export interface UpstreamAuth {
|
|
|
3
3
|
/** Returns headers to merge into every upstream request. May refresh tokens internally. */
|
|
4
4
|
headers(): Promise<Record<string, string>>;
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Thrown when an OAuth token endpoint responds with an error or a malformed body.
|
|
8
|
+
* Carries the HTTP `status` and raw `responseBody` so callers can branch on them.
|
|
9
|
+
*/
|
|
10
|
+
export declare class TokenRequestError extends Error {
|
|
11
|
+
readonly status?: number;
|
|
12
|
+
readonly responseBody?: string;
|
|
13
|
+
constructor(message: string, opts?: {
|
|
14
|
+
status?: number;
|
|
15
|
+
responseBody?: string;
|
|
16
|
+
cause?: unknown;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
6
19
|
export interface ApiKeyAuthOptions {
|
|
7
20
|
/** The API key / token value. */
|
|
8
21
|
key: string;
|
|
@@ -34,6 +47,10 @@ export interface ClientCredentialsOptions {
|
|
|
34
47
|
refreshSkewSeconds?: number;
|
|
35
48
|
/** Timeout (ms) for the token request. Default 10000. Pass 0 to disable. */
|
|
36
49
|
timeoutMs?: number;
|
|
50
|
+
/** Retries for transient token-endpoint failures (network, 429, 5xx). Default 0. */
|
|
51
|
+
retries?: number;
|
|
52
|
+
/** Base backoff (ms), doubled each retry. Default 200. */
|
|
53
|
+
retryBaseDelayMs?: number;
|
|
37
54
|
/** Injectable for tests. */
|
|
38
55
|
fetch?: typeof globalThis.fetch;
|
|
39
56
|
/** Injectable clock (ms). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/upstream/index.ts"],"names":[],"mappings":"AAMA,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,2FAA2F;IAC3F,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,YAAY,CAQhE;AAED,iFAAiF;AACjF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAEpE,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,SAAkB,GAAG,YAAY,CAQrF;AAED,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,wBAAwB,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/upstream/index.ts"],"names":[],"mappings":"AAMA,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,2FAA2F;IAC3F,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC5C;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;gBACnB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAMhG;AAED,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,YAAY,CAQhE;AAED,iFAAiF;AACjF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAEpE,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,SAAkB,GAAG,YAAY,CAQrF;AAED,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,wBAAwB,GAAG,YAAY,CAsElF;AAED,+FAA+F;AAC/F,MAAM,MAAM,YAAY,GACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AAMrE,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,iFAAiF;IACjF,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,UAAU,CAAC,KAAK,CAmBvF"}
|
package/dist/upstream/index.js
CHANGED
|
@@ -2,7 +2,21 @@
|
|
|
2
2
|
* Upstream auth: how your MCP server authenticates to the API/service it wraps.
|
|
3
3
|
* Zero dependencies, zero transport assumptions. Works with stdio or HTTP servers.
|
|
4
4
|
*/
|
|
5
|
-
import { DEFAULT_TIMEOUT_MS, fetchWithTimeout } from '../internal/http.js';
|
|
5
|
+
import { DEFAULT_TIMEOUT_MS, fetchWithRetry, fetchWithTimeout } from '../internal/http.js';
|
|
6
|
+
/**
|
|
7
|
+
* Thrown when an OAuth token endpoint responds with an error or a malformed body.
|
|
8
|
+
* Carries the HTTP `status` and raw `responseBody` so callers can branch on them.
|
|
9
|
+
*/
|
|
10
|
+
export class TokenRequestError extends Error {
|
|
11
|
+
status;
|
|
12
|
+
responseBody;
|
|
13
|
+
constructor(message, opts) {
|
|
14
|
+
super(message, opts?.cause !== undefined ? { cause: opts.cause } : undefined);
|
|
15
|
+
this.name = 'TokenRequestError';
|
|
16
|
+
this.status = opts?.status;
|
|
17
|
+
this.responseBody = opts?.responseBody;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
6
20
|
/** Static API-key auth. The most common MCP-server-to-API pattern. */
|
|
7
21
|
export function apiKeyAuth(opts) {
|
|
8
22
|
if (!opts.key)
|
|
@@ -48,11 +62,11 @@ export function clientCredentialsAuth(opts) {
|
|
|
48
62
|
body.set('scope', opts.scope);
|
|
49
63
|
if (opts.audience)
|
|
50
64
|
body.set('audience', opts.audience);
|
|
51
|
-
const res = await
|
|
65
|
+
const res = await fetchWithRetry(fetchImpl, opts.tokenUrl, {
|
|
52
66
|
method: 'POST',
|
|
53
67
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json' },
|
|
54
68
|
body,
|
|
55
|
-
}, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
69
|
+
}, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS, { retries: opts.retries, retryBaseDelayMs: opts.retryBaseDelayMs });
|
|
56
70
|
const text = await res.text();
|
|
57
71
|
let json;
|
|
58
72
|
try {
|
|
@@ -62,11 +76,14 @@ export function clientCredentialsAuth(opts) {
|
|
|
62
76
|
json = {};
|
|
63
77
|
}
|
|
64
78
|
if (!res.ok) {
|
|
65
|
-
throw new
|
|
79
|
+
throw new TokenRequestError(`clientCredentialsAuth: token request failed (${res.status}): ${String(json.error ?? text)}`, { status: res.status, responseBody: text });
|
|
66
80
|
}
|
|
67
81
|
const token = json.access_token;
|
|
68
82
|
if (typeof token !== 'string' || !token) {
|
|
69
|
-
throw new
|
|
83
|
+
throw new TokenRequestError('clientCredentialsAuth: response missing access_token', {
|
|
84
|
+
status: res.status,
|
|
85
|
+
responseBody: text,
|
|
86
|
+
});
|
|
70
87
|
}
|
|
71
88
|
const expiresIn = typeof json.expires_in === 'number' ? json.expires_in : 3600;
|
|
72
89
|
cached = { token, expiresAtMs: now() + expiresIn * 1000 };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/upstream/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/upstream/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koduhai/mcp-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Auth and versioning for MCP servers, solved. Upstream API auth (API key / bearer / OAuth client-credentials), API versioning with a get_version tool, and a one-call OAuth 2.1 Resource Server (JWKS + introspection verifiers, RFC 9728 metadata) on top of the MCP SDK.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -43,6 +43,10 @@
|
|
|
43
43
|
"./auth": {
|
|
44
44
|
"types": "./dist/auth/index.d.ts",
|
|
45
45
|
"import": "./dist/auth/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./server": {
|
|
48
|
+
"types": "./dist/server/index.d.ts",
|
|
49
|
+
"import": "./dist/server/index.js"
|
|
46
50
|
}
|
|
47
51
|
},
|
|
48
52
|
"files": [
|
|
@@ -50,6 +54,10 @@
|
|
|
50
54
|
"README.md",
|
|
51
55
|
"LICENSE"
|
|
52
56
|
],
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public",
|
|
59
|
+
"provenance": true
|
|
60
|
+
},
|
|
53
61
|
"engines": {
|
|
54
62
|
"node": ">=20"
|
|
55
63
|
},
|
|
@@ -60,6 +68,12 @@
|
|
|
60
68
|
"format": "prettier --write .",
|
|
61
69
|
"format:check": "prettier --check .",
|
|
62
70
|
"test": "vitest run",
|
|
71
|
+
"test:watch": "vitest",
|
|
72
|
+
"test:coverage": "vitest run --coverage",
|
|
73
|
+
"check": "npm run typecheck && npm run lint && npm run format:check && npm test",
|
|
74
|
+
"typecheck:examples": "tsc -p examples/tsconfig.json",
|
|
75
|
+
"check:exports": "publint && attw --pack . --profile esm-only",
|
|
76
|
+
"docs": "typedoc",
|
|
63
77
|
"prepublishOnly": "npm run build"
|
|
64
78
|
},
|
|
65
79
|
"peerDependencies": {
|
|
@@ -79,17 +93,21 @@
|
|
|
79
93
|
}
|
|
80
94
|
},
|
|
81
95
|
"devDependencies": {
|
|
96
|
+
"@arethetypeswrong/cli": "^0.18.3",
|
|
82
97
|
"@eslint/js": "^10.0.1",
|
|
83
98
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
84
99
|
"@types/express": "^5.0.0",
|
|
85
100
|
"@types/node": "^25.9.3",
|
|
86
101
|
"@types/supertest": "^7.2.0",
|
|
102
|
+
"@vitest/coverage-v8": "^4.1.8",
|
|
87
103
|
"eslint": "^10.4.1",
|
|
88
104
|
"eslint-config-prettier": "^10.1.8",
|
|
89
105
|
"express": "^5.0.0",
|
|
90
106
|
"jose": "^6.0.0",
|
|
91
107
|
"prettier": "^3.8.4",
|
|
108
|
+
"publint": "^0.3.21",
|
|
92
109
|
"supertest": "^7.0.0",
|
|
110
|
+
"typedoc": "^0.28.19",
|
|
93
111
|
"typescript": "^6.0.3",
|
|
94
112
|
"typescript-eslint": "^8.61.0",
|
|
95
113
|
"vitest": "^4.1.8"
|