@ttoss/http-server-mcp 0.19.1 → 0.21.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 +99 -0
- package/dist/index.cjs +133 -13
- package/dist/index.d.cts +101 -10
- package/dist/index.d.mts +105 -13
- package/dist/index.mjs +133 -14
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -366,6 +366,74 @@ createMcpRouter(mcpServer, {
|
|
|
366
366
|
|
|
367
367
|
The discovery endpoint (`/.well-known/oauth-protected-resource`) remains publicly accessible even when `aliases` includes `'/'`.
|
|
368
368
|
|
|
369
|
+
## Gated Tool Registrar
|
|
370
|
+
|
|
371
|
+
`createGatedToolRegistrar` wraps `server.registerTool` with a consistent authentication and authorization pipeline so you don't repeat the same boilerplate in every handler.
|
|
372
|
+
|
|
373
|
+
Every registered tool automatically:
|
|
374
|
+
|
|
375
|
+
1. Resolves the caller's identity (defaults to `getIdentity()` from the request context).
|
|
376
|
+
2. Checks that the caller holds a required OAuth scope — returns an `isError` result (not a throw) when the scope is absent.
|
|
377
|
+
3. Runs global `gates` then per-tool `def.gates` in order; a throwing gate rejects the call. Both receive `ToolCallContext` (identity **and** the validated call args).
|
|
378
|
+
4. Merges `buildContext` output into the handler args.
|
|
379
|
+
5. Wraps `null`/`undefined` results in a configurable "Not found" error result.
|
|
380
|
+
6. Calls `onError` on handler throw before rethrowing, for telemetry. Gate/scope failures do **not** trigger `onError`.
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
import {
|
|
384
|
+
createGatedToolRegistrar,
|
|
385
|
+
getIdentity,
|
|
386
|
+
McpServer,
|
|
387
|
+
} from '@ttoss/http-server-mcp';
|
|
388
|
+
import { z } from 'zod';
|
|
389
|
+
|
|
390
|
+
const { register } = createGatedToolRegistrar({
|
|
391
|
+
server,
|
|
392
|
+
resolveIdentity: () => {
|
|
393
|
+
const jwt = getIdentity<{ sub: string; scope: string }>();
|
|
394
|
+
const scopes = jwt?.scope?.split(' ') ?? [];
|
|
395
|
+
return { userId: jwt!.sub, scopes };
|
|
396
|
+
},
|
|
397
|
+
buildContext: ({ identity }) => ({ tenantId: lookupTenant(identity.userId) }),
|
|
398
|
+
onError: (err, { handler, identity }) => {
|
|
399
|
+
logger.error({ err, handler, userId: identity.userId });
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
register({
|
|
404
|
+
name: 'list-campaigns',
|
|
405
|
+
description: 'List all ad campaigns for the caller.',
|
|
406
|
+
requiredScope: 'campaigns:read',
|
|
407
|
+
inputSchema: { limit: z.number().optional() },
|
|
408
|
+
method: async ({ userId, tenantId, limit }) =>
|
|
409
|
+
fetchCampaigns(tenantId, limit),
|
|
410
|
+
});
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
**`resolveIdentity`** is called once per invocation. Omit it to use the default `getIdentity()` from the MCP request context.
|
|
414
|
+
|
|
415
|
+
**`gates`** (global and per-tool) are async functions that receive a `ToolCallContext` — both the resolved identity and the validated call args — and throw to reject. The full context lets gates vary their predicate based on what the caller is asking for, not just who they are.
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
register({
|
|
419
|
+
name: 'activate-ad-account',
|
|
420
|
+
description: 'Activate or deactivate an ad account.',
|
|
421
|
+
requiredScope: 'accounts:write',
|
|
422
|
+
inputSchema: { accountId: z.number(), isActive: z.boolean() },
|
|
423
|
+
// arg-conditional gate: activating requires more checks than deactivating
|
|
424
|
+
gates: [
|
|
425
|
+
({ args }) =>
|
|
426
|
+
args.isActive
|
|
427
|
+
? checkSubscriptionGates(['mustNotExceedMaxActive', 'mustHaveBudget'])
|
|
428
|
+
: checkSubscriptionGates(['mustIncludeService']),
|
|
429
|
+
],
|
|
430
|
+
method: async ({ userId, accountId, isActive }) =>
|
|
431
|
+
toggleAdAccount(userId, accountId, isActive),
|
|
432
|
+
});
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**`buildContext`** injects request-scoped values (DB clients, tenant IDs) into every handler call without threading them through each individual tool. It receives the full `ToolCallContext` so context can vary by identity or by call args.
|
|
436
|
+
|
|
369
437
|
## Issuing tokens for MCP clients
|
|
370
438
|
|
|
371
439
|
The `auth` option above covers the **resource-server** half of MCP authorization — it verifies tokens issued by an external authorization server (Cognito, Auth0, …). To make your own first-party server _issue_ the tokens an MCP client runs the full OAuth flow against, add the [`@ttoss/http-server-auth`](https://ttoss.dev/docs/modules/packages/http-server-auth) plugin's `oauthServer()` and pair it with `createMcpRouter({ auth: { verifyToken } })` so one deployment both issues and verifies tokens. See the [OAuth Authorization Server](https://ttoss.dev/docs/engineering/guidelines/oauth-authorization-server) guideline.
|
|
@@ -446,6 +514,37 @@ Returns the `WWW-Authenticate` header value for a 401 response, formatted per th
|
|
|
446
514
|
|
|
447
515
|
**Returns:** `string` — The full `WWW-Authenticate` header value
|
|
448
516
|
|
|
517
|
+
### `createGatedToolRegistrar(options)`
|
|
518
|
+
|
|
519
|
+
Factory that returns a `register` helper for tools that require authentication and a specific OAuth scope.
|
|
520
|
+
|
|
521
|
+
**Parameters (`options`):**
|
|
522
|
+
|
|
523
|
+
- `server` (`McpServer`) — The MCP server to register tools on.
|
|
524
|
+
- `resolveIdentity` (`() => ToolIdentity`, optional) — Called once per invocation to resolve `{ userId, scopes? }`. Defaults to `getIdentity()` from the request context.
|
|
525
|
+
- `gates` (`Array<(ctx: ToolCallContext) => void | Promise<void>>`, optional) — Global guards run after the scope check, in order, before any per-tool gates. Each receives `{ identity, args, handler }`. Throw to reject the call.
|
|
526
|
+
- `enforceScope` (`boolean`, optional, default `true`) — When `true`, checks `def.requiredScope` against `identity.scopes` and returns an `isError` result on mismatch. Set to `false` when all authorization is handled by `gates`.
|
|
527
|
+
- `buildContext` (`(ctx: ToolCallContext) => Record<string, unknown>`, optional) — Produces extra key-value pairs merged into every handler's args. Receives the full `ToolCallContext` so context can vary by identity or by call args.
|
|
528
|
+
- `onError` (`(error, ctx: ToolCallContext) => void | Promise<void>`, optional) — Called when the handler throws, before the error is rethrown. Gate/scope failures do **not** trigger this hook.
|
|
529
|
+
- `notFoundMessage` (`string`, optional, default `"Not found"`) — `isError` message returned when the handler resolves to `null`/`undefined`.
|
|
530
|
+
|
|
531
|
+
**Returns:** `{ register: (def: GatedToolDef) => void }`
|
|
532
|
+
|
|
533
|
+
The `GatedToolDef` passed to `register` has:
|
|
534
|
+
|
|
535
|
+
- `name` — Tool name.
|
|
536
|
+
- `description` — Human-readable description.
|
|
537
|
+
- `requiredScope` — Single scope that must appear in `identity.scopes`.
|
|
538
|
+
- `inputSchema` — Zod field map or `ZodObject`, forwarded to `server.registerTool`.
|
|
539
|
+
- `gates` (`Array<(ctx: ToolCallContext) => void | Promise<void>>`, optional) — Per-tool guards appended after the global `gates`. Receive the full `ToolCallContext` enabling arg-conditional authorization.
|
|
540
|
+
- `method` — Async handler. Receives merged call args + `buildContext` output.
|
|
541
|
+
|
|
542
|
+
**`ToolCallContext`** is the object passed to gates, `buildContext`, and `onError`:
|
|
543
|
+
|
|
544
|
+
- `identity` (`ToolIdentity`) — The resolved caller identity (`{ userId, scopes? }`).
|
|
545
|
+
- `args` (`Record<string, unknown>`) — The validated tool input (post SDK parse).
|
|
546
|
+
- `handler` (`string`) — The tool name, for error attribution.
|
|
547
|
+
|
|
449
548
|
### `registerToolFromSchema(server, params)`
|
|
450
549
|
|
|
451
550
|
Registers a tool using a **plain JSON Schema** object for `inputSchema` instead of a Zod shape.
|
package/dist/index.cjs
CHANGED
|
@@ -2,14 +2,145 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, {
|
|
3
3
|
value: 'Module'
|
|
4
4
|
});
|
|
5
|
-
let node_async_hooks = require("node:async_hooks");
|
|
6
5
|
let _modelcontextprotocol_sdk_server_streamableHttp_js = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
7
6
|
let _ttoss_auth_core_amazon_cognito = require("@ttoss/auth-core/amazon-cognito");
|
|
8
7
|
let _ttoss_http_server = require("@ttoss/http-server");
|
|
9
8
|
let _ttoss_http_server_auth = require("@ttoss/http-server-auth");
|
|
10
9
|
let zod = require("zod");
|
|
10
|
+
let node_async_hooks = require("node:async_hooks");
|
|
11
11
|
let _modelcontextprotocol_sdk_server_mcp_js = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
12
12
|
|
|
13
|
+
//#region src/context.ts
|
|
14
|
+
var requestContextStore = new node_async_hooks.AsyncLocalStorage();
|
|
15
|
+
/**
|
|
16
|
+
* Returns the verified JWT payload for the current MCP request.
|
|
17
|
+
* Only available inside a tool handler when `auth` is configured on the router.
|
|
18
|
+
*
|
|
19
|
+
* Accepts an optional type parameter to avoid casting at call sites:
|
|
20
|
+
* `getIdentity<{ sub: string; email: string }>()` returns `T | undefined`.
|
|
21
|
+
* Omitting the type parameter keeps the return type as `unknown | undefined`.
|
|
22
|
+
*/
|
|
23
|
+
var getIdentity = () => {
|
|
24
|
+
return requestContextStore.getStore()?.identity;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/createGatedToolRegistrar.ts
|
|
29
|
+
var toolError = message => {
|
|
30
|
+
return {
|
|
31
|
+
content: [{
|
|
32
|
+
type: "text",
|
|
33
|
+
text: JSON.stringify({
|
|
34
|
+
error: message
|
|
35
|
+
})
|
|
36
|
+
}],
|
|
37
|
+
isError: true
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Factory that returns a `register` helper for MCP tools that require
|
|
42
|
+
* authentication and a specific OAuth scope.
|
|
43
|
+
*
|
|
44
|
+
* Every registered tool automatically:
|
|
45
|
+
* 1. Resolves the caller identity (default: `getIdentity()`). Returns an
|
|
46
|
+
* `isError` result when the identity is absent (unauthenticated request).
|
|
47
|
+
* 2. When `enforceScope` is `true` (default), checks `requiredScope` — returns
|
|
48
|
+
* an `isError` result when the scope is absent, consistent with how MCP
|
|
49
|
+
* surfaces authorization errors. The package's `checkScopes` helper is not
|
|
50
|
+
* reused here because it throws rather than returning an `isError` result,
|
|
51
|
+
* and it reads identity from context itself.
|
|
52
|
+
* 3. Runs global `gates` then per-`register` `def.gates` in order; a throwing
|
|
53
|
+
* gate rejects the call. Every gate receives the full {@link ToolCallContext}
|
|
54
|
+
* (identity **and** the validated call args), enabling arg-conditional gates.
|
|
55
|
+
* Gates own their own error handling; `onError` covers the tool handler only.
|
|
56
|
+
* 4. Merges `buildContext` output into the handler args.
|
|
57
|
+
* 5. Wraps `null`/`undefined` results in a configurable "Not found" error result.
|
|
58
|
+
* 6. Calls `onError` on handler throw before rethrowing.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const { register } = createGatedToolRegistrar({
|
|
63
|
+
* server,
|
|
64
|
+
* resolveIdentity: () => {
|
|
65
|
+
* const jwt = getIdentity<{ sub: string; scopes: string[] }>();
|
|
66
|
+
* return { userId: jwt!.sub, scopes: jwt!.scopes };
|
|
67
|
+
* },
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* register({
|
|
71
|
+
* name: 'activate-campaign',
|
|
72
|
+
* description: 'Activate or deactivate a campaign.',
|
|
73
|
+
* requiredScope: 'campaigns:write',
|
|
74
|
+
* inputSchema: { isActive: z.boolean() },
|
|
75
|
+
* // arg-conditional gate: active vs. inactive have different restrictions
|
|
76
|
+
* gates: [
|
|
77
|
+
* ({ args }) =>
|
|
78
|
+
* args.isActive
|
|
79
|
+
* ? subscriptionGate(['mustNotExceedMaxActive', 'mustHaveBudget'])
|
|
80
|
+
* : subscriptionGate(['mustIncludeService']),
|
|
81
|
+
* ],
|
|
82
|
+
* method: async ({ userId, isActive }) => toggleCampaign(userId, isActive),
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
var checkScope = (identity, requiredScope) => {
|
|
87
|
+
if (!(Array.isArray(identity.scopes) ? identity.scopes : []).includes(requiredScope)) return toolError(`This tool requires the "${requiredScope}" scope.`);
|
|
88
|
+
return null;
|
|
89
|
+
};
|
|
90
|
+
var runGates = async (allGates, ctx) => {
|
|
91
|
+
for (const gate of allGates) await gate(ctx);
|
|
92
|
+
};
|
|
93
|
+
var createGatedToolRegistrar = ({
|
|
94
|
+
server,
|
|
95
|
+
resolveIdentity = getIdentity,
|
|
96
|
+
gates = [],
|
|
97
|
+
enforceScope = true,
|
|
98
|
+
onError,
|
|
99
|
+
buildContext,
|
|
100
|
+
notFoundMessage = "Not found"
|
|
101
|
+
}) => {
|
|
102
|
+
const register = def => {
|
|
103
|
+
server.registerTool(def.name, {
|
|
104
|
+
description: def.description,
|
|
105
|
+
inputSchema: def.inputSchema
|
|
106
|
+
}, async args => {
|
|
107
|
+
const identity = resolveIdentity();
|
|
108
|
+
if (!identity) return toolError("Unauthorized");
|
|
109
|
+
const ctx = {
|
|
110
|
+
identity,
|
|
111
|
+
args,
|
|
112
|
+
handler: def.name
|
|
113
|
+
};
|
|
114
|
+
if (enforceScope) {
|
|
115
|
+
const scopeError = checkScope(identity, def.requiredScope);
|
|
116
|
+
if (scopeError) return scopeError;
|
|
117
|
+
}
|
|
118
|
+
await runGates([...gates, ...(def.gates ?? [])], ctx);
|
|
119
|
+
const extra = buildContext ? buildContext(ctx) : {};
|
|
120
|
+
try {
|
|
121
|
+
const result = await def.method({
|
|
122
|
+
...args,
|
|
123
|
+
...extra
|
|
124
|
+
});
|
|
125
|
+
if (result == null) return toolError(notFoundMessage);
|
|
126
|
+
return {
|
|
127
|
+
content: [{
|
|
128
|
+
type: "text",
|
|
129
|
+
text: JSON.stringify(result)
|
|
130
|
+
}]
|
|
131
|
+
};
|
|
132
|
+
} catch (error) {
|
|
133
|
+
if (onError) await onError(error, ctx);
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
register
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
//#endregion
|
|
13
144
|
//#region src/index.ts
|
|
14
145
|
/** MCP lifecycle/discovery methods reachable before a client authenticates. */
|
|
15
146
|
var DEFAULT_PUBLIC_METHODS = ["initialize", "tools/list"];
|
|
@@ -27,7 +158,6 @@ var buildVerifyToken = auth => {
|
|
|
27
158
|
if (auth.verifyToken) return auth.verifyToken;
|
|
28
159
|
throw new Error("McpAuthOptions requires either cognitoUserPool or verifyToken");
|
|
29
160
|
};
|
|
30
|
-
var requestContextStore = new node_async_hooks.AsyncLocalStorage();
|
|
31
161
|
/**
|
|
32
162
|
* Generic HTTP helper for use inside MCP tool handlers.
|
|
33
163
|
*
|
|
@@ -115,17 +245,6 @@ var apiCall = async (method, url, options) => {
|
|
|
115
245
|
return response.text();
|
|
116
246
|
};
|
|
117
247
|
/**
|
|
118
|
-
* Returns the verified JWT payload for the current MCP request.
|
|
119
|
-
* Only available inside a tool handler when `auth` is configured on the router.
|
|
120
|
-
*
|
|
121
|
-
* Accepts an optional type parameter to avoid casting at call sites:
|
|
122
|
-
* `getIdentity<{ sub: string; email: string }>()` returns `T | undefined`.
|
|
123
|
-
* Omitting the type parameter keeps the return type as `unknown | undefined`.
|
|
124
|
-
*/
|
|
125
|
-
var getIdentity = () => {
|
|
126
|
-
return requestContextStore.getStore()?.identity;
|
|
127
|
-
};
|
|
128
|
-
/**
|
|
129
248
|
* Asserts that the current request's token contains all required scopes.
|
|
130
249
|
* Throws if any scope is missing — the MCP SDK catches this and returns a
|
|
131
250
|
* tool error to the client. Use inside tool handlers for per-tool authorization.
|
|
@@ -414,6 +533,7 @@ Object.defineProperty(exports, 'McpServer', {
|
|
|
414
533
|
});
|
|
415
534
|
exports.apiCall = apiCall;
|
|
416
535
|
exports.checkScopes = checkScopes;
|
|
536
|
+
exports.createGatedToolRegistrar = createGatedToolRegistrar;
|
|
417
537
|
exports.createMcpRouter = createMcpRouter;
|
|
418
538
|
exports.getIdentity = getIdentity;
|
|
419
539
|
exports.registerToolFromSchema = registerToolFromSchema;
|
package/dist/index.d.cts
CHANGED
|
@@ -665,6 +665,106 @@ declare namespace Application {
|
|
|
665
665
|
const HttpError: typeof HttpErrors.HttpError;
|
|
666
666
|
}
|
|
667
667
|
//#endregion
|
|
668
|
+
//#region src/context.d.ts
|
|
669
|
+
/**
|
|
670
|
+
* Returns the verified JWT payload for the current MCP request.
|
|
671
|
+
* Only available inside a tool handler when `auth` is configured on the router.
|
|
672
|
+
*
|
|
673
|
+
* Accepts an optional type parameter to avoid casting at call sites:
|
|
674
|
+
* `getIdentity<{ sub: string; email: string }>()` returns `T | undefined`.
|
|
675
|
+
* Omitting the type parameter keeps the return type as `unknown | undefined`.
|
|
676
|
+
*/
|
|
677
|
+
declare const getIdentity: <T = unknown>() => T | undefined;
|
|
678
|
+
//#endregion
|
|
679
|
+
//#region src/createGatedToolRegistrar.d.ts
|
|
680
|
+
/** Resolved identity for a gated tool call. */
|
|
681
|
+
type ToolIdentity = {
|
|
682
|
+
userId: string;
|
|
683
|
+
scopes?: string[];
|
|
684
|
+
};
|
|
685
|
+
/**
|
|
686
|
+
* Full context passed to gates, `buildContext`, and `onError` on every tool
|
|
687
|
+
* invocation. Having all three fields in one object means gate callbacks can
|
|
688
|
+
* be both identity-aware and args-aware without multiple parameters.
|
|
689
|
+
*/
|
|
690
|
+
type ToolCallContext = {
|
|
691
|
+
/** The resolved caller identity. */identity: ToolIdentity;
|
|
692
|
+
/**
|
|
693
|
+
* The validated tool input (post SDK parse). Present for gates and
|
|
694
|
+
* `buildContext`. Arg-conditional gates read this to vary their predicate
|
|
695
|
+
* per call.
|
|
696
|
+
*/
|
|
697
|
+
args: Record<string, unknown>; /** Tool name, for error attribution and gate labelling. */
|
|
698
|
+
handler: string;
|
|
699
|
+
};
|
|
700
|
+
/** Definition for a single gated tool. */
|
|
701
|
+
type GatedToolDef = {
|
|
702
|
+
/** Tool name as registered with the MCP server. */name: string; /** Human-readable tool description. */
|
|
703
|
+
description: string; /** The single scope that must be present on the caller's token. */
|
|
704
|
+
requiredScope: string; /** Zod field map or ZodObject — passed through to `server.registerTool`. */
|
|
705
|
+
inputSchema: unknown;
|
|
706
|
+
/**
|
|
707
|
+
* Per-tool gates merged after the global `gates`. Useful for arg-conditional
|
|
708
|
+
* authorization (e.g. different subscription tiers based on call args).
|
|
709
|
+
* Each gate receives the full {@link ToolCallContext} (identity + args).
|
|
710
|
+
* Throw to reject the call; return (or resolve) to continue.
|
|
711
|
+
*/
|
|
712
|
+
gates?: Array<(ctx: ToolCallContext) => void | Promise<void>>; /** The tool handler. Receives merged call args + `buildContext` output. */
|
|
713
|
+
method: (args: Record<string, unknown>) => Promise<unknown>;
|
|
714
|
+
};
|
|
715
|
+
/** Options for {@link createGatedToolRegistrar}. */
|
|
716
|
+
type CreateGatedToolRegistrarOptions = {
|
|
717
|
+
/** The MCP server instance to register tools on. */server: McpServer$1;
|
|
718
|
+
/**
|
|
719
|
+
* Called once per tool invocation to resolve the caller's identity.
|
|
720
|
+
* Defaults to `getIdentity()` from the request context.
|
|
721
|
+
*/
|
|
722
|
+
resolveIdentity?: () => ToolIdentity;
|
|
723
|
+
/**
|
|
724
|
+
* Global authorization gates run after the scope check, in order, before
|
|
725
|
+
* per-tool gates. Each receives the full {@link ToolCallContext} — both
|
|
726
|
+
* identity and the validated call args — so gate predicates may be
|
|
727
|
+
* conditional on either.
|
|
728
|
+
* Throw to reject the call; return (or resolve) to continue.
|
|
729
|
+
* Gates own their own error handling — `onError` covers the tool handler only.
|
|
730
|
+
*/
|
|
731
|
+
gates?: Array<(ctx: ToolCallContext) => void | Promise<void>>;
|
|
732
|
+
/**
|
|
733
|
+
* When `true` (default), checks `def.requiredScope` against `identity.scopes`
|
|
734
|
+
* and returns an `isError` result when the scope is absent. Set to `false`
|
|
735
|
+
* to skip the scope check (e.g. when all scopes are enforced by `gates`).
|
|
736
|
+
*/
|
|
737
|
+
enforceScope?: boolean;
|
|
738
|
+
/**
|
|
739
|
+
* Called when the tool **handler** throws. Use for error reporting/telemetry.
|
|
740
|
+
* The error is always rethrown after this hook completes.
|
|
741
|
+
* Note: scope-check failures and gate rejections do not trigger `onError`.
|
|
742
|
+
*/
|
|
743
|
+
onError?: (error: unknown, ctx: ToolCallContext) => void | Promise<void>;
|
|
744
|
+
/**
|
|
745
|
+
* Called once per invocation to produce extra key-value pairs that are
|
|
746
|
+
* merged into the handler args. Receives the full {@link ToolCallContext}
|
|
747
|
+
* so context can vary by identity or by call args.
|
|
748
|
+
*/
|
|
749
|
+
buildContext?: (ctx: ToolCallContext) => Record<string, unknown>;
|
|
750
|
+
/**
|
|
751
|
+
* Message returned as an `isError` result when the handler resolves to
|
|
752
|
+
* `null` or `undefined`. Defaults to `"Not found"`.
|
|
753
|
+
*/
|
|
754
|
+
notFoundMessage?: string;
|
|
755
|
+
};
|
|
756
|
+
declare const createGatedToolRegistrar: ({
|
|
757
|
+
server,
|
|
758
|
+
resolveIdentity,
|
|
759
|
+
gates,
|
|
760
|
+
enforceScope,
|
|
761
|
+
onError,
|
|
762
|
+
buildContext,
|
|
763
|
+
notFoundMessage
|
|
764
|
+
}: CreateGatedToolRegistrarOptions) => {
|
|
765
|
+
register: (def: GatedToolDef) => void;
|
|
766
|
+
};
|
|
767
|
+
//#endregion
|
|
668
768
|
//#region src/index.d.ts
|
|
669
769
|
type Context$1 = Application.Context;
|
|
670
770
|
/** Amazon Cognito user pool configuration for JWT verification. */
|
|
@@ -787,15 +887,6 @@ interface ApiCallOptions {
|
|
|
787
887
|
* ```
|
|
788
888
|
*/
|
|
789
889
|
declare const apiCall: (method: string, url: string, options?: ApiCallOptions) => Promise<unknown>;
|
|
790
|
-
/**
|
|
791
|
-
* Returns the verified JWT payload for the current MCP request.
|
|
792
|
-
* Only available inside a tool handler when `auth` is configured on the router.
|
|
793
|
-
*
|
|
794
|
-
* Accepts an optional type parameter to avoid casting at call sites:
|
|
795
|
-
* `getIdentity<{ sub: string; email: string }>()` returns `T | undefined`.
|
|
796
|
-
* Omitting the type parameter keeps the return type as `unknown | undefined`.
|
|
797
|
-
*/
|
|
798
|
-
declare const getIdentity: <T = unknown>() => T | undefined;
|
|
799
890
|
/**
|
|
800
891
|
* Asserts that the current request's token contains all required scopes.
|
|
801
892
|
* Throws if any scope is missing — the MCP SDK catches this and returns a
|
|
@@ -1025,4 +1116,4 @@ interface RegisterToolFromSchemaParams {
|
|
|
1025
1116
|
*/
|
|
1026
1117
|
declare const registerToolFromSchema: (server: McpServer$1, params: RegisterToolFromSchemaParams) => void;
|
|
1027
1118
|
//#endregion
|
|
1028
|
-
export { ApiCallOptions, CognitoUserPoolConfig, JsonObjectSchema, McpAuthOptions, McpRouterOptions, McpServer, RegisterToolFromSchemaParams, apiCall, checkScopes, createMcpRouter, getIdentity, registerToolFromSchema, z };
|
|
1119
|
+
export { ApiCallOptions, CognitoUserPoolConfig, type CreateGatedToolRegistrarOptions, type GatedToolDef, JsonObjectSchema, McpAuthOptions, McpRouterOptions, McpServer, RegisterToolFromSchemaParams, type ToolCallContext, type ToolIdentity, apiCall, checkScopes, createGatedToolRegistrar, createMcpRouter, getIdentity, registerToolFromSchema, z };
|
package/dist/index.d.mts
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
/// <reference types="node" />
|
|
3
3
|
import { Router } from "@ttoss/http-server";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
6
|
import { McpServer, McpServer as McpServer$1 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
7
|
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
7
8
|
import accepts from "accepts";
|
|
8
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
9
|
+
import { AsyncLocalStorage as AsyncLocalStorage$1 } from "async_hooks";
|
|
9
10
|
import Cookies from "cookies";
|
|
10
11
|
import { EventEmitter } from "events";
|
|
11
12
|
import { IncomingHttpHeaders, IncomingMessage, OutgoingHttpHeaders, Server, ServerResponse } from "http";
|
|
@@ -403,7 +404,7 @@ declare class Application<StateT = Application.DefaultState, ContextT = Applicat
|
|
|
403
404
|
response: Application.BaseResponse;
|
|
404
405
|
silent: boolean;
|
|
405
406
|
keys: Keygrip | string[];
|
|
406
|
-
ctxStorage: AsyncLocalStorage<ContextT> | undefined;
|
|
407
|
+
ctxStorage: AsyncLocalStorage$1<ContextT> | undefined;
|
|
407
408
|
/**
|
|
408
409
|
* @param {object} [options] Application options
|
|
409
410
|
* @param {string} [options.env='development'] Environment
|
|
@@ -421,7 +422,7 @@ declare class Application<StateT = Application.DefaultState, ContextT = Applicat
|
|
|
421
422
|
subdomainOffset?: number | undefined;
|
|
422
423
|
proxyIpHeader?: string | undefined;
|
|
423
424
|
maxIpsCount?: number | undefined;
|
|
424
|
-
asyncLocalStorage?: boolean | AsyncLocalStorage<ContextT> | undefined;
|
|
425
|
+
asyncLocalStorage?: boolean | AsyncLocalStorage$1<ContextT> | undefined;
|
|
425
426
|
});
|
|
426
427
|
/**
|
|
427
428
|
* Shorthand for:
|
|
@@ -665,6 +666,106 @@ declare namespace Application {
|
|
|
665
666
|
const HttpError: typeof HttpErrors.HttpError;
|
|
666
667
|
}
|
|
667
668
|
//#endregion
|
|
669
|
+
//#region src/context.d.ts
|
|
670
|
+
/**
|
|
671
|
+
* Returns the verified JWT payload for the current MCP request.
|
|
672
|
+
* Only available inside a tool handler when `auth` is configured on the router.
|
|
673
|
+
*
|
|
674
|
+
* Accepts an optional type parameter to avoid casting at call sites:
|
|
675
|
+
* `getIdentity<{ sub: string; email: string }>()` returns `T | undefined`.
|
|
676
|
+
* Omitting the type parameter keeps the return type as `unknown | undefined`.
|
|
677
|
+
*/
|
|
678
|
+
declare const getIdentity: <T = unknown>() => T | undefined;
|
|
679
|
+
//#endregion
|
|
680
|
+
//#region src/createGatedToolRegistrar.d.ts
|
|
681
|
+
/** Resolved identity for a gated tool call. */
|
|
682
|
+
type ToolIdentity = {
|
|
683
|
+
userId: string;
|
|
684
|
+
scopes?: string[];
|
|
685
|
+
};
|
|
686
|
+
/**
|
|
687
|
+
* Full context passed to gates, `buildContext`, and `onError` on every tool
|
|
688
|
+
* invocation. Having all three fields in one object means gate callbacks can
|
|
689
|
+
* be both identity-aware and args-aware without multiple parameters.
|
|
690
|
+
*/
|
|
691
|
+
type ToolCallContext = {
|
|
692
|
+
/** The resolved caller identity. */identity: ToolIdentity;
|
|
693
|
+
/**
|
|
694
|
+
* The validated tool input (post SDK parse). Present for gates and
|
|
695
|
+
* `buildContext`. Arg-conditional gates read this to vary their predicate
|
|
696
|
+
* per call.
|
|
697
|
+
*/
|
|
698
|
+
args: Record<string, unknown>; /** Tool name, for error attribution and gate labelling. */
|
|
699
|
+
handler: string;
|
|
700
|
+
};
|
|
701
|
+
/** Definition for a single gated tool. */
|
|
702
|
+
type GatedToolDef = {
|
|
703
|
+
/** Tool name as registered with the MCP server. */name: string; /** Human-readable tool description. */
|
|
704
|
+
description: string; /** The single scope that must be present on the caller's token. */
|
|
705
|
+
requiredScope: string; /** Zod field map or ZodObject — passed through to `server.registerTool`. */
|
|
706
|
+
inputSchema: unknown;
|
|
707
|
+
/**
|
|
708
|
+
* Per-tool gates merged after the global `gates`. Useful for arg-conditional
|
|
709
|
+
* authorization (e.g. different subscription tiers based on call args).
|
|
710
|
+
* Each gate receives the full {@link ToolCallContext} (identity + args).
|
|
711
|
+
* Throw to reject the call; return (or resolve) to continue.
|
|
712
|
+
*/
|
|
713
|
+
gates?: Array<(ctx: ToolCallContext) => void | Promise<void>>; /** The tool handler. Receives merged call args + `buildContext` output. */
|
|
714
|
+
method: (args: Record<string, unknown>) => Promise<unknown>;
|
|
715
|
+
};
|
|
716
|
+
/** Options for {@link createGatedToolRegistrar}. */
|
|
717
|
+
type CreateGatedToolRegistrarOptions = {
|
|
718
|
+
/** The MCP server instance to register tools on. */server: McpServer$1;
|
|
719
|
+
/**
|
|
720
|
+
* Called once per tool invocation to resolve the caller's identity.
|
|
721
|
+
* Defaults to `getIdentity()` from the request context.
|
|
722
|
+
*/
|
|
723
|
+
resolveIdentity?: () => ToolIdentity;
|
|
724
|
+
/**
|
|
725
|
+
* Global authorization gates run after the scope check, in order, before
|
|
726
|
+
* per-tool gates. Each receives the full {@link ToolCallContext} — both
|
|
727
|
+
* identity and the validated call args — so gate predicates may be
|
|
728
|
+
* conditional on either.
|
|
729
|
+
* Throw to reject the call; return (or resolve) to continue.
|
|
730
|
+
* Gates own their own error handling — `onError` covers the tool handler only.
|
|
731
|
+
*/
|
|
732
|
+
gates?: Array<(ctx: ToolCallContext) => void | Promise<void>>;
|
|
733
|
+
/**
|
|
734
|
+
* When `true` (default), checks `def.requiredScope` against `identity.scopes`
|
|
735
|
+
* and returns an `isError` result when the scope is absent. Set to `false`
|
|
736
|
+
* to skip the scope check (e.g. when all scopes are enforced by `gates`).
|
|
737
|
+
*/
|
|
738
|
+
enforceScope?: boolean;
|
|
739
|
+
/**
|
|
740
|
+
* Called when the tool **handler** throws. Use for error reporting/telemetry.
|
|
741
|
+
* The error is always rethrown after this hook completes.
|
|
742
|
+
* Note: scope-check failures and gate rejections do not trigger `onError`.
|
|
743
|
+
*/
|
|
744
|
+
onError?: (error: unknown, ctx: ToolCallContext) => void | Promise<void>;
|
|
745
|
+
/**
|
|
746
|
+
* Called once per invocation to produce extra key-value pairs that are
|
|
747
|
+
* merged into the handler args. Receives the full {@link ToolCallContext}
|
|
748
|
+
* so context can vary by identity or by call args.
|
|
749
|
+
*/
|
|
750
|
+
buildContext?: (ctx: ToolCallContext) => Record<string, unknown>;
|
|
751
|
+
/**
|
|
752
|
+
* Message returned as an `isError` result when the handler resolves to
|
|
753
|
+
* `null` or `undefined`. Defaults to `"Not found"`.
|
|
754
|
+
*/
|
|
755
|
+
notFoundMessage?: string;
|
|
756
|
+
};
|
|
757
|
+
declare const createGatedToolRegistrar: ({
|
|
758
|
+
server,
|
|
759
|
+
resolveIdentity,
|
|
760
|
+
gates,
|
|
761
|
+
enforceScope,
|
|
762
|
+
onError,
|
|
763
|
+
buildContext,
|
|
764
|
+
notFoundMessage
|
|
765
|
+
}: CreateGatedToolRegistrarOptions) => {
|
|
766
|
+
register: (def: GatedToolDef) => void;
|
|
767
|
+
};
|
|
768
|
+
//#endregion
|
|
668
769
|
//#region src/index.d.ts
|
|
669
770
|
type Context$1 = Application.Context;
|
|
670
771
|
/** Amazon Cognito user pool configuration for JWT verification. */
|
|
@@ -787,15 +888,6 @@ interface ApiCallOptions {
|
|
|
787
888
|
* ```
|
|
788
889
|
*/
|
|
789
890
|
declare const apiCall: (method: string, url: string, options?: ApiCallOptions) => Promise<unknown>;
|
|
790
|
-
/**
|
|
791
|
-
* Returns the verified JWT payload for the current MCP request.
|
|
792
|
-
* Only available inside a tool handler when `auth` is configured on the router.
|
|
793
|
-
*
|
|
794
|
-
* Accepts an optional type parameter to avoid casting at call sites:
|
|
795
|
-
* `getIdentity<{ sub: string; email: string }>()` returns `T | undefined`.
|
|
796
|
-
* Omitting the type parameter keeps the return type as `unknown | undefined`.
|
|
797
|
-
*/
|
|
798
|
-
declare const getIdentity: <T = unknown>() => T | undefined;
|
|
799
891
|
/**
|
|
800
892
|
* Asserts that the current request's token contains all required scopes.
|
|
801
893
|
* Throws if any scope is missing — the MCP SDK catches this and returns a
|
|
@@ -1025,4 +1117,4 @@ interface RegisterToolFromSchemaParams {
|
|
|
1025
1117
|
*/
|
|
1026
1118
|
declare const registerToolFromSchema: (server: McpServer$1, params: RegisterToolFromSchemaParams) => void;
|
|
1027
1119
|
//#endregion
|
|
1028
|
-
export { ApiCallOptions, CognitoUserPoolConfig, JsonObjectSchema, McpAuthOptions, McpRouterOptions, McpServer, RegisterToolFromSchemaParams, apiCall, checkScopes, createMcpRouter, getIdentity, registerToolFromSchema, z };
|
|
1120
|
+
export { ApiCallOptions, CognitoUserPoolConfig, type CreateGatedToolRegistrarOptions, type GatedToolDef, JsonObjectSchema, McpAuthOptions, McpRouterOptions, McpServer, RegisterToolFromSchemaParams, type ToolCallContext, type ToolIdentity, apiCall, checkScopes, createGatedToolRegistrar, createMcpRouter, getIdentity, registerToolFromSchema, z };
|
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,143 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
2
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
3
|
import { CognitoJwtVerifier } from "@ttoss/auth-core/amazon-cognito";
|
|
5
4
|
import { Router } from "@ttoss/http-server";
|
|
6
5
|
import { authMiddleware } from "@ttoss/http-server-auth";
|
|
7
6
|
import { z, z as z$1 } from "zod";
|
|
7
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
8
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
9
|
|
|
10
|
+
//#region src/context.ts
|
|
11
|
+
var requestContextStore = new AsyncLocalStorage();
|
|
12
|
+
/**
|
|
13
|
+
* Returns the verified JWT payload for the current MCP request.
|
|
14
|
+
* Only available inside a tool handler when `auth` is configured on the router.
|
|
15
|
+
*
|
|
16
|
+
* Accepts an optional type parameter to avoid casting at call sites:
|
|
17
|
+
* `getIdentity<{ sub: string; email: string }>()` returns `T | undefined`.
|
|
18
|
+
* Omitting the type parameter keeps the return type as `unknown | undefined`.
|
|
19
|
+
*/
|
|
20
|
+
var getIdentity = () => {
|
|
21
|
+
return requestContextStore.getStore()?.identity;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/createGatedToolRegistrar.ts
|
|
26
|
+
var toolError = message => {
|
|
27
|
+
return {
|
|
28
|
+
content: [{
|
|
29
|
+
type: "text",
|
|
30
|
+
text: JSON.stringify({
|
|
31
|
+
error: message
|
|
32
|
+
})
|
|
33
|
+
}],
|
|
34
|
+
isError: true
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Factory that returns a `register` helper for MCP tools that require
|
|
39
|
+
* authentication and a specific OAuth scope.
|
|
40
|
+
*
|
|
41
|
+
* Every registered tool automatically:
|
|
42
|
+
* 1. Resolves the caller identity (default: `getIdentity()`). Returns an
|
|
43
|
+
* `isError` result when the identity is absent (unauthenticated request).
|
|
44
|
+
* 2. When `enforceScope` is `true` (default), checks `requiredScope` — returns
|
|
45
|
+
* an `isError` result when the scope is absent, consistent with how MCP
|
|
46
|
+
* surfaces authorization errors. The package's `checkScopes` helper is not
|
|
47
|
+
* reused here because it throws rather than returning an `isError` result,
|
|
48
|
+
* and it reads identity from context itself.
|
|
49
|
+
* 3. Runs global `gates` then per-`register` `def.gates` in order; a throwing
|
|
50
|
+
* gate rejects the call. Every gate receives the full {@link ToolCallContext}
|
|
51
|
+
* (identity **and** the validated call args), enabling arg-conditional gates.
|
|
52
|
+
* Gates own their own error handling; `onError` covers the tool handler only.
|
|
53
|
+
* 4. Merges `buildContext` output into the handler args.
|
|
54
|
+
* 5. Wraps `null`/`undefined` results in a configurable "Not found" error result.
|
|
55
|
+
* 6. Calls `onError` on handler throw before rethrowing.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const { register } = createGatedToolRegistrar({
|
|
60
|
+
* server,
|
|
61
|
+
* resolveIdentity: () => {
|
|
62
|
+
* const jwt = getIdentity<{ sub: string; scopes: string[] }>();
|
|
63
|
+
* return { userId: jwt!.sub, scopes: jwt!.scopes };
|
|
64
|
+
* },
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* register({
|
|
68
|
+
* name: 'activate-campaign',
|
|
69
|
+
* description: 'Activate or deactivate a campaign.',
|
|
70
|
+
* requiredScope: 'campaigns:write',
|
|
71
|
+
* inputSchema: { isActive: z.boolean() },
|
|
72
|
+
* // arg-conditional gate: active vs. inactive have different restrictions
|
|
73
|
+
* gates: [
|
|
74
|
+
* ({ args }) =>
|
|
75
|
+
* args.isActive
|
|
76
|
+
* ? subscriptionGate(['mustNotExceedMaxActive', 'mustHaveBudget'])
|
|
77
|
+
* : subscriptionGate(['mustIncludeService']),
|
|
78
|
+
* ],
|
|
79
|
+
* method: async ({ userId, isActive }) => toggleCampaign(userId, isActive),
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
var checkScope = (identity, requiredScope) => {
|
|
84
|
+
if (!(Array.isArray(identity.scopes) ? identity.scopes : []).includes(requiredScope)) return toolError(`This tool requires the "${requiredScope}" scope.`);
|
|
85
|
+
return null;
|
|
86
|
+
};
|
|
87
|
+
var runGates = async (allGates, ctx) => {
|
|
88
|
+
for (const gate of allGates) await gate(ctx);
|
|
89
|
+
};
|
|
90
|
+
var createGatedToolRegistrar = ({
|
|
91
|
+
server,
|
|
92
|
+
resolveIdentity = getIdentity,
|
|
93
|
+
gates = [],
|
|
94
|
+
enforceScope = true,
|
|
95
|
+
onError,
|
|
96
|
+
buildContext,
|
|
97
|
+
notFoundMessage = "Not found"
|
|
98
|
+
}) => {
|
|
99
|
+
const register = def => {
|
|
100
|
+
server.registerTool(def.name, {
|
|
101
|
+
description: def.description,
|
|
102
|
+
inputSchema: def.inputSchema
|
|
103
|
+
}, async args => {
|
|
104
|
+
const identity = resolveIdentity();
|
|
105
|
+
if (!identity) return toolError("Unauthorized");
|
|
106
|
+
const ctx = {
|
|
107
|
+
identity,
|
|
108
|
+
args,
|
|
109
|
+
handler: def.name
|
|
110
|
+
};
|
|
111
|
+
if (enforceScope) {
|
|
112
|
+
const scopeError = checkScope(identity, def.requiredScope);
|
|
113
|
+
if (scopeError) return scopeError;
|
|
114
|
+
}
|
|
115
|
+
await runGates([...gates, ...(def.gates ?? [])], ctx);
|
|
116
|
+
const extra = buildContext ? buildContext(ctx) : {};
|
|
117
|
+
try {
|
|
118
|
+
const result = await def.method({
|
|
119
|
+
...args,
|
|
120
|
+
...extra
|
|
121
|
+
});
|
|
122
|
+
if (result == null) return toolError(notFoundMessage);
|
|
123
|
+
return {
|
|
124
|
+
content: [{
|
|
125
|
+
type: "text",
|
|
126
|
+
text: JSON.stringify(result)
|
|
127
|
+
}]
|
|
128
|
+
};
|
|
129
|
+
} catch (error) {
|
|
130
|
+
if (onError) await onError(error, ctx);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
};
|
|
135
|
+
return {
|
|
136
|
+
register
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
//#endregion
|
|
10
141
|
//#region src/index.ts
|
|
11
142
|
/** MCP lifecycle/discovery methods reachable before a client authenticates. */
|
|
12
143
|
var DEFAULT_PUBLIC_METHODS = ["initialize", "tools/list"];
|
|
@@ -24,7 +155,6 @@ var buildVerifyToken = auth => {
|
|
|
24
155
|
if (auth.verifyToken) return auth.verifyToken;
|
|
25
156
|
throw new Error("McpAuthOptions requires either cognitoUserPool or verifyToken");
|
|
26
157
|
};
|
|
27
|
-
var requestContextStore = new AsyncLocalStorage();
|
|
28
158
|
/**
|
|
29
159
|
* Generic HTTP helper for use inside MCP tool handlers.
|
|
30
160
|
*
|
|
@@ -112,17 +242,6 @@ var apiCall = async (method, url, options) => {
|
|
|
112
242
|
return response.text();
|
|
113
243
|
};
|
|
114
244
|
/**
|
|
115
|
-
* Returns the verified JWT payload for the current MCP request.
|
|
116
|
-
* Only available inside a tool handler when `auth` is configured on the router.
|
|
117
|
-
*
|
|
118
|
-
* Accepts an optional type parameter to avoid casting at call sites:
|
|
119
|
-
* `getIdentity<{ sub: string; email: string }>()` returns `T | undefined`.
|
|
120
|
-
* Omitting the type parameter keeps the return type as `unknown | undefined`.
|
|
121
|
-
*/
|
|
122
|
-
var getIdentity = () => {
|
|
123
|
-
return requestContextStore.getStore()?.identity;
|
|
124
|
-
};
|
|
125
|
-
/**
|
|
126
245
|
* Asserts that the current request's token contains all required scopes.
|
|
127
246
|
* Throws if any scope is missing — the MCP SDK catches this and returns a
|
|
128
247
|
* tool error to the client. Use inside tool handlers for per-tool authorization.
|
|
@@ -403,4 +522,4 @@ var registerToolFromSchema = (server, params) => {
|
|
|
403
522
|
};
|
|
404
523
|
|
|
405
524
|
//#endregion
|
|
406
|
-
export { McpServer, apiCall, checkScopes, createMcpRouter, getIdentity, registerToolFromSchema, z };
|
|
525
|
+
export { McpServer, apiCall, checkScopes, createGatedToolRegistrar, createMcpRouter, getIdentity, registerToolFromSchema, z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/http-server-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server integration for @ttoss/http-server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
37
37
|
"zod": "^4.4.3",
|
|
38
38
|
"@ttoss/http-server": "^0.7.1",
|
|
39
|
-
"@ttoss/
|
|
40
|
-
"@ttoss/auth
|
|
39
|
+
"@ttoss/auth-core": "^0.10.0",
|
|
40
|
+
"@ttoss/http-server-auth": "^0.3.7"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/koa": "^3.0.3",
|