mcp-usage-control-mcp 1.0.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.
@@ -0,0 +1,178 @@
1
+ import type { ServerContext } from '@modelcontextprotocol/server';
2
+ import { type Principal, type UsageControl, type UsageLease, type UsageLeaseResumeState } from 'mcp-usage-control';
3
+ type MaybePromise<T> = T | Promise<T>;
4
+ export interface ProtectToolOptions<TArgs, TResult> {
5
+ control: UsageControl;
6
+ tool: string;
7
+ /**
8
+ * Set to true when the MCP tool has no input schema.
9
+ *
10
+ * The SDK's TypeScript callback type is `(ctx)` for no-input tools, while
11
+ * some server dispatch paths invoke the callback at runtime as `({}, ctx)`.
12
+ * An empty object is indistinguishable from valid args for an empty input
13
+ * schema, so this adapter requires an explicit mode instead of guessing.
14
+ */
15
+ noInput?: boolean;
16
+ principal(ctx: ServerContext): MaybePromise<Principal>;
17
+ operationId(args: TArgs, ctx: ServerContext): MaybePromise<string>;
18
+ /** Disable only when the application renews the lease itself. Defaults to true. */
19
+ leaseHeartbeat?: boolean;
20
+ /**
21
+ * Best-effort notification that automatic lease renewal became acknowledgement-ambiguous,
22
+ * or that a later renewal confirmed the lease again. The callback is advisory only: it
23
+ * never changes authoritative accounting state and callback failures are ignored.
24
+ */
25
+ onLeaseRenewalState?(event: LeaseRenewalStateEvent): MaybePromise<void>;
26
+ successUnits?(input: {
27
+ result: TResult;
28
+ args: TArgs;
29
+ ctx: ServerContext;
30
+ lease: UsageLease;
31
+ }): MaybePromise<number>;
32
+ toolErrorUnits?(input: {
33
+ result: TResult;
34
+ args: TArgs;
35
+ ctx: ServerContext;
36
+ lease: UsageLease;
37
+ }): MaybePromise<number>;
38
+ errorUnits?(input: {
39
+ error: unknown;
40
+ args: TArgs;
41
+ ctx: ServerContext;
42
+ lease: UsageLease;
43
+ }): MaybePromise<number>;
44
+ }
45
+ export type LeaseRenewalStateEvent = {
46
+ status: 'uncertain';
47
+ lease: UsageLease;
48
+ error: unknown;
49
+ } | {
50
+ status: 'confirmed';
51
+ lease: UsageLease;
52
+ };
53
+ export type NoInputProtectToolOptions<TResult> = ProtectToolOptions<undefined, TResult> & {
54
+ noInput: true;
55
+ };
56
+ export type InputProtectToolOptions<TArgs, TResult> = ProtectToolOptions<TArgs, TResult> & {
57
+ noInput?: false;
58
+ };
59
+ export type NoInputProtectedToolHandler<TResult> = (ctx: ServerContext) => Promise<TResult>;
60
+ export type InputProtectedToolHandler<TArgs, TResult> = (args: TArgs, ctx: ServerContext) => Promise<TResult>;
61
+ /** Decoded payload expected from the SDK requestState verification hook. */
62
+ export interface McpUsageRequestStatePayload {
63
+ mcpUsageControl: 1;
64
+ flowId: string;
65
+ }
66
+ /**
67
+ * Binding checked atomically before a suspended flow is consumed.
68
+ * The args hash prevents a retry from changing the original tool arguments.
69
+ */
70
+ export interface McpUsageFlowBinding {
71
+ principalId: string;
72
+ tenantId?: string;
73
+ tool: string;
74
+ argsHash: string;
75
+ }
76
+ /** Serializable trusted server-side state for one suspended MCP usage flow. */
77
+ export interface McpUsageFlowRecord {
78
+ flowId: string;
79
+ binding: McpUsageFlowBinding;
80
+ lease: UsageLeaseResumeState;
81
+ /** First handler entry is round 0; the first retry is round 1. */
82
+ round: number;
83
+ expiresAt: number;
84
+ /** Original handler-authored requestState, retained server-side rather than trusted from the client. */
85
+ applicationRequestState?: string;
86
+ }
87
+ /**
88
+ * Server-side suspended-flow storage.
89
+ *
90
+ * `consume()` MUST atomically compare `binding`, reject expired state using the
91
+ * store's authoritative time domain, and remove the flow only when it matches
92
+ * and remains valid. A mismatched or expired caller must receive undefined
93
+ * without consuming a legitimate live flow. A successfully returned record is
94
+ * authoritative proof that suspended-flow expiry passed; callers MUST NOT
95
+ * reinterpret that result using an unrelated application-host clock. This
96
+ * one-time consume prevents concurrent retry re-entry.
97
+ */
98
+ export interface McpUsageFlowStore {
99
+ suspend(record: McpUsageFlowRecord): MaybePromise<void>;
100
+ consume(flowId: string, binding: McpUsageFlowBinding): MaybePromise<McpUsageFlowRecord | undefined>;
101
+ }
102
+ /**
103
+ * Process-local flow store for tests and single-process servers.
104
+ *
105
+ * Instantiate it outside a `createMcpHandler` per-request factory. Distributed
106
+ * or horizontally scaled servers should provide a durable store with atomic
107
+ * compare-and-consume semantics instead.
108
+ */
109
+ export declare class MemoryMcpUsageFlowStore implements McpUsageFlowStore {
110
+ private readonly flows;
111
+ suspend(record: McpUsageFlowRecord): void;
112
+ consume(flowId: string, binding: McpUsageFlowBinding): McpUsageFlowRecord | undefined;
113
+ private pruneExpired;
114
+ }
115
+ export interface McpUsageRequestStateMinter {
116
+ /**
117
+ * Mint an integrity-protected requestState value for the client round-trip.
118
+ * Use the same codec whose `verify` hook is configured on the MCP server.
119
+ */
120
+ mint(payload: McpUsageRequestStatePayload, ctx: ServerContext): MaybePromise<string>;
121
+ }
122
+ export interface McpUsageFlowContext {
123
+ /** First handler entry is 0; each successful resume increments it by one. */
124
+ readonly round: number;
125
+ /** Stable logical operation ID from the first round. */
126
+ readonly operationId: string;
127
+ /**
128
+ * Handler-authored requestState captured from the prior input_required result.
129
+ * It came from trusted server-side flow storage; the wrapper-owned wire
130
+ * requestState is not exposed here.
131
+ */
132
+ readonly applicationRequestState?: string;
133
+ }
134
+ export interface ProtectMultiRoundToolOptions<TArgs, TResult> extends ProtectToolOptions<TArgs, TResult> {
135
+ flowStore: McpUsageFlowStore;
136
+ requestState: McpUsageRequestStateMinter;
137
+ /** Explicit human/input suspension lease duration. Required to avoid an accidental unbounded hold. */
138
+ suspendTtlMs: number;
139
+ /** Maximum number of resumed rounds. Defaults to 8. */
140
+ maxRounds?: number;
141
+ /** Test/custom ID generator. Defaults to a cryptographically random ID. */
142
+ flowId?: () => MaybePromise<string>;
143
+ }
144
+ export type NoInputProtectMultiRoundToolOptions<TResult> = ProtectMultiRoundToolOptions<undefined, TResult> & {
145
+ noInput: true;
146
+ };
147
+ export type InputProtectMultiRoundToolOptions<TArgs, TResult> = ProtectMultiRoundToolOptions<TArgs, TResult> & {
148
+ noInput?: false;
149
+ };
150
+ export declare class UsageSettlementError extends Error {
151
+ readonly settlementError: unknown;
152
+ readonly executionError?: unknown | undefined;
153
+ constructor(message: string, settlementError: unknown, executionError?: unknown | undefined);
154
+ }
155
+ export declare class UsageClassificationError extends Error {
156
+ readonly classificationError: unknown;
157
+ readonly executionError?: unknown | undefined;
158
+ constructor(message: string, classificationError: unknown, executionError?: unknown | undefined);
159
+ }
160
+ export declare class UnsupportedMcpUsageFlowError extends Error {
161
+ constructor(message: string);
162
+ }
163
+ export declare class McpUsageResumeError extends Error {
164
+ constructor(message: string);
165
+ }
166
+ export declare class McpUsageRoundsExceededError extends Error {
167
+ constructor(message: string);
168
+ }
169
+ /** No-input-schema overload. `noInput: true` is required. */
170
+ export declare function protectTool<TResult>(options: NoInputProtectToolOptions<TResult>, handler: (args: undefined, ctx: ServerContext) => MaybePromise<TResult>): NoInputProtectedToolHandler<TResult>;
171
+ /** Input-schema overload. `noInput` must be omitted or false. */
172
+ export declare function protectTool<TArgs, TResult>(options: InputProtectToolOptions<TArgs, TResult>, handler: (args: TArgs, ctx: ServerContext) => MaybePromise<TResult>): InputProtectedToolHandler<TArgs, TResult>;
173
+ /** No-input-schema multi-round overload. */
174
+ export declare function protectMultiRoundTool<TResult>(options: NoInputProtectMultiRoundToolOptions<TResult>, handler: (args: undefined, ctx: ServerContext, flow: McpUsageFlowContext) => MaybePromise<TResult>): NoInputProtectedToolHandler<TResult>;
175
+ /** Input-schema multi-round overload. */
176
+ export declare function protectMultiRoundTool<TArgs, TResult>(options: InputProtectMultiRoundToolOptions<TArgs, TResult>, handler: (args: TArgs, ctx: ServerContext, flow: McpUsageFlowContext) => MaybePromise<TResult>): InputProtectedToolHandler<TArgs, TResult>;
177
+ export {};
178
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}