@usethrottle/mcp 0.1.1 → 0.2.1
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 +9 -2
- package/dist/contract-index.json +1 -1
- package/dist/docs-index.json +1 -1
- package/dist/lib.cjs +3328 -0
- package/dist/lib.cjs.map +1 -0
- package/dist/lib.d.cts +219 -0
- package/dist/lib.d.ts +219 -0
- package/dist/lib.js +3294 -0
- package/dist/lib.js.map +1 -0
- package/dist/mcp.js +2053 -142
- package/dist/mcp.js.map +1 -1
- package/package.json +11 -1
package/dist/lib.d.cts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { ActionDefinition } from '@core/action-catalog';
|
|
3
|
+
|
|
4
|
+
interface AuthCtx {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
apiBaseUrl: string;
|
|
7
|
+
}
|
|
8
|
+
interface RequestOptions {
|
|
9
|
+
body?: unknown;
|
|
10
|
+
query?: Record<string, unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Sent as `Idempotency-Key`. Writes must pass one: an agent that retries is the
|
|
13
|
+
* normal case, and the API dedupes on
|
|
14
|
+
* `(workspace, application, environment, key, method, path)`.
|
|
15
|
+
*/
|
|
16
|
+
idempotencyKey?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Sent as `X-Throttle-Application-Id` on this one request only — see
|
|
19
|
+
* `PerCallOptions`.
|
|
20
|
+
*/
|
|
21
|
+
applicationId?: string;
|
|
22
|
+
}
|
|
23
|
+
interface PerCallOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Overrides which application a single `get`/`list` call reads from (the
|
|
26
|
+
* `oauth_token` auth branch validates this against the grant's own
|
|
27
|
+
* workspace membership; see `resolveOAuthApplication`). Scoped to this one
|
|
28
|
+
* request — never stored on the client instance — so concurrent calls with
|
|
29
|
+
* different application ids cannot bleed into each other.
|
|
30
|
+
*/
|
|
31
|
+
applicationId?: string;
|
|
32
|
+
}
|
|
33
|
+
interface Pagination {
|
|
34
|
+
cursor: string | null;
|
|
35
|
+
hasMore: boolean;
|
|
36
|
+
}
|
|
37
|
+
interface ListResult<T> {
|
|
38
|
+
data: T[];
|
|
39
|
+
pagination: Pagination | null;
|
|
40
|
+
}
|
|
41
|
+
type Fetcher = typeof fetch;
|
|
42
|
+
declare class ThrottleClient {
|
|
43
|
+
private auth;
|
|
44
|
+
private readonly fetchImpl;
|
|
45
|
+
constructor(auth: AuthCtx, fetchImpl?: Fetcher);
|
|
46
|
+
/**
|
|
47
|
+
* Swap the credential every later request is sent with. The hosted remote
|
|
48
|
+
* server builds one client per MCP session at `initialize`, but an OAuth
|
|
49
|
+
* access token lives one hour and the MCP client refreshes it underneath
|
|
50
|
+
* the session — each request then arrives with a newer bearer than the one
|
|
51
|
+
* the session was opened with. Without this, the session keeps calling the
|
|
52
|
+
* REST API with the token it was born with and every tool fails with a 401
|
|
53
|
+
* the moment that first token expires, even though the caller is still
|
|
54
|
+
* perfectly authenticated.
|
|
55
|
+
*/
|
|
56
|
+
setApiKey(apiKey: string): void;
|
|
57
|
+
private requestJson;
|
|
58
|
+
/** Unwraps the `{ data }` envelope. Key presence, not `??` — `{data: null}` unwraps to null. */
|
|
59
|
+
get<T>(path: string, query?: Record<string, unknown>, options?: PerCallOptions): Promise<T>;
|
|
60
|
+
list<T>(path: string, query?: Record<string, unknown>, options?: PerCallOptions): Promise<ListResult<T>>;
|
|
61
|
+
post<T>(path: string, options?: RequestOptions): Promise<T>;
|
|
62
|
+
patch<T>(path: string, options?: RequestOptions): Promise<T>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* `describe_endpoint` and `validate_payload`, answered from the OpenAPI contract
|
|
67
|
+
* bundled at build time. No network, no API quota.
|
|
68
|
+
*
|
|
69
|
+
* Why this exists: Throttle's public API is strict camelCase and rejects the
|
|
70
|
+
* retired snake_case aliases — and those aliases are exactly what a model writing
|
|
71
|
+
* commerce code will guess, because that is what the rest of the internet's
|
|
72
|
+
* examples look like. Naming the replacement turns a 400-debug loop into one call.
|
|
73
|
+
*/
|
|
74
|
+
interface ContractField {
|
|
75
|
+
name: string;
|
|
76
|
+
type?: string;
|
|
77
|
+
required: boolean;
|
|
78
|
+
description?: string;
|
|
79
|
+
enum?: string[];
|
|
80
|
+
}
|
|
81
|
+
interface ContractOperation {
|
|
82
|
+
method: string;
|
|
83
|
+
/** OpenAPI-style path, e.g. `/api/v1/customers/{customerId}/addresses/{id}`. */
|
|
84
|
+
path: string;
|
|
85
|
+
summary?: string;
|
|
86
|
+
description?: string;
|
|
87
|
+
pathParams: string[];
|
|
88
|
+
queryParams: ContractField[];
|
|
89
|
+
bodyFields: ContractField[] | null;
|
|
90
|
+
}
|
|
91
|
+
interface ContractIndex {
|
|
92
|
+
generatedAt: string;
|
|
93
|
+
operations: ContractOperation[];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* `search_docs`, answered from an index of the docs pages in `apps/web`,
|
|
98
|
+
* bundled at build time.
|
|
99
|
+
*
|
|
100
|
+
* Scoring mirrors the CLI's proven approach: title hits beat heading hits, which
|
|
101
|
+
* beat body hits, and an exact phrase beats scattered terms. Deliberately simple —
|
|
102
|
+
* the agent gets a title, a canonical docs.usethrottle.dev URL and an excerpt, then
|
|
103
|
+
* fetches the page itself if its client can.
|
|
104
|
+
*/
|
|
105
|
+
interface DocsEntry {
|
|
106
|
+
title: string;
|
|
107
|
+
route: string;
|
|
108
|
+
headings: string[];
|
|
109
|
+
text: string;
|
|
110
|
+
}
|
|
111
|
+
interface DocsIndex {
|
|
112
|
+
generatedAt: string;
|
|
113
|
+
entries: DocsEntry[];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
interface Identity {
|
|
117
|
+
type: string;
|
|
118
|
+
scopes: string[];
|
|
119
|
+
workspace: {
|
|
120
|
+
id: string;
|
|
121
|
+
name: string | null;
|
|
122
|
+
slug: string | null;
|
|
123
|
+
} | null;
|
|
124
|
+
application: {
|
|
125
|
+
id: string;
|
|
126
|
+
name: string | null;
|
|
127
|
+
slug: string | null;
|
|
128
|
+
} | null;
|
|
129
|
+
environment: {
|
|
130
|
+
id: string;
|
|
131
|
+
slug: string;
|
|
132
|
+
kind: string;
|
|
133
|
+
providerEnvironment: 'sandbox' | 'production';
|
|
134
|
+
};
|
|
135
|
+
apiKey: {
|
|
136
|
+
id: string;
|
|
137
|
+
name: string;
|
|
138
|
+
keyPrefix: string;
|
|
139
|
+
} | null;
|
|
140
|
+
}
|
|
141
|
+
interface HandlerContext {
|
|
142
|
+
client: ThrottleClient;
|
|
143
|
+
identity: Identity;
|
|
144
|
+
contract: ContractIndex;
|
|
145
|
+
docs: DocsIndex;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
declare const VERSION: string;
|
|
149
|
+
interface RegistrationPolicy {
|
|
150
|
+
identity: Identity;
|
|
151
|
+
allowWrites: boolean;
|
|
152
|
+
allowLiveWrites: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Whether sandbox-only writes (`seed_test_data`) register without
|
|
155
|
+
* `allowWrites`. Defaults to true — the documented CLI behaviour, where
|
|
156
|
+
* seeding a non-production environment needs no flag. The hosted remote
|
|
157
|
+
* server passes false: it is published as strictly read-only, and a
|
|
158
|
+
* directory reviewer connecting with a non-production credential must not
|
|
159
|
+
* find a tool that creates customers and orders.
|
|
160
|
+
*/
|
|
161
|
+
allowSandboxWrites?: boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Whether `credentialScoped` actions (`api_get`) register. Defaults to true
|
|
164
|
+
* for the CLI. The hosted server passes false: on an OAuth surface every
|
|
165
|
+
* tool declares the scopes it asks consent for, and a tool that reads any
|
|
166
|
+
* path cannot.
|
|
167
|
+
*/
|
|
168
|
+
allowCredentialScoped?: boolean;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Which tools this session gets. Pure and exported so the policy is testable
|
|
172
|
+
* without standing up a transport.
|
|
173
|
+
*
|
|
174
|
+
* Four independent gates, in order of how expensive it is to get them wrong:
|
|
175
|
+
*
|
|
176
|
+
* 1. **Implemented.** `0.1.0` ships the read/sandbox half; the catalog describes
|
|
177
|
+
* the money writes before this package implements them.
|
|
178
|
+
* 2. **Scope.** Delegated to the catalog's `canRunAction`, which uses the API's own
|
|
179
|
+
* `hasScope`. A tool the credential cannot execute is not registered at all,
|
|
180
|
+
* rather than failing at call time — the model never sees an affordance it
|
|
181
|
+
* cannot use.
|
|
182
|
+
* 3. **Intent.** Holding a write scope means the credential *may* write; it does
|
|
183
|
+
* not mean the operator intended this session to. That is `--allow-writes`.
|
|
184
|
+
* 4. **Blast radius.** Against a production credential, writes need
|
|
185
|
+
* `--allow-live-writes` on top. Sandbox-only actions invert the rule: they are
|
|
186
|
+
* free in a non-production environment and forbidden in production regardless
|
|
187
|
+
* of flags.
|
|
188
|
+
*/
|
|
189
|
+
declare function registerableActions(policy: RegistrationPolicy): ActionDefinition[];
|
|
190
|
+
/**
|
|
191
|
+
* The server's `instructions`, which most clients put in front of the model before
|
|
192
|
+
* it picks a tool. Leads with the environment because the single most damaging
|
|
193
|
+
* mistake an agent can make here is not knowing whether it is looking at live data.
|
|
194
|
+
*/
|
|
195
|
+
declare function buildInstructions(identity: Identity, actions: ActionDefinition[], policy: {
|
|
196
|
+
allowWrites: boolean;
|
|
197
|
+
allowLiveWrites: boolean;
|
|
198
|
+
}): string;
|
|
199
|
+
interface CreateServerOptions extends RegistrationPolicy {
|
|
200
|
+
client: ThrottleClient;
|
|
201
|
+
contract: ContractIndex;
|
|
202
|
+
docs: DocsIndex;
|
|
203
|
+
/**
|
|
204
|
+
* The `WWW-Authenticate` challenge value the hosting transport advertises
|
|
205
|
+
* (RFC 9728 `Bearer resource_metadata="..."`). When set, a tool call that
|
|
206
|
+
* fails because the REST API rejected the credential (HTTP 401 — an expired
|
|
207
|
+
* or revoked OAuth access token) carries it back as
|
|
208
|
+
* `_meta["mcp/www_authenticate"]`, which is what ChatGPT and other remote
|
|
209
|
+
* clients key their re-authorization UI on. The stdio CLI leaves it unset:
|
|
210
|
+
* its operator-provided key has no re-auth flow to trigger.
|
|
211
|
+
*/
|
|
212
|
+
authChallenge?: string;
|
|
213
|
+
}
|
|
214
|
+
declare function createServer(options: CreateServerOptions): McpServer;
|
|
215
|
+
|
|
216
|
+
declare function loadDocsIndex(): DocsIndex;
|
|
217
|
+
declare function loadContractIndex(): ContractIndex;
|
|
218
|
+
|
|
219
|
+
export { type ContractIndex, type CreateServerOptions, type DocsIndex, type HandlerContext, type Identity, type RegistrationPolicy, ThrottleClient, VERSION, buildInstructions, createServer, loadContractIndex, loadDocsIndex, registerableActions };
|
package/dist/lib.d.ts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { ActionDefinition } from '@core/action-catalog';
|
|
3
|
+
|
|
4
|
+
interface AuthCtx {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
apiBaseUrl: string;
|
|
7
|
+
}
|
|
8
|
+
interface RequestOptions {
|
|
9
|
+
body?: unknown;
|
|
10
|
+
query?: Record<string, unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Sent as `Idempotency-Key`. Writes must pass one: an agent that retries is the
|
|
13
|
+
* normal case, and the API dedupes on
|
|
14
|
+
* `(workspace, application, environment, key, method, path)`.
|
|
15
|
+
*/
|
|
16
|
+
idempotencyKey?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Sent as `X-Throttle-Application-Id` on this one request only — see
|
|
19
|
+
* `PerCallOptions`.
|
|
20
|
+
*/
|
|
21
|
+
applicationId?: string;
|
|
22
|
+
}
|
|
23
|
+
interface PerCallOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Overrides which application a single `get`/`list` call reads from (the
|
|
26
|
+
* `oauth_token` auth branch validates this against the grant's own
|
|
27
|
+
* workspace membership; see `resolveOAuthApplication`). Scoped to this one
|
|
28
|
+
* request — never stored on the client instance — so concurrent calls with
|
|
29
|
+
* different application ids cannot bleed into each other.
|
|
30
|
+
*/
|
|
31
|
+
applicationId?: string;
|
|
32
|
+
}
|
|
33
|
+
interface Pagination {
|
|
34
|
+
cursor: string | null;
|
|
35
|
+
hasMore: boolean;
|
|
36
|
+
}
|
|
37
|
+
interface ListResult<T> {
|
|
38
|
+
data: T[];
|
|
39
|
+
pagination: Pagination | null;
|
|
40
|
+
}
|
|
41
|
+
type Fetcher = typeof fetch;
|
|
42
|
+
declare class ThrottleClient {
|
|
43
|
+
private auth;
|
|
44
|
+
private readonly fetchImpl;
|
|
45
|
+
constructor(auth: AuthCtx, fetchImpl?: Fetcher);
|
|
46
|
+
/**
|
|
47
|
+
* Swap the credential every later request is sent with. The hosted remote
|
|
48
|
+
* server builds one client per MCP session at `initialize`, but an OAuth
|
|
49
|
+
* access token lives one hour and the MCP client refreshes it underneath
|
|
50
|
+
* the session — each request then arrives with a newer bearer than the one
|
|
51
|
+
* the session was opened with. Without this, the session keeps calling the
|
|
52
|
+
* REST API with the token it was born with and every tool fails with a 401
|
|
53
|
+
* the moment that first token expires, even though the caller is still
|
|
54
|
+
* perfectly authenticated.
|
|
55
|
+
*/
|
|
56
|
+
setApiKey(apiKey: string): void;
|
|
57
|
+
private requestJson;
|
|
58
|
+
/** Unwraps the `{ data }` envelope. Key presence, not `??` — `{data: null}` unwraps to null. */
|
|
59
|
+
get<T>(path: string, query?: Record<string, unknown>, options?: PerCallOptions): Promise<T>;
|
|
60
|
+
list<T>(path: string, query?: Record<string, unknown>, options?: PerCallOptions): Promise<ListResult<T>>;
|
|
61
|
+
post<T>(path: string, options?: RequestOptions): Promise<T>;
|
|
62
|
+
patch<T>(path: string, options?: RequestOptions): Promise<T>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* `describe_endpoint` and `validate_payload`, answered from the OpenAPI contract
|
|
67
|
+
* bundled at build time. No network, no API quota.
|
|
68
|
+
*
|
|
69
|
+
* Why this exists: Throttle's public API is strict camelCase and rejects the
|
|
70
|
+
* retired snake_case aliases — and those aliases are exactly what a model writing
|
|
71
|
+
* commerce code will guess, because that is what the rest of the internet's
|
|
72
|
+
* examples look like. Naming the replacement turns a 400-debug loop into one call.
|
|
73
|
+
*/
|
|
74
|
+
interface ContractField {
|
|
75
|
+
name: string;
|
|
76
|
+
type?: string;
|
|
77
|
+
required: boolean;
|
|
78
|
+
description?: string;
|
|
79
|
+
enum?: string[];
|
|
80
|
+
}
|
|
81
|
+
interface ContractOperation {
|
|
82
|
+
method: string;
|
|
83
|
+
/** OpenAPI-style path, e.g. `/api/v1/customers/{customerId}/addresses/{id}`. */
|
|
84
|
+
path: string;
|
|
85
|
+
summary?: string;
|
|
86
|
+
description?: string;
|
|
87
|
+
pathParams: string[];
|
|
88
|
+
queryParams: ContractField[];
|
|
89
|
+
bodyFields: ContractField[] | null;
|
|
90
|
+
}
|
|
91
|
+
interface ContractIndex {
|
|
92
|
+
generatedAt: string;
|
|
93
|
+
operations: ContractOperation[];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* `search_docs`, answered from an index of the docs pages in `apps/web`,
|
|
98
|
+
* bundled at build time.
|
|
99
|
+
*
|
|
100
|
+
* Scoring mirrors the CLI's proven approach: title hits beat heading hits, which
|
|
101
|
+
* beat body hits, and an exact phrase beats scattered terms. Deliberately simple —
|
|
102
|
+
* the agent gets a title, a canonical docs.usethrottle.dev URL and an excerpt, then
|
|
103
|
+
* fetches the page itself if its client can.
|
|
104
|
+
*/
|
|
105
|
+
interface DocsEntry {
|
|
106
|
+
title: string;
|
|
107
|
+
route: string;
|
|
108
|
+
headings: string[];
|
|
109
|
+
text: string;
|
|
110
|
+
}
|
|
111
|
+
interface DocsIndex {
|
|
112
|
+
generatedAt: string;
|
|
113
|
+
entries: DocsEntry[];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
interface Identity {
|
|
117
|
+
type: string;
|
|
118
|
+
scopes: string[];
|
|
119
|
+
workspace: {
|
|
120
|
+
id: string;
|
|
121
|
+
name: string | null;
|
|
122
|
+
slug: string | null;
|
|
123
|
+
} | null;
|
|
124
|
+
application: {
|
|
125
|
+
id: string;
|
|
126
|
+
name: string | null;
|
|
127
|
+
slug: string | null;
|
|
128
|
+
} | null;
|
|
129
|
+
environment: {
|
|
130
|
+
id: string;
|
|
131
|
+
slug: string;
|
|
132
|
+
kind: string;
|
|
133
|
+
providerEnvironment: 'sandbox' | 'production';
|
|
134
|
+
};
|
|
135
|
+
apiKey: {
|
|
136
|
+
id: string;
|
|
137
|
+
name: string;
|
|
138
|
+
keyPrefix: string;
|
|
139
|
+
} | null;
|
|
140
|
+
}
|
|
141
|
+
interface HandlerContext {
|
|
142
|
+
client: ThrottleClient;
|
|
143
|
+
identity: Identity;
|
|
144
|
+
contract: ContractIndex;
|
|
145
|
+
docs: DocsIndex;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
declare const VERSION: string;
|
|
149
|
+
interface RegistrationPolicy {
|
|
150
|
+
identity: Identity;
|
|
151
|
+
allowWrites: boolean;
|
|
152
|
+
allowLiveWrites: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Whether sandbox-only writes (`seed_test_data`) register without
|
|
155
|
+
* `allowWrites`. Defaults to true — the documented CLI behaviour, where
|
|
156
|
+
* seeding a non-production environment needs no flag. The hosted remote
|
|
157
|
+
* server passes false: it is published as strictly read-only, and a
|
|
158
|
+
* directory reviewer connecting with a non-production credential must not
|
|
159
|
+
* find a tool that creates customers and orders.
|
|
160
|
+
*/
|
|
161
|
+
allowSandboxWrites?: boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Whether `credentialScoped` actions (`api_get`) register. Defaults to true
|
|
164
|
+
* for the CLI. The hosted server passes false: on an OAuth surface every
|
|
165
|
+
* tool declares the scopes it asks consent for, and a tool that reads any
|
|
166
|
+
* path cannot.
|
|
167
|
+
*/
|
|
168
|
+
allowCredentialScoped?: boolean;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Which tools this session gets. Pure and exported so the policy is testable
|
|
172
|
+
* without standing up a transport.
|
|
173
|
+
*
|
|
174
|
+
* Four independent gates, in order of how expensive it is to get them wrong:
|
|
175
|
+
*
|
|
176
|
+
* 1. **Implemented.** `0.1.0` ships the read/sandbox half; the catalog describes
|
|
177
|
+
* the money writes before this package implements them.
|
|
178
|
+
* 2. **Scope.** Delegated to the catalog's `canRunAction`, which uses the API's own
|
|
179
|
+
* `hasScope`. A tool the credential cannot execute is not registered at all,
|
|
180
|
+
* rather than failing at call time — the model never sees an affordance it
|
|
181
|
+
* cannot use.
|
|
182
|
+
* 3. **Intent.** Holding a write scope means the credential *may* write; it does
|
|
183
|
+
* not mean the operator intended this session to. That is `--allow-writes`.
|
|
184
|
+
* 4. **Blast radius.** Against a production credential, writes need
|
|
185
|
+
* `--allow-live-writes` on top. Sandbox-only actions invert the rule: they are
|
|
186
|
+
* free in a non-production environment and forbidden in production regardless
|
|
187
|
+
* of flags.
|
|
188
|
+
*/
|
|
189
|
+
declare function registerableActions(policy: RegistrationPolicy): ActionDefinition[];
|
|
190
|
+
/**
|
|
191
|
+
* The server's `instructions`, which most clients put in front of the model before
|
|
192
|
+
* it picks a tool. Leads with the environment because the single most damaging
|
|
193
|
+
* mistake an agent can make here is not knowing whether it is looking at live data.
|
|
194
|
+
*/
|
|
195
|
+
declare function buildInstructions(identity: Identity, actions: ActionDefinition[], policy: {
|
|
196
|
+
allowWrites: boolean;
|
|
197
|
+
allowLiveWrites: boolean;
|
|
198
|
+
}): string;
|
|
199
|
+
interface CreateServerOptions extends RegistrationPolicy {
|
|
200
|
+
client: ThrottleClient;
|
|
201
|
+
contract: ContractIndex;
|
|
202
|
+
docs: DocsIndex;
|
|
203
|
+
/**
|
|
204
|
+
* The `WWW-Authenticate` challenge value the hosting transport advertises
|
|
205
|
+
* (RFC 9728 `Bearer resource_metadata="..."`). When set, a tool call that
|
|
206
|
+
* fails because the REST API rejected the credential (HTTP 401 — an expired
|
|
207
|
+
* or revoked OAuth access token) carries it back as
|
|
208
|
+
* `_meta["mcp/www_authenticate"]`, which is what ChatGPT and other remote
|
|
209
|
+
* clients key their re-authorization UI on. The stdio CLI leaves it unset:
|
|
210
|
+
* its operator-provided key has no re-auth flow to trigger.
|
|
211
|
+
*/
|
|
212
|
+
authChallenge?: string;
|
|
213
|
+
}
|
|
214
|
+
declare function createServer(options: CreateServerOptions): McpServer;
|
|
215
|
+
|
|
216
|
+
declare function loadDocsIndex(): DocsIndex;
|
|
217
|
+
declare function loadContractIndex(): ContractIndex;
|
|
218
|
+
|
|
219
|
+
export { type ContractIndex, type CreateServerOptions, type DocsIndex, type HandlerContext, type Identity, type RegistrationPolicy, ThrottleClient, VERSION, buildInstructions, createServer, loadContractIndex, loadDocsIndex, registerableActions };
|