@12-apps/mcp 3.1.0 → 3.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/ADOPTING.md +32 -0
- package/dist/chunk-7QVYU63E.js +7 -0
- package/dist/chunk-7QVYU63E.js.map +1 -0
- package/dist/chunk-FYEVBTDU.js +162 -0
- package/dist/chunk-FYEVBTDU.js.map +1 -0
- package/dist/chunk-HAZOPC6U.js +229 -0
- package/dist/chunk-HAZOPC6U.js.map +1 -0
- package/dist/chunk-UIILEGAC.js +1247 -0
- package/dist/chunk-UIILEGAC.js.map +1 -0
- package/dist/chunk-WJJNKKNS.js +63 -0
- package/dist/chunk-WJJNKKNS.js.map +1 -0
- package/dist/coverage-gate/index.d.ts +129 -0
- package/dist/coverage-gate/index.js +163 -0
- package/dist/coverage-gate/index.js.map +1 -0
- package/dist/create-api-mcp-oauth-CwVXKK-A.d.ts +647 -0
- package/dist/generate/index.d.ts +91 -0
- package/dist/generate/index.js +101 -0
- package/dist/generate/index.js.map +1 -0
- package/dist/generate-Dx3cK8th.d.ts +184 -0
- package/dist/guide-DV5MQbCg.d.ts +135 -0
- package/dist/hono/index.d.ts +28 -0
- package/dist/hono/index.js +25 -0
- package/dist/hono/index.js.map +1 -0
- package/dist/index.d.ts +382 -0
- package/dist/index.js +331 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth/index.d.ts +446 -0
- package/dist/oauth/index.js +279 -0
- package/dist/oauth/index.js.map +1 -0
- package/dist/react/index.d.ts +239 -0
- package/dist/react/index.js +1183 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +31 -10
- package/prisma/migrations/20260812150000_add_mcp_oauth_tables/migration.sql +6 -6
- package/src/index.ts +13 -0
- package/src/server/jsonrpc.ts +167 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { J as JsonSchema, G as GeneratedTool, D as DispatchConfig, a as DispatchResult, b as ToolAnnotations, R as RequestAuth, T as ToolManifest } from './generate-Dx3cK8th.js';
|
|
2
|
+
export { A as AuthResolver, c as GenerateOptions, O as OpenApiDocument, d as OpenApiOperation, e as OpenApiParameter, f as OpenApiRequestBody, g as OpenApiResponse, P as ParameterLocation, h as ToolParameter, i as generateTools } from './generate-Dx3cK8th.js';
|
|
3
|
+
export { A as AI_CAPABILITIES, a as AI_PERMISSION_MODEL, b as AiCapability, c as AiConnectPromptSpec, d as AiHostBrand, e as AiHostConfigureStage, f as AiHostGuide, g as AiHostLink, h as AiProvider, i as aiConnectPrompt, j as aiHostGuides, p as providerForHostId } from './guide-DV5MQbCg.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Raised when a JSON Schema cannot be turned into a flat, self-contained tool
|
|
7
|
+
* input — an unresolvable `$ref`, an unsupported pointer, or a recursive schema.
|
|
8
|
+
* The MCP tool surface is deliberately finite and flat (it is handed to an LLM
|
|
9
|
+
* and committed to the drift manifest), so recursion is rejected rather than
|
|
10
|
+
* silently truncated.
|
|
11
|
+
*/
|
|
12
|
+
declare class UnsupportedSchemaError extends Error {
|
|
13
|
+
constructor(message: string);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Inline every local `$ref` in a JSON Schema and drop the now-empty `$defs`/
|
|
17
|
+
* `definitions` containers, yielding a flat, self-contained schema. Diamond reuse
|
|
18
|
+
* (the same definition referenced by sibling branches) is fine; only a true cycle
|
|
19
|
+
* — a definition that references itself up the resolution stack — is rejected.
|
|
20
|
+
*
|
|
21
|
+
* A schema with no `$ref`/definitions is returned structurally unchanged, so
|
|
22
|
+
* inlining an already-flat spec is a no-op (the drift gate stays a stable diff).
|
|
23
|
+
*/
|
|
24
|
+
declare function inlineSchemaRefs(schema: JsonSchema): JsonSchema;
|
|
25
|
+
|
|
26
|
+
/** Raised when tool arguments cannot be routed onto the HTTP request. */
|
|
27
|
+
declare class DispatchInputError extends Error {
|
|
28
|
+
constructor(message: string);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Execute one generated tool by proxying to its HTTP endpoint, forwarding the
|
|
32
|
+
* caller's bearer verbatim. This function performs NO authorization — the
|
|
33
|
+
* endpoint does, exactly as it would for a first-party request. That is the whole
|
|
34
|
+
* point of the passthrough: the agent can do precisely what the user can.
|
|
35
|
+
*/
|
|
36
|
+
declare function dispatchTool(tool: GeneratedTool, args: Record<string, unknown>, config: DispatchConfig): Promise<DispatchResult>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The registry is the transport-agnostic seam between the generated tools and the
|
|
40
|
+
* MCP SDK. The consuming app owns the HTTP/JSON-RPC transport (mounting it at
|
|
41
|
+
* `/api/mcp`) and, per request, resolves {@link RequestAuth} and calls
|
|
42
|
+
* {@link ToolRegistry.listTools} / {@link ToolRegistry.callTool}. Keeping the
|
|
43
|
+
* SDK out of this package means the core stays testable and portable.
|
|
44
|
+
*/
|
|
45
|
+
/** An MCP tool descriptor as advertised to clients (subset of the MCP schema). */
|
|
46
|
+
interface McpToolDescriptor {
|
|
47
|
+
name: string;
|
|
48
|
+
description: string;
|
|
49
|
+
inputSchema: JsonSchema;
|
|
50
|
+
outputSchema?: JsonSchema;
|
|
51
|
+
annotations: ToolAnnotations;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* `_meta` key carrying the upstream HTTP status of a dispatched call.
|
|
55
|
+
*
|
|
56
|
+
* `isError` is one bit, and it collapses answers that mean opposite things: a
|
|
57
|
+
* 404 for a record that does not exist, a 403 a guard correctly refused, a
|
|
58
|
+
* domain refusal ("this store does not use comandas"), and a 500 where the route
|
|
59
|
+
* threw all arrive identical. Callers that need to tell "correctly refused" from
|
|
60
|
+
* "actually broken" — `mcp:smoke` above all — cannot, because the status is
|
|
61
|
+
* known at dispatch and then dropped. Publishing it under a namespaced `_meta`
|
|
62
|
+
* key (permitted by the MCP result schema) keeps `isError` as the agent-facing
|
|
63
|
+
* signal while making the distinction recoverable.
|
|
64
|
+
*/
|
|
65
|
+
declare const HTTP_STATUS_META_KEY = "dispatch/httpStatus";
|
|
66
|
+
/** An MCP tool-call result (subset of the MCP schema). */
|
|
67
|
+
interface McpToolResult {
|
|
68
|
+
content: Array<{
|
|
69
|
+
type: "text";
|
|
70
|
+
text: string;
|
|
71
|
+
}>;
|
|
72
|
+
isError: boolean;
|
|
73
|
+
/** Machine-readable output matching the advertised outputSchema. */
|
|
74
|
+
structuredContent?: Record<string, unknown>;
|
|
75
|
+
/** Out-of-band metadata; carries {@link HTTP_STATUS_META_KEY} when dispatched. */
|
|
76
|
+
_meta?: Record<string, unknown>;
|
|
77
|
+
}
|
|
78
|
+
interface ToolRegistry {
|
|
79
|
+
listTools(auth?: RequestAuth): McpToolDescriptor[];
|
|
80
|
+
callTool(name: string, args: Record<string, unknown>, auth: RequestAuth): Promise<McpToolResult>;
|
|
81
|
+
}
|
|
82
|
+
interface RegistryOptions {
|
|
83
|
+
tools: GeneratedTool[];
|
|
84
|
+
/** Origin the tools proxy to (usually the app's own public URL). */
|
|
85
|
+
baseUrl: string;
|
|
86
|
+
fetchImpl?: typeof fetch;
|
|
87
|
+
/**
|
|
88
|
+
* Optional visibility filter — e.g. hide mutating tools, or tools whose
|
|
89
|
+
* required scope the caller lacks. Authorization is still enforced upstream;
|
|
90
|
+
* this only shapes what the agent is shown.
|
|
91
|
+
*/
|
|
92
|
+
isVisible?: (tool: GeneratedTool, auth?: RequestAuth) => boolean;
|
|
93
|
+
}
|
|
94
|
+
declare function createToolRegistry(options: RegistryOptions): ToolRegistry;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The MCP JSON-RPC 2.0 request half of the Streamable HTTP transport.
|
|
98
|
+
*
|
|
99
|
+
* Implemented directly rather than via the MCP SDK because the SDK's transport is
|
|
100
|
+
* Node-`http` oriented, and a host serving Web `Request`/`Response` (a Next route
|
|
101
|
+
* handler, a Hono route) has no `http.IncomingMessage` to hand it. It covers the
|
|
102
|
+
* methods a client needs to discover and call tools: `initialize`, `tools/list`,
|
|
103
|
+
* `tools/call`, plus `ping`.
|
|
104
|
+
*
|
|
105
|
+
* WHAT IS MECHANISM AND LIVES HERE: the envelope, the method table, the error
|
|
106
|
+
* codes, the well-formedness rule, and the notification convention. None of it
|
|
107
|
+
* varies per host — it is JSON-RPC 2.0 and the MCP specification.
|
|
108
|
+
*
|
|
109
|
+
* WHAT IS VOCABULARY AND STAYS WITH THE HOST: the server's NAME, its version, and
|
|
110
|
+
* the `instructions` string an agent reads on connect. Those describe one
|
|
111
|
+
* particular product's tool surface, so they arrive as {@link McpJsonRpcOptions}
|
|
112
|
+
* rather than being written here.
|
|
113
|
+
*/
|
|
114
|
+
/** The MCP protocol revision this transport implements. */
|
|
115
|
+
declare const MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
116
|
+
/**
|
|
117
|
+
* JSON-RPC error code for "authentication required", returned by `tools/call`
|
|
118
|
+
* when the request carried no valid bearer. Outside the reserved -32768..-32000
|
|
119
|
+
* band's *defined* codes on purpose: it is an implementation-defined server
|
|
120
|
+
* error, and a host maps it to HTTP 401.
|
|
121
|
+
*/
|
|
122
|
+
declare const UNAUTHORIZED_CODE = -32001;
|
|
123
|
+
interface JsonRpcRequest {
|
|
124
|
+
jsonrpc: "2.0";
|
|
125
|
+
id?: string | number | null;
|
|
126
|
+
method: string;
|
|
127
|
+
params?: unknown;
|
|
128
|
+
}
|
|
129
|
+
interface JsonRpcResponse {
|
|
130
|
+
jsonrpc: "2.0";
|
|
131
|
+
id: string | number | null;
|
|
132
|
+
result?: unknown;
|
|
133
|
+
error?: {
|
|
134
|
+
code: number;
|
|
135
|
+
message: string;
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/** What a client is told it connected to, in `initialize`'s `serverInfo`. */
|
|
139
|
+
interface McpServerInfo {
|
|
140
|
+
/** The server's name, as a connected host displays it. */
|
|
141
|
+
name: string;
|
|
142
|
+
/**
|
|
143
|
+
* The advertised surface version.
|
|
144
|
+
*
|
|
145
|
+
* This is the ONLY signal a client gets that the tool surface changed: the
|
|
146
|
+
* transport is request/response only, so `notifications/tools/list_changed`
|
|
147
|
+
* can never be sent, and a host that cached `tools/list` at the handshake has
|
|
148
|
+
* no other reason to ask again. See `server/surface-lock.ts` for the guard
|
|
149
|
+
* that makes forgetting to move it a build error instead of a comment.
|
|
150
|
+
*/
|
|
151
|
+
version: string;
|
|
152
|
+
}
|
|
153
|
+
interface McpJsonRpcOptions {
|
|
154
|
+
/** The host's identity, returned verbatim in `initialize`. */
|
|
155
|
+
serverInfo: McpServerInfo;
|
|
156
|
+
/**
|
|
157
|
+
* Server-level guidance surfaced to the model on `initialize` (the MCP spec's
|
|
158
|
+
* optional `instructions` field). Omitted from the result when absent, rather
|
|
159
|
+
* than sent empty — a blank string is a claim that there is guidance.
|
|
160
|
+
*/
|
|
161
|
+
instructions?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Override the advertised protocol revision. Defaults to
|
|
164
|
+
* {@link MCP_PROTOCOL_VERSION}; a host should not normally set it.
|
|
165
|
+
*/
|
|
166
|
+
protocolVersion?: string;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Handle one MCP JSON-RPC request.
|
|
170
|
+
*
|
|
171
|
+
* Returns `null` for notifications (no id, no reply expected). `auth` is the
|
|
172
|
+
* verified caller identity, or `null` when the request carried no valid bearer —
|
|
173
|
+
* `tools/call` then returns {@link UNAUTHORIZED_CODE}, which the host surfaces as
|
|
174
|
+
* HTTP 401. Discovery (`initialize`, `ping`, `tools/list`) stays open, so a client
|
|
175
|
+
* can read the surface before it has a token.
|
|
176
|
+
*/
|
|
177
|
+
declare function handleMcpJsonRpc(request: JsonRpcRequest, registry: ToolRegistry, auth: RequestAuth | null, options: McpJsonRpcOptions): Promise<JsonRpcResponse | null>;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* The manifest is the committed source-of-truth artifact the CI drift gate
|
|
181
|
+
* (`mcp:check` → `12-apps/ci` `mcp-contract.yml`) diffs against a fresh
|
|
182
|
+
* regeneration. If an endpoint's schema changes without the manifest being
|
|
183
|
+
* regenerated, the diff fails the build — that is how the served MCP surface is
|
|
184
|
+
* kept in lockstep with the endpoint surface.
|
|
185
|
+
*/
|
|
186
|
+
interface BuildManifestOptions {
|
|
187
|
+
/** Bumped intentionally on any tool-shape change (mirrors the golden catalog). */
|
|
188
|
+
version: number;
|
|
189
|
+
/** Human label for the spec, e.g. "acme web @ openapi.json". */
|
|
190
|
+
source: string;
|
|
191
|
+
}
|
|
192
|
+
declare function buildManifest(tools: GeneratedTool[], options: BuildManifestOptions): ToolManifest;
|
|
193
|
+
/**
|
|
194
|
+
* Canonical JSON for a manifest — deep-key-sorted and trailing-newline'd, so the
|
|
195
|
+
* committed artifact and a regeneration diff cleanly (no key-order or whitespace
|
|
196
|
+
* churn). `mcp:check` regenerates, serializes with this, and `git diff --exit-code`s.
|
|
197
|
+
*/
|
|
198
|
+
declare function serializeManifest(manifest: ToolManifest): string;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Making a server's advertised version impossible to leave behind.
|
|
202
|
+
*
|
|
203
|
+
* THE PROBLEM, which every MCP server on this transport has. `tools/list` is
|
|
204
|
+
* answered on request and there is no server→client stream, so a server cannot
|
|
205
|
+
* push `notifications/tools/list_changed` — and one that declares
|
|
206
|
+
* `capabilities.tools.listChanged` without being able to send it is worse than
|
|
207
|
+
* one that is honest, because the host then stops checking for itself. What is
|
|
208
|
+
* left is `serverInfo.version` from the `initialize` handshake. A host caches the
|
|
209
|
+
* tool list against it, so a version that never moves gives it no reason to ever
|
|
210
|
+
* ask again: a tool that shipped stays invisible to every ALREADY CONNECTED
|
|
211
|
+
* client for as long as that connection lives.
|
|
212
|
+
*
|
|
213
|
+
* That is not a hypothetical. In the origin host a new tool reached production,
|
|
214
|
+
* answered on its route, and did not appear in a live connector — behind a
|
|
215
|
+
* `serverInfo.version` frozen at its initial value while ~280 tools were added
|
|
216
|
+
* underneath it. Nothing was broken; the only thing asking anyone to bump it was
|
|
217
|
+
* a comment, and a rule enforced by a comment is not enforced.
|
|
218
|
+
*
|
|
219
|
+
* THE MECHANISM. An app commits a lock recording WHICH surface its current
|
|
220
|
+
* version stands for. Its generator recomputes the digest and refuses to write
|
|
221
|
+
* the artifacts when the digest moved while the version did not, naming the
|
|
222
|
+
* value to set. Because the same generator run under `--check` is what the
|
|
223
|
+
* contract gate already diffs, the failure lands in CI and in a pre-push hook
|
|
224
|
+
* without a new job, without git history, and without any event-sensitivity.
|
|
225
|
+
*
|
|
226
|
+
* WHY A DIGEST OF THE SURFACE, NOT A PATHS FILTER. A `paths:` list over the
|
|
227
|
+
* server's own directory is wrong in both directions: it fires on edits no
|
|
228
|
+
* client can see (a comment in an auth helper) and misses real ones that enter
|
|
229
|
+
* from outside it (a schema whose ceiling is imported from a storage module).
|
|
230
|
+
* Hashing what the tools ARE — the canonical manifest serialization — has
|
|
231
|
+
* neither failure mode: it is exactly the bytes `tools/list` would return.
|
|
232
|
+
*/
|
|
233
|
+
/** The committed record: which surface an app's current version stands for. */
|
|
234
|
+
interface SurfaceLock {
|
|
235
|
+
/** The app's surface version at the time `digest` was recorded. */
|
|
236
|
+
version: number;
|
|
237
|
+
/** Digest of the served tool surface (see {@link surfaceDigest}). */
|
|
238
|
+
digest: string;
|
|
239
|
+
}
|
|
240
|
+
/** Everything {@link surfaceLockProblem} needs to judge one generation. */
|
|
241
|
+
interface SurfaceLockCheck {
|
|
242
|
+
/** The lock as committed, or `null` when there is none to contradict. */
|
|
243
|
+
previous: SurfaceLock | null;
|
|
244
|
+
/** The surface version the app currently declares. */
|
|
245
|
+
version: number;
|
|
246
|
+
/** Digest of the surface being generated now. */
|
|
247
|
+
digest: string;
|
|
248
|
+
/**
|
|
249
|
+
* Where the app's version constant lives, repo-relative — quoted in the
|
|
250
|
+
* failure so the fix is a path and a value rather than a hunt.
|
|
251
|
+
*/
|
|
252
|
+
versionLocation: string;
|
|
253
|
+
/** The constant's name, if the app does not use the default. */
|
|
254
|
+
versionName?: string;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Digest of a served tool surface — every tool's name, description, annotations
|
|
258
|
+
* and input/output schemas, in the manifest's own canonical (deep-key-sorted)
|
|
259
|
+
* serialization. Stable across unrelated reordering, and identical for two
|
|
260
|
+
* surfaces that a client could not tell apart.
|
|
261
|
+
*/
|
|
262
|
+
declare function surfaceDigest(tools: GeneratedTool[], source: string): string;
|
|
263
|
+
/** Canonical JSON for a committed lock (trailing newline, like the manifest). */
|
|
264
|
+
declare function serializeSurfaceLock(lock: SurfaceLock): string;
|
|
265
|
+
/**
|
|
266
|
+
* Decide whether an app's current version may stand for its current surface.
|
|
267
|
+
*
|
|
268
|
+
* Returns the problem as a sentence ready to print, or `null` when the pair is
|
|
269
|
+
* consistent. Four outcomes, and three of them pass:
|
|
270
|
+
*
|
|
271
|
+
* - surface unchanged → fine, whatever the version did (a release bump with no
|
|
272
|
+
* surface change is legitimate and must not be blocked);
|
|
273
|
+
* - surface changed AND version moved → fine, that is the whole contract;
|
|
274
|
+
* - no lock to contradict (first run, or the file was deleted) → fine, it is
|
|
275
|
+
* simply recorded;
|
|
276
|
+
* - surface changed and version did not → the failure this exists for.
|
|
277
|
+
*/
|
|
278
|
+
declare function surfaceLockProblem(check: SurfaceLockCheck): string | null;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* OAuth 2.0 Protected Resource Metadata (RFC 9728), as required by the MCP
|
|
282
|
+
* authorization spec: the MCP endpoint is an OAuth *resource server*. Agent hosts
|
|
283
|
+
* (Claude.ai / ChatGPT connectors) discover where to obtain a token by reading
|
|
284
|
+
* `/.well-known/oauth-protected-resource`, and on a 401 the resource server points
|
|
285
|
+
* them at that document via a `WWW-Authenticate` challenge.
|
|
286
|
+
*
|
|
287
|
+
* This module only builds the discovery documents/headers — validating the
|
|
288
|
+
* resulting access token is the app's job (the {@link import("../types").AuthResolver}),
|
|
289
|
+
* because it depends on the app's authorization server and key material.
|
|
290
|
+
*/
|
|
291
|
+
interface ProtectedResourceMetadataInput {
|
|
292
|
+
/** Canonical resource identifier — the MCP endpoint URL (the token audience). */
|
|
293
|
+
resource: string;
|
|
294
|
+
/** Authorization server issuer URLs that can mint tokens for this resource. */
|
|
295
|
+
authorizationServers: string[];
|
|
296
|
+
/** Scopes the resource server understands (advertised to clients). */
|
|
297
|
+
scopesSupported?: string[];
|
|
298
|
+
/** Human-facing docs URL for the protected resource, if any. */
|
|
299
|
+
resourceDocumentation?: string;
|
|
300
|
+
}
|
|
301
|
+
/** The RFC 9728 metadata document served at `/.well-known/oauth-protected-resource`. */
|
|
302
|
+
interface ProtectedResourceMetadata {
|
|
303
|
+
resource: string;
|
|
304
|
+
authorization_servers: string[];
|
|
305
|
+
bearer_methods_supported: string[];
|
|
306
|
+
scopes_supported?: string[];
|
|
307
|
+
resource_documentation?: string;
|
|
308
|
+
}
|
|
309
|
+
declare function buildProtectedResourceMetadata(input: ProtectedResourceMetadataInput): ProtectedResourceMetadata;
|
|
310
|
+
/**
|
|
311
|
+
* Build the `WWW-Authenticate` value for an unauthorized MCP response, pointing
|
|
312
|
+
* the client at the protected-resource metadata so it can start the OAuth flow.
|
|
313
|
+
* Per RFC 9728 §5.1 the challenge carries a `resource_metadata` parameter.
|
|
314
|
+
*/
|
|
315
|
+
declare function bearerChallenge(params: {
|
|
316
|
+
resourceMetadataUrl: string;
|
|
317
|
+
error?: "invalid_token" | "insufficient_scope";
|
|
318
|
+
errorDescription?: string;
|
|
319
|
+
}): string;
|
|
320
|
+
/** Standard path for the protected-resource metadata document. */
|
|
321
|
+
declare const PROTECTED_RESOURCE_METADATA_PATH = "/.well-known/oauth-protected-resource";
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* OAuth 2.0 Authorization Server Metadata (RFC 8414), the discovery half that
|
|
325
|
+
* complements the RFC 9728 protected-resource metadata in `resource-metadata.ts`.
|
|
326
|
+
* Agent hosts (Claude.ai / ChatGPT connectors) read
|
|
327
|
+
* `/.well-known/oauth-authorization-server` to learn where to start the OAuth
|
|
328
|
+
* 2.1 Authorization Code + PKCE flow.
|
|
329
|
+
*
|
|
330
|
+
* This builder is a pure function of `(issuer, scopes)` with no Next.js/request
|
|
331
|
+
* coupling, so it can move verbatim into the future `@12-apps/mcp` extraction.
|
|
332
|
+
* It derives every endpoint from the same issuer origin the resource metadata
|
|
333
|
+
* advertises, so the two discovery documents cannot drift.
|
|
334
|
+
*/
|
|
335
|
+
interface AuthorizationServerMetadataInput {
|
|
336
|
+
/** Authorization server issuer URL (origin) — also the resource issuer. */
|
|
337
|
+
issuer: string;
|
|
338
|
+
/** Scopes the authorization server advertises (from the shared scope source). */
|
|
339
|
+
scopesSupported: string[];
|
|
340
|
+
/**
|
|
341
|
+
* Client authentication methods the token endpoint accepts. Defaults to
|
|
342
|
+
* public PKCE clients (`none`) plus HTTP Basic client-secret auth.
|
|
343
|
+
*/
|
|
344
|
+
tokenEndpointAuthMethods?: string[];
|
|
345
|
+
/**
|
|
346
|
+
* Where the endpoints are actually mounted, if not at the defaults below. A
|
|
347
|
+
* host that moves an endpoint MUST move it here too: this document is the only
|
|
348
|
+
* thing a connector reads before its first request, so a path that lies here is
|
|
349
|
+
* a flow that fails at the first hop (12-23 — `createApiMcpOauth` passes its
|
|
350
|
+
* resolved paths, so the two cannot disagree).
|
|
351
|
+
*/
|
|
352
|
+
paths?: Partial<AuthorizationServerPaths>;
|
|
353
|
+
}
|
|
354
|
+
/** The endpoint paths this document advertises, relative to the issuer origin. */
|
|
355
|
+
interface AuthorizationServerPaths {
|
|
356
|
+
authorize: string;
|
|
357
|
+
token: string;
|
|
358
|
+
register: string;
|
|
359
|
+
jwks: string;
|
|
360
|
+
}
|
|
361
|
+
/** The RFC 8414 document served at `/.well-known/oauth-authorization-server`. */
|
|
362
|
+
interface AuthorizationServerMetadata {
|
|
363
|
+
issuer: string;
|
|
364
|
+
authorization_endpoint: string;
|
|
365
|
+
token_endpoint: string;
|
|
366
|
+
registration_endpoint: string;
|
|
367
|
+
jwks_uri: string;
|
|
368
|
+
scopes_supported: string[];
|
|
369
|
+
response_types_supported: string[];
|
|
370
|
+
grant_types_supported: string[];
|
|
371
|
+
code_challenge_methods_supported: string[];
|
|
372
|
+
token_endpoint_auth_methods_supported: string[];
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Build the RFC 8414 authorization-server metadata document from an issuer
|
|
376
|
+
* origin and the supported scopes. Endpoints are derived from `issuer`; the
|
|
377
|
+
* OAuth 2.1 + PKCE contract fixes `response_types_supported`,
|
|
378
|
+
* `grant_types_supported`, and `code_challenge_methods_supported`.
|
|
379
|
+
*/
|
|
380
|
+
declare function buildAuthorizationServerMetadata(input: AuthorizationServerMetadataInput): AuthorizationServerMetadata;
|
|
381
|
+
|
|
382
|
+
export { type AuthorizationServerMetadata, type AuthorizationServerMetadataInput, type AuthorizationServerPaths, type BuildManifestOptions, DispatchConfig, DispatchInputError, DispatchResult, GeneratedTool, HTTP_STATUS_META_KEY, type JsonRpcRequest, type JsonRpcResponse, JsonSchema, MCP_PROTOCOL_VERSION, type McpJsonRpcOptions, type McpServerInfo, type McpToolDescriptor, type McpToolResult, PROTECTED_RESOURCE_METADATA_PATH, type ProtectedResourceMetadata, type ProtectedResourceMetadataInput, type RegistryOptions, RequestAuth, type SurfaceLock, type SurfaceLockCheck, ToolAnnotations, ToolManifest, type ToolRegistry, UNAUTHORIZED_CODE, UnsupportedSchemaError, bearerChallenge, buildAuthorizationServerMetadata, buildManifest, buildProtectedResourceMetadata, createToolRegistry, dispatchTool, handleMcpJsonRpc, inlineSchemaRefs, serializeManifest, serializeSurfaceLock, surfaceDigest, surfaceLockProblem };
|