@dereekb/firebase-server 13.36.0 → 13.37.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/calcom/package.json +10 -10
- package/discord/package.json +10 -10
- package/index.cjs.js +1 -1
- package/index.esm.js +1 -1
- package/mailgun/package.json +9 -9
- package/mcp/index.cjs.js +282 -63
- package/mcp/index.esm.js +280 -61
- package/mcp/package.json +13 -12
- package/mcp/src/lib/controller/mcp.controller.d.ts +28 -3
- package/mcp/src/lib/controller/mcp.wellknown.controller.d.ts +21 -1
- package/mcp/src/lib/mcp.config.d.ts +9 -7
- package/mcp/src/lib/mcp.module.d.ts +2 -1
- package/mcp/src/lib/service/mcp.server.factory.d.ts +5 -4
- package/mcp/src/lib/service/mcp.tool-generator.d.ts +1 -1
- package/mcp/src/lib/service/mcp.visibility.d.ts +1 -1
- package/mcp/src/lib/transport/streamable-http.transport.d.ts +16 -11
- package/model/index.cjs.js +1 -1
- package/model/index.esm.js +1 -1
- package/model/package.json +9 -9
- package/oidc/index.cjs.js +257 -67
- package/oidc/index.esm.js +256 -69
- package/oidc/package.json +10 -10
- package/oidc/src/lib/profile.d.ts +21 -0
- package/oidc/src/lib/service/index.d.ts +1 -0
- package/oidc/src/lib/service/oidc.config.service.d.ts +14 -0
- package/oidc/src/lib/service/oidc.interaction-policy.d.ts +35 -0
- package/oidc/src/lib/service/oidc.service.d.ts +29 -0
- package/package.json +14 -13
- package/test/index.cjs.js +8 -8
- package/test/index.esm.js +8 -8
- package/test/package.json +11 -11
- package/twilio/package.json +8 -8
- package/zoho/package.json +10 -10
|
@@ -12,7 +12,8 @@ export interface OAuthProtectedResourceMetadata {
|
|
|
12
12
|
/**
|
|
13
13
|
* Scopes the resource accepts (RFC 9728 §2). Advertised so dynamic-registration
|
|
14
14
|
* MCP clients (e.g. the Claude Code CLI) know which scopes to request on the
|
|
15
|
-
* authorization call
|
|
15
|
+
* authorization call — they request this list verbatim, so it carries only scopes
|
|
16
|
+
* such a client can actually be granted. Omitted when the resolved list is empty.
|
|
16
17
|
*/
|
|
17
18
|
readonly scopes_supported?: ReadonlyArray<OidcScope>;
|
|
18
19
|
}
|
|
@@ -25,10 +26,29 @@ export interface OAuthProtectedResourceMetadata {
|
|
|
25
26
|
* URIs must live at the host root. Apps need to exclude `.well-known/{*path}`
|
|
26
27
|
* from any global API route prefix (see `FIREBASE_SERVER_OIDC_ROUTES_FOR_GLOBAL_ROUTE_EXCLUDE`
|
|
27
28
|
* in `firebase-server/oidc` for the corresponding OIDC excludes).
|
|
29
|
+
*
|
|
30
|
+
* Because the document must be reachable at the origin root, the MCP endpoint has to be
|
|
31
|
+
* exposed through a host that serves the app at `/` — Firebase Hosting, or the hosting
|
|
32
|
+
* emulator in development. Pointing a client straight at the Functions emulator origin
|
|
33
|
+
* (`http://localhost:<port>/<project>/<region>/<function>/mcp`) breaks discovery: that
|
|
34
|
+
* runtime only routes `/<project>/<region>/<function>/…`, so nothing answers at the root
|
|
35
|
+
* and a client that has not yet seen a 401 challenge cannot find the issuer.
|
|
28
36
|
*/
|
|
29
37
|
export declare class McpWellKnownController {
|
|
30
38
|
private readonly mcpConfig;
|
|
31
39
|
private readonly oidcProviderConfigService;
|
|
32
40
|
constructor(mcpConfig: McpModuleConfig, oidcProviderConfigService: OidcProviderConfigService);
|
|
41
|
+
/**
|
|
42
|
+
* Serves both RFC 9728 discovery URLs — the primary form (§3.1), which inserts the resource's
|
|
43
|
+
* path after the well-known prefix (`/.well-known/oauth-protected-resource/mcp`), and the bare
|
|
44
|
+
* form (`/.well-known/oauth-protected-resource`) that clients probe as a fallback.
|
|
45
|
+
*
|
|
46
|
+
* The document is identical either way; the resource identity comes from
|
|
47
|
+
* {@link McpModuleConfig.mcpUrl}, not from the request path. Serving the primary form means
|
|
48
|
+
* discovery succeeds on a client's first probe rather than depending on it implementing the
|
|
49
|
+
* fallback.
|
|
50
|
+
*
|
|
51
|
+
* @returns The protected-resource metadata document.
|
|
52
|
+
*/
|
|
33
53
|
getProtectedResourceMetadata(): OAuthProtectedResourceMetadata;
|
|
34
54
|
}
|
|
@@ -83,8 +83,9 @@ export interface McpReasonParameterConfig {
|
|
|
83
83
|
/**
|
|
84
84
|
* Filter applied to the OIDC provider's advertised scope list when building the MCP
|
|
85
85
|
* protected-resource metadata's `scopes_supported`. Receives every scope the provider
|
|
86
|
-
* issues (from `OidcProviderConfigService.
|
|
87
|
-
* advertise. Supplied via {@link McpModuleConfig.scopesSupported};
|
|
86
|
+
* issues to an arbitrary client (from `OidcProviderConfigService.clientRequestableScopesSupported`)
|
|
87
|
+
* and returns the subset to advertise. Supplied via {@link McpModuleConfig.scopesSupported};
|
|
88
|
+
* when unset, all of them are advertised.
|
|
88
89
|
*/
|
|
89
90
|
export type McpScopesSupportedFilter = (allScopes: readonly OidcScope[]) => readonly OidcScope[];
|
|
90
91
|
/**
|
|
@@ -127,11 +128,12 @@ export declare abstract class McpModuleConfig {
|
|
|
127
128
|
* protected-resource discovery document's `scopes_supported` (RFC 9728 §2).
|
|
128
129
|
*
|
|
129
130
|
* The base list is pulled automatically from the OIDC provider config via the
|
|
130
|
-
* injected {@link OidcProviderConfigService.
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
131
|
+
* injected {@link OidcProviderConfigService.clientRequestableScopesSupported}, so
|
|
132
|
+
* the MCP resource advertises the scopes the issuer grants an arbitrary client
|
|
133
|
+
* without the app restating them. Scopes only an admin-assigned provider profile
|
|
134
|
+
* unlocks are already excluded — requesting one is fatal at the consent unlock
|
|
135
|
+
* gate. Provide this only to narrow the set further; it returns the subset to
|
|
136
|
+
* advertise. When unset, the whole base list is advertised.
|
|
135
137
|
*
|
|
136
138
|
* Advertising these matters because dynamic-registration MCP clients (the Claude
|
|
137
139
|
* Code CLI) read `scopes_supported` to decide which scopes to request on the
|
|
@@ -17,7 +17,8 @@ export interface McpModuleMetadataConfig extends Pick<ModuleMetadata, 'imports'
|
|
|
17
17
|
* - {@link ModelApiDispatchConfig} — so the MCP server can reuse the call model dispatch chain.
|
|
18
18
|
* - {@link McpModuleConfig} — issuer + resource URLs for protected-resource discovery.
|
|
19
19
|
* - `OidcProviderConfigService` (from `@dereekb/firebase-server/oidc`) — the `McpWellKnownController`
|
|
20
|
-
* reads the provider's `
|
|
20
|
+
* reads the provider's `clientRequestableScopesSupported` to advertise them on the
|
|
21
|
+
* protected-resource document.
|
|
21
22
|
*
|
|
22
23
|
* In practice, downstream apps typically import their own `*ModelApiModule` first (which provides
|
|
23
24
|
* `ModelApiCallModelDispatchService` + `MODEL_API_NEST_APPLICATION_CONTEXT`) and add the
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/server';
|
|
2
2
|
import { type Request } from 'express';
|
|
3
3
|
import { ModelApiCallModelDispatchService, ModelApiGetService, FirebaseServerStorageService, type FirebaseServerAuthData } from '@dereekb/firebase-server';
|
|
4
4
|
import { McpModuleConfig, type McpAuthRoleReader } from '../mcp.config';
|
|
@@ -17,9 +17,10 @@ export interface McpRequestContext {
|
|
|
17
17
|
* Injectable factory that builds {@link McpServer} instances pre-wired to the
|
|
18
18
|
* call model dispatch chain.
|
|
19
19
|
*
|
|
20
|
-
* The factory is invoked per Streamable HTTP request
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* The factory is invoked per Streamable HTTP request. That is the shape the MCP
|
|
21
|
+
* SDK's 2026-07-28 entry (`createMcpHandler`) requires — it builds a fresh server
|
|
22
|
+
* per request and has no session concept at all — and it is equally what the SDK
|
|
23
|
+
* recommends for stateless 2025-era serving, so one factory backs both eras.
|
|
23
24
|
*/
|
|
24
25
|
export declare class McpServerFactoryService {
|
|
25
26
|
private readonly mcpConfig;
|
|
@@ -2,7 +2,7 @@ import { type Maybe } from '@dereekb/util';
|
|
|
2
2
|
import { type FirestoreModelType, type KnownOnCallFunctionType, type OidcModelScopeRequirement, type OidcScopeTerm } from '@dereekb/firebase';
|
|
3
3
|
import { type ModelApiDetailsResult, type OnCallModelFunctionApiDetails, type FirebaseServerAuthData, type McpToolDetailsBuilder, type McpVisibilityRule } from '@dereekb/firebase-server';
|
|
4
4
|
import { type Request } from 'express';
|
|
5
|
-
import {
|
|
5
|
+
import type { CallToolResult, ToolAnnotations } from '@modelcontextprotocol/server';
|
|
6
6
|
import { type McpManifestToolEntry } from './mcp.manifest';
|
|
7
7
|
import { type McpToolFilterMetadata } from './mcp.visibility';
|
|
8
8
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Maybe } from '@dereekb/util';
|
|
2
2
|
import { type CallModelOidcScope, type OidcScopeTerm } from '@dereekb/firebase';
|
|
3
3
|
import { type McpToolVisibility, type McpVisibilityContext, type McpVisibilityRule } from '@dereekb/firebase-server';
|
|
4
|
-
import {
|
|
4
|
+
import type { ToolAnnotations } from '@modelcontextprotocol/server';
|
|
5
5
|
/**
|
|
6
6
|
* Normalized classification of a {@link McpToolVisibility} value computed at boot.
|
|
7
7
|
*
|
|
@@ -1,21 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type McpServer } from '@modelcontextprotocol/server';
|
|
2
2
|
import { type Request, type Response } from 'express';
|
|
3
3
|
/**
|
|
4
|
-
* Handles a single Streamable HTTP JSON-RPC request
|
|
4
|
+
* Handles a single Streamable HTTP JSON-RPC request, building a fresh MCP server for it.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* Both protocol eras are served, each by its own leg:
|
|
7
|
+
*
|
|
8
|
+
* - **2026-07-28 (modern)** — `createMcpHandler`, which is per-request and stateless by
|
|
9
|
+
* construction: there is no `Mcp-Session-Id` and no transport bookkeeping.
|
|
10
|
+
* - **2025-era (legacy)** — a `NodeStreamableHTTPServerTransport` in stateless mode, which is
|
|
11
|
+
* byte-for-byte what this endpoint served before the SDK v2 upgrade.
|
|
12
|
+
*
|
|
13
|
+
* The legacy leg is wired by hand (the SDK's documented `isLegacyRequest` composition) rather
|
|
14
|
+
* than left to `createMcpHandler`'s built-in `legacy: 'stateless'` fallback, because that
|
|
15
|
+
* fallback builds its transport with `sessionIdGenerator` alone and therefore answers in
|
|
16
|
+
* `text/event-stream`. See {@link handleLegacyMcpRequest} for why that framing is not viable
|
|
17
|
+
* here.
|
|
10
18
|
*
|
|
11
19
|
* The caller is expected to have already validated the bearer token (via the
|
|
12
20
|
* OIDC bearer middleware) before this function runs.
|
|
13
21
|
*
|
|
14
22
|
* @param req - The Express request carrying the JSON-RPC body.
|
|
15
23
|
* @param res - The Express response.
|
|
16
|
-
* @param
|
|
17
|
-
* @param server.connect - The MCP server's connect method that binds the transport before request handling.
|
|
24
|
+
* @param buildServer - Factory producing the MCP server that backs this request.
|
|
18
25
|
*/
|
|
19
|
-
export declare function handleStreamableHttpMcpRequest(req: Request, res: Response,
|
|
20
|
-
connect: (transport: StreamableHTTPServerTransport) => Promise<void>;
|
|
21
|
-
}): Promise<void>;
|
|
26
|
+
export declare function handleStreamableHttpMcpRequest(req: Request, res: Response, buildServer: () => McpServer): Promise<void>;
|
package/model/index.cjs.js
CHANGED
|
@@ -14770,7 +14770,7 @@ function enrichSignedUploadUrlInputSchema(defaultInputSchema, purposeKeys) {
|
|
|
14770
14770
|
if (defaultInputSchema != null && (typeof defaultInputSchema === "undefined" ? "undefined" : _type_of$3(defaultInputSchema)) === 'object') {
|
|
14771
14771
|
var _base_properties;
|
|
14772
14772
|
var base = defaultInputSchema;
|
|
14773
|
-
var purposeProperty = (_base_properties = base.properties) === null || _base_properties === void 0 ? void 0 : _base_properties
|
|
14773
|
+
var purposeProperty = (_base_properties = base.properties) === null || _base_properties === void 0 ? void 0 : _base_properties['purpose'];
|
|
14774
14774
|
if (purposeProperty != null && (typeof purposeProperty === "undefined" ? "undefined" : _type_of$3(purposeProperty)) === 'object') {
|
|
14775
14775
|
var quotedPurposes = purposeKeys.map(function(purpose) {
|
|
14776
14776
|
return '"'.concat(purpose, '"');
|
package/model/index.esm.js
CHANGED
|
@@ -14768,7 +14768,7 @@ function enrichSignedUploadUrlInputSchema(defaultInputSchema, purposeKeys) {
|
|
|
14768
14768
|
if (defaultInputSchema != null && (typeof defaultInputSchema === "undefined" ? "undefined" : _type_of$3(defaultInputSchema)) === 'object') {
|
|
14769
14769
|
var _base_properties;
|
|
14770
14770
|
var base = defaultInputSchema;
|
|
14771
|
-
var purposeProperty = (_base_properties = base.properties) === null || _base_properties === void 0 ? void 0 : _base_properties
|
|
14771
|
+
var purposeProperty = (_base_properties = base.properties) === null || _base_properties === void 0 ? void 0 : _base_properties['purpose'];
|
|
14772
14772
|
if (purposeProperty != null && (typeof purposeProperty === "undefined" ? "undefined" : _type_of$3(purposeProperty)) === 'object') {
|
|
14773
14773
|
var quotedPurposes = purposeKeys.map(function(purpose) {
|
|
14774
14774
|
return '"'.concat(purpose, '"');
|
package/model/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/model",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.37.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
-
"@dereekb/analytics": "13.
|
|
6
|
-
"@dereekb/date": "13.
|
|
7
|
-
"@dereekb/firebase": "13.
|
|
8
|
-
"@dereekb/firebase-server": "13.
|
|
9
|
-
"@dereekb/model": "13.
|
|
10
|
-
"@dereekb/nestjs": "13.
|
|
11
|
-
"@dereekb/rxjs": "13.
|
|
12
|
-
"@dereekb/util": "13.
|
|
5
|
+
"@dereekb/analytics": "13.37.0",
|
|
6
|
+
"@dereekb/date": "13.37.0",
|
|
7
|
+
"@dereekb/firebase": "13.37.0",
|
|
8
|
+
"@dereekb/firebase-server": "13.37.0",
|
|
9
|
+
"@dereekb/model": "13.37.0",
|
|
10
|
+
"@dereekb/nestjs": "13.37.0",
|
|
11
|
+
"@dereekb/rxjs": "13.37.0",
|
|
12
|
+
"@dereekb/util": "13.37.0",
|
|
13
13
|
"@nestjs/common": "^11.1.19",
|
|
14
14
|
"@nestjs/config": "^4.0.4",
|
|
15
15
|
"archiver": "^7.0.1",
|